From b3bd8e195e24d2c8f391e70164fed38fc8146513 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Thu, 26 Sep 2024 13:46:17 -0700 Subject: [PATCH 001/426] Minor clean to remove unused field from ImportedClass --- Sources/JExtractSwift/ImportedDecls.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Sources/JExtractSwift/ImportedDecls.swift b/Sources/JExtractSwift/ImportedDecls.swift index 725061f5..92b9f9d2 100644 --- a/Sources/JExtractSwift/ImportedDecls.swift +++ b/Sources/JExtractSwift/ImportedDecls.swift @@ -28,8 +28,6 @@ public struct ImportedProtocol: ImportedDecl { public struct ImportedClass: ImportedDecl { public var name: ImportedTypeName - public var implementedInterfaces: Set = [] - public var initializers: [ImportedFunc] = [] public var methods: [ImportedFunc] = [] @@ -126,6 +124,8 @@ public struct ImportedFunc: ImportedDecl, CustomStringConvertible { /// This is a full name such as init(cap:name:). public var identifier: String + /// This is the base identifier for the function, e.g., "init" for an + /// initializer or "f" for "f(a:b:)". public var baseIdentifier: String { guard let idx = identifier.firstIndex(of: "(") else { return identifier @@ -134,7 +134,7 @@ public struct ImportedFunc: ImportedDecl, CustomStringConvertible { } /// A display name to use to refer to the Swift declaration with its - /// enclosing type. + /// enclosing type, if there is one. public var displayName: String { if let parentName { return "\(parentName.swiftTypeName).\(identifier)" From 11e285da90cf50ddef5940c639052ea71b092aa3 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Thu, 26 Sep 2024 14:23:15 -0700 Subject: [PATCH 002/426] Maintain a Swift type name -> imported type mapping in jextract-swift Switch the representation of the imported types from a flat list over to a dictionary mapping from the Swift name to the imported type. We need this so that we can find information about the Swift type when it is referenced elsewhere in the syntax tree, such as extensions or uses of that type in other function signatures. While here, stop recording intermediate results within the visitor itself. Instead, keep a reference to the full translator and record results there incrementally. This will become more important when we start handling extensions. --- Sources/JExtractSwift/ImportedDecls.swift | 18 +++++- .../Swift2JavaTranslator+Printing.swift | 12 ++-- .../JExtractSwift/Swift2JavaTranslator.swift | 15 +++-- Sources/JExtractSwift/Swift2JavaVisitor.swift | 61 +++++++++---------- Sources/JExtractSwift/SwiftDylib.swift | 2 +- .../JExtractSwiftTests/FuncImportTests.swift | 16 ++--- 6 files changed, 62 insertions(+), 62 deletions(-) diff --git a/Sources/JExtractSwift/ImportedDecls.swift b/Sources/JExtractSwift/ImportedDecls.swift index 92b9f9d2..d6e0119e 100644 --- a/Sources/JExtractSwift/ImportedDecls.swift +++ b/Sources/JExtractSwift/ImportedDecls.swift @@ -25,17 +25,28 @@ public struct ImportedProtocol: ImportedDecl { public var identifier: String } -public struct ImportedClass: ImportedDecl { +/// Describes a Swift nominal type (e.g., a class, struct, enum) that has been +/// imported and is being translated into Java. +public struct ImportedNominalType: ImportedDecl { public var name: ImportedTypeName + public var kind: NominalTypeKind public var initializers: [ImportedFunc] = [] public var methods: [ImportedFunc] = [] - public init(name: ImportedTypeName) { + public init(name: ImportedTypeName, kind: NominalTypeKind) { self.name = name + self.kind = kind } } +public enum NominalTypeKind { + case `actor` + case `class` + case `enum` + case `struct` +} + public struct ImportedParam: Hashable { let param: FunctionParameterSyntax @@ -97,9 +108,10 @@ public struct ImportedTypeName: Hashable { javaType.className } - public init(swiftTypeName: String, javaType: JavaType) { + public init(swiftTypeName: String, javaType: JavaType, swiftMangledName: String? = nil) { self.swiftTypeName = swiftTypeName self.javaType = javaType + self.swiftMangledName = swiftMangledName ?? "" } } diff --git a/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift b/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift index ba55d12f..158b44ef 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift @@ -27,7 +27,7 @@ extension Swift2JavaTranslator { public func writeImportedTypesTo(outputDirectory: String) throws { var printer = CodePrinter() - for ty in importedTypes { + for (_, ty) in importedTypes.sorted(by: { (lhs, rhs) in lhs.key < rhs.key }) { let filename = "\(ty.name.javaClassName!).java" log.info("Printing contents: \(filename)") printImportedClass(&printer, ty) @@ -106,7 +106,7 @@ extension Swift2JavaTranslator { } } - public func printImportedClass(_ printer: inout CodePrinter, _ decl: ImportedClass) { + public func printImportedClass(_ printer: inout CodePrinter, _ decl: ImportedNominalType) { printHeader(&printer) printPackage(&printer) printImports(&printer) // TODO print any imports the file may need, it we talk to other Swift modules @@ -164,7 +164,7 @@ extension Swift2JavaTranslator { printer.print("") } - public func printClass(_ printer: inout CodePrinter, _ decl: ImportedClass, body: (inout CodePrinter) -> Void) { + public func printClass(_ printer: inout CodePrinter, _ decl: ImportedNominalType, body: (inout CodePrinter) -> Void) { printer.printTypeDecl("public final class \(decl.name.javaClassName!)") { printer in // ==== Storage of the class // FIXME: implement the self storage for the memory address and accessors @@ -270,7 +270,7 @@ extension Swift2JavaTranslator { ) } - private func printClassMemorySegmentConstructor(_ printer: inout CodePrinter, _ decl: ImportedClass) { + private func printClassMemorySegmentConstructor(_ printer: inout CodePrinter, _ decl: ImportedNominalType) { printer.print( """ /** Instances are created using static {@code init} methods rather than through the constructor directly. */ @@ -282,7 +282,7 @@ extension Swift2JavaTranslator { } /// Print a property where we can store the "self" pointer of a class. - private func printClassSelfProperty(_ printer: inout CodePrinter, _ decl: ImportedClass) { + private func printClassSelfProperty(_ printer: inout CodePrinter, _ decl: ImportedNominalType) { printer.print( """ // Pointer to the referred to class instance's "self". @@ -295,7 +295,7 @@ extension Swift2JavaTranslator { ) } - private func printClassMemoryLayout(_ printer: inout CodePrinter, _ decl: ImportedClass) { + private func printClassMemoryLayout(_ printer: inout CodePrinter, _ decl: ImportedNominalType) { printer.print( """ private static final GroupLayout $LAYOUT = MemoryLayout.structLayout( diff --git a/Sources/JExtractSwift/Swift2JavaTranslator.swift b/Sources/JExtractSwift/Swift2JavaTranslator.swift index e642d9ee..ec57d972 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator.swift @@ -37,7 +37,9 @@ public final class Swift2JavaTranslator { // TODO: consider how/if we need to store those etc public var importedGlobalFuncs: [ImportedFunc] = [] - public var importedTypes: [ImportedClass] = [] + /// A mapping from Swift type names (e.g., A.B) over to the imported nominal + /// type representation. + public var importedTypes: [String: ImportedNominalType] = [:] public init( javaPackage: String, @@ -83,13 +85,10 @@ extension Swift2JavaTranslator { let visitor = Swift2JavaVisitor( moduleName: self.swiftModuleName, targetJavaPackage: self.javaPackage, - log: log + translator: self ) visitor.walk(sourceFileSyntax) - self.importedGlobalFuncs.append(contentsOf: visitor.javaMethodDecls) - self.importedTypes.append(contentsOf: visitor.javaTypeDecls) - try await self.postProcessImportedDecls() } @@ -119,7 +118,7 @@ extension Swift2JavaTranslator { return funcDecl } - importedTypes = try await importedTypes._mapAsync { tyDecl in + importedTypes = Dictionary(uniqueKeysWithValues: try await importedTypes._mapAsync { (tyName, tyDecl) in var tyDecl = tyDecl log.info("Mapping type: \(tyDecl.name)") @@ -140,8 +139,8 @@ extension Swift2JavaTranslator { return funcDecl } - return tyDecl - } + return (tyName, tyDecl) + }) } } diff --git a/Sources/JExtractSwift/Swift2JavaVisitor.swift b/Sources/JExtractSwift/Swift2JavaVisitor.swift index 65337b8a..d05b83b8 100644 --- a/Sources/JExtractSwift/Swift2JavaVisitor.swift +++ b/Sources/JExtractSwift/Swift2JavaVisitor.swift @@ -16,23 +16,23 @@ import SwiftParser import SwiftSyntax final class Swift2JavaVisitor: SyntaxVisitor { - let log: Logger + let translator: Swift2JavaTranslator /// The Swift module we're visiting declarations in let moduleName: String + /// The target java package we are going to generate types into eventually, /// store this along with type names as we import them. let targetJavaPackage: String - var javaMethodDecls: [ImportedFunc] = [] - var javaTypeDecls: [ImportedClass] = [] + var currentTypeName: String? = nil - var currentTypeDecl: ImportedClass? = nil + var log: Logger { translator.log } - init(moduleName: String, targetJavaPackage: String, log: Logger) { + init(moduleName: String, targetJavaPackage: String, translator: Swift2JavaTranslator) { self.moduleName = moduleName self.targetJavaPackage = targetJavaPackage - self.log = log + self.translator = translator super.init(viewMode: .all) } @@ -43,30 +43,28 @@ final class Swift2JavaVisitor: SyntaxVisitor { } log.info("Import: \(node.kind) \(node.name)") - currentTypeDecl = ImportedClass( + let typeName = node.name.text + currentTypeName = typeName + translator.importedTypes[typeName] = ImportedNominalType( // TODO: support nested classes (parent name here) name: ImportedTypeName( - swiftTypeName: node.name.text, + swiftTypeName: typeName, javaType: .class( package: targetJavaPackage, - name: node.name.text - ) - ) + name: typeName + ), + swiftMangledName: node.mangledNameFromComment + ), + kind: .class ) - // Retrieve the mangled name, if available. - if let mangledName = node.mangledNameFromComment { - currentTypeDecl!.name.swiftMangledName = mangledName - } - return .visitChildren } override func visitPost(_ node: ClassDeclSyntax) { - if let currentTypeDecl { + if currentTypeName != nil { log.info("Completed import: \(node.kind) \(node.name)") - self.javaTypeDecls.append(currentTypeDecl) - self.currentTypeDecl = nil + currentTypeName = nil } } @@ -113,7 +111,7 @@ final class Swift2JavaVisitor: SyntaxVisitor { let fullName = "\(node.name.text)(\(argumentLabelsStr))" var funcDecl = ImportedFunc( - parentName: currentTypeDecl?.name, + parentName: currentTypeName.map { translator.importedTypes[$0] }??.name, identifier: fullName, returnType: javaResultType, parameters: params @@ -125,26 +123,26 @@ final class Swift2JavaVisitor: SyntaxVisitor { funcDecl.swiftMangledName = mangledName } - if var currentTypeDecl = self.currentTypeDecl { - log.info("Record method in \(currentTypeDecl.name.javaType.description)") - currentTypeDecl.methods.append(funcDecl) - self.currentTypeDecl = currentTypeDecl + if let currentTypeName { + log.info("Record method in \(currentTypeName)") + translator.importedTypes[currentTypeName]?.methods.append(funcDecl) } else { - javaMethodDecls.append(funcDecl) + translator.importedGlobalFuncs.append(funcDecl) } return .skipChildren } override func visit(_ node: InitializerDeclSyntax) -> SyntaxVisitorContinueKind { - guard var currentTypeDecl = self.currentTypeDecl else { + guard let currentTypeName, + let currentType = translator.importedTypes[currentTypeName] else { fatalError("Initializer must be within a current type, was: \(node)") } guard node.shouldImport(log: log) else { return .skipChildren } - self.log.info("Import initializer: \(node.kind) \(currentTypeDecl.name.javaType.description)") + self.log.info("Import initializer: \(node.kind) \(currentType.name.javaType.description)") let params: [ImportedParam] do { params = try node.signature.parameterClause.parameters.map { param in @@ -164,9 +162,9 @@ final class Swift2JavaVisitor: SyntaxVisitor { "init(\(params.compactMap { $0.effectiveName ?? "_" }.joined(separator: ":")))" var funcDecl = ImportedFunc( - parentName: currentTypeDecl.name, + parentName: currentType.name, identifier: initIdentifier, - returnType: currentTypeDecl.name, + returnType: currentType.name, parameters: params ) funcDecl.isInit = true @@ -177,9 +175,8 @@ final class Swift2JavaVisitor: SyntaxVisitor { funcDecl.swiftMangledName = mangledName } - log.info("Record initializer method in \(currentTypeDecl.name.javaType.description): \(funcDecl.identifier)") - currentTypeDecl.initializers.append(funcDecl) - self.currentTypeDecl = currentTypeDecl + log.info("Record initializer method in \(currentType.name.javaType.description): \(funcDecl.identifier)") + translator.importedTypes[currentTypeName]!.initializers.append(funcDecl) return .skipChildren } diff --git a/Sources/JExtractSwift/SwiftDylib.swift b/Sources/JExtractSwift/SwiftDylib.swift index 8be8f6a7..1f656ea7 100644 --- a/Sources/JExtractSwift/SwiftDylib.swift +++ b/Sources/JExtractSwift/SwiftDylib.swift @@ -31,7 +31,7 @@ package struct SwiftDylib { // FIXME: remove this entire utility; replace with self.log = Logger(label: "SwiftDylib(\(path))", logLevel: .trace) // TODO: take from env } - package func fillInTypeMangledName(_ decl: ImportedClass) async throws -> ImportedClass { + package func fillInTypeMangledName(_ decl: ImportedNominalType) async throws -> ImportedNominalType { // TODO: this is hacky, not precise at all and will be removed entirely guard decl.name.swiftMangledName.isEmpty else { // it was already processed diff --git a/Tests/JExtractSwiftTests/FuncImportTests.swift b/Tests/JExtractSwiftTests/FuncImportTests.swift index 57f7e0eb..57ff7173 100644 --- a/Tests/JExtractSwiftTests/FuncImportTests.swift +++ b/Tests/JExtractSwiftTests/FuncImportTests.swift @@ -181,9 +181,7 @@ final class MethodImportTests: XCTestCase { try await st.analyze(swiftInterfacePath: "/fake/__FakeModule/SwiftFile.swiftinterface", text: class_interfaceFile) - let funcDecl: ImportedFunc = st.importedTypes.first { - $0.name.javaClassName == "MySwiftClass" - }!.methods.first { + let funcDecl: ImportedFunc = st.importedTypes["MySwiftClass"]!.methods.first { $0.baseIdentifier == "helloMemberFunction" }! @@ -224,9 +222,7 @@ final class MethodImportTests: XCTestCase { try await st.analyze(swiftInterfacePath: "/fake/__FakeModule/SwiftFile.swiftinterface", text: class_interfaceFile) - let funcDecl: ImportedFunc = st.importedTypes.first { - $0.name.javaClassName == "MySwiftClass" - }!.methods.first { + let funcDecl: ImportedFunc = st.importedTypes["MySwiftClass"]!.methods.first { $0.baseIdentifier == "helloMemberFunction" }! @@ -267,9 +263,7 @@ final class MethodImportTests: XCTestCase { try await st.analyze(swiftInterfacePath: "/fake/__FakeModule/SwiftFile.swiftinterface", text: class_interfaceFile) - let funcDecl: ImportedFunc = st.importedTypes.first { - $0.name.javaClassName == "MySwiftClass" - }!.methods.first { + let funcDecl: ImportedFunc = st.importedTypes["MySwiftClass"]!.methods.first { $0.baseIdentifier == "helloMemberFunction" }! @@ -302,9 +296,7 @@ final class MethodImportTests: XCTestCase { try await st.analyze(swiftInterfacePath: "/fake/__FakeModule/SwiftFile.swiftinterface", text: class_interfaceFile) - let funcDecl: ImportedFunc = st.importedTypes.first { - $0.name.javaClassName == "MySwiftClass" - }!.methods.first { + let funcDecl: ImportedFunc = st.importedTypes["MySwiftClass"]!.methods.first { $0.baseIdentifier == "makeInt" }! From b9a29c5489b1bf878508bfeaadee523a94cd7be1 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Thu, 26 Sep 2024 21:45:27 -0700 Subject: [PATCH 003/426] Introduce basic support for resolving nominal types within single module Implement rudimentary name lookup and extension binding for nominal type names so we can resolve Swift type names within a module. --- .../JExtractSwift/NominalTypeResolution.swift | 352 ++++++++++++++++++ .../NominalTypeResolutionTests.swift | 63 ++++ 2 files changed, 415 insertions(+) create mode 100644 Sources/JExtractSwift/NominalTypeResolution.swift create mode 100644 Tests/JExtractSwiftTests/NominalTypeResolutionTests.swift diff --git a/Sources/JExtractSwift/NominalTypeResolution.swift b/Sources/JExtractSwift/NominalTypeResolution.swift new file mode 100644 index 00000000..e2649069 --- /dev/null +++ b/Sources/JExtractSwift/NominalTypeResolution.swift @@ -0,0 +1,352 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import SwiftSyntax + +/// Perform nominal type resolution, including the binding of extensions to +/// their extended nominal types and mapping type names to their full names. +@_spi(Testing) +public class NominalTypeResolution { + /// A syntax node for a nominal type declaration. + @_spi(Testing) + public typealias NominalTypeDeclSyntaxNode = any DeclGroupSyntax & NamedDeclSyntax + + /// Mapping from the syntax identifier for a given type declaration node, + /// such as StructDeclSyntax, to the set of extensions of this particular + /// type. + private var extensionsByType: [SyntaxIdentifier: [ExtensionDeclSyntax]] = [:] + + /// Mapping from extension declarations to the type declaration that they + /// extend. + private var resolvedExtensions: [ExtensionDeclSyntax: NominalTypeDeclSyntaxNode] = [:] + + /// Extensions that have been encountered but not yet resolved to + private var unresolvedExtensions: [ExtensionDeclSyntax] = [] + + /// Mapping from qualified nominal type names to their syntax nodes. + private var topLevelNominalTypes: [String: NominalTypeDeclSyntaxNode] = [:] + + @_spi(Testing) public init() { } +} + +// MARK: Nominal type name resolution. +extension NominalTypeResolution { + /// Compute the fully-qualified name of the given nominal type node. + /// + /// This produces the name that can be resolved back to the nominal type + /// via resolveNominalType(_:). + @_spi(Testing) + public func fullyQualifiedName(of node: NominalTypeDeclSyntaxNode) -> String? { + let nameComponents = fullyQualifiedNameComponents(of: node) + return nameComponents.isEmpty ? nil : nameComponents.joined(separator: ".") + } + + private func fullyQualifiedNameComponents(of node: NominalTypeDeclSyntaxNode) -> [String] { + var nameComponents: [String] = [] + + var currentNode = Syntax(node) + while true { + // If it's a nominal type, add its name. + if let nominal = currentNode.asProtocol(SyntaxProtocol.self) as? NominalTypeDeclSyntaxNode, + let nominalName = nominal.name.identifier?.name { + nameComponents.append(nominalName) + } + + // If it's an extension, add the full name of the extended type. + if let extensionDecl = currentNode.as(ExtensionDeclSyntax.self), + let extendedNominal = extendedType(of: extensionDecl) { + let extendedNominalNameComponents = fullyQualifiedNameComponents(of: extendedNominal) + return extendedNominalNameComponents + nameComponents.reversed() + } + + guard let parent = currentNode.parent else { + break + + } + currentNode = parent + } + + return nameComponents.reversed() + } + + /// Resolve a nominal type name to its syntax node, or nil if it cannot be + /// resolved for any reason. + @_spi(Testing) + public func resolveNominalType(_ name: String) -> NominalTypeDeclSyntaxNode? { + let components = name.split(separator: ".") + return resolveNominalType(components) + } + + /// Resolve a nominal type name to its syntax node, or nil if it cannot be + /// resolved for any reason. + private func resolveNominalType(_ nameComponents: some Sequence) -> NominalTypeDeclSyntaxNode? { + // Resolve the name components in order. + var currentNode: NominalTypeDeclSyntaxNode? = nil + for nameComponentStr in nameComponents { + let nameComponent = String(nameComponentStr) + + var nextNode: NominalTypeDeclSyntaxNode? = nil + if let currentNode { + nextNode = lookupNominalType(nameComponent, in: currentNode) + } else { + nextNode = topLevelNominalTypes[nameComponent] + } + + // If we couldn't resolve the next name, we're done. + guard let nextNode else { + return nil + } + + currentNode = nextNode + } + + return currentNode + } + + /// Look for a nominal type with the given name within this declaration group, + /// which could be a nominal type declaration or extension thereof. + private func lookupNominalType( + _ name: String, + inDeclGroup parentNode: some DeclGroupSyntax + ) -> NominalTypeDeclSyntaxNode? { + for member in parentNode.memberBlock.members { + let memberDecl = member.decl.asProtocol(DeclSyntaxProtocol.self) + + // If we have a member with the given name that is a nominal type + // declaration, we found what we're looking for. + if let namedMemberDecl = memberDecl.asProtocol(NamedDeclSyntax.self), + namedMemberDecl.name.identifier?.name == name, + let nominalTypeDecl = memberDecl as? NominalTypeDeclSyntaxNode + { + return nominalTypeDecl + } + } + + return nil + } + + /// Lookup nominal type name within a given nominal type. + private func lookupNominalType( + _ name: String, + in parentNode: NominalTypeDeclSyntaxNode + ) -> NominalTypeDeclSyntaxNode? { + // Look in the parent node itself. + if let found = lookupNominalType(name, inDeclGroup: parentNode) { + return found + } + + // Look in known extensions of the parent node. + if let extensions = extensionsByType[parentNode.id] { + for extensionDecl in extensions { + if let found = lookupNominalType(name, inDeclGroup: extensionDecl) { + return found + } + } + } + + return nil + } +} + +// MARK: Binding extensions +extension NominalTypeResolution { + /// Look up the nominal type declaration to which this extension is bound. + @_spi(Testing) + public func extendedType(of extensionDecl: ExtensionDeclSyntax) -> NominalTypeDeclSyntaxNode? { + return resolvedExtensions[extensionDecl] + } + + /// Bind all of the unresolved extensions to their nominal types. + /// + /// Returns the list of extensions that could not be resolved. + @_spi(Testing) + public func bindExtensions() -> [ExtensionDeclSyntax] { + while !unresolvedExtensions.isEmpty { + // Try to resolve all of the unresolved extensions. + let numExtensionsBefore = unresolvedExtensions.count + unresolvedExtensions.removeAll { extensionDecl in + // Try to resolve the type referenced by this extension declaration. If + // it fails, we'll try again later. + let nestedTypeNameComponents = extensionDecl.nestedTypeName + guard let resolvedType = resolveNominalType(nestedTypeNameComponents) else { + return false + } + + // We have successfully resolved the extended type. Record it and + // remove the extension from the list of unresolved extensions. + extensionsByType[resolvedType.id, default: []].append(extensionDecl) + resolvedExtensions[extensionDecl] = resolvedType + + return true + } + + // If we didn't resolve anything, we're done. + if numExtensionsBefore == unresolvedExtensions.count { + break + } + + assert(numExtensionsBefore > unresolvedExtensions.count) + } + + // Any unresolved extensions at this point are fundamentally unresolvable. + return unresolvedExtensions + } +} + +extension ExtensionDeclSyntax { + /// Produce the nested type name for the given + fileprivate var nestedTypeName: [String] { + var nameComponents: [String] = [] + var extendedType = extendedType + while true { + switch extendedType.as(TypeSyntaxEnum.self) { + case .attributedType(let attributedType): + extendedType = attributedType.baseType + continue + + case .identifierType(let identifierType): + guard let identifier = identifierType.name.identifier else { + return [] + } + + nameComponents.append(identifier.name) + return nameComponents.reversed() + + case .memberType(let memberType): + guard let identifier = memberType.name.identifier else { + return [] + } + + nameComponents.append(identifier.name) + extendedType = memberType.baseType + continue + + // Structural types implemented as nominal types. + case .arrayType: + return ["Array"] + + case .dictionaryType: + return ["Dictionary"] + + case .implicitlyUnwrappedOptionalType, .optionalType: + return [ "Optional" ] + + // Types that never involve nominals. + + case .classRestrictionType, .compositionType, .functionType, .metatypeType, + .missingType, .namedOpaqueReturnType, .packElementType, + .packExpansionType, .someOrAnyType, .suppressedType, .tupleType: + return [] + } + } + } +} + +// MARK: Adding source files to the resolution. +extension NominalTypeResolution { + /// Add the given source file. + @_spi(Testing) + public func addSourceFile(_ sourceFile: SourceFileSyntax) { + let visitor = NominalAndExtensionFinder(typeResolution: self) + visitor.walk(sourceFile) + } + + private class NominalAndExtensionFinder: SyntaxVisitor { + var typeResolution: NominalTypeResolution + var nestingDepth = 0 + + init(typeResolution: NominalTypeResolution) { + self.typeResolution = typeResolution + super.init(viewMode: .sourceAccurate) + } + + // Entering nominal type declarations. + + func visitNominal(_ node: NominalTypeDeclSyntaxNode) { + if nestingDepth == 0 { + typeResolution.topLevelNominalTypes[node.name.text] = node + } + + nestingDepth += 1 + } + + override func visit(_ node: ActorDeclSyntax) -> SyntaxVisitorContinueKind { + visitNominal(node) + return .visitChildren + } + + override func visit(_ node: ClassDeclSyntax) -> SyntaxVisitorContinueKind { + visitNominal(node) + return .visitChildren + } + + override func visit(_ node: EnumDeclSyntax) -> SyntaxVisitorContinueKind { + visitNominal(node) + return .visitChildren + } + + override func visit(_ node: ProtocolDeclSyntax) -> SyntaxVisitorContinueKind { + visitNominal(node) + return .visitChildren + } + + override func visit(_ node: StructDeclSyntax) -> SyntaxVisitorContinueKind { + visitNominal(node) + return .visitChildren + } + + // Exiting nominal type declarations. + func visitPostNominal(_ node: NominalTypeDeclSyntaxNode) { + assert(nestingDepth > 0) + nestingDepth -= 1 + } + + override func visitPost(_ node: ActorDeclSyntax) { + visitPostNominal(node) + } + + override func visitPost(_ node: ClassDeclSyntax) { + visitPostNominal(node) + } + + override func visitPost(_ node: EnumDeclSyntax) { + visitPostNominal(node) + } + + override func visitPost(_ node: ProtocolDeclSyntax) { + visitPostNominal(node) + } + + override func visitPost(_ node: StructDeclSyntax) { + visitPostNominal(node) + } + + // Extension handling + override func visit(_ node: ExtensionDeclSyntax) -> SyntaxVisitorContinueKind { + // Note that the extension is unresolved. We'll bind it later. + typeResolution.unresolvedExtensions.append(node) + nestingDepth += 1 + return .visitChildren + } + + override func visitPost(_ node: ExtensionDeclSyntax) { + nestingDepth -= 1 + } + + // Avoid stepping into functions. + + override func visit(_ node: CodeBlockSyntax) -> SyntaxVisitorContinueKind { + return .skipChildren + } + } +} diff --git a/Tests/JExtractSwiftTests/NominalTypeResolutionTests.swift b/Tests/JExtractSwiftTests/NominalTypeResolutionTests.swift new file mode 100644 index 00000000..88b181b1 --- /dev/null +++ b/Tests/JExtractSwiftTests/NominalTypeResolutionTests.swift @@ -0,0 +1,63 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +@_spi(Testing) import JExtractSwift +import SwiftSyntax +import SwiftParser +import Testing + +@Suite("Nominal type lookup") +struct NominalTypeLookupSuite { + func checkNominalRoundTrip( + _ resolution: NominalTypeResolution, + name: String, + fileID: String = #fileID, + fileParh: String = #filePath, + line: Int = #line, + column: Int = #column + ) { + let sourceLocation = SourceLocation(fileID: fileID, filePath: fileParh, line: line, column: column) + let nominal = resolution.resolveNominalType(name) + #expect(nominal != nil, sourceLocation: sourceLocation) + if let nominal { + #expect(resolution.fullyQualifiedName(of: nominal) == name, sourceLocation: sourceLocation) + } + } + + @Test func lookupBindingTests() { + let resolution = NominalTypeResolution() + resolution.addSourceFile(""" + extension X { + struct Y { + } + } + + struct X { + } + + extension X.Y { + struct Z { } + } + """) + + // Bind all extensions and verify that all were bound. + #expect(resolution.bindExtensions().isEmpty) + + checkNominalRoundTrip(resolution, name: "X") + checkNominalRoundTrip(resolution, name: "X.Y") + checkNominalRoundTrip(resolution, name: "X.Y.Z") + #expect(resolution.resolveNominalType("Y") == nil) + #expect(resolution.resolveNominalType("X.Z") == nil) + } +} + From 42a64e49f03dc6d7d83a656c2665d69b20ea897d Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Thu, 26 Sep 2024 22:49:42 -0700 Subject: [PATCH 004/426] Use nominal type resolution to translate members of extensions Use the new nominal type resolution functionality within jextract-swift to resolve extensions to their corresponding nominal types, so that members of those extensions show up as member of the resulting Java class. --- .../JExtractSwift/NominalTypeResolution.swift | 9 +-- .../JExtractSwift/Swift2JavaTranslator.swift | 6 ++ Sources/JExtractSwift/Swift2JavaVisitor.swift | 64 +++++++++++++++---- .../JExtractSwiftTests/FuncImportTests.swift | 46 +++++++++++++ 4 files changed, 108 insertions(+), 17 deletions(-) diff --git a/Sources/JExtractSwift/NominalTypeResolution.swift b/Sources/JExtractSwift/NominalTypeResolution.swift index e2649069..4cb4d34a 100644 --- a/Sources/JExtractSwift/NominalTypeResolution.swift +++ b/Sources/JExtractSwift/NominalTypeResolution.swift @@ -17,10 +17,6 @@ import SwiftSyntax /// their extended nominal types and mapping type names to their full names. @_spi(Testing) public class NominalTypeResolution { - /// A syntax node for a nominal type declaration. - @_spi(Testing) - public typealias NominalTypeDeclSyntaxNode = any DeclGroupSyntax & NamedDeclSyntax - /// Mapping from the syntax identifier for a given type declaration node, /// such as StructDeclSyntax, to the set of extensions of this particular /// type. @@ -39,6 +35,10 @@ public class NominalTypeResolution { @_spi(Testing) public init() { } } +/// A syntax node for a nominal type declaration. +@_spi(Testing) +public typealias NominalTypeDeclSyntaxNode = any DeclGroupSyntax & NamedDeclSyntax + // MARK: Nominal type name resolution. extension NominalTypeResolution { /// Compute the fully-qualified name of the given nominal type node. @@ -170,6 +170,7 @@ extension NominalTypeResolution { /// /// Returns the list of extensions that could not be resolved. @_spi(Testing) + @discardableResult public func bindExtensions() -> [ExtensionDeclSyntax] { while !unresolvedExtensions.isEmpty { // Try to resolve all of the unresolved extensions. diff --git a/Sources/JExtractSwift/Swift2JavaTranslator.swift b/Sources/JExtractSwift/Swift2JavaTranslator.swift index ec57d972..d5396872 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator.swift @@ -41,6 +41,8 @@ public final class Swift2JavaTranslator { /// type representation. public var importedTypes: [String: ImportedNominalType] = [:] + let nominalResolution: NominalTypeResolution = NominalTypeResolution() + public init( javaPackage: String, swiftModuleName: String @@ -82,6 +84,10 @@ extension Swift2JavaTranslator { let sourceFileSyntax = Parser.parse(source: text) + // Find all of the types and extensions, then bind the extensions. + nominalResolution.addSourceFile(sourceFileSyntax) + nominalResolution.bindExtensions() + let visitor = Swift2JavaVisitor( moduleName: self.swiftModuleName, targetJavaPackage: self.javaPackage, diff --git a/Sources/JExtractSwift/Swift2JavaVisitor.swift b/Sources/JExtractSwift/Swift2JavaVisitor.swift index d05b83b8..db4625bb 100644 --- a/Sources/JExtractSwift/Swift2JavaVisitor.swift +++ b/Sources/JExtractSwift/Swift2JavaVisitor.swift @@ -25,6 +25,7 @@ final class Swift2JavaVisitor: SyntaxVisitor { /// store this along with type names as we import them. let targetJavaPackage: String + /// The current type name as a nested name like A.B.C. var currentTypeName: String? = nil var log: Logger { translator.log } @@ -37,27 +38,46 @@ final class Swift2JavaVisitor: SyntaxVisitor { super.init(viewMode: .all) } - override func visit(_ node: ClassDeclSyntax) -> SyntaxVisitorContinueKind { - guard node.shouldImport(log: log) else { - return .skipChildren + /// Try to resolve the given nominal type node into its imported + /// representation. + func resolveNominalType( + _ nominal: some DeclGroupSyntax & NamedDeclSyntax, + kind: NominalTypeKind + ) -> ImportedNominalType? { + if !nominal.shouldImport(log: log) { + return nil + } + + guard let fullName = translator.nominalResolution.fullyQualifiedName(of: nominal) else { + return nil + } + + if let alreadyImported = translator.importedTypes[fullName] { + return alreadyImported } - log.info("Import: \(node.kind) \(node.name)") - let typeName = node.name.text - currentTypeName = typeName - translator.importedTypes[typeName] = ImportedNominalType( - // TODO: support nested classes (parent name here) + let importedNominal = ImportedNominalType( name: ImportedTypeName( - swiftTypeName: typeName, + swiftTypeName: fullName, javaType: .class( package: targetJavaPackage, - name: typeName + name: fullName ), - swiftMangledName: node.mangledNameFromComment + swiftMangledName: nominal.mangledNameFromComment ), - kind: .class + kind: kind ) + translator.importedTypes[fullName] = importedNominal + return importedNominal + } + + override func visit(_ node: ClassDeclSyntax) -> SyntaxVisitorContinueKind { + guard let importedNominalType = resolveNominalType(node, kind: .class) else { + return .skipChildren + } + + currentTypeName = importedNominalType.name.swiftTypeName return .visitChildren } @@ -68,6 +88,24 @@ final class Swift2JavaVisitor: SyntaxVisitor { } } + override func visit(_ node: ExtensionDeclSyntax) -> SyntaxVisitorContinueKind { + // Resolve the extended type of the extension as an imported nominal, and + // recurse if we found it. + guard let nominal = translator.nominalResolution.extendedType(of: node), + let importedNominalType = resolveNominalType(nominal, kind: .class) else { + return .skipChildren + } + + currentTypeName = importedNominalType.name.swiftTypeName + return .visitChildren + } + + override func visitPost(_ node: ExtensionDeclSyntax) { + if currentTypeName != nil { + currentTypeName = nil + } + } + override func visit(_ node: FunctionDeclSyntax) -> SyntaxVisitorContinueKind { guard node.shouldImport(log: log) else { return .skipChildren @@ -182,7 +220,7 @@ final class Swift2JavaVisitor: SyntaxVisitor { } } -extension ClassDeclSyntax { +extension DeclGroupSyntax where Self: NamedDeclSyntax { func shouldImport(log: Logger) -> Bool { guard (accessControlModifiers.first { $0.isPublic }) != nil else { log.trace("Cannot import \(self.name) because: is not public") diff --git a/Tests/JExtractSwiftTests/FuncImportTests.swift b/Tests/JExtractSwiftTests/FuncImportTests.swift index 57ff7173..e670cd77 100644 --- a/Tests/JExtractSwiftTests/FuncImportTests.swift +++ b/Tests/JExtractSwiftTests/FuncImportTests.swift @@ -37,6 +37,11 @@ final class MethodImportTests: XCTestCase { // MANGLED NAME: $s14MySwiftLibrary23globalTakeLongIntString1l3i321sys5Int64V_s5Int32VSStF public func globalTakeIntLongString(i32: Int32, l: Int64, s: String) + extension MySwiftClass { + // MANGLED NAME: $s14MySwiftLibrary0aB5ClassC22helloMemberFunctionInExtension + public func helloMemberInExtension() + } + // MANGLED NAME: $s14MySwiftLibrary0aB5ClassCMa public class MySwiftClass { // MANGLED NAME: $s14MySwiftLibrary0aB5ClassC3len3capACSi_SitcfC @@ -213,6 +218,47 @@ final class MethodImportTests: XCTestCase { ) } + func test_method_class_helloMemberInExtension_self_memorySegment() async throws { + let st = Swift2JavaTranslator( + javaPackage: "com.example.swift", + swiftModuleName: "__FakeModule" + ) + st.log.logLevel = .trace + + try await st.analyze(swiftInterfacePath: "/fake/__FakeModule/SwiftFile.swiftinterface", text: class_interfaceFile) + + let funcDecl: ImportedFunc = st.importedTypes["MySwiftClass"]!.methods.first { + $0.baseIdentifier == "helloMemberInExtension" + }! + + let output = CodePrinter.toString { printer in + st.printFuncDowncallMethod(&printer, decl: funcDecl, selfVariant: .memorySegment) + } + + assertOutput( + output, + expected: + """ + /** + * {@snippet lang=swift : + * public func helloMemberInExtension() + * } + */ + public static void helloMemberInExtension(java.lang.foreign.MemorySegment self$) { + var mh$ = helloMemberInExtension.HANDLE; + try { + if (TRACE_DOWNCALLS) { + traceDowncall(self$); + } + mh$.invokeExact(self$); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + """ + ) + } + func test_method_class_helloMemberFunction_self_wrapper() async throws { let st = Swift2JavaTranslator( javaPackage: "com.example.swift", From 3c71e834a673e27aa5402f500a3666640d5448f0 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Fri, 27 Sep 2024 10:24:44 +0100 Subject: [PATCH 005/426] move entirely over to swift testing --- .../Asserts/TextAssertions.swift | 16 ++++++-- .../JExtractSwiftTests/FuncImportTests.swift | 19 +++++----- .../FunctionDescriptorImportTests.swift | 15 +++++--- .../InitClassImportTests.swift | 38 ------------------- .../JExtractSwiftTests/SwiftDylibTests.swift | 12 +++--- 5 files changed, 38 insertions(+), 62 deletions(-) delete mode 100644 Tests/JExtractSwiftTests/InitClassImportTests.swift diff --git a/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift b/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift index c6a372ba..b03d3d74 100644 --- a/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift +++ b/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift @@ -12,9 +12,17 @@ //===----------------------------------------------------------------------===// import JExtractSwift -import XCTest +import Testing +import struct Foundation.CharacterSet -func assertOutput(_ got: String, expected: String, file: StaticString = #filePath, line: UInt = #line) { +func assertOutput( + _ got: String, + expected: String, + fileID: String = #fileID, + filePath: String = #filePath, + line: Int = #line, + column: Int = #column +) { let gotLines = got.split(separator: "\n") let expectedLines = expected.split(separator: "\n") @@ -39,7 +47,9 @@ func assertOutput(_ got: String, expected: String, file: StaticString = #filePat diffLineNumbers.append(no) - XCTAssertEqual(ge, ee, file: file, line: line) + let sourceLocation = SourceLocation( + fileID: fileID, filePath: filePath, line: line, column: column) + #expect(ge == ee, sourceLocation: sourceLocation) } } diff --git a/Tests/JExtractSwiftTests/FuncImportTests.swift b/Tests/JExtractSwiftTests/FuncImportTests.swift index 57f7e0eb..89abf871 100644 --- a/Tests/JExtractSwiftTests/FuncImportTests.swift +++ b/Tests/JExtractSwiftTests/FuncImportTests.swift @@ -12,10 +12,9 @@ //===----------------------------------------------------------------------===// import JExtractSwift -import XCTest +import Testing -// TODO: Adopt Testing instead -final class MethodImportTests: XCTestCase { +final class MethodImportTests { let class_interfaceFile = """ // swift-interface-format-version: 1.0 @@ -51,7 +50,7 @@ final class MethodImportTests: XCTestCase { } """ - func test_method_helloWorld() async throws { + @Test func method_helloWorld() async throws { let st = Swift2JavaTranslator( javaPackage: "com.example.swift", swiftModuleName: "__FakeModule" @@ -90,7 +89,7 @@ final class MethodImportTests: XCTestCase { ) } - func test_method_globalTakeInt() async throws { + @Test func method_globalTakeInt() async throws { let st = Swift2JavaTranslator( javaPackage: "com.example.swift", swiftModuleName: "__FakeModule" @@ -131,7 +130,7 @@ final class MethodImportTests: XCTestCase { ) } - func test_method_globalTakeIntLongString() async throws { + @Test func method_globalTakeIntLongString() async throws { let st = Swift2JavaTranslator( javaPackage: "com.example.swift", swiftModuleName: "__FakeModule" @@ -172,7 +171,7 @@ final class MethodImportTests: XCTestCase { ) } - func test_method_class_helloMemberFunction_self_memorySegment() async throws { + @Test func method_class_helloMemberFunction_self_memorySegment() async throws { let st = Swift2JavaTranslator( javaPackage: "com.example.swift", swiftModuleName: "__FakeModule" @@ -215,7 +214,7 @@ final class MethodImportTests: XCTestCase { ) } - func test_method_class_helloMemberFunction_self_wrapper() async throws { + @Test func method_class_helloMemberFunction_self_wrapper() async throws { let st = Swift2JavaTranslator( javaPackage: "com.example.swift", swiftModuleName: "__FakeModule" @@ -258,7 +257,7 @@ final class MethodImportTests: XCTestCase { ) } - func test_method_class_helloMemberFunction_wrapper() async throws { + @Test func method_class_helloMemberFunction_wrapper() async throws { let st = Swift2JavaTranslator( javaPackage: "com.example.swift", swiftModuleName: "__FakeModule" @@ -293,7 +292,7 @@ final class MethodImportTests: XCTestCase { ) } - func test_method_class_makeInt_wrapper() async throws { + @Test func method_class_makeInt_wrapper() async throws { let st = Swift2JavaTranslator( javaPackage: "com.example.swift", swiftModuleName: "__FakeModule" diff --git a/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift b/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift index 345c3b9c..064672e1 100644 --- a/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift +++ b/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift @@ -12,10 +12,10 @@ //===----------------------------------------------------------------------===// import JExtractSwift -import XCTest +import Testing -// TODO: Adopt Testing instead -final class FunctionDescriptorTests: XCTestCase { +@Suite +final class FunctionDescriptorTests { let interfaceFile = """ // swift-interface-format-version: 1.0 @@ -73,7 +73,8 @@ final class FunctionDescriptorTests: XCTestCase { try await body(output) } - func test_FunctionDescriptor_globalTakeInt() async throws { + @Test + func FunctionDescriptor_globalTakeInt() async throws { try await functionDescriptorTest("globalTakeInt") { output in assertOutput( output, @@ -87,7 +88,8 @@ final class FunctionDescriptorTests: XCTestCase { } } - func test_FunctionDescriptor_globalTakeLongIntString() async throws { + @Test + func FunctionDescriptor_globalTakeLongIntString() async throws { try await functionDescriptorTest("globalTakeLongInt") { output in assertOutput( output, @@ -102,7 +104,8 @@ final class FunctionDescriptorTests: XCTestCase { } } - func test_FunctionDescriptor_echoInt() async throws { + @Test + func FunctionDescriptor_echoInt() async throws { try await functionDescriptorTest("echoInt") { output in assertOutput( output, diff --git a/Tests/JExtractSwiftTests/InitClassImportTests.swift b/Tests/JExtractSwiftTests/InitClassImportTests.swift deleted file mode 100644 index 5c34bad6..00000000 --- a/Tests/JExtractSwiftTests/InitClassImportTests.swift +++ /dev/null @@ -1,38 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -import JExtractSwift -import XCTest - -// TODO: Adopt Testing instead -final class InitClassImportTests: XCTestCase { - let class_interfaceFile = - """ - // swift-interface-format-version: 1.0 - // swift-compiler-version: Apple Swift version 6.0 effective-5.10 (swiftlang-6.0.0.7.6 clang-1600.0.24.1) - // swift-module-flags: -target arm64-apple-macosx15.0 -enable-objc-interop -enable-library-evolution -module-name MySwiftLibrary - import Darwin.C - import Darwin - import Swift - import _Concurrency - import _StringProcessing - import _SwiftConcurrencyShims - - public class MySwiftClass { - public init(len: Swift.Int, cap: Swift.Int) - - @objc deinit - } - """ - -} diff --git a/Tests/JExtractSwiftTests/SwiftDylibTests.swift b/Tests/JExtractSwiftTests/SwiftDylibTests.swift index e187a2f7..09dbb166 100644 --- a/Tests/JExtractSwiftTests/SwiftDylibTests.swift +++ b/Tests/JExtractSwiftTests/SwiftDylibTests.swift @@ -12,22 +12,24 @@ //===----------------------------------------------------------------------===// import JExtractSwift -import XCTest +import Testing -final class SwiftDylibTests: XCTestCase { +final class SwiftDylibTests { + + @Test func test_nm() async throws { let dylib = SwiftDylib(path: ".build/arm64-apple-macosx/debug/libJavaKitExample.dylib")! let names = try await dylib.nmSymbolNames(grepDemangled: ["MySwiftClass", "len"]) - XCTAssertTrue( + #expect( names.contains { $0.descriptiveName.contains("JavaKitExample.MySwiftClass.len.getter") } ) let getter = names.findPropertyGetter() - XCTAssertEqual(getter?.mangledName, "$s14JavaKitExample12MySwiftClassC3lenSivg") - XCTAssertEqual(getter?.descriptiveName, "JavaKitExample.MySwiftClass.len.getter : Swift.Int") + #expect(getter?.mangledName == "$s14JavaKitExample12MySwiftClassC3lenSivg") + #expect(getter?.descriptiveName == "JavaKitExample.MySwiftClass.len.getter : Swift.Int") } } From f32ea3194d12afd1b6b167d1e918c774deabbfd9 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Fri, 27 Sep 2024 10:48:19 +0100 Subject: [PATCH 006/426] Update Sources/JExtractSwift/NominalTypeResolution.swift --- Sources/JExtractSwift/NominalTypeResolution.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/JExtractSwift/NominalTypeResolution.swift b/Sources/JExtractSwift/NominalTypeResolution.swift index 4cb4d34a..c655598c 100644 --- a/Sources/JExtractSwift/NominalTypeResolution.swift +++ b/Sources/JExtractSwift/NominalTypeResolution.swift @@ -205,7 +205,7 @@ extension NominalTypeResolution { } extension ExtensionDeclSyntax { - /// Produce the nested type name for the given + /// Produce the nested type name for the given decl fileprivate var nestedTypeName: [String] { var nameComponents: [String] = [] var extendedType = extendedType From a8185fde30d12c1bc1363ba0dda73ced3004e2a4 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Fri, 27 Sep 2024 10:50:37 +0100 Subject: [PATCH 007/426] fix typo in variable name (#6) --- Tests/JExtractSwiftTests/NominalTypeResolutionTests.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tests/JExtractSwiftTests/NominalTypeResolutionTests.swift b/Tests/JExtractSwiftTests/NominalTypeResolutionTests.swift index 88b181b1..bb8fce6c 100644 --- a/Tests/JExtractSwiftTests/NominalTypeResolutionTests.swift +++ b/Tests/JExtractSwiftTests/NominalTypeResolutionTests.swift @@ -22,11 +22,11 @@ struct NominalTypeLookupSuite { _ resolution: NominalTypeResolution, name: String, fileID: String = #fileID, - fileParh: String = #filePath, + filePath: String = #filePath, line: Int = #line, column: Int = #column ) { - let sourceLocation = SourceLocation(fileID: fileID, filePath: fileParh, line: line, column: column) + let sourceLocation = SourceLocation(fileID: fileID, filePath: filePath, line: line, column: column) let nominal = resolution.resolveNominalType(name) #expect(nominal != nil, sourceLocation: sourceLocation) if let nominal { From a6cf88342a2ce4e4447f4e204ab6d4e5b5e915e8 Mon Sep 17 00:00:00 2001 From: "LamTrinh.Dev" Date: Fri, 27 Sep 2024 22:05:27 +0700 Subject: [PATCH 008/426] Fix the typo issue for README.md that replaces `interopability` to `interoperability`. (#7) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 23225e83..cc208d40 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Swift Java Interoperability Tools and Libraries -This repository contains two approaches to Swift/Java interopability. +This repository contains two approaches to Swift/Java interoperability. - A Swift library (`JavaKit`) and bindings generator that allows a Swift program to make use of Java libraries by wrapping Java classes in corresponding Swift types, allowing Swift to directly call any wrapped Java API. - The `jextract-swift` tool which is similar to the JDK's `jextract` which allows to extract Java sources which are used From c99e58f2b30f098fb016bae46be37807fe74ac11 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Fri, 27 Sep 2024 11:53:31 -0700 Subject: [PATCH 009/426] Move more type handling over to TranslatedType so we can centralize there --- Sources/JExtractSwift/ImportedDecls.swift | 39 ++++++++++++++++--- Sources/JExtractSwift/JavaTypes.swift | 7 ---- .../Swift2JavaTranslator+Printing.swift | 10 ++--- .../JExtractSwift/Swift2JavaTranslator.swift | 14 ++++++- Sources/JExtractSwift/Swift2JavaVisitor.swift | 26 ++++++------- Sources/JExtractSwift/SwiftDylib.swift | 8 ++-- Sources/JExtractSwift/TranslatedType.swift | 21 +++++++++- Sources/JavaTypes/JavaType+SwiftNames.swift | 4 -- 8 files changed, 87 insertions(+), 42 deletions(-) diff --git a/Sources/JExtractSwift/ImportedDecls.swift b/Sources/JExtractSwift/ImportedDecls.swift index d6e0119e..62fe2c95 100644 --- a/Sources/JExtractSwift/ImportedDecls.swift +++ b/Sources/JExtractSwift/ImportedDecls.swift @@ -28,16 +28,27 @@ public struct ImportedProtocol: ImportedDecl { /// Describes a Swift nominal type (e.g., a class, struct, enum) that has been /// imported and is being translated into Java. public struct ImportedNominalType: ImportedDecl { - public var name: ImportedTypeName + public let swiftTypeName: String + public let javaType: JavaType + public var swiftMangledName: String? public var kind: NominalTypeKind public var initializers: [ImportedFunc] = [] public var methods: [ImportedFunc] = [] - public init(name: ImportedTypeName, kind: NominalTypeKind) { - self.name = name + public init(swiftTypeName: String, javaType: JavaType, swiftMangledName: String? = nil, kind: NominalTypeKind) { + self.swiftTypeName = swiftTypeName + self.javaType = javaType + self.swiftMangledName = swiftMangledName self.kind = kind } + + var importedTypeName: ImportedTypeName { + ImportedTypeName( + swiftTypeName: swiftTypeName, + javaType: javaType + ) + } } public enum NominalTypeKind { @@ -172,13 +183,31 @@ public struct ImportedFunc: ImportedDecl, CustomStringConvertible { case .pointer: let selfParam: FunctionParameterSyntax = "self$: $swift_pointer" params.append( - ImportedParam(param: selfParam, type: java_lang_foreign_MemorySegment(swiftTypeName: "Self.self")) + ImportedParam( + param: selfParam, + type: TranslatedType( + cCompatibleConvention: .indirect, + originalSwiftType: "\(raw: parentName.swiftTypeName)", + cCompatibleSwiftType: "UnsafeRawPointer", + cCompatibleJavaMemoryLayout: .memorySegment, + javaType: .javaForeignMemorySegment + ).importedTypeName + ) ) case .memorySegment: let selfParam: FunctionParameterSyntax = "self$: $java_lang_foreign_MemorySegment" params.append( - ImportedParam(param: selfParam, type: java_lang_foreign_MemorySegment(swiftTypeName: "")) + ImportedParam( + param: selfParam, + type: TranslatedType( + cCompatibleConvention: .indirect, + originalSwiftType: "\(raw: parentName.swiftTypeName)", + cCompatibleSwiftType: "UnsafeRawPointer", + cCompatibleJavaMemoryLayout: .memorySegment, + javaType: .javaForeignMemorySegment + ).importedTypeName + ) ) case .wrapper: diff --git a/Sources/JExtractSwift/JavaTypes.swift b/Sources/JExtractSwift/JavaTypes.swift index 1c526583..e38df600 100644 --- a/Sources/JExtractSwift/JavaTypes.swift +++ b/Sources/JExtractSwift/JavaTypes.swift @@ -13,13 +13,6 @@ import JavaTypes -func java_lang_foreign_MemorySegment(swiftTypeName: String) -> ImportedTypeName { - ImportedTypeName( - swiftTypeName: swiftTypeName, - javaType: .javaForeignMemorySegment - ) -} - extension JavaType { /// The description of the type java.lang.foreign.MemorySegment. static var javaForeignMemorySegment: JavaType { diff --git a/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift b/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift index 158b44ef..57e11b52 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift @@ -28,7 +28,7 @@ extension Swift2JavaTranslator { var printer = CodePrinter() for (_, ty) in importedTypes.sorted(by: { (lhs, rhs) in lhs.key < rhs.key }) { - let filename = "\(ty.name.javaClassName!).java" + let filename = "\(ty.javaType).java" log.info("Printing contents: \(filename)") printImportedClass(&printer, ty) @@ -116,7 +116,7 @@ extension Swift2JavaTranslator { printer.print( """ // FIXME: this detecting is somewhat off - public static final String TYPE_METADATA_NAME = "\(decl.name.swiftMangledName)"; + public static final String TYPE_METADATA_NAME = "\(decl.swiftMangledName!)"; static final MemorySegment TYPE_METADATA = SwiftKit.getTypeByMangledNameInEnvironment(TYPE_METADATA_NAME); """ ) @@ -165,7 +165,7 @@ extension Swift2JavaTranslator { } public func printClass(_ printer: inout CodePrinter, _ decl: ImportedNominalType, body: (inout CodePrinter) -> Void) { - printer.printTypeDecl("public final class \(decl.name.javaClassName!)") { printer in + printer.printTypeDecl("public final class \(decl.javaType)") { printer in // ==== Storage of the class // FIXME: implement the self storage for the memory address and accessors printClassSelfProperty(&printer, decl) @@ -274,7 +274,7 @@ extension Swift2JavaTranslator { printer.print( """ /** Instances are created using static {@code init} methods rather than through the constructor directly. */ - private \(decl.name.javaClassName!)(MemorySegment selfMemorySegment) { + private \(decl.javaType)(MemorySegment selfMemorySegment) { this.selfMemorySegment = selfMemorySegment; } """ @@ -307,7 +307,7 @@ extension Swift2JavaTranslator { // SWIFT_INT.withName("heapObject"), // ... // SWIFT_INT.withName("cap") - ).withName("\(decl.name.javaClassName!)"); // TODO: is the name right? + ).withName("\(decl.javaType)"); // TODO: is the name right? /** * When other types refer to this type, they refer to by a pointer, diff --git a/Sources/JExtractSwift/Swift2JavaTranslator.swift b/Sources/JExtractSwift/Swift2JavaTranslator.swift index d5396872..d64a7212 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator.swift @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// import Foundation +import JavaTypes import SwiftBasicFormat import SwiftParser import SwiftSyntax @@ -56,6 +57,15 @@ public final class Swift2JavaTranslator { // MARK: Analysis extension Swift2JavaTranslator { + /// The primitive Java type to use for Swift's Int type, which follows the + /// size of a pointer. + /// + /// FIXME: Consider whether to extract this information from the Swift + /// interface file, so that it would be 'int' for 32-bit targets or 'long' for + /// 64-bit targets but make the Java code different for the two, vs. adding + /// a checked truncation operation at the Java/Swift board. + var javaPrimitiveForSwiftInt: JavaType { .long } + public func analyze( swiftInterfacePath: String, text: String? = nil @@ -126,11 +136,11 @@ extension Swift2JavaTranslator { importedTypes = Dictionary(uniqueKeysWithValues: try await importedTypes._mapAsync { (tyName, tyDecl) in var tyDecl = tyDecl - log.info("Mapping type: \(tyDecl.name)") + log.info("Mapping type: \(tyDecl.swiftTypeName)") tyDecl = try await dylib.fillInTypeMangledName(tyDecl) - log.info("Mapping members of: \(tyDecl.name)") + log.info("Mapping members of: \(tyDecl.swiftTypeName)") tyDecl.initializers = try await tyDecl.initializers._mapAsync { initDecl in dylib.log.logLevel = .trace diff --git a/Sources/JExtractSwift/Swift2JavaVisitor.swift b/Sources/JExtractSwift/Swift2JavaVisitor.swift index db4625bb..b936bca0 100644 --- a/Sources/JExtractSwift/Swift2JavaVisitor.swift +++ b/Sources/JExtractSwift/Swift2JavaVisitor.swift @@ -57,14 +57,12 @@ final class Swift2JavaVisitor: SyntaxVisitor { } let importedNominal = ImportedNominalType( - name: ImportedTypeName( - swiftTypeName: fullName, - javaType: .class( - package: targetJavaPackage, - name: fullName - ), - swiftMangledName: nominal.mangledNameFromComment + swiftTypeName: fullName, + javaType: .class( + package: targetJavaPackage, + name: fullName ), + swiftMangledName: nominal.mangledNameFromComment, kind: kind ) @@ -77,7 +75,7 @@ final class Swift2JavaVisitor: SyntaxVisitor { return .skipChildren } - currentTypeName = importedNominalType.name.swiftTypeName + currentTypeName = importedNominalType.swiftTypeName return .visitChildren } @@ -96,7 +94,7 @@ final class Swift2JavaVisitor: SyntaxVisitor { return .skipChildren } - currentTypeName = importedNominalType.name.swiftTypeName + currentTypeName = importedNominalType.swiftTypeName return .visitChildren } @@ -149,7 +147,7 @@ final class Swift2JavaVisitor: SyntaxVisitor { let fullName = "\(node.name.text)(\(argumentLabelsStr))" var funcDecl = ImportedFunc( - parentName: currentTypeName.map { translator.importedTypes[$0] }??.name, + parentName: currentTypeName.map { translator.importedTypes[$0] }??.importedTypeName, identifier: fullName, returnType: javaResultType, parameters: params @@ -180,7 +178,7 @@ final class Swift2JavaVisitor: SyntaxVisitor { return .skipChildren } - self.log.info("Import initializer: \(node.kind) \(currentType.name.javaType.description)") + self.log.info("Import initializer: \(node.kind) \(currentType.javaType.description)") let params: [ImportedParam] do { params = try node.signature.parameterClause.parameters.map { param in @@ -200,9 +198,9 @@ final class Swift2JavaVisitor: SyntaxVisitor { "init(\(params.compactMap { $0.effectiveName ?? "_" }.joined(separator: ":")))" var funcDecl = ImportedFunc( - parentName: currentType.name, + parentName: currentType.importedTypeName, identifier: initIdentifier, - returnType: currentType.name, + returnType: currentType.importedTypeName, parameters: params ) funcDecl.isInit = true @@ -213,7 +211,7 @@ final class Swift2JavaVisitor: SyntaxVisitor { funcDecl.swiftMangledName = mangledName } - log.info("Record initializer method in \(currentType.name.javaType.description): \(funcDecl.identifier)") + log.info("Record initializer method in \(currentType.javaType.description): \(funcDecl.identifier)") translator.importedTypes[currentTypeName]!.initializers.append(funcDecl) return .skipChildren diff --git a/Sources/JExtractSwift/SwiftDylib.swift b/Sources/JExtractSwift/SwiftDylib.swift index 1f656ea7..486aa3ab 100644 --- a/Sources/JExtractSwift/SwiftDylib.swift +++ b/Sources/JExtractSwift/SwiftDylib.swift @@ -33,19 +33,19 @@ package struct SwiftDylib { // FIXME: remove this entire utility; replace with package func fillInTypeMangledName(_ decl: ImportedNominalType) async throws -> ImportedNominalType { // TODO: this is hacky, not precise at all and will be removed entirely - guard decl.name.swiftMangledName.isEmpty else { + guard decl.swiftMangledName == nil else { // it was already processed return decl } var decl = decl let names = try await nmSymbolNames(grepDemangled: [ - decl.name.swiftTypeName, + decl.swiftTypeName, "type metadata for", ]) if let name = names.first { - log.trace("Selected mangled name for '\(decl.name.javaType.description)': \(name)") - decl.name.swiftMangledName = name.mangledName + log.trace("Selected mangled name for '\(decl.javaType.description)': \(name)") + decl.swiftMangledName = name.mangledName } return decl diff --git a/Sources/JExtractSwift/TranslatedType.swift b/Sources/JExtractSwift/TranslatedType.swift index 16a4ced1..d18fe6b1 100644 --- a/Sources/JExtractSwift/TranslatedType.swift +++ b/Sources/JExtractSwift/TranslatedType.swift @@ -102,6 +102,19 @@ extension Swift2JavaVisitor { ) } + // If this is the Swift "Int" type, it's primitive in Java but might + // map to either "int" or "long" depending whether the platform is + // 32-bit or 64-bit. + if parent == nil, name == "Int" { + return TranslatedType( + cCompatibleConvention: .direct, + originalSwiftType: "\(raw: name)", + cCompatibleSwiftType: "Swift.\(raw: name)", + cCompatibleJavaMemoryLayout: .int, + javaType: translator.javaPrimitiveForSwiftInt + ) + } + // Identify the various pointer types from the standard library. if let (requiresArgument, _, _) = name.isNameOfSwiftPointerType { // Dig out the pointee type if needed. @@ -220,10 +233,16 @@ extension TranslatedType { javaType: javaType ) } - } + enum CCompatibleJavaMemoryLayout { + /// A primitive Java type. case primitive(JavaType) + + /// The Swift "Int" type, which may be either a Java int (32-bit platforms) or + /// Java long (64-bit platforms). + case int + case memorySegment } diff --git a/Sources/JavaTypes/JavaType+SwiftNames.swift b/Sources/JavaTypes/JavaType+SwiftNames.swift index e43b15cd..088cb545 100644 --- a/Sources/JavaTypes/JavaType+SwiftNames.swift +++ b/Sources/JavaTypes/JavaType+SwiftNames.swift @@ -63,10 +63,6 @@ extension JavaType { case "Float": self = .float case "Double": self = .double case "Void": self = .void - - /// NOTE: This is only correct for 64-bit platforms. - case "Int": self = .long - default: return nil } } From 1245f75904f180972a1c65c73de06dc7c75b4644 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Fri, 27 Sep 2024 12:39:55 -0700 Subject: [PATCH 010/426] Start modeling the TranslatedType -> ForeignValueLayout mapping --- Sources/JExtractSwift/ImportedDecls.swift | 4 +- .../JavaConstants/ForeignValueLayouts.swift | 2 +- Sources/JExtractSwift/TranslatedType.swift | 44 ++++++++++++++++--- 3 files changed, 42 insertions(+), 8 deletions(-) diff --git a/Sources/JExtractSwift/ImportedDecls.swift b/Sources/JExtractSwift/ImportedDecls.swift index 62fe2c95..6a7f6198 100644 --- a/Sources/JExtractSwift/ImportedDecls.swift +++ b/Sources/JExtractSwift/ImportedDecls.swift @@ -189,7 +189,7 @@ public struct ImportedFunc: ImportedDecl, CustomStringConvertible { cCompatibleConvention: .indirect, originalSwiftType: "\(raw: parentName.swiftTypeName)", cCompatibleSwiftType: "UnsafeRawPointer", - cCompatibleJavaMemoryLayout: .memorySegment, + cCompatibleJavaMemoryLayout: .heapObject, javaType: .javaForeignMemorySegment ).importedTypeName ) @@ -204,7 +204,7 @@ public struct ImportedFunc: ImportedDecl, CustomStringConvertible { cCompatibleConvention: .indirect, originalSwiftType: "\(raw: parentName.swiftTypeName)", cCompatibleSwiftType: "UnsafeRawPointer", - cCompatibleJavaMemoryLayout: .memorySegment, + cCompatibleJavaMemoryLayout: .heapObject, javaType: .javaForeignMemorySegment ).importedTypeName ) diff --git a/Sources/JExtractSwift/JavaConstants/ForeignValueLayouts.swift b/Sources/JExtractSwift/JavaConstants/ForeignValueLayouts.swift index 639c8c4a..a63f565d 100644 --- a/Sources/JExtractSwift/JavaConstants/ForeignValueLayouts.swift +++ b/Sources/JExtractSwift/JavaConstants/ForeignValueLayouts.swift @@ -54,7 +54,6 @@ public struct ForeignValueLayout: CustomStringConvertible { } extension ForeignValueLayout { - public static let SwiftSelf = Self(inlineComment: "Self", javaConstant: "SWIFT_SELF") public static let SwiftPointer = Self(javaConstant: "SWIFT_POINTER") public static let SwiftBool = Self(javaConstant: "SWIFT_BOOL") @@ -63,6 +62,7 @@ extension ForeignValueLayout { public static let SwiftInt64 = Self(javaConstant: "SWIFT_INT64") public static let SwiftInt32 = Self(javaConstant: "SWIFT_INT32") public static let SwiftInt16 = Self(javaConstant: "SWIFT_INT16") + public static let SwiftUInt16 = Self(javaConstant: "SWIFT_UINT16") public static let SwiftInt8 = Self(javaConstant: "SWIFT_INT8") public static let SwiftFloat = Self(javaConstant: "SWIFT_FLOAT") diff --git a/Sources/JExtractSwift/TranslatedType.swift b/Sources/JExtractSwift/TranslatedType.swift index d18fe6b1..31343d67 100644 --- a/Sources/JExtractSwift/TranslatedType.swift +++ b/Sources/JExtractSwift/TranslatedType.swift @@ -33,7 +33,7 @@ extension Swift2JavaVisitor { cCompatibleConvention: .direct, originalSwiftType: type, cCompatibleSwiftType: "@convention(c) () -> Void", - cCompatibleJavaMemoryLayout: .memorySegment, + cCompatibleJavaMemoryLayout: .cFunction, javaType: .javaLangRunnable ) } @@ -134,7 +134,7 @@ extension Swift2JavaVisitor { cCompatibleConvention: .direct, originalSwiftType: type, cCompatibleSwiftType: "UnsafeMutableRawPointer", - cCompatibleJavaMemoryLayout: .memorySegment, + cCompatibleJavaMemoryLayout: .heapObject, javaType: .javaForeignMemorySegment ) } @@ -155,7 +155,7 @@ extension Swift2JavaVisitor { cCompatibleConvention: .indirect, originalSwiftType: type, cCompatibleSwiftType: "UnsafeMutablePointer<\(type)>", - cCompatibleJavaMemoryLayout: .memorySegment, + cCompatibleJavaMemoryLayout: .heapObject, javaType: .class(package: nil, name: name) ) } @@ -235,15 +235,49 @@ extension TranslatedType { } } +/// Describes the C-compatible layout as it should be referenced from Java. enum CCompatibleJavaMemoryLayout { - /// A primitive Java type. + /// A primitive Java type that has a direct counterpart in C. case primitive(JavaType) /// The Swift "Int" type, which may be either a Java int (32-bit platforms) or /// Java long (64-bit platforms). case int - case memorySegment + /// A Swift heap object, which is treated as a pointer for interoperability + /// purposes but must be retained/released to keep it alive. + case heapObject + + /// A C function pointer. In Swift, this will be a @convention(c) function. + /// In Java, a downcall handle to a function. + case cFunction +} + +extension TranslatedType { + /// Determine the foreign value layout to use for the translated type with + /// the Java Foreign Function and Memory API. + var foreignValueLayout: ForeignValueLayout { + switch cCompatibleJavaMemoryLayout { + case .primitive(let javaType): + switch javaType { + case .boolean: return .SwiftBool + case .byte: return .SwiftInt8 + case .char: return .SwiftUInt16 + case .short: return .SwiftInt16 + case .int: return .SwiftInt32 + case .long: return .SwiftInt64 + case .float: return .SwiftFloat + case .double: return .SwiftDouble + case .array, .class, .void: fatalError("Not a primitive type") + } + + case .int: + return .SwiftInt + + case .heapObject, .cFunction: + return .SwiftPointer + } + } } enum TypeTranslationError: Error { From f87dd0e53a8153bf9809da031293532773068e18 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Fri, 27 Sep 2024 13:09:41 -0700 Subject: [PATCH 011/426] Finish the migration from ImportedTypeName over to TranslatedType TranslatedType captures more information about how the type is represented in Swift, Java, and the intermediate stages in between. --- Sources/JExtractSwift/ImportedDecls.swift | 69 +++++-------------- .../Swift2JavaTranslator+MemoryLayouts.swift | 56 +-------------- .../Swift2JavaTranslator+Printing.swift | 19 +++-- Sources/JExtractSwift/Swift2JavaVisitor.swift | 21 ++---- Sources/JExtractSwift/TranslatedType.swift | 12 ++-- 5 files changed, 38 insertions(+), 139 deletions(-) diff --git a/Sources/JExtractSwift/ImportedDecls.swift b/Sources/JExtractSwift/ImportedDecls.swift index 6a7f6198..71c17abd 100644 --- a/Sources/JExtractSwift/ImportedDecls.swift +++ b/Sources/JExtractSwift/ImportedDecls.swift @@ -15,16 +15,12 @@ import Foundation import JavaTypes import SwiftSyntax -protocol ImportedDecl: Hashable { +protocol ImportedDecl { } public typealias JavaPackage = String -public struct ImportedProtocol: ImportedDecl { - public var identifier: String -} - /// Describes a Swift nominal type (e.g., a class, struct, enum) that has been /// imported and is being translated into Java. public struct ImportedNominalType: ImportedDecl { @@ -43,9 +39,12 @@ public struct ImportedNominalType: ImportedDecl { self.kind = kind } - var importedTypeName: ImportedTypeName { - ImportedTypeName( - swiftTypeName: swiftTypeName, + var translatedType: TranslatedType { + TranslatedType( + cCompatibleConvention: .direct, + originalSwiftType: "\(raw: swiftTypeName)", + cCompatibleSwiftType: "\(raw: swiftTypeName)", + cCompatibleJavaMemoryLayout: .heapObject, javaType: javaType ) } @@ -58,7 +57,7 @@ public enum NominalTypeKind { case `struct` } -public struct ImportedParam: Hashable { +public struct ImportedParam { let param: FunctionParameterSyntax var firstName: String? { @@ -89,7 +88,7 @@ public struct ImportedParam: Hashable { } // The mapped-to Java type of the above Java type, collections and optionals may be replaced with Java ones etc. - var type: ImportedTypeName + var type: TranslatedType } extension ImportedParam { @@ -102,30 +101,6 @@ extension ImportedParam { } } -public struct ImportedTypeName: Hashable { - public var swiftTypeName: String - - public var swiftMangledName: String = "" - - public var javaType: JavaType - - public var isVoid: Bool { javaType == .void } - - public var fullyQualifiedName: String { javaType.description } - - /// Retrieve the Java class name that this type describes, or nil if it - /// doesn't represent a class at all. - public var javaClassName: String? { - javaType.className - } - - public init(swiftTypeName: String, javaType: JavaType, swiftMangledName: String? = nil) { - self.swiftTypeName = swiftTypeName - self.javaType = javaType - self.swiftMangledName = swiftMangledName ?? "" - } -} - // TODO: this is used in different contexts and needs a cleanup public enum SelfParameterVariant { /// Make a method that accepts the raw memory pointer as a MemorySegment @@ -141,7 +116,7 @@ public struct ImportedFunc: ImportedDecl, CustomStringConvertible { /// this will contain that declaration's imported name. /// /// This is necessary when rendering accessor Java code we need the type that "self" is expecting to have. - public var parentName: ImportedTypeName? + var parentName: TranslatedType? public var hasParent: Bool { parentName != nil } /// This is a full name such as init(cap:name:). @@ -166,7 +141,7 @@ public struct ImportedFunc: ImportedDecl, CustomStringConvertible { return identifier } - public var returnType: ImportedTypeName + public var returnType: TranslatedType public var parameters: [ImportedParam] public func effectiveParameters(selfVariant: SelfParameterVariant?) -> [ImportedParam] { @@ -185,28 +160,18 @@ public struct ImportedFunc: ImportedDecl, CustomStringConvertible { params.append( ImportedParam( param: selfParam, - type: TranslatedType( - cCompatibleConvention: .indirect, - originalSwiftType: "\(raw: parentName.swiftTypeName)", - cCompatibleSwiftType: "UnsafeRawPointer", - cCompatibleJavaMemoryLayout: .heapObject, - javaType: .javaForeignMemorySegment - ).importedTypeName + type: parentName ) ) case .memorySegment: let selfParam: FunctionParameterSyntax = "self$: $java_lang_foreign_MemorySegment" + var parentForSelf = parentName + parentForSelf.javaType = .javaForeignMemorySegment params.append( ImportedParam( param: selfParam, - type: TranslatedType( - cCompatibleConvention: .indirect, - originalSwiftType: "\(raw: parentName.swiftTypeName)", - cCompatibleSwiftType: "UnsafeRawPointer", - cCompatibleJavaMemoryLayout: .heapObject, - javaType: .javaForeignMemorySegment - ).importedTypeName + type: parentForSelf ) ) @@ -230,9 +195,9 @@ public struct ImportedFunc: ImportedDecl, CustomStringConvertible { public var isInit: Bool = false public init( - parentName: ImportedTypeName?, + parentName: TranslatedType?, identifier: String, - returnType: ImportedTypeName, + returnType: TranslatedType, parameters: [ImportedParam] ) { self.parentName = parentName diff --git a/Sources/JExtractSwift/Swift2JavaTranslator+MemoryLayouts.swift b/Sources/JExtractSwift/Swift2JavaTranslator+MemoryLayouts.swift index 8378a15f..5109446b 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator+MemoryLayouts.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator+MemoryLayouts.swift @@ -16,8 +16,6 @@ import SwiftBasicFormat import SwiftParser import SwiftSyntax -let SWIFT_POINTER = "SWIFT_POINTER" - extension Swift2JavaTranslator { public func javaMemoryLayoutDescriptors( forParametersOf decl: ImportedFunc, @@ -31,61 +29,9 @@ extension Swift2JavaTranslator { // decl.isInit ? nil : .wrapper for param in decl.effectiveParameters(selfVariant: selfVariant) { - if let paramLayout = javaMemoryLayoutDescriptor(param.type) { - layouts.append(paramLayout) - } + layouts.append(param.type.foreignValueLayout) } return layouts } - - // This may reach for another types $layout I think - public func javaMemoryLayoutDescriptor(_ ty: ImportedTypeName) -> ForeignValueLayout? { - switch ty.swiftTypeName { - case "Bool": - return .SwiftBool - case "Int": - return .SwiftInt - case "Int32": - return .SwiftInt32 - case "Int64": - return .SwiftInt64 - case "Float": - return .SwiftFloat - case "Double": - return .SwiftDouble - case "Void": - return nil - case "Never": - return nil - case "Swift.UnsafePointer": - return .SwiftPointer - default: - break - } - - // not great? - if ty.swiftTypeName == "Self.self" { - return .SwiftPointer - } - - // not great? - if ty.swiftTypeName == "(any Any.Type)?" { - return .SwiftPointer - } - - if ty.swiftTypeName == "() -> ()" { - return .SwiftPointer - } - - // TODO: Java has OptionalLong, OptionalInt, OptionalDouble types. - // if ty.swiftTypeName.hasSuffix("?") { - // if ty.swiftTypeName == "Int?" { - // return JavaOptionalLong - // } else .. - // } - - // Last fallback is to try to get the type's $layout() - return ForeignValueLayout(inlineComment: ty.swiftTypeName, customType: ty.fullyQualifiedName) - } } diff --git a/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift b/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift index 57e11b52..262a6ccd 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift @@ -421,7 +421,7 @@ extension Swift2JavaTranslator { * \(decl.swiftDeclRaw ?? "") * } */ - public static \(parentName.javaClassName!) init(\(renderJavaParamDecls(decl, selfVariant: .none))) { + public static \(parentName.javaType) init(\(renderJavaParamDecls(decl, selfVariant: .none))) { var mh$ = \(descClassIdentifier).HANDLE; try { if (TRACE_DOWNCALLS) { @@ -429,7 +429,7 @@ extension Swift2JavaTranslator { } var self = (MemorySegment) mh$.invokeExact(\(renderForwardParams(decl, selfVariant: nil)), TYPE_METADATA); - return new \(parentName.javaClassName!)(self); + return new \(parentName.javaType)(self); } catch (Throwable ex$) { throw new AssertionError("should not reach here", ex$); } @@ -524,10 +524,10 @@ extension Swift2JavaTranslator { decl: ImportedFunc, selfVariant: SelfParameterVariant? ) { - let returnTy = decl.returnType.fullyQualifiedName + let returnTy = decl.returnType.javaType let maybeReturnCast: String - if decl.returnType.isVoid { + if decl.returnType.javaType == .void { maybeReturnCast = "" // nothing to return or cast to } else { maybeReturnCast = "return (\(returnTy))" @@ -601,7 +601,7 @@ extension Swift2JavaTranslator { } for p in decl.effectiveParameters(selfVariant: selfVariant) { - let param = "\(p.type.fullyQualifiedName) \(p.effectiveName ?? nextUniqueParamName())" + let param = "\(p.type.javaType.description) \(p.effectiveName ?? nextUniqueParamName())" ps.append(param) } @@ -641,7 +641,7 @@ extension Swift2JavaTranslator { selfVariant: .pointer ) - if decl.returnType.isVoid { + if decl.returnType.javaType == .void { printer.print("FunctionDescriptor.ofVoid("); printer.indent() } else { @@ -655,10 +655,9 @@ extension Swift2JavaTranslator { // when initializing, we return a pointer to the newly created object printer.print("/* -> */\(ForeignValueLayout.SwiftPointer)", .parameterNewlineSeparator(returnTyIsLastTy)) } else { - if var returnDesc = javaMemoryLayoutDescriptor(decl.returnType) { - returnDesc.inlineComment = " -> " - printer.print(returnDesc, .parameterNewlineSeparator(returnTyIsLastTy)) - } + var returnDesc = decl.returnType.foreignValueLayout + returnDesc.inlineComment = " -> " + printer.print(returnDesc, .parameterNewlineSeparator(returnTyIsLastTy)) } } diff --git a/Sources/JExtractSwift/Swift2JavaVisitor.swift b/Sources/JExtractSwift/Swift2JavaVisitor.swift index b936bca0..57f906ba 100644 --- a/Sources/JExtractSwift/Swift2JavaVisitor.swift +++ b/Sources/JExtractSwift/Swift2JavaVisitor.swift @@ -120,18 +120,18 @@ final class Swift2JavaVisitor: SyntaxVisitor { } let params: [ImportedParam] - let javaResultType: ImportedTypeName + let javaResultType: TranslatedType do { params = try node.signature.parameterClause.parameters.map { param in // TODO: more robust parameter handling // TODO: More robust type handling return ImportedParam( param: param, - type: try mapTypeToJava(name: param.type) + type: try cCompatibleType(for: param.type) ) } - javaResultType = try mapTypeToJava(name: returnTy) + javaResultType = try cCompatibleType(for: returnTy) } catch { self.log.info("Unable to import function \(node.name) - \(error)") return .skipChildren @@ -147,7 +147,7 @@ final class Swift2JavaVisitor: SyntaxVisitor { let fullName = "\(node.name.text)(\(argumentLabelsStr))" var funcDecl = ImportedFunc( - parentName: currentTypeName.map { translator.importedTypes[$0] }??.importedTypeName, + parentName: currentTypeName.map { translator.importedTypes[$0] }??.translatedType, identifier: fullName, returnType: javaResultType, parameters: params @@ -186,7 +186,7 @@ final class Swift2JavaVisitor: SyntaxVisitor { // TODO: More robust type handling return ImportedParam( param: param, - type: try mapTypeToJava(name: param.type) + type: try cCompatibleType(for: param.type) ) } } catch { @@ -198,9 +198,9 @@ final class Swift2JavaVisitor: SyntaxVisitor { "init(\(params.compactMap { $0.effectiveName ?? "_" }.joined(separator: ":")))" var funcDecl = ImportedFunc( - parentName: currentType.importedTypeName, + parentName: currentType.translatedType, identifier: initIdentifier, - returnType: currentType.importedTypeName, + returnType: currentType.translatedType, parameters: params ) funcDecl.isInit = true @@ -254,13 +254,6 @@ extension FunctionDeclSyntax { } } -extension Swift2JavaVisitor { - // TODO: this is more more complicated, we need to know our package and imports etc - func mapTypeToJava(name swiftType: TypeSyntax) throws -> ImportedTypeName { - return try cCompatibleType(for: swiftType).importedTypeName - } -} - private let mangledNameCommentPrefix = "MANGLED NAME: " extension SyntaxProtocol { diff --git a/Sources/JExtractSwift/TranslatedType.swift b/Sources/JExtractSwift/TranslatedType.swift index 31343d67..a376896a 100644 --- a/Sources/JExtractSwift/TranslatedType.swift +++ b/Sources/JExtractSwift/TranslatedType.swift @@ -207,7 +207,7 @@ enum ParameterConvention { case indirect } -struct TranslatedType { +public struct TranslatedType { /// How a parameter of this type will be passed through C functions. var cCompatibleConvention: ParameterConvention @@ -224,14 +224,10 @@ struct TranslatedType { /// The Java type that is used to present these values in Java. var javaType: JavaType -} -extension TranslatedType { - var importedTypeName: ImportedTypeName { - ImportedTypeName( - swiftTypeName: originalSwiftType.trimmedDescription, - javaType: javaType - ) + /// Produce a Swift type name to reference this type. + var swiftTypeName: String { + originalSwiftType.trimmedDescription } } From 885b45ab40af7b79687889e6e528fda9e22176f2 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Fri, 27 Sep 2024 13:40:28 -0700 Subject: [PATCH 012/426] Go through nominal type resolution when translating types. When determining how to translate a Swift nominal type for Java, go through the nominal lookup mechanism so we will (1) only find types that we actually know about, rather than guessing, and (2) lazily form the imported type record so we can handle seeing types out-of-order. --- Sources/JExtractSwift/ImportedDecls.swift | 2 +- .../JExtractSwift/Swift2JavaTranslator.swift | 45 +++++++++++++++++++ Sources/JExtractSwift/Swift2JavaVisitor.swift | 36 +-------------- Sources/JExtractSwift/TranslatedType.swift | 24 ++++------ .../JExtractSwiftTests/FuncImportTests.swift | 8 +++- 5 files changed, 64 insertions(+), 51 deletions(-) diff --git a/Sources/JExtractSwift/ImportedDecls.swift b/Sources/JExtractSwift/ImportedDecls.swift index 71c17abd..8ae683dc 100644 --- a/Sources/JExtractSwift/ImportedDecls.swift +++ b/Sources/JExtractSwift/ImportedDecls.swift @@ -43,7 +43,7 @@ public struct ImportedNominalType: ImportedDecl { TranslatedType( cCompatibleConvention: .direct, originalSwiftType: "\(raw: swiftTypeName)", - cCompatibleSwiftType: "\(raw: swiftTypeName)", + cCompatibleSwiftType: "UnsafeRawPointer", cCompatibleJavaMemoryLayout: .heapObject, javaType: javaType ) diff --git a/Sources/JExtractSwift/Swift2JavaTranslator.swift b/Sources/JExtractSwift/Swift2JavaTranslator.swift index d64a7212..d66e23c2 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator.swift @@ -182,6 +182,51 @@ extension Swift2JavaTranslator { } +// ==== ---------------------------------------------------------------------------------------------------------------- +// MARK: Type translation +extension Swift2JavaTranslator { + /// Try to resolve the given nominal type node into its imported + /// representation. + func importedNominalType( + _ nominal: some DeclGroupSyntax & NamedDeclSyntax + ) -> ImportedNominalType? { + if !nominal.shouldImport(log: log) { + return nil + } + + guard let fullName = nominalResolution.fullyQualifiedName(of: nominal) else { + return nil + } + + if let alreadyImported = importedTypes[fullName] { + return alreadyImported + } + + // Determine the nominal type kind. + let kind: NominalTypeKind + switch Syntax(nominal).as(SyntaxEnum.self) { + case .actorDecl: kind = .actor + case .classDecl: kind = .class + case .enumDecl: kind = .enum + case .structDecl: kind = .struct + default: return nil + } + + let importedNominal = ImportedNominalType( + swiftTypeName: fullName, + javaType: .class( + package: javaPackage, + name: fullName + ), + swiftMangledName: nominal.mangledNameFromComment, + kind: kind + ) + + importedTypes[fullName] = importedNominal + return importedNominal + } +} + // ==== ---------------------------------------------------------------------------------------------------------------- // MARK: Errors diff --git a/Sources/JExtractSwift/Swift2JavaVisitor.swift b/Sources/JExtractSwift/Swift2JavaVisitor.swift index 57f906ba..a4190889 100644 --- a/Sources/JExtractSwift/Swift2JavaVisitor.swift +++ b/Sources/JExtractSwift/Swift2JavaVisitor.swift @@ -38,40 +38,8 @@ final class Swift2JavaVisitor: SyntaxVisitor { super.init(viewMode: .all) } - /// Try to resolve the given nominal type node into its imported - /// representation. - func resolveNominalType( - _ nominal: some DeclGroupSyntax & NamedDeclSyntax, - kind: NominalTypeKind - ) -> ImportedNominalType? { - if !nominal.shouldImport(log: log) { - return nil - } - - guard let fullName = translator.nominalResolution.fullyQualifiedName(of: nominal) else { - return nil - } - - if let alreadyImported = translator.importedTypes[fullName] { - return alreadyImported - } - - let importedNominal = ImportedNominalType( - swiftTypeName: fullName, - javaType: .class( - package: targetJavaPackage, - name: fullName - ), - swiftMangledName: nominal.mangledNameFromComment, - kind: kind - ) - - translator.importedTypes[fullName] = importedNominal - return importedNominal - } - override func visit(_ node: ClassDeclSyntax) -> SyntaxVisitorContinueKind { - guard let importedNominalType = resolveNominalType(node, kind: .class) else { + guard let importedNominalType = translator.importedNominalType(node) else { return .skipChildren } @@ -90,7 +58,7 @@ final class Swift2JavaVisitor: SyntaxVisitor { // Resolve the extended type of the extension as an imported nominal, and // recurse if we found it. guard let nominal = translator.nominalResolution.extendedType(of: node), - let importedNominalType = resolveNominalType(nominal, kind: .class) else { + let importedNominalType = translator.importedNominalType(nominal) else { return .skipChildren } diff --git a/Sources/JExtractSwift/TranslatedType.swift b/Sources/JExtractSwift/TranslatedType.swift index a376896a..1f6ddd20 100644 --- a/Sources/JExtractSwift/TranslatedType.swift +++ b/Sources/JExtractSwift/TranslatedType.swift @@ -116,7 +116,7 @@ extension Swift2JavaVisitor { } // Identify the various pointer types from the standard library. - if let (requiresArgument, _, _) = name.isNameOfSwiftPointerType { + if let (requiresArgument, _, hasCount) = name.isNameOfSwiftPointerType, !hasCount { // Dig out the pointee type if needed. if requiresArgument { guard let genericArguments else { @@ -144,20 +144,14 @@ extension Swift2JavaVisitor { throw TypeTranslationError.unexpectedGenericArguments(type, genericArguments) } - // Nested types aren't mapped into Java. - if parent != nil { - throw TypeTranslationError.nestedType(type) + // Look up the imported types by name to resolve it to a nominal type. + let swiftTypeName = type.trimmedDescription // FIXME: This is a hack. + guard let resolvedNominal = translator.nominalResolution.resolveNominalType(swiftTypeName), + let importedNominal = translator.importedNominalType(resolvedNominal) else { + throw TypeTranslationError.unknown(type) } - // Swift types are passed indirectly. - // FIXME: Look up type names to figure out which ones are exposed and how. - return TranslatedType( - cCompatibleConvention: .indirect, - originalSwiftType: type, - cCompatibleSwiftType: "UnsafeMutablePointer<\(type)>", - cCompatibleJavaMemoryLayout: .heapObject, - javaType: .class(package: nil, name: name) - ) + return importedNominal.translatedType } } @@ -286,6 +280,6 @@ enum TypeTranslationError: Error { /// Missing generic arguments. case missingGenericArguments(TypeSyntax) - /// Type syntax nodes cannot be mapped. - case nestedType(TypeSyntax) + /// Unknown nominal type. + case unknown(TypeSyntax) } diff --git a/Tests/JExtractSwiftTests/FuncImportTests.swift b/Tests/JExtractSwiftTests/FuncImportTests.swift index 04158f8f..3b4695c7 100644 --- a/Tests/JExtractSwiftTests/FuncImportTests.swift +++ b/Tests/JExtractSwiftTests/FuncImportTests.swift @@ -53,6 +53,12 @@ final class MethodImportTests { @objc deinit } + + // FIXME: Hack to allow us to translate "String", even though it's not + // actually available + // MANGLED NAME: $ss + public class String { + } """ @Test func method_helloWorld() async throws { @@ -161,7 +167,7 @@ final class MethodImportTests { * public func globalTakeIntLongString(i32: Int32, l: Int64, s: String) * } */ - public static void globalTakeIntLongString(int i32, long l, String s) { + public static void globalTakeIntLongString(int i32, long l, com.example.swift.String s) { var mh$ = globalTakeIntLongString.HANDLE; try { if (TRACE_DOWNCALLS) { From 71670be8f8773e0a8efab1f60622e1b9908dba59 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Fri, 27 Sep 2024 15:48:55 -0700 Subject: [PATCH 013/426] Expose Java-friendly instance methods and constructors for Swift types When projecting a Swift type into a Java class, map Swift methods into instance methods (rather than static methods) and Swift initializers into Java constructors (rather than static 'init' methods). --- .../java/org/example/HelloJava2Swift.java | 5 +- Sources/JExtractSwift/ImportedDecls.swift | 16 +++--- .../Swift2JavaTranslator+Printing.swift | 33 ++++++++---- Sources/JExtractSwift/Swift2JavaVisitor.swift | 2 +- Sources/JExtractSwift/TranslatedType.swift | 8 +++ .../JExtractSwiftTests/FuncImportTests.swift | 51 +++++++++++++++++-- 6 files changed, 93 insertions(+), 22 deletions(-) diff --git a/JavaSwiftKitDemo/src/main/java/org/example/HelloJava2Swift.java b/JavaSwiftKitDemo/src/main/java/org/example/HelloJava2Swift.java index 3b1ea973..4aa00b25 100644 --- a/JavaSwiftKitDemo/src/main/java/org/example/HelloJava2Swift.java +++ b/JavaSwiftKitDemo/src/main/java/org/example/HelloJava2Swift.java @@ -60,9 +60,12 @@ static void tests() { JavaKitExample.globalTakeInt(1337); - MySwiftClass obj = MySwiftClass.init(2222, 7777); + MySwiftClass obj = new MySwiftClass(2222, 7777); SwiftKit.retain(obj.$memorySegment()); System.out.println("[java] obj ref count = " + SwiftKit.retainCount(obj.$memorySegment())); + + obj.voidMethod(); + obj.takeIntMethod(42); } } diff --git a/Sources/JExtractSwift/ImportedDecls.swift b/Sources/JExtractSwift/ImportedDecls.swift index 8ae683dc..a1254d51 100644 --- a/Sources/JExtractSwift/ImportedDecls.swift +++ b/Sources/JExtractSwift/ImportedDecls.swift @@ -48,6 +48,14 @@ public struct ImportedNominalType: ImportedDecl { javaType: javaType ) } + + /// The Java class name without the package. + public var javaClassName: String { + switch javaType { + case .class(package: _, name: let name): name + default: javaType.description + } + } } public enum NominalTypeKind { @@ -116,7 +124,7 @@ public struct ImportedFunc: ImportedDecl, CustomStringConvertible { /// this will contain that declaration's imported name. /// /// This is necessary when rendering accessor Java code we need the type that "self" is expecting to have. - var parentName: TranslatedType? + public var parentName: TranslatedType? public var hasParent: Bool { parentName != nil } /// This is a full name such as init(cap:name:). @@ -152,7 +160,7 @@ public struct ImportedFunc: ImportedDecl, CustomStringConvertible { // // allocating initializer takes a Self.Type instead, but it's also a pointer switch selfVariant { - case nil: + case nil, .wrapper: break case .pointer: @@ -174,10 +182,6 @@ public struct ImportedFunc: ImportedDecl, CustomStringConvertible { type: parentForSelf ) ) - - case .wrapper: - let selfParam: FunctionParameterSyntax = "self$: \(raw: parentName.swiftTypeName)" - params.append(ImportedParam(param: selfParam, type: parentName)) } // TODO: add any metadata for generics and other things we may need to add here diff --git a/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift b/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift index 262a6ccd..46274c35 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift @@ -28,7 +28,7 @@ extension Swift2JavaTranslator { var printer = CodePrinter() for (_, ty) in importedTypes.sorted(by: { (lhs, rhs) in lhs.key < rhs.key }) { - let filename = "\(ty.javaType).java" + let filename = "\(ty.javaClassName).java" log.info("Printing contents: \(filename)") printImportedClass(&printer, ty) @@ -165,7 +165,7 @@ extension Swift2JavaTranslator { } public func printClass(_ printer: inout CodePrinter, _ decl: ImportedNominalType, body: (inout CodePrinter) -> Void) { - printer.printTypeDecl("public final class \(decl.javaType)") { printer in + printer.printTypeDecl("public final class \(decl.javaClassName)") { printer in // ==== Storage of the class // FIXME: implement the self storage for the memory address and accessors printClassSelfProperty(&printer, decl) @@ -274,7 +274,7 @@ extension Swift2JavaTranslator { printer.print( """ /** Instances are created using static {@code init} methods rather than through the constructor directly. */ - private \(decl.javaType)(MemorySegment selfMemorySegment) { + private \(decl.javaClassName)(MemorySegment selfMemorySegment) { this.selfMemorySegment = selfMemorySegment; } """ @@ -412,24 +412,32 @@ extension Swift2JavaTranslator { printMethodDowncallHandleForAddrDesc(&printer) } + printClassInitializerConstructor(&printer, decl, parentName: parentName) + } + + public func printClassInitializerConstructor( + _ printer: inout CodePrinter, + _ decl: ImportedFunc, + parentName: TranslatedType + ) { + let descClassIdentifier = renderDescClassName(decl) printer.print( """ /** - * Create an instance of the {@code \(parentName.javaType)} Swift class. + * Create an instance of {@code \(parentName.unqualifiedJavaTypeName)}. * - * {@snippet lang=Swift: + * {@snippet lang=swift : * \(decl.swiftDeclRaw ?? "") * } */ - public static \(parentName.javaType) init(\(renderJavaParamDecls(decl, selfVariant: .none))) { + public \(parentName.unqualifiedJavaTypeName)(\(renderJavaParamDecls(decl, selfVariant: .wrapper))) { var mh$ = \(descClassIdentifier).HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall(\(renderForwardParams(decl, selfVariant: nil))); } - var self = (MemorySegment) mh$.invokeExact(\(renderForwardParams(decl, selfVariant: nil)), TYPE_METADATA); - return new \(parentName.javaType)(self); + this.selfMemorySegment = (MemorySegment) mh$.invokeExact(\(renderForwardParams(decl, selfVariant: nil)), TYPE_METADATA); } catch (Throwable ex$) { throw new AssertionError("should not reach here", ex$); } @@ -542,8 +550,8 @@ extension Swift2JavaTranslator { * \(/*TODO: make a printSnippet func*/decl.swiftDeclRaw ?? "") * } */ - public static \(returnTy) \(decl.baseIdentifier)(\(renderJavaParamDecls(decl, selfVariant: .wrapper))) { - \(maybeReturnCast) \(decl.baseIdentifier)(\(renderForwardParams(decl, selfVariant: .memorySegment))); + public \(returnTy) \(decl.baseIdentifier)(\(renderJavaParamDecls(decl, selfVariant: .wrapper))) { + \(maybeReturnCast) \(decl.baseIdentifier)(\(renderForwardParams(decl, selfVariant: .wrapper))); } """ ) @@ -630,6 +638,11 @@ extension Swift2JavaTranslator { ps.append(param) } + // Add the forwarding "self" + if selfVariant == .wrapper && !decl.isInit { + ps.append("$memorySegment()") + } + return ps.joined(separator: ", ") } diff --git a/Sources/JExtractSwift/Swift2JavaVisitor.swift b/Sources/JExtractSwift/Swift2JavaVisitor.swift index a4190889..e4524461 100644 --- a/Sources/JExtractSwift/Swift2JavaVisitor.swift +++ b/Sources/JExtractSwift/Swift2JavaVisitor.swift @@ -163,7 +163,7 @@ final class Swift2JavaVisitor: SyntaxVisitor { } let initIdentifier = - "init(\(params.compactMap { $0.effectiveName ?? "_" }.joined(separator: ":")))" + "init(\(String(params.flatMap { "\($0.effectiveName ?? "_"):" })))" var funcDecl = ImportedFunc( parentName: currentType.translatedType, diff --git a/Sources/JExtractSwift/TranslatedType.swift b/Sources/JExtractSwift/TranslatedType.swift index 1f6ddd20..8262aff4 100644 --- a/Sources/JExtractSwift/TranslatedType.swift +++ b/Sources/JExtractSwift/TranslatedType.swift @@ -223,6 +223,14 @@ public struct TranslatedType { var swiftTypeName: String { originalSwiftType.trimmedDescription } + + /// Produce the "unqualified" Java type name. + var unqualifiedJavaTypeName: String { + switch javaType { + case .class(package: _, name: let name): name + default: javaType.description + } + } } /// Describes the C-compatible layout as it should be referenced from Java. diff --git a/Tests/JExtractSwiftTests/FuncImportTests.swift b/Tests/JExtractSwiftTests/FuncImportTests.swift index 3b4695c7..4c210b3e 100644 --- a/Tests/JExtractSwiftTests/FuncImportTests.swift +++ b/Tests/JExtractSwiftTests/FuncImportTests.swift @@ -331,8 +331,8 @@ final class MethodImportTests { * public func helloMemberFunction() * } */ - public static void helloMemberFunction(com.example.swift.MySwiftClass self$) { - helloMemberFunction(self$); + public void helloMemberFunction() { + helloMemberFunction($memorySegment()); } """ ) @@ -364,11 +364,54 @@ final class MethodImportTests { * public func makeInt() -> Int * } */ - public static long makeInt(com.example.swift.MySwiftClass self$) { - return (long) makeInt(self$); + public long makeInt() { + return (long) makeInt($memorySegment()); } """ ) } + @Test func class_constructor() async throws { + let st = Swift2JavaTranslator( + javaPackage: "com.example.swift", + swiftModuleName: "__FakeModule" + ) + st.log.logLevel = .trace + + try await st.analyze(swiftInterfacePath: "/fake/__FakeModule/SwiftFile.swiftinterface", text: class_interfaceFile) + + let initDecl: ImportedFunc = st.importedTypes["MySwiftClass"]!.initializers.first { + $0.identifier == "init(len:cap:)" + }! + + let output = CodePrinter.toString { printer in + st.printClassInitializerConstructor(&printer, initDecl, parentName: initDecl.parentName!) + } + + assertOutput( + output, + expected: + """ + /** + * Create an instance of {@code MySwiftClass}. + * + * {@snippet lang=swift : + * public init(len: Swift.Int, cap: Swift.Int) + * } + */ + public MySwiftClass(long len, long cap) { + var mh$ = init_len_cap.HANDLE; + try { + if (TRACE_DOWNCALLS) { + traceDowncall(len, cap); + } + + this.selfMemorySegment = (MemorySegment) mh$.invokeExact(len, cap, TYPE_METADATA); + } catch (Throwable ex$) { + throw new AssertionError(\"should not reach here\", ex$); + } + } + """ + ) + } } From 12bc2e5157ae7bb68bb0169af7a0483cc9b1f0bd Mon Sep 17 00:00:00 2001 From: Lokesh T R Date: Mon, 30 Sep 2024 10:23:24 +0530 Subject: [PATCH 014/426] Refactor `@ExposeToJava` to `@ImplementsJava` in the `USER_GUIDE` (#11) --- ...{ExposeToJavaMacro.swift => ImplementsJavaMacro.swift} | 0 USER_GUIDE.md | 8 ++++---- 2 files changed, 4 insertions(+), 4 deletions(-) rename Sources/JavaKitMacros/{ExposeToJavaMacro.swift => ImplementsJavaMacro.swift} (100%) diff --git a/Sources/JavaKitMacros/ExposeToJavaMacro.swift b/Sources/JavaKitMacros/ImplementsJavaMacro.swift similarity index 100% rename from Sources/JavaKitMacros/ExposeToJavaMacro.swift rename to Sources/JavaKitMacros/ImplementsJavaMacro.swift diff --git a/USER_GUIDE.md b/USER_GUIDE.md index 6421d0a5..6420ec4e 100644 --- a/USER_GUIDE.md +++ b/USER_GUIDE.md @@ -61,7 +61,7 @@ import JavaRuntime @JavaClass("org.swift.javakit.HelloSwiftMain") struct HelloSwiftMain { - @ExposeToJava + @ImplementsJava static func main(arguments: [String], environment: JNIEnvironment) { print("Command line arguments are: \(arguments)") } @@ -94,7 +94,7 @@ struct HelloSwiftMain: ParsableCommand { @Option(name: .shortAndLong, help: "Enable verbose output") var verbose: Bool = false - @ExposeToJava + @ImplementsJava static func main(arguments: [String], environment: JNIEnvironment) { let command = Self.parseOrExit(arguments) command.run(environment: environment) @@ -322,12 +322,12 @@ struct HelloSwift { ... } ``` Implementations of `native` methods can be written within the Swift type or an -extension thereof, and should be marked with `@ExposeToJava`. For example: +extension thereof, and should be marked with `@ImplementsJava`. For example: ```swift @JavaClass("org.swift.javakit.HelloSwift") extension HelloSwift { - @ExposeToJava + @ImplementsJava func reportStatistics(_ meaning: String, _ numbers: [Double]) -> String { let average = numbers.isEmpty ? 0.0 : numbers.reduce(0.0) { $0 + $1 } / Double(numbers.count) return "Average of \(meaning) is \(average)" From 0ccc1d923e2ca4c4aecb46664dc3559b2a4f384f Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Wed, 25 Sep 2024 16:53:47 -0700 Subject: [PATCH 015/426] Remove the extraction of mangled names via "nm" and supporting code The Swift compiler is growing an option to emit mangled names along with various operations. Build example .swiftinterfaces with that option and rely on parsing the mangled name from there instead of 'nm'. --- Makefile | 2 + Package.resolved | 9 - Package.swift | 21 - .../Convenience/Collection+Extensions.swift | 24 - Sources/JExtractSwift/Swift2Java.swift | 6 +- .../JExtractSwift/Swift2JavaTranslator.swift | 59 +- Sources/JExtractSwift/SwiftDylib.swift | 206 - .../JExtractSwiftTool/JExtractSwiftTool.swift | 4 +- Sources/JavaKitExample/MySwiftLibrary.swift | 2 +- .../Platforms/Subprocess+Darwin.swift | 251 - .../Platforms/Subprocess+Linux.swift | 141 - .../Platforms/Subprocess+Unix.swift | 321 - Sources/_Subprocess/Subprocess+API.swift | 228 - .../_Subprocess/Subprocess+AsyncBytes.swift | 115 - .../Subprocess+Configuration.swift | 621 - Sources/_Subprocess/Subprocess+IO.swift | 400 - Sources/_Subprocess/Subprocess.swift | 233 - Sources/_Subprocess/_LockedState.swift | 159 - Sources/_SubprocessCShims/CMakeLists.txt | 51 - .../include/CFUniCharBitmapData.h | 17 - .../include/CFUniCharBitmapData.inc.h | 14707 ---------------- .../_SubprocessCShims/include/_CShimsMacros.h | 24 - .../include/_CShimsTargetConditionals.h | 56 - Sources/_SubprocessCShims/include/_CStdlib.h | 156 - .../include/_SubprocessCShims.h | 32 - .../_SubprocessCShims/include/bplist_shims.h | 19 - .../include/filemanager_shims.h | 49 - Sources/_SubprocessCShims/include/io_shims.h | 89 - .../include/module.modulemap | 5 - .../include/platform_shims.h | 71 - .../_SubprocessCShims/include/process_shims.h | 64 - .../_SubprocessCShims/include/string_shims.h | 49 - Sources/_SubprocessCShims/include/uuid.h | 81 - Sources/_SubprocessCShims/platform_shims.c | 69 - Sources/_SubprocessCShims/process_shims.c | 301 - Sources/_SubprocessCShims/string_shims.c | 0 Sources/_SubprocessCShims/uuid.c | 0 .../JExtractSwiftTests/FuncImportTests.swift | 36 +- .../FunctionDescriptorImportTests.swift | 20 +- .../JExtractSwiftTests/SwiftDylibTests.swift | 35 - Tests/JavaKitTests/BasicRuntimeTests.swift | 2 +- WIP.md | 3 - 42 files changed, 40 insertions(+), 18698 deletions(-) delete mode 100644 Sources/JExtractSwift/SwiftDylib.swift delete mode 100644 Sources/_Subprocess/Platforms/Subprocess+Darwin.swift delete mode 100644 Sources/_Subprocess/Platforms/Subprocess+Linux.swift delete mode 100644 Sources/_Subprocess/Platforms/Subprocess+Unix.swift delete mode 100644 Sources/_Subprocess/Subprocess+API.swift delete mode 100644 Sources/_Subprocess/Subprocess+AsyncBytes.swift delete mode 100644 Sources/_Subprocess/Subprocess+Configuration.swift delete mode 100644 Sources/_Subprocess/Subprocess+IO.swift delete mode 100644 Sources/_Subprocess/Subprocess.swift delete mode 100644 Sources/_Subprocess/_LockedState.swift delete mode 100644 Sources/_SubprocessCShims/CMakeLists.txt delete mode 100644 Sources/_SubprocessCShims/include/CFUniCharBitmapData.h delete mode 100644 Sources/_SubprocessCShims/include/CFUniCharBitmapData.inc.h delete mode 100644 Sources/_SubprocessCShims/include/_CShimsMacros.h delete mode 100644 Sources/_SubprocessCShims/include/_CShimsTargetConditionals.h delete mode 100644 Sources/_SubprocessCShims/include/_CStdlib.h delete mode 100644 Sources/_SubprocessCShims/include/_SubprocessCShims.h delete mode 100644 Sources/_SubprocessCShims/include/bplist_shims.h delete mode 100644 Sources/_SubprocessCShims/include/filemanager_shims.h delete mode 100644 Sources/_SubprocessCShims/include/io_shims.h delete mode 100644 Sources/_SubprocessCShims/include/module.modulemap delete mode 100644 Sources/_SubprocessCShims/include/platform_shims.h delete mode 100644 Sources/_SubprocessCShims/include/process_shims.h delete mode 100644 Sources/_SubprocessCShims/include/string_shims.h delete mode 100644 Sources/_SubprocessCShims/include/uuid.h delete mode 100644 Sources/_SubprocessCShims/platform_shims.c delete mode 100644 Sources/_SubprocessCShims/process_shims.c delete mode 100644 Sources/_SubprocessCShims/string_shims.c delete mode 100644 Sources/_SubprocessCShims/uuid.c delete mode 100644 Tests/JExtractSwiftTests/SwiftDylibTests.swift diff --git a/Makefile b/Makefile index 0e5b4817..b37b4d5f 100644 --- a/Makefile +++ b/Makefile @@ -74,7 +74,9 @@ define make_swiftinterface -emit-module-interface-path ${JEXTRACT_BUILD_DIR}/${$@_MODULE}/${$@_FILENAME}.swiftinterface \ -emit-module-path ${JEXTRACT_BUILD_DIR}/${$@_MODULE}/${$@_FILENAME}.swiftmodule \ -enable-library-evolution \ + -Xfrontend -abi-comments-in-module-interface \ -module-name ${$@_MODULE} \ + -Xfrontend -abi-comments-in-module-interface \ Sources/${$@_MODULE}/${$@_FILENAME}.swift echo "Generated: ${JEXTRACT_BUILD_DIR}/${$@_MODULE}/${$@_FILENAME}.swiftinterface" endef diff --git a/Package.resolved b/Package.resolved index 60931987..5d9d4417 100644 --- a/Package.resolved +++ b/Package.resolved @@ -17,15 +17,6 @@ "branch" : "main", "revision" : "16dc4f87937fa8a639f064d4b2369c4d3e0fc672" } - }, - { - "identity" : "swift-system", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-system", - "state" : { - "revision" : "d2ba781702a1d8285419c15ee62fd734a9437ff5", - "version" : "1.3.2" - } } ], "version" : 2 diff --git a/Package.swift b/Package.swift index a4869eec..1e47f8cd 100644 --- a/Package.swift +++ b/Package.swift @@ -97,7 +97,6 @@ let package = Package( dependencies: [ .package(url: "https://github.com/swiftlang/swift-syntax.git", branch: "main"), .package(url: "https://github.com/apple/swift-argument-parser", from: "1.5.0"), - .package(url: "https://github.com/apple/swift-system", from: "1.0.0"), ], targets: [ .macro( @@ -195,25 +194,6 @@ let package = Package( ] ), - // FIXME: This is swift-foundation's proposed Subprocess; remove when available - // https://github.com/apple/swift-foundation/pull/439 - .target( - name: "_Subprocess", - dependencies: [ - "_SubprocessCShims", - .product(name: "SystemPackage", package: "swift-system"), - ] - ), - .target( - name: "_SubprocessCShims", - cSettings: [ - .define( - "_CRT_SECURE_NO_WARNINGS", - .when(platforms: [.windows]) - ) - ] - ), - .target( name: "JExtractSwift", dependencies: [ @@ -221,7 +201,6 @@ let package = Package( .product(name: "SwiftSyntax", package: "swift-syntax"), .product(name: "SwiftSyntaxBuilder", package: "swift-syntax"), .product(name: "ArgumentParser", package: "swift-argument-parser"), - "_Subprocess", "JavaTypes", ] ), diff --git a/Sources/JExtractSwift/Convenience/Collection+Extensions.swift b/Sources/JExtractSwift/Convenience/Collection+Extensions.swift index 1f8cb0e6..944ffd4b 100644 --- a/Sources/JExtractSwift/Convenience/Collection+Extensions.swift +++ b/Sources/JExtractSwift/Convenience/Collection+Extensions.swift @@ -11,30 +11,6 @@ // //===----------------------------------------------------------------------===// -extension Collection { - - @_alwaysEmitIntoClient - public func _mapAsync( - _ transform: (Element) async throws(E) -> T - ) async throws(E) -> [T] { - let initialCapacity = underestimatedCount - var result = Array() - result.reserveCapacity(initialCapacity) - - var iterator = self.makeIterator() - - // Add elements up to the initial capacity without checking for regrowth. - for _ in 0..( diff --git a/Sources/JExtractSwift/Swift2Java.swift b/Sources/JExtractSwift/Swift2Java.swift index ab97da2a..ce8bc5c4 100644 --- a/Sources/JExtractSwift/Swift2Java.swift +++ b/Sources/JExtractSwift/Swift2Java.swift @@ -17,7 +17,7 @@ import SwiftSyntax import SwiftSyntaxBuilder /// Command-line utility, similar to `jextract` to export Swift types to Java. -public struct SwiftToJava: AsyncParsableCommand { +public struct SwiftToJava: ParsableCommand { public init() {} public static var _commandName: String { @@ -40,7 +40,7 @@ public struct SwiftToJava: AsyncParsableCommand { @Argument(help: "The Swift interface files to export to Java.") var swiftInterfaceFiles: [String] - public func run() async throws { + public func run() throws { let interfaceFiles = self.swiftInterfaceFiles.dropFirst() print("Interface files: \(interfaceFiles)") @@ -55,7 +55,7 @@ public struct SwiftToJava: AsyncParsableCommand { print("[\(fileNo)/\(interfaceFiles.count)] Importing module '\(swiftModule)', interface file: \(interfaceFile)") defer { fileNo += 1 } - try await translator.analyze(swiftInterfacePath: interfaceFile) + try translator.analyze(swiftInterfacePath: interfaceFile) try translator.writeImportedTypesTo(outputDirectory: outputDirectory) print("[\(fileNo)/\(interfaceFiles.count)] Imported interface file: \(interfaceFile) " + "done.".green) diff --git a/Sources/JExtractSwift/Swift2JavaTranslator.swift b/Sources/JExtractSwift/Swift2JavaTranslator.swift index d66e23c2..018944ff 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator.swift @@ -69,7 +69,7 @@ extension Swift2JavaTranslator { public func analyze( swiftInterfacePath: String, text: String? = nil - ) async throws { + ) throws { if text == nil { precondition( swiftInterfacePath.hasSuffix(Self.SWIFT_INTERFACE_SUFFIX), @@ -84,12 +84,12 @@ extension Swift2JavaTranslator { log.trace("Analyze: \(swiftInterfacePath)") let text = try text ?? String(contentsOfFile: swiftInterfacePath) - try await analyzeSwiftInterface(interfaceFilePath: swiftInterfacePath, text: text) + try analyzeSwiftInterface(interfaceFilePath: swiftInterfacePath, text: text) log.info("Done processing: \(swiftInterfacePath)") } - package func analyzeSwiftInterface(interfaceFilePath: String, text: String) async throws { + package func analyzeSwiftInterface(interfaceFilePath: String, text: String) throws { assert(interfaceFilePath.hasSuffix(Self.SWIFT_INTERFACE_SUFFIX)) let sourceFileSyntax = Parser.parse(source: text) @@ -104,59 +104,6 @@ extension Swift2JavaTranslator { translator: self ) visitor.walk(sourceFileSyntax) - - try await self.postProcessImportedDecls() - } - - public func postProcessImportedDecls() async throws { - log.info( - "Post process imported decls...", - metadata: [ - "types": "\(importedTypes.count)", - "global/funcs": "\(importedGlobalFuncs.count)", - ] - ) - - // FIXME: the use of dylibs to get symbols is a hack we need to remove and replace with interfaces containing mangled names - let dylibPath = ".build/arm64-apple-macosx/debug/lib\(swiftModuleName).dylib" - guard var dylib = SwiftDylib(path: dylibPath) else { - log.warning( - """ - Unable to find mangled names for imported symbols. Dylib not found: \(dylibPath) This method of obtaining symbols is a workaround; it will be removed. - """ - ) - return - } - - importedGlobalFuncs = try await importedGlobalFuncs._mapAsync { funcDecl in - let funcDecl = try await dylib.fillInMethodMangledName(funcDecl) - log.info("Mapped method '\(funcDecl.identifier)' -> '\(funcDecl.swiftMangledName)'") - return funcDecl - } - - importedTypes = Dictionary(uniqueKeysWithValues: try await importedTypes._mapAsync { (tyName, tyDecl) in - var tyDecl = tyDecl - log.info("Mapping type: \(tyDecl.swiftTypeName)") - - tyDecl = try await dylib.fillInTypeMangledName(tyDecl) - - log.info("Mapping members of: \(tyDecl.swiftTypeName)") - tyDecl.initializers = try await tyDecl.initializers._mapAsync { initDecl in - dylib.log.logLevel = .trace - - let initDecl = try await dylib.fillInAllocatingInitMangledName(initDecl) - log.info("Mapped initializer '\(initDecl.identifier)' -> '\(initDecl.swiftMangledName)'") - return initDecl - } - - tyDecl.methods = try await tyDecl.methods._mapAsync { funcDecl in - let funcDecl = try await dylib.fillInMethodMangledName(funcDecl) - log.info("Mapped method '\(funcDecl.identifier)' -> '\(funcDecl.swiftMangledName)'") - return funcDecl - } - - return (tyName, tyDecl) - }) } } diff --git a/Sources/JExtractSwift/SwiftDylib.swift b/Sources/JExtractSwift/SwiftDylib.swift deleted file mode 100644 index 486aa3ab..00000000 --- a/Sources/JExtractSwift/SwiftDylib.swift +++ /dev/null @@ -1,206 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -import Foundation -import SwiftBasicFormat -import SwiftParser -import SwiftSyntax -import _Subprocess - -/// Hacky way to get hold of symbols until swift interfaces can include them. -package struct SwiftDylib { // FIXME: remove this entire utility; replace with more rich .swiftinterface files - let path: String - var log: Logger - - package init?(path: String) { - guard FileManager.default.fileExists(atPath: path) else { - return nil - } - - self.path = path - self.log = Logger(label: "SwiftDylib(\(path))", logLevel: .trace) // TODO: take from env - } - - package func fillInTypeMangledName(_ decl: ImportedNominalType) async throws -> ImportedNominalType { - // TODO: this is hacky, not precise at all and will be removed entirely - guard decl.swiftMangledName == nil else { - // it was already processed - return decl - } - - var decl = decl - let names = try await nmSymbolNames(grepDemangled: [ - decl.swiftTypeName, - "type metadata for", - ]) - if let name = names.first { - log.trace("Selected mangled name for '\(decl.javaType.description)': \(name)") - decl.swiftMangledName = name.mangledName - } - - return decl - } - - package func fillInMethodMangledName(_ decl: ImportedFunc) async throws -> ImportedFunc { - // TODO: this is hacky, not precise at all and will be removed entirely - guard decl.swiftMangledName.isEmpty else { - // it was already processed - return decl - } - - var decl = decl - let names = try await nmSymbolNames(grepDemangled: [decl.baseIdentifier]) - if let name = names.first { - log.trace("Selected mangled name for '\(decl.identifier)': \(name)") - decl.swiftMangledName = name.mangledName - } - - return decl - } - - package func fillInInitMangledName(_ decl: ImportedFunc) async throws -> ImportedFunc { - // TODO: this is hacky, not precise at all and will be removed entirely - guard decl.swiftMangledName.isEmpty else { - // it was already processed - return decl - } - - var decl = decl - let names = try await nmSymbolNames(grepDemangled: [ - decl.returnType.swiftTypeName, - ".init(", - ]) - if let name = names.first { - log.trace("Selected mangled name for '\(decl.identifier)': \(name)") - decl.swiftMangledName = name.mangledName - } - - return decl - } - - package func fillInAllocatingInitMangledName(_ decl: ImportedFunc) async throws -> ImportedFunc { - // TODO: this is hacky, not precise at all and will be removed entirely - guard decl.swiftMangledName.isEmpty else { - // it was already processed - return decl - } - - var decl = decl - let names = try await nmSymbolNames(grepDemangled: ["\(decl.parentName!.swiftTypeName)", "__allocating_init("]) - if let name = names.first { - log.trace("Selected mangled name: \(name)") - decl.swiftMangledName = name.mangledName - } - - return decl - } - - /// Note that this is just a hack / workaround until swiftinterface files contain mangled names/ - /// So not even trying to make this very efficient. We find the symbols from the dylib and some - /// heuristic matching. - package func nmSymbolNames(grepDemangled: [String]) async throws -> [SwiftSymbolName] { - let nmResult = try await Subprocess.run( - .named("nm"), - arguments: ["-gU", path] - ) - - print(">>> nm -gU \(path)") - - let nmOutput = String( - data: nmResult.standardOutput, - encoding: .utf8 - )! - let nmLines = nmOutput.split(separator: "\n") - - let demangledOutput = try await swiftDemangle(nmOutput) - let demangledLines = demangledOutput.split(separator: "\n") - - var results: [SwiftSymbolName] = [] - for (sym, dem) in zip(nmLines, demangledLines) - where grepDemangled.allSatisfy({ g in dem.contains(g) }) { - guard let mangledName = sym.split(separator: " ").last else { - continue - } - - let descriptiveName = dem.split(separator: " ").dropFirst(2).joined(separator: " ") - - let name = SwiftSymbolName( - mangledName: String(mangledName), - descriptiveName: descriptiveName - ) - results.append(name) - } - - return results - } - - package func swiftDemangle(_ input: String) async throws -> String { - let input = input.utf8CString.map { UInt8($0) } - - let demangleResult = try await Subprocess.run( - .named("swift"), - arguments: ["demangle"], - input: input - ) - - let demangledOutput = String( - data: demangleResult.standardOutput, - encoding: .utf8 - )! - - return demangledOutput - } -} - -package struct SwiftSymbolName { - package let mangledName: String - package let descriptiveName: String - - init(mangledName: String, descriptiveName: String) { - self.mangledName = String(mangledName.trimmingPrefix("_")) - self.descriptiveName = descriptiveName - } -} - -extension Array { - func flatten() -> Array where Element == Optional { - self.compactMap { $0 } - } -} - -// Those are hacky ways to find symbols, all this should be deleted and we should use metadata from swiftinterface files -package extension Collection where Element == SwiftSymbolName { - func findInit() -> SwiftSymbolName? { - self.first { - $0.descriptiveName.contains(".init(") - } - } - - func findAllocatingInit() -> SwiftSymbolName? { - self.first { - $0.descriptiveName.contains(".__allocating_init(") - } - } - - func findPropertyGetter() -> SwiftSymbolName? { - self.first { - $0.descriptiveName.contains(".getter : ") - } - } - - func findPropertySetter() -> SwiftSymbolName? { - self.first { - $0.descriptiveName.contains(".setter : ") - } - } -} diff --git a/Sources/JExtractSwiftTool/JExtractSwiftTool.swift b/Sources/JExtractSwiftTool/JExtractSwiftTool.swift index 2e3c339f..0e6a195a 100644 --- a/Sources/JExtractSwiftTool/JExtractSwiftTool.swift +++ b/Sources/JExtractSwiftTool/JExtractSwiftTool.swift @@ -15,8 +15,8 @@ import JExtractSwift @main struct JExtractSwift { - static func main() async throws { + static func main() throws { let command = SwiftToJava.parseOrExit(CommandLine.arguments) - try await command.run() + try command.run() } } diff --git a/Sources/JavaKitExample/MySwiftLibrary.swift b/Sources/JavaKitExample/MySwiftLibrary.swift index 115a281d..66acfbc8 100644 --- a/Sources/JavaKitExample/MySwiftLibrary.swift +++ b/Sources/JavaKitExample/MySwiftLibrary.swift @@ -73,5 +73,5 @@ public class MySwiftClass { private func p(_ msg: String, file: String = #fileID, line: UInt = #line, function: String = #function) { print("[swift][\(file):\(line)](\(function)) \(msg)") - fflush(stdout) + fflush(Darwin.stdout) } diff --git a/Sources/_Subprocess/Platforms/Subprocess+Darwin.swift b/Sources/_Subprocess/Platforms/Subprocess+Darwin.swift deleted file mode 100644 index 746ba51c..00000000 --- a/Sources/_Subprocess/Platforms/Subprocess+Darwin.swift +++ /dev/null @@ -1,251 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// -//===----------------------------------------------------------------------===// - -#if canImport(Darwin) - -import Darwin -import Foundation -import SystemPackage - -#if FOUNDATION_FRAMEWORK -@_implementationOnly import _SubprocessCShims -#else -internal import _SubprocessCShims -#endif - -// Darwin specific implementation -extension Subprocess.Configuration { - internal typealias StringOrRawBytes = Subprocess.StringOrRawBytes - - internal func spawn( - withInput input: Subprocess.ExecutionInput, - output: Subprocess.ExecutionOutput, - error: Subprocess.ExecutionOutput - ) throws -> Subprocess { - let ( - executablePath, - env, argv, - intendedWorkingDir, - uidPtr, gidPtr, supplementaryGroups - ) = try self.preSpawn() - defer { - for ptr in env { ptr?.deallocate() } - for ptr in argv { ptr?.deallocate() } - uidPtr?.deallocate() - gidPtr?.deallocate() - } - - // Setup file actions and spawn attributes - var fileActions: posix_spawn_file_actions_t? = nil - var spawnAttributes: posix_spawnattr_t? = nil - // Setup stdin, stdout, and stderr - posix_spawn_file_actions_init(&fileActions) - defer { - posix_spawn_file_actions_destroy(&fileActions) - } - // Input - var result: Int32 = -1 - if let inputRead = input.getReadFileDescriptor() { - result = posix_spawn_file_actions_adddup2(&fileActions, inputRead.rawValue, 0) - guard result == 0 else { - try self.cleanupAll(input: input, output: output, error: error) - throw POSIXError(.init(rawValue: result) ?? .ENODEV) - } - } - if let inputWrite = input.getWriteFileDescriptor() { - // Close parent side - result = posix_spawn_file_actions_addclose(&fileActions, inputWrite.rawValue) - guard result == 0 else { - try self.cleanupAll(input: input, output: output, error: error) - throw POSIXError(.init(rawValue: result) ?? .ENODEV) - } - } - // Output - if let outputWrite = output.getWriteFileDescriptor() { - result = posix_spawn_file_actions_adddup2(&fileActions, outputWrite.rawValue, 1) - guard result == 0 else { - try self.cleanupAll(input: input, output: output, error: error) - throw POSIXError(.init(rawValue: result) ?? .ENODEV) - } - } - if let outputRead = output.getReadFileDescriptor() { - // Close parent side - result = posix_spawn_file_actions_addclose(&fileActions, outputRead.rawValue) - guard result == 0 else { - try self.cleanupAll(input: input, output: output, error: error) - throw POSIXError(.init(rawValue: result) ?? .ENODEV) - } - } - // Error - if let errorWrite = error.getWriteFileDescriptor() { - result = posix_spawn_file_actions_adddup2(&fileActions, errorWrite.rawValue, 2) - guard result == 0 else { - try self.cleanupAll(input: input, output: output, error: error) - throw POSIXError(.init(rawValue: result) ?? .ENODEV) - } - } - if let errorRead = error.getReadFileDescriptor() { - // Close parent side - result = posix_spawn_file_actions_addclose(&fileActions, errorRead.rawValue) - guard result == 0 else { - try self.cleanupAll(input: input, output: output, error: error) - throw POSIXError(.init(rawValue: result) ?? .ENODEV) - } - } - // Setup spawnAttributes - posix_spawnattr_init(&spawnAttributes) - defer { - posix_spawnattr_destroy(&spawnAttributes) - } - var noSignals = sigset_t() - var allSignals = sigset_t() - sigemptyset(&noSignals) - sigfillset(&allSignals) - posix_spawnattr_setsigmask(&spawnAttributes, &noSignals) - posix_spawnattr_setsigdefault(&spawnAttributes, &allSignals) - // Configure spawnattr - var flags: Int32 = POSIX_SPAWN_CLOEXEC_DEFAULT | POSIX_SPAWN_SETSIGMASK | POSIX_SPAWN_SETSIGDEF - if self.platformOptions.createProcessGroup { - flags |= POSIX_SPAWN_SETPGROUP - } - var spawnAttributeError = posix_spawnattr_setflags(&spawnAttributes, Int16(flags)) - // Set QualityOfService - // spanattr_qos seems to only accept `QOS_CLASS_UTILITY` or `QOS_CLASS_BACKGROUND` - // and returns an error of `EINVAL` if anything else is provided - if spawnAttributeError == 0 && self.platformOptions.qualityOfService == .utility { - spawnAttributeError = posix_spawnattr_set_qos_class_np(&spawnAttributes, QOS_CLASS_UTILITY) - } else if spawnAttributeError == 0 && self.platformOptions.qualityOfService == .background { - spawnAttributeError = posix_spawnattr_set_qos_class_np(&spawnAttributes, QOS_CLASS_BACKGROUND) - } - - // Setup cwd - var chdirError: Int32 = 0 - if intendedWorkingDir != .currentWorkingDirectory { - chdirError = intendedWorkingDir.withPlatformString { workDir in - return posix_spawn_file_actions_addchdir_np(&fileActions, workDir) - } - } - - // Error handling - if chdirError != 0 || spawnAttributeError != 0 { - try self.cleanupAll(input: input, output: output, error: error) - if spawnAttributeError != 0 { - throw POSIXError(.init(rawValue: result) ?? .ENODEV) - } - - if chdirError != 0 { - throw CocoaError( - .fileNoSuchFile, - userInfo: [ - .debugDescriptionErrorKey: - "Cannot failed to change the working directory to \(intendedWorkingDir) with errno \(chdirError)" - ] - ) - } - } - // Run additional config - if let spawnConfig = self.platformOptions.preSpawnAttributeConfigurator { - try spawnConfig(&spawnAttributes) - } - if let fileAttributeConfig = self.platformOptions.preSpawnFileAttributeConfigurator { - try fileAttributeConfig(&fileActions) - } - // Spawn - var pid: pid_t = 0 - let spawnError: CInt = executablePath.withCString { exePath in - return supplementaryGroups.withOptionalUnsafeBufferPointer { sgroups in - return _subprocess_spawn( - &pid, - exePath, - &fileActions, - &spawnAttributes, - argv, - env, - uidPtr, - gidPtr, - Int32(supplementaryGroups?.count ?? 0), - sgroups?.baseAddress, - self.platformOptions.createSession ? 1 : 0 - ) - } - } - // Spawn error - if spawnError != 0 { - try self.cleanupAll(input: input, output: output, error: error) - throw POSIXError(.init(rawValue: spawnError) ?? .ENODEV) - } - return Subprocess( - processIdentifier: .init(value: pid), - executionInput: input, - executionOutput: output, - executionError: error - ) - } -} - -// Special keys used in Error's user dictionary -extension String { - static let debugDescriptionErrorKey = "NSDebugDescription" -} - -// MARK: - Platform Specific Options -extension Subprocess { - /// The collection of platform-specific configurations - public struct PlatformOptions: Sendable { - public var qualityOfService: QualityOfService = .default - // Set user ID for the subprocess - public var userID: Int? = nil - // Set group ID for the subprocess - public var groupID: Int? = nil - // Set list of supplementary group IDs for the subprocess - public var supplementaryGroups: [Int]? = nil - // Creates a session and sets the process group ID - // i.e. Detach from the terminal. - public var createSession: Bool = false - // Create a new process group - public var createProcessGroup: Bool = false - public var launchRequirementData: Data? = nil - public var preSpawnAttributeConfigurator: (@Sendable (inout posix_spawnattr_t?) throws -> Void)? - public var preSpawnFileAttributeConfigurator: (@Sendable (inout posix_spawn_file_actions_t?) throws -> Void)? - - public init( - qualityOfService: QualityOfService, - userID: Int?, - groupID: Int?, - supplementaryGroups: [Int]?, - createSession: Bool, - createProcessGroup: Bool, - launchRequirementData: Data? - ) { - self.qualityOfService = qualityOfService - self.userID = userID - self.groupID = groupID - self.supplementaryGroups = supplementaryGroups - self.createSession = createSession - self.createProcessGroup = createProcessGroup - self.launchRequirementData = launchRequirementData - } - - public static var `default`: Self { - return .init( - qualityOfService: .default, - userID: nil, - groupID: nil, - supplementaryGroups: nil, - createSession: false, - createProcessGroup: false, - launchRequirementData: nil - ) - } - } -} - -#endif // canImport(Darwin) diff --git a/Sources/_Subprocess/Platforms/Subprocess+Linux.swift b/Sources/_Subprocess/Platforms/Subprocess+Linux.swift deleted file mode 100644 index 2f92ed50..00000000 --- a/Sources/_Subprocess/Platforms/Subprocess+Linux.swift +++ /dev/null @@ -1,141 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// -//===----------------------------------------------------------------------===// - -#if canImport(Glibc) - -import Glibc -import Foundation -import SystemPackage -import FoundationEssentials -package import _SubprocessCShims - -// Linux specific implementations -extension Subprocess.Configuration { - internal typealias StringOrRawBytes = Subprocess.StringOrRawBytes - - internal func spawn( - withInput input: Subprocess.ExecutionInput, - output: Subprocess.ExecutionOutput, - error: Subprocess.ExecutionOutput - ) throws -> Subprocess { - let ( - executablePath, - env, argv, - intendedWorkingDir, - uidPtr, gidPtr, - supplementaryGroups - ) = try self.preSpawn() - defer { - for ptr in env { ptr?.deallocate() } - for ptr in argv { ptr?.deallocate() } - uidPtr?.deallocate() - gidPtr?.deallocate() - } - - let fileDescriptors: [CInt] = [ - input.getReadFileDescriptor().rawValue, input.getWriteFileDescriptor()?.rawValue ?? 0, - output.getWriteFileDescriptor().rawValue, output.getReadFileDescriptor()?.rawValue ?? 0, - error.getWriteFileDescriptor().rawValue, error.getReadFileDescriptor()?.rawValue ?? 0, - ] - - var workingDirectory: String? - if intendedWorkingDir != FilePath.currentWorkingDirectory { - // Only pass in working directory if it's different - workingDirectory = intendedWorkingDir.string - } - // Spawn - var pid: pid_t = 0 - let spawnError: CInt = executablePath.withCString { exePath in - return workingDirectory.withOptionalCString { workingDir in - return supplementaryGroups.withOptionalUnsafeBufferPointer { sgroups in - return fileDescriptors.withUnsafeBufferPointer { fds in - return _subprocess_fork_exec( - &pid, - exePath, - workingDir, - fds.baseAddress!, - argv, - env, - uidPtr, - gidPtr, - CInt(supplementaryGroups?.count ?? 0), - sgroups?.baseAddress, - self.platformOptions.createSession ? 1 : 0, - self.platformOptions.createProcessGroup ? 1 : 0 - ) - } - } - } - } - // Spawn error - if spawnError != 0 { - try self.cleanupAll(input: input, output: output, error: error) - throw POSIXError(.init(rawValue: spawnError) ?? .ENODEV) - } - return Subprocess( - processIdentifier: .init(value: pid), - executionInput: input, - executionOutput: output, - executionError: error - ) - } -} - -// MARK: - Platform Specific Options -extension Subprocess { - public struct PlatformOptions: Sendable { - // Set user ID for the subprocess - public var userID: Int? = nil - // Set group ID for the subprocess - public var groupID: Int? = nil - // Set list of supplementary group IDs for the subprocess - public var supplementaryGroups: [Int]? = nil - // Creates a session and sets the process group ID - // i.e. Detach from the terminal. - public var createSession: Bool = false - // Create a new process group - public var createProcessGroup: Bool = false - // This callback is run after `fork` but before `exec`. - // Use it to perform any custom process setup - public var customProcessConfigurator: (@Sendable () -> Void)? = nil - - public init( - userID: Int?, - groupID: Int?, - supplementaryGroups: [Int]?, - createSession: Bool, - createProcessGroup: Bool - ) { - self.userID = userID - self.groupID = groupID - self.supplementaryGroups = supplementaryGroups - self.createSession = createSession - self.createProcessGroup = createProcessGroup - } - - public static var `default`: Self { - return .init( - userID: nil, - groupID: nil, - supplementaryGroups: nil, - createSession: false, - createProcessGroup: false - ) - } - } -} - -// Special keys used in Error's user dictionary -extension String { - static let debugDescriptionErrorKey = "DebugDescription" -} - -#endif // canImport(Glibc) diff --git a/Sources/_Subprocess/Platforms/Subprocess+Unix.swift b/Sources/_Subprocess/Platforms/Subprocess+Unix.swift deleted file mode 100644 index 40551261..00000000 --- a/Sources/_Subprocess/Platforms/Subprocess+Unix.swift +++ /dev/null @@ -1,321 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// -//===----------------------------------------------------------------------===// - -#if canImport(Darwin) || canImport(Glibc) - -#if canImport(Darwin) -import Darwin -#elseif canImport(Glibc) -import Glibc -#endif - -import Foundation -import SystemPackage - -#if FOUNDATION_FRAMEWORK -@_implementationOnly import _SubprocessCShims -#else -package import _SubprocessCShims -#endif - -import Dispatch - -// MARK: - Signals -extension Subprocess { - public struct Signal: Hashable, Sendable { - public let rawValue: Int32 - - private init(rawValue: Int32) { - self.rawValue = rawValue - } - - public static var interrupt: Self { .init(rawValue: SIGINT) } - public static var terminate: Self { .init(rawValue: SIGTERM) } - public static var suspend: Self { .init(rawValue: SIGSTOP) } - public static var resume: Self { .init(rawValue: SIGCONT) } - public static var kill: Self { .init(rawValue: SIGKILL) } - public static var terminalClosed: Self { .init(rawValue: SIGHUP) } - public static var quit: Self { .init(rawValue: SIGQUIT) } - public static var userDefinedOne: Self { .init(rawValue: SIGUSR1) } - public static var userDefinedTwo: Self { .init(rawValue: SIGUSR2) } - public static var alarm: Self { .init(rawValue: SIGALRM) } - public static var windowSizeChange: Self { .init(rawValue: SIGWINCH) } - } - - public func sendSignal(_ signal: Signal, toProcessGroup shouldSendToProcessGroup: Bool) throws { - let pid = shouldSendToProcessGroup ? -(self.processIdentifier.value) : self.processIdentifier.value - guard kill(pid, signal.rawValue) == 0 else { - throw POSIXError(.init(rawValue: errno)!) - } - } -} - -// MARK: Environment Resolution -extension Subprocess.Environment { - internal static let pathEnvironmentVariableName = "PATH" - - internal func pathValue() -> String? { - switch self.config { - case .inherit(let overrides): - // If PATH value exists in overrides, use it - if let value = overrides[.string(Self.pathEnvironmentVariableName)] { - return value.stringValue - } - // Fall back to current process - return ProcessInfo.processInfo.environment[Self.pathEnvironmentVariableName] - case .custom(let fullEnvironment): - if let value = fullEnvironment[.string(Self.pathEnvironmentVariableName)] { - return value.stringValue - } - return nil - } - } - - // This method follows the standard "create" rule: `env` needs to be - // manually deallocated - internal func createEnv() -> [UnsafeMutablePointer?] { - func createFullCString( - fromKey keyContainer: Subprocess.StringOrRawBytes, - value valueContainer: Subprocess.StringOrRawBytes - ) -> UnsafeMutablePointer { - let rawByteKey: UnsafeMutablePointer = keyContainer.createRawBytes() - let rawByteValue: UnsafeMutablePointer = valueContainer.createRawBytes() - defer { - rawByteKey.deallocate() - rawByteValue.deallocate() - } - /// length = `key` + `=` + `value` + `\null` - let totalLength = keyContainer.count + 1 + valueContainer.count + 1 - let fullString: UnsafeMutablePointer = .allocate(capacity: totalLength) - #if canImport(Darwin) - _ = snprintf(ptr: fullString, totalLength, "%s=%s", rawByteKey, rawByteValue) - #else - _ = _shims_snprintf(fullString, CInt(totalLength), "%s=%s", rawByteKey, rawByteValue) - #endif - return fullString - } - - var env: [UnsafeMutablePointer?] = [] - switch self.config { - case .inherit(let updates): - var current = ProcessInfo.processInfo.environment - for (keyContainer, valueContainer) in updates { - if let stringKey = keyContainer.stringValue { - // Remove the value from current to override it - current.removeValue(forKey: stringKey) - } - // Fast path - if case .string(let stringKey) = keyContainer, - case .string(let stringValue) = valueContainer - { - let fullString = "\(stringKey)=\(stringValue)" - env.append(strdup(fullString)) - continue - } - - env.append(createFullCString(fromKey: keyContainer, value: valueContainer)) - } - // Add the rest of `current` to env - for (key, value) in current { - let fullString = "\(key)=\(value)" - env.append(strdup(fullString)) - } - case .custom(let customValues): - for (keyContainer, valueContainer) in customValues { - // Fast path - if case .string(let stringKey) = keyContainer, - case .string(let stringValue) = valueContainer - { - let fullString = "\(stringKey)=\(stringValue)" - env.append(strdup(fullString)) - continue - } - env.append(createFullCString(fromKey: keyContainer, value: valueContainer)) - } - } - env.append(nil) - return env - } -} - -// MARK: Args Creation -extension Subprocess.Arguments { - // This method follows the standard "create" rule: `args` needs to be - // manually deallocated - internal func createArgs(withExecutablePath executablePath: String) -> [UnsafeMutablePointer?] { - var argv: [UnsafeMutablePointer?] = self.storage.map { $0.createRawBytes() } - // argv[0] = executable path - if let override = self.executablePathOverride { - argv.insert(override.createRawBytes(), at: 0) - } else { - argv.insert(strdup(executablePath), at: 0) - } - argv.append(nil) - return argv - } -} - -// MARK: - Executable Searching -extension Subprocess.Executable { - internal static var defaultSearchPaths: Set { - return Set([ - "/usr/bin", - "/bin", - "/usr/sbin", - "/sbin", - "/usr/local/bin", - ]) - } - - internal func resolveExecutablePath(withPathValue pathValue: String?) -> String? { - switch self.storage { - case .executable(let executableName): - // If the executableName in is already a full path, return it directly - if Subprocess.Configuration.pathAccessible(executableName, mode: X_OK) { - return executableName - } - // Get $PATH from environment - let searchPaths: Set - if let pathValue = pathValue { - let localSearchPaths = pathValue.split(separator: ":").map { String($0) } - searchPaths = Set(localSearchPaths).union(Self.defaultSearchPaths) - } else { - searchPaths = Self.defaultSearchPaths - } - - for path in searchPaths { - let fullPath = "\(path)/\(executableName)" - let fileExists = Subprocess.Configuration.pathAccessible(fullPath, mode: X_OK) - if fileExists { - return fullPath - } - } - case .path(let executablePath): - // Use path directly - return executablePath.string - } - return nil - } -} - -// MARK: - Configuration -extension Subprocess.Configuration { - internal func preSpawn() throws -> ( - executablePath: String, - env: [UnsafeMutablePointer?], - argv: [UnsafeMutablePointer?], - intendedWorkingDir: FilePath, - uidPtr: UnsafeMutablePointer?, - gidPtr: UnsafeMutablePointer?, - supplementaryGroups: [gid_t]? - ) { - // Prepare environment - let env = self.environment.createEnv() - // Prepare executable path - guard - let executablePath = self.executable.resolveExecutablePath( - withPathValue: self.environment.pathValue() - ) - else { - for ptr in env { ptr?.deallocate() } - throw CocoaError( - .executableNotLoadable, - userInfo: [ - "description": "\(self.executable.description) is not an executable" - ] - ) - } - // Prepare arguments - let argv: [UnsafeMutablePointer?] = self.arguments.createArgs(withExecutablePath: executablePath) - // Prepare workingDir - let intendedWorkingDir = self.workingDirectory - guard Self.pathAccessible(intendedWorkingDir.string, mode: F_OK) else { - for ptr in env { ptr?.deallocate() } - for ptr in argv { ptr?.deallocate() } - throw CocoaError( - .fileNoSuchFile, - userInfo: [ - "description": "Failed to set working directory to \(intendedWorkingDir)" - ] - ) - } - - var uidPtr: UnsafeMutablePointer? = nil - if let userID = self.platformOptions.userID { - uidPtr = .allocate(capacity: 1) - uidPtr?.pointee = uid_t(userID) - } - var gidPtr: UnsafeMutablePointer? = nil - if let groupID = self.platformOptions.groupID { - gidPtr = .allocate(capacity: 1) - gidPtr?.pointee = gid_t(groupID) - } - var supplementaryGroups: [gid_t]? - if let groupsValue = self.platformOptions.supplementaryGroups { - supplementaryGroups = groupsValue.map { gid_t($0) } - } - return ( - executablePath: executablePath, - env: env, argv: argv, - intendedWorkingDir: intendedWorkingDir, - uidPtr: uidPtr, gidPtr: gidPtr, - supplementaryGroups: supplementaryGroups - ) - } - - internal static func pathAccessible(_ path: String, mode: Int32) -> Bool { - return path.withCString { - return access($0, mode) == 0 - } - } -} - -// MARK: - Process Monitoring -@Sendable -internal func monitorProcessTermination( - forProcessWithIdentifier pid: Subprocess.ProcessIdentifier -) async -> Subprocess.TerminationStatus { - return await withCheckedContinuation { continuation in - let source = DispatchSource.makeProcessSource( - identifier: pid.value, - eventMask: [.exit, .signal] - ) - source.setEventHandler { - source.cancel() - var status: Int32 = -1 - waitpid(pid.value, &status, 0) - if _was_process_exited(status) != 0 { - continuation.resume(returning: .exited(_get_exit_code(status))) - return - } - if _was_process_signaled(status) != 0 { - continuation.resume(returning: .unhandledException(_get_signal_code(status))) - return - } - fatalError("Unexpected exit status type: \(status)") - } - source.resume() - } -} - -// MARK: - Read Buffer Size -extension Subprocess { - @inline(__always) - internal static var readBufferSize: Int { - #if canImport(Darwin) - return 16384 - #else - return Platform.pageSize - #endif // canImport(Darwin) - } -} - -#endif // canImport(Darwin) || canImport(Glibc) diff --git a/Sources/_Subprocess/Subprocess+API.swift b/Sources/_Subprocess/Subprocess+API.swift deleted file mode 100644 index 63872ee1..00000000 --- a/Sources/_Subprocess/Subprocess+API.swift +++ /dev/null @@ -1,228 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// -//===----------------------------------------------------------------------===// - -import Foundation -import SystemPackage - -extension Subprocess { - public static func run( - _ executable: Executable, - arguments: Arguments = [], - environment: Environment = .inherit, - workingDirectory: FilePath? = nil, - platformOptions: PlatformOptions = .default, - input: InputMethod = .noInput, - output: CollectedOutputMethod = .collect, - error: CollectedOutputMethod = .collect - ) async throws -> CollectedResult { - let result = try await self.run( - executable, - arguments: arguments, - environment: environment, - workingDirectory: workingDirectory, - platformOptions: platformOptions, - input: input, - output: .init(method: output.method), - error: .init(method: error.method) - ) { subprocess in - let (standardOutput, standardError) = try await subprocess.captureIOs() - return ( - processIdentifier: subprocess.processIdentifier, - standardOutput: standardOutput, - standardError: standardError - ) - } - return CollectedResult( - processIdentifier: result.value.processIdentifier, - terminationStatus: result.terminationStatus, - standardOutput: result.value.standardOutput, - standardError: result.value.standardError - ) - } - - public static func run( - _ executable: Executable, - arguments: Arguments = [], - environment: Environment = .inherit, - workingDirectory: FilePath? = nil, - platformOptions: PlatformOptions = .default, - input: some Sequence, - output: CollectedOutputMethod = .collect, - error: CollectedOutputMethod = .collect - ) async throws -> CollectedResult { - let result = try await self.run( - executable, - arguments: arguments, - environment: environment, - workingDirectory: workingDirectory, - platformOptions: platformOptions, - output: .init(method: output.method), - error: .init(method: output.method) - ) { subprocess, writer in - try await writer.write(input) - try await writer.finish() - let (standardOutput, standardError) = try await subprocess.captureIOs() - return ( - processIdentifier: subprocess.processIdentifier, - standardOutput: standardOutput, - standardError: standardError - ) - } - return CollectedResult( - processIdentifier: result.value.processIdentifier, - terminationStatus: result.terminationStatus, - standardOutput: result.value.standardOutput, - standardError: result.value.standardError - ) - } - - public static func run( - _ executable: Executable, - arguments: Arguments = [], - environment: Environment = .inherit, - workingDirectory: FilePath? = nil, - platformOptions: PlatformOptions = .default, - input: S, - output: CollectedOutputMethod = .collect, - error: CollectedOutputMethod = .collect - ) async throws -> CollectedResult where S.Element == UInt8 { - let result = try await self.run( - executable, - arguments: arguments, - environment: environment, - workingDirectory: workingDirectory, - platformOptions: platformOptions, - output: .init(method: output.method), - error: .init(method: output.method) - ) { subprocess, writer in - try await writer.write(input) - try await writer.finish() - let (standardOutput, standardError) = try await subprocess.captureIOs() - return ( - processIdentifier: subprocess.processIdentifier, - standardOutput: standardOutput, - standardError: standardError - ) - } - return CollectedResult( - processIdentifier: result.value.processIdentifier, - terminationStatus: result.terminationStatus, - standardOutput: result.value.standardOutput, - standardError: result.value.standardError - ) - } -} - -// MARK: Custom Execution Body -extension Subprocess { - public static func run( - _ executable: Executable, - arguments: Arguments = [], - environment: Environment = .inherit, - workingDirectory: FilePath? = nil, - platformOptions: PlatformOptions = .default, - input: InputMethod = .noInput, - output: RedirectedOutputMethod = .redirectToSequence, - error: RedirectedOutputMethod = .redirectToSequence, - _ body: (@Sendable @escaping (Subprocess) async throws -> R) - ) async throws -> ExecutionResult { - return try await Configuration( - executable: executable, - arguments: arguments, - environment: environment, - workingDirectory: workingDirectory, - platformOptions: platformOptions - ) - .run(input: input, output: output, error: error, body) - } - - public static func run( - _ executable: Executable, - arguments: Arguments = [], - environment: Environment = .inherit, - workingDirectory: FilePath? = nil, - platformOptions: PlatformOptions, - input: some Sequence, - output: RedirectedOutputMethod = .redirectToSequence, - error: RedirectedOutputMethod = .redirectToSequence, - _ body: (@Sendable @escaping (Subprocess) async throws -> R) - ) async throws -> ExecutionResult { - return try await Configuration( - executable: executable, - arguments: arguments, - environment: environment, - workingDirectory: workingDirectory, - platformOptions: platformOptions - ) - .run(output: output, error: error) { execution, writer in - try await writer.write(input) - try await writer.finish() - return try await body(execution) - } - } - - public static func run( - _ executable: Executable, - arguments: Arguments = [], - environment: Environment = .inherit, - workingDirectory: FilePath? = nil, - platformOptions: PlatformOptions = .default, - input: S, - output: RedirectedOutputMethod = .redirectToSequence, - error: RedirectedOutputMethod = .redirectToSequence, - _ body: (@Sendable @escaping (Subprocess) async throws -> R) - ) async throws -> ExecutionResult where S.Element == UInt8 { - return try await Configuration( - executable: executable, - arguments: arguments, - environment: environment, - workingDirectory: workingDirectory, - platformOptions: platformOptions - ) - .run(output: output, error: error) { execution, writer in - try await writer.write(input) - try await writer.finish() - return try await body(execution) - } - } - - public static func run( - _ executable: Executable, - arguments: Arguments = [], - environment: Environment = .inherit, - workingDirectory: FilePath? = nil, - platformOptions: PlatformOptions = .default, - output: RedirectedOutputMethod = .redirectToSequence, - error: RedirectedOutputMethod = .redirectToSequence, - _ body: (@Sendable @escaping (Subprocess, StandardInputWriter) async throws -> R) - ) async throws -> ExecutionResult { - return try await Configuration( - executable: executable, - arguments: arguments, - environment: environment, - workingDirectory: workingDirectory, - platformOptions: platformOptions - ) - .run(output: output, error: error, body) - } -} - -// MARK: - Configuration Based -extension Subprocess { - public static func run( - using configuration: Configuration, - output: RedirectedOutputMethod = .redirectToSequence, - error: RedirectedOutputMethod = .redirectToSequence, - _ body: (@Sendable @escaping (Subprocess, StandardInputWriter) async throws -> R) - ) async throws -> ExecutionResult { - return try await configuration.run(output: output, error: error, body) - } -} diff --git a/Sources/_Subprocess/Subprocess+AsyncBytes.swift b/Sources/_Subprocess/Subprocess+AsyncBytes.swift deleted file mode 100644 index bdd08caa..00000000 --- a/Sources/_Subprocess/Subprocess+AsyncBytes.swift +++ /dev/null @@ -1,115 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// -//===----------------------------------------------------------------------===// - -import Dispatch -import Foundation -import SystemPackage - -extension Subprocess { - public struct AsyncBytes: AsyncSequence, Sendable, _AsyncSequence { - public typealias Error = any Swift.Error - - public typealias Element = UInt8 - - @_nonSendable - public struct Iterator: AsyncIteratorProtocol { - public typealias Element = UInt8 - - private let fileDescriptor: FileDescriptor - private var buffer: [UInt8] - private var currentPosition: Int - private var finished: Bool - - internal init(fileDescriptor: FileDescriptor) { - self.fileDescriptor = fileDescriptor - self.buffer = [] - self.currentPosition = 0 - self.finished = false - } - - private mutating func reloadBufferAndNext() async throws -> UInt8? { - if self.finished { - return nil - } - try Task.checkCancellation() - do { - self.buffer = try await self.fileDescriptor.read( - upToLength: Subprocess.readBufferSize - ) - self.currentPosition = 0 - if self.buffer.count < Subprocess.readBufferSize { - self.finished = true - } - } catch { - self.finished = true - throw error - } - return try await self.next() - } - - public mutating func next() async throws -> UInt8? { - if currentPosition < buffer.count { - let value = buffer[currentPosition] - self.currentPosition += 1 - return value - } - return try await self.reloadBufferAndNext() - } - - private func read(from fileDescriptor: FileDescriptor, maxLength: Int) async throws -> [UInt8] { - return try await withCheckedThrowingContinuation { continuation in - DispatchIO.read( - fromFileDescriptor: fileDescriptor.rawValue, - maxLength: maxLength, - runningHandlerOn: .main - ) { data, error in - guard error == 0 else { - continuation.resume( - throwing: POSIXError( - .init(rawValue: error) ?? .ENODEV - ) - ) - return - } - continuation.resume(returning: Array(data)) - } - } - } - } - - private let fileDescriptor: FileDescriptor - - init(fileDescriptor: FileDescriptor) { - self.fileDescriptor = fileDescriptor - } - - public func makeAsyncIterator() -> Iterator { - return Iterator(fileDescriptor: self.fileDescriptor) - } - } -} - -extension RangeReplaceableCollection { - /// Creates a new instance of a collection containing the elements of an asynchronous sequence. - /// - /// - Parameter source: The asynchronous sequence of elements for the new collection. - @inlinable - public init(_ source: Source) async rethrows where Source.Element == Element { - self.init() - for try await item in source { - append(item) - } - } -} - -public protocol _AsyncSequence: AsyncSequence { - associatedtype Error -} diff --git a/Sources/_Subprocess/Subprocess+Configuration.swift b/Sources/_Subprocess/Subprocess+Configuration.swift deleted file mode 100644 index a50f1fc5..00000000 --- a/Sources/_Subprocess/Subprocess+Configuration.swift +++ /dev/null @@ -1,621 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// -//===----------------------------------------------------------------------===// - -import Foundation -@preconcurrency import SystemPackage - -#if FOUNDATION_FRAMEWORK -@_implementationOnly import _SubprocessCShims -#else -package import _SubprocessCShims -#endif - -#if canImport(Darwin) -import Darwin -#elseif canImport(Glibc) -import Glibc -#endif - -extension Subprocess { - public struct Configuration: Sendable { - - internal enum RunState: Sendable { - case workBody(Result) - case monitorChildProcess(TerminationStatus) - } - - // Configurable properties - public var executable: Executable - public var arguments: Arguments - public var environment: Environment - public var workingDirectory: FilePath - public var platformOptions: PlatformOptions - - public init( - executable: Executable, - arguments: Arguments = [], - environment: Environment = .inherit, - workingDirectory: FilePath? = nil, - platformOptions: PlatformOptions = .default - ) { - self.executable = executable - self.arguments = arguments - self.environment = environment - self.workingDirectory = workingDirectory ?? .currentWorkingDirectory - self.platformOptions = platformOptions - } - - /// Close each input individually, and throw the first error if there's multiple errors thrown - @Sendable - private func cleanup( - process: Subprocess, - childSide: Bool, - parentSide: Bool, - attemptToTerminateSubProcess: Bool - ) throws { - guard childSide || parentSide || attemptToTerminateSubProcess else { - return - } - - let inputCloseFunc: () throws -> Void - let outputCloseFunc: () throws -> Void - let errorCloseFunc: () throws -> Void - if childSide && parentSide { - // Close all - inputCloseFunc = process.executionInput.closeAll - outputCloseFunc = process.executionOutput.closeAll - errorCloseFunc = process.executionError.closeAll - } else if childSide { - // Close child only - inputCloseFunc = process.executionInput.closeChildSide - outputCloseFunc = process.executionOutput.closeChildSide - errorCloseFunc = process.executionError.closeChildSide - } else { - // Close parent only - inputCloseFunc = process.executionInput.closeParentSide - outputCloseFunc = process.executionOutput.closeParentSide - errorCloseFunc = process.executionError.closeParentSide - } - - var inputError: Error? - var outputError: Error? - var errorError: Error? // lol - do { - try inputCloseFunc() - } catch { - inputError = error - } - - do { - try outputCloseFunc() - } catch { - outputError = error - } - - do { - try errorCloseFunc() - } catch { - errorError = error // lolol - } - - // Attempt to kill the subprocess - var killError: Error? - if attemptToTerminateSubProcess { - do { - try process.sendSignal(.kill, toProcessGroup: true) - } catch { - guard let posixError: POSIXError = error as? POSIXError else { - killError = error - return - } - // Ignore ESRCH (no such process) - if posixError.code != .ESRCH { - killError = error - } - } - } - - if let inputError = inputError { - throw inputError - } - - if let outputError = outputError { - throw outputError - } - - if let errorError = errorError { - throw errorError - } - - if let killError = killError { - throw killError - } - } - - /// Close each input individually, and throw the first error if there's multiple errors thrown - @Sendable - internal func cleanupAll( - input: ExecutionInput, - output: ExecutionOutput, - error: ExecutionOutput - ) throws { - var inputError: Error? - var outputError: Error? - var errorError: Error? - - do { - try input.closeAll() - } catch { - inputError = error - } - - do { - try output.closeAll() - } catch { - outputError = error - } - - do { - try error.closeAll() - } catch { - errorError = error - } - - if let inputError = inputError { - throw inputError - } - if let outputError = outputError { - throw outputError - } - if let errorError = errorError { - throw errorError - } - } - - internal func run( - output: RedirectedOutputMethod, - error: RedirectedOutputMethod, - _ body: @Sendable @escaping (Subprocess, StandardInputWriter) async throws -> R - ) async throws -> ExecutionResult { - let (readFd, writeFd) = try FileDescriptor.pipe() - let executionInput: ExecutionInput = .init(storage: .customWrite(readFd, writeFd)) - let executionOutput: ExecutionOutput = try output.createExecutionOutput() - let executionError: ExecutionOutput = try error.createExecutionOutput() - let process: Subprocess = try self.spawn( - withInput: executionInput, - output: executionOutput, - error: executionError - ) - // After spawn, cleanup child side fds - try self.cleanup( - process: process, - childSide: true, - parentSide: false, - attemptToTerminateSubProcess: false - ) - return try await withTaskCancellationHandler { - return try await withThrowingTaskGroup(of: RunState.self) { group in - group.addTask { - let status = await monitorProcessTermination( - forProcessWithIdentifier: process.processIdentifier - ) - return .monitorChildProcess(status) - } - group.addTask { - do { - let result = try await body(process, .init(input: executionInput)) - try self.cleanup( - process: process, - childSide: false, - parentSide: true, - attemptToTerminateSubProcess: false - ) - return .workBody(result) - } catch { - // Cleanup everything - try self.cleanup( - process: process, - childSide: true, - parentSide: true, - attemptToTerminateSubProcess: true - ) - throw error - } - } - - var result: R! - var terminationStatus: TerminationStatus! - while let state = try await group.next() { - switch state { - case .monitorChildProcess(let status): - // We don't really care about termination status here - terminationStatus = status - case .workBody(let workResult): - result = workResult - } - } - return ExecutionResult(terminationStatus: terminationStatus, value: result) - } - } onCancel: { - // Attempt to terminate the child process - // Since the task has already been cancelled, - // this is the best we can do - try? self.cleanup( - process: process, - childSide: true, - parentSide: true, - attemptToTerminateSubProcess: true - ) - } - } - - internal func run( - input: InputMethod, - output: RedirectedOutputMethod, - error: RedirectedOutputMethod, - _ body: (@Sendable @escaping (Subprocess) async throws -> R) - ) async throws -> ExecutionResult { - let executionInput = try input.createExecutionInput() - let executionOutput = try output.createExecutionOutput() - let executionError = try error.createExecutionOutput() - let process = try self.spawn( - withInput: executionInput, - output: executionOutput, - error: executionError - ) - // After spawn, clean up child side - try self.cleanup( - process: process, - childSide: true, - parentSide: false, - attemptToTerminateSubProcess: false - ) - return try await withTaskCancellationHandler { - return try await withThrowingTaskGroup(of: RunState.self) { group in - group.addTask { - let status = await monitorProcessTermination( - forProcessWithIdentifier: process.processIdentifier - ) - return .monitorChildProcess(status) - } - group.addTask { - do { - let result = try await body(process) - try self.cleanup( - process: process, - childSide: false, - parentSide: true, - attemptToTerminateSubProcess: false - ) - return .workBody(result) - } catch { - try self.cleanup( - process: process, - childSide: true, - parentSide: true, - attemptToTerminateSubProcess: true - ) - throw error - } - } - - var result: R! - var terminationStatus: TerminationStatus! - while let state = try await group.next() { - switch state { - case .monitorChildProcess(let status): - terminationStatus = status - case .workBody(let workResult): - result = workResult - } - } - return ExecutionResult(terminationStatus: terminationStatus, value: result) - } - } onCancel: { - // Attempt to terminate the child process - // Since the task has already been cancelled, - // this is the best we can do - try? self.cleanup( - process: process, - childSide: true, - parentSide: true, - attemptToTerminateSubProcess: true - ) - } - } - } -} - -// MARK: - Executable -extension Subprocess { - public struct Executable: Sendable, CustomStringConvertible, Hashable { - internal enum Configuration: Sendable, Hashable { - case executable(String) - case path(FilePath) - } - - internal let storage: Configuration - - public var description: String { - switch storage { - case .executable(let executableName): - return executableName - case .path(let filePath): - return filePath.string - } - } - - private init(_config: Configuration) { - self.storage = _config - } - - public static func named(_ executableName: String) -> Self { - return .init(_config: .executable(executableName)) - } - - public static func at(_ filePath: FilePath) -> Self { - return .init(_config: .path(filePath)) - } - - public func resolveExecutablePath(in environment: Environment) -> FilePath? { - if let path = self.resolveExecutablePath(withPathValue: environment.pathValue()) { - return FilePath(path) - } - return nil - } - } -} - -// MARK: - Arguments -extension Subprocess { - public struct Arguments: Sendable, ExpressibleByArrayLiteral { - public typealias ArrayLiteralElement = String - - internal let storage: [StringOrRawBytes] - internal let executablePathOverride: StringOrRawBytes? - - public init(arrayLiteral elements: String...) { - self.storage = elements.map { .string($0) } - self.executablePathOverride = nil - } - - public init(executablePathOverride: String?, remainingValues: [String]) { - self.storage = remainingValues.map { .string($0) } - if let executablePathOverride = executablePathOverride { - self.executablePathOverride = .string(executablePathOverride) - } else { - self.executablePathOverride = nil - } - } - - public init(executablePathOverride: Data?, remainingValues: [Data]) { - self.storage = remainingValues.map { .rawBytes($0.toArray()) } - if let override = executablePathOverride { - self.executablePathOverride = .rawBytes(override.toArray()) - } else { - self.executablePathOverride = nil - } - } - } -} - -// MARK: - Environment -extension Subprocess { - public struct Environment: Sendable { - internal enum Configuration { - case inherit([StringOrRawBytes: StringOrRawBytes]) - case custom([StringOrRawBytes: StringOrRawBytes]) - } - - internal let config: Configuration - - init(config: Configuration) { - self.config = config - } - - public static var inherit: Self { - return .init(config: .inherit([:])) - } - - public func updating(_ newValue: [String: String]) -> Self { - return .init(config: .inherit(newValue.wrapToStringOrRawBytes())) - } - - public func updating(_ newValue: [Data: Data]) -> Self { - return .init(config: .inherit(newValue.wrapToStringOrRawBytes())) - } - - public static func custom(_ newValue: [String: String]) -> Self { - return .init(config: .custom(newValue.wrapToStringOrRawBytes())) - } - - public static func custom(_ newValue: [Data: Data]) -> Self { - return .init(config: .custom(newValue.wrapToStringOrRawBytes())) - } - } -} - -fileprivate extension Dictionary where Key == String, Value == String { - func wrapToStringOrRawBytes() -> [Subprocess.StringOrRawBytes: Subprocess.StringOrRawBytes] { - var result = Dictionary< - Subprocess.StringOrRawBytes, - Subprocess.StringOrRawBytes - >(minimumCapacity: self.count) - for (key, value) in self { - result[.string(key)] = .string(value) - } - return result - } -} - -fileprivate extension Dictionary where Key == Data, Value == Data { - func wrapToStringOrRawBytes() -> [Subprocess.StringOrRawBytes: Subprocess.StringOrRawBytes] { - var result = Dictionary< - Subprocess.StringOrRawBytes, - Subprocess.StringOrRawBytes - >(minimumCapacity: self.count) - for (key, value) in self { - result[.rawBytes(key.toArray())] = .rawBytes(value.toArray()) - } - return result - } -} - -fileprivate extension Data { - func toArray() -> [T] { - return self.withUnsafeBytes { ptr in - return Array(ptr.bindMemory(to: T.self)) - } - } -} - -// MARK: - ProcessIdentifier -extension Subprocess { - public struct ProcessIdentifier: Sendable, Hashable { - let value: pid_t - - internal init(value: pid_t) { - self.value = value - } - } -} - -// MARK: - TerminationStatus -extension Subprocess { - public enum TerminationStatus: Sendable, Hashable, Codable { - #if canImport(WinSDK) - public typealias Code = DWORD - #else - public typealias Code = CInt - #endif - - #if canImport(WinSDK) - case stillActive - #endif - - case exited(Code) - case unhandledException(Code) - - public var isSuccess: Bool { - switch self { - case .exited(let exitCode): - return exitCode == 0 - case .unhandledException(_): - return false - } - } - - public var isUnhandledException: Bool { - switch self { - case .exited(_): - return false - case .unhandledException(_): - return true - } - } - } -} - -// MARK: - Internal -extension Subprocess { - internal enum StringOrRawBytes: Sendable, Hashable { - case string(String) - case rawBytes([CChar]) - - // Return value needs to be deallocated manually by callee - func createRawBytes() -> UnsafeMutablePointer { - switch self { - case .string(let string): - return strdup(string) - case .rawBytes(let rawBytes): - return strdup(rawBytes) - } - } - - var stringValue: String? { - switch self { - case .string(let string): - return string - case .rawBytes(let rawBytes): - return String(validatingUTF8: rawBytes) - } - } - - var count: Int { - switch self { - case .string(let string): - return string.count - case .rawBytes(let rawBytes): - return strnlen(rawBytes, Int.max) - } - } - - func hash(into hasher: inout Hasher) { - // If Raw bytes is valid UTF8, hash it as so - switch self { - case .string(let string): - hasher.combine(string) - case .rawBytes(let bytes): - if let stringValue = self.stringValue { - hasher.combine(stringValue) - } else { - hasher.combine(bytes) - } - } - } - } -} - -extension FilePath { - static var currentWorkingDirectory: Self { - let path = getcwd(nil, 0)! - defer { free(path) } - return .init(String(cString: path)) - } -} - -extension Optional where Wrapped: Collection { - func withOptionalUnsafeBufferPointer(_ body: ((UnsafeBufferPointer)?) throws -> R) rethrows -> R { - switch self { - case .some(let wrapped): - guard let array: Array = wrapped as? Array else { - return try body(nil) - } - return try array.withUnsafeBufferPointer { ptr in - return try body(ptr) - } - case .none: - return try body(nil) - } - } -} - -extension Optional where Wrapped == String { - func withOptionalCString(_ body: ((UnsafePointer)?) throws -> R) rethrows -> R { - switch self { - case .none: - return try body(nil) - case .some(let wrapped): - return try wrapped.withCString { - return try body($0) - } - } - } -} - -// MARK: - Stubs for the one from Foundation -public enum QualityOfService: Int, Sendable { - case userInteractive = 0x21 - case userInitiated = 0x19 - case utility = 0x11 - case background = 0x09 - case `default` = -1 -} diff --git a/Sources/_Subprocess/Subprocess+IO.swift b/Sources/_Subprocess/Subprocess+IO.swift deleted file mode 100644 index f71bb2dc..00000000 --- a/Sources/_Subprocess/Subprocess+IO.swift +++ /dev/null @@ -1,400 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// -//===----------------------------------------------------------------------===// - -import Dispatch -import Foundation -import SystemPackage - -// MARK: - Input -extension Subprocess { - public struct InputMethod: Sendable, Hashable { - internal enum Storage: Sendable, Hashable { - case noInput - case fileDescriptor(FileDescriptor, Bool) - } - - internal let method: Storage - - internal init(method: Storage) { - self.method = method - } - - internal func createExecutionInput() throws -> ExecutionInput { - switch self.method { - case .noInput: - let devnull: FileDescriptor = try .open("/dev/null", .readOnly) - return .init(storage: .noInput(devnull)) - case .fileDescriptor(let fileDescriptor, let closeWhenDone): - return .init(storage: .fileDescriptor(fileDescriptor, closeWhenDone)) - } - } - - public static var noInput: Self { - return .init(method: .noInput) - } - - public static func readFrom(_ fd: FileDescriptor, closeAfterProcessSpawned: Bool) -> Self { - return .init(method: .fileDescriptor(fd, closeAfterProcessSpawned)) - } - } -} - -extension Subprocess { - public struct CollectedOutputMethod: Sendable, Hashable { - internal enum Storage: Sendable, Hashable { - case discarded - case fileDescriptor(FileDescriptor, Bool) - case collected(Int) - } - - internal let method: Storage - - internal init(method: Storage) { - self.method = method - } - - public static var discard: Self { - return .init(method: .discarded) - } - - public static var collect: Self { - return .init(method: .collected(128 * 1024)) - } - - public static func writeTo(_ fd: FileDescriptor, closeAfterProcessSpawned: Bool) -> Self { - return .init(method: .fileDescriptor(fd, closeAfterProcessSpawned)) - } - - public static func collect(limit: Int) -> Self { - return .init(method: .collected(limit)) - } - - internal func createExecutionOutput() throws -> ExecutionOutput { - switch self.method { - case .discarded: - // Bind to /dev/null - let devnull: FileDescriptor = try .open("/dev/null", .writeOnly) - return .init(storage: .discarded(devnull)) - case .fileDescriptor(let fileDescriptor, let closeWhenDone): - return .init(storage: .fileDescriptor(fileDescriptor, closeWhenDone)) - case .collected(let limit): - let (readFd, writeFd) = try FileDescriptor.pipe() - return .init(storage: .collected(limit, readFd, writeFd)) - } - } - } - - public struct RedirectedOutputMethod: Sendable, Hashable { - typealias Storage = CollectedOutputMethod.Storage - - internal let method: Storage - - internal init(method: Storage) { - self.method = method - } - - public static var discard: Self { - return .init(method: .discarded) - } - - public static var redirectToSequence: Self { - return .init(method: .collected(128 * 1024)) - } - - public static func writeTo(_ fd: FileDescriptor, closeAfterProcessSpawned: Bool) -> Self { - return .init(method: .fileDescriptor(fd, closeAfterProcessSpawned)) - } - - internal func createExecutionOutput() throws -> ExecutionOutput { - switch self.method { - case .discarded: - // Bind to /dev/null - let devnull: FileDescriptor = try .open("/dev/null", .writeOnly) - return .init(storage: .discarded(devnull)) - case .fileDescriptor(let fileDescriptor, let closeWhenDone): - return .init(storage: .fileDescriptor(fileDescriptor, closeWhenDone)) - case .collected(let limit): - let (readFd, writeFd) = try FileDescriptor.pipe() - return .init(storage: .collected(limit, readFd, writeFd)) - } - } - } -} - -// MARK: - Execution IO -extension Subprocess { - internal final class ExecutionInput: Sendable { - - internal enum Storage: Sendable { - case noInput(FileDescriptor?) - case customWrite(FileDescriptor?, FileDescriptor?) - case fileDescriptor(FileDescriptor?, Bool) - } - - let storage: LockedState - - internal init(storage: Storage) { - self.storage = .init(initialState: storage) - } - - internal func getReadFileDescriptor() -> FileDescriptor? { - return self.storage.withLock { - switch $0 { - case .noInput(let readFd): - return readFd - case .customWrite(let readFd, _): - return readFd - case .fileDescriptor(let readFd, _): - return readFd - } - } - } - - internal func getWriteFileDescriptor() -> FileDescriptor? { - return self.storage.withLock { - switch $0 { - case .noInput(_), .fileDescriptor(_, _): - return nil - case .customWrite(_, let writeFd): - return writeFd - } - } - } - - internal func closeChildSide() throws { - try self.storage.withLock { - switch $0 { - case .noInput(let devnull): - try devnull?.close() - $0 = .noInput(nil) - case .customWrite(let readFd, let writeFd): - try readFd?.close() - $0 = .customWrite(nil, writeFd) - case .fileDescriptor(let fd, let closeWhenDone): - // User passed in fd - if closeWhenDone { - try fd?.close() - $0 = .fileDescriptor(nil, closeWhenDone) - } - } - } - } - - internal func closeParentSide() throws { - try self.storage.withLock { - switch $0 { - case .noInput(_), .fileDescriptor(_, _): - break - case .customWrite(let readFd, let writeFd): - // The parent fd should have been closed - // in the `body` when writer.finish() is called - // But in case it isn't call it agian - try writeFd?.close() - $0 = .customWrite(readFd, nil) - } - } - } - - internal func closeAll() throws { - try self.storage.withLock { - switch $0 { - case .noInput(let readFd): - try readFd?.close() - $0 = .noInput(nil) - case .customWrite(let readFd, let writeFd): - var readFdCloseError: Error? - var writeFdCloseError: Error? - do { - try readFd?.close() - } catch { - readFdCloseError = error - } - do { - try writeFd?.close() - } catch { - writeFdCloseError = error - } - $0 = .customWrite(nil, nil) - if let readFdCloseError { - throw readFdCloseError - } - if let writeFdCloseError { - throw writeFdCloseError - } - case .fileDescriptor(let fd, let closeWhenDone): - try fd?.close() - $0 = .fileDescriptor(nil, closeWhenDone) - } - } - } - } - - internal final class ExecutionOutput: Sendable { - internal enum Storage: Sendable { - case discarded(FileDescriptor?) - case fileDescriptor(FileDescriptor?, Bool) - case collected(Int, FileDescriptor?, FileDescriptor?) - } - - private let storage: LockedState - - internal init(storage: Storage) { - self.storage = .init(initialState: storage) - } - - internal func getWriteFileDescriptor() -> FileDescriptor? { - return self.storage.withLock { - switch $0 { - case .discarded(let writeFd): - return writeFd - case .fileDescriptor(let writeFd, _): - return writeFd - case .collected(_, _, let writeFd): - return writeFd - } - } - } - - internal func getReadFileDescriptor() -> FileDescriptor? { - return self.storage.withLock { - switch $0 { - case .discarded(_), .fileDescriptor(_, _): - return nil - case .collected(_, let readFd, _): - return readFd - } - } - } - - internal func consumeCollectedFileDescriptor() -> (limit: Int, fd: FileDescriptor?)? { - return self.storage.withLock { - switch $0 { - case .discarded(_), .fileDescriptor(_, _): - // The output has been written somewhere else - return nil - case .collected(let limit, let readFd, let writeFd): - $0 = .collected(limit, nil, writeFd) - return (limit, readFd) - } - } - } - - internal func closeChildSide() throws { - try self.storage.withLock { - switch $0 { - case .discarded(let writeFd): - try writeFd?.close() - $0 = .discarded(nil) - case .fileDescriptor(let fd, let closeWhenDone): - // User passed fd - if closeWhenDone { - try fd?.close() - $0 = .fileDescriptor(nil, closeWhenDone) - } - case .collected(let limit, let readFd, let writeFd): - try writeFd?.close() - $0 = .collected(limit, readFd, nil) - } - } - } - - internal func closeParentSide() throws { - try self.storage.withLock { - switch $0 { - case .discarded(_), .fileDescriptor(_, _): - break - case .collected(let limit, let readFd, let writeFd): - try readFd?.close() - $0 = .collected(limit, nil, writeFd) - } - } - } - - internal func closeAll() throws { - try self.storage.withLock { - switch $0 { - case .discarded(let writeFd): - try writeFd?.close() - $0 = .discarded(nil) - case .fileDescriptor(let fd, let closeWhenDone): - try fd?.close() - $0 = .fileDescriptor(nil, closeWhenDone) - case .collected(let limit, let readFd, let writeFd): - var readFdCloseError: Error? - var writeFdCloseError: Error? - do { - try readFd?.close() - } catch { - readFdCloseError = error - } - do { - try writeFd?.close() - } catch { - writeFdCloseError = error - } - $0 = .collected(limit, nil, nil) - if let readFdCloseError { - throw readFdCloseError - } - if let writeFdCloseError { - throw writeFdCloseError - } - } - } - } - } -} - -// MARK: - Private Helpers -extension FileDescriptor { - internal func read(upToLength maxLength: Int) async throws -> [UInt8] { - return try await withCheckedThrowingContinuation { continuation in - DispatchIO.read( - fromFileDescriptor: self.rawValue, - maxLength: maxLength, - runningHandlerOn: .main - ) { data, error in - guard error == 0 else { - continuation.resume( - throwing: POSIXError( - .init(rawValue: error) ?? .ENODEV - ) - ) - return - } - continuation.resume(returning: Array(data)) - } - } - } - - internal func write(_ data: S) async throws where S.Element == UInt8 { - try await withCheckedThrowingContinuation { (continuation: CheckedContinuation) -> Void in - let dispatchData: DispatchData = Array(data).withUnsafeBytes { - return DispatchData(bytes: $0) - } - DispatchIO.write( - toFileDescriptor: self.rawValue, - data: dispatchData, - runningHandlerOn: .main - ) { _, error in - guard error == 0 else { - continuation.resume( - throwing: POSIXError( - .init(rawValue: error) ?? .ENODEV - ) - ) - return - } - continuation.resume() - } - } - } -} diff --git a/Sources/_Subprocess/Subprocess.swift b/Sources/_Subprocess/Subprocess.swift deleted file mode 100644 index fe61ba81..00000000 --- a/Sources/_Subprocess/Subprocess.swift +++ /dev/null @@ -1,233 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// -//===----------------------------------------------------------------------===// - -import Foundation -import SystemPackage - -/// An object that represents a subprocess of the current process. -/// -/// Using `Subprocess`, your program can run another program as a subprocess -/// and can monitor that program’s execution. A `Subprocess` object creates a -/// **separate executable** entity; it’s different from `Thread` because it doesn’t -/// share memory space with the process that creates it. -public struct Subprocess: Sendable { - /// The process identifier of the current subprocess - public let processIdentifier: ProcessIdentifier - - internal let executionInput: ExecutionInput - internal let executionOutput: ExecutionOutput - internal let executionError: ExecutionOutput - internal var extracted: Bool = false - - internal init( - processIdentifier: ProcessIdentifier, - executionInput: ExecutionInput, - executionOutput: ExecutionOutput, - executionError: ExecutionOutput - ) { - self.processIdentifier = processIdentifier - self.executionInput = executionInput - self.executionOutput = executionOutput - self.executionError = executionError - } - - /// The standard output of the subprocess. - /// Accessing this property will **fatalError** if - /// - `.output` wasn't set to `.redirectToSequence` when the subprocess was spawned; - /// - This property was accessed multiple times. Subprocess communicates with - /// parent process via pipe under the hood and each pipe can only be consumed ones. - public var standardOutput: some _AsyncSequence { - guard - let (_, fd) = self.executionOutput - .consumeCollectedFileDescriptor() - else { - fatalError("The standard output was not redirected") - } - guard let fd = fd else { - fatalError("The standard output has already been closed") - } - return AsyncBytes(fileDescriptor: fd) - } - - /// The standard error of the subprocess. - /// Accessing this property will **fatalError** if - /// - `.error` wasn't set to `.redirectToSequence` when the subprocess was spawned; - /// - This property was accessed multiple times. Subprocess communicates with - /// parent process via pipe under the hood and each pipe can only be consumed ones. - public var standardError: some _AsyncSequence { - guard - let (_, fd) = self.executionError - .consumeCollectedFileDescriptor() - else { - fatalError("The standard error was not redirected") - } - guard let fd = fd else { - fatalError("The standard error has already been closed") - } - return AsyncBytes(fileDescriptor: fd) - } -} - -// MARK: - StandardInputWriter -extension Subprocess { - @_nonSendable - public struct StandardInputWriter { - - private let input: ExecutionInput - - init(input: ExecutionInput) { - self.input = input - } - - public func write(_ sequence: S) async throws where S: Sequence, S.Element == UInt8 { - guard let fd: FileDescriptor = self.input.getWriteFileDescriptor() else { - fatalError("Attempting to write to a file descriptor that's already closed") - } - try await fd.write(sequence) - } - - public func write(_ sequence: S) async throws where S: Sequence, S.Element == CChar { - try await self.write(sequence.map { UInt8($0) }) - } - - public func write(_ asyncSequence: S) async throws where S.Element == CChar { - let sequence = try await Array(asyncSequence).map { UInt8($0) } - try await self.write(sequence) - } - - public func write(_ asyncSequence: S) async throws where S.Element == UInt8 { - let sequence = try await Array(asyncSequence) - try await self.write(sequence) - } - - public func finish() async throws { - try self.input.closeParentSide() - } - } -} - -// MARK: - Result -extension Subprocess { - public struct ExecutionResult: Sendable { - public let terminationStatus: TerminationStatus - public let value: T - - internal init(terminationStatus: TerminationStatus, value: T) { - self.terminationStatus = terminationStatus - self.value = value - } - } - - public struct CollectedResult: Sendable, Hashable { - public let processIdentifier: ProcessIdentifier - public let terminationStatus: TerminationStatus - private let _standardOutput: Data? - private let _standardError: Data? - public var standardOutput: Data { - guard let output = self._standardOutput else { - fatalError("standardOutput is only available if the Subprocess was ran with .collect as output") - } - return output - } - public var standardError: Data { - guard let output = self._standardError else { - fatalError("standardError is only available if the Subprocess was ran with .collect as error ") - } - return output - } - - internal init( - processIdentifier: ProcessIdentifier, - terminationStatus: TerminationStatus, - standardOutput: Data?, - standardError: Data? - ) { - self.processIdentifier = processIdentifier - self.terminationStatus = terminationStatus - self._standardOutput = standardOutput - self._standardError = standardError - } - } -} - -extension Subprocess.ExecutionResult: Equatable where T: Equatable {} - -extension Subprocess.ExecutionResult: Hashable where T: Hashable {} - -extension Subprocess.ExecutionResult: Codable where T: Codable {} - -// MARK: Internal -extension Subprocess { - internal enum OutputCapturingState { - case standardOutputCaptured(Data?) - case standardErrorCaptured(Data?) - } - - private func capture(fileDescriptor: FileDescriptor, maxLength: Int) async throws -> Data { - let chunkSize: Int = min(Subprocess.readBufferSize, maxLength) - var buffer: [UInt8] = [] - while buffer.count <= maxLength { - let captured = try await fileDescriptor.read(upToLength: chunkSize) - buffer += captured - if captured.count < chunkSize { - break - } - } - return Data(buffer) - } - - internal func captureStandardOutput() async throws -> Data? { - guard - let (limit, readFd) = self.executionOutput - .consumeCollectedFileDescriptor(), - let readFd = readFd - else { - return nil - } - return try await self.capture(fileDescriptor: readFd, maxLength: limit) - } - - internal func captureStandardError() async throws -> Data? { - guard - let (limit, readFd) = self.executionError - .consumeCollectedFileDescriptor(), - let readFd = readFd - else { - return nil - } - return try await self.capture(fileDescriptor: readFd, maxLength: limit) - } - - internal func captureIOs() async throws -> (standardOut: Data?, standardError: Data?) { - return try await withThrowingTaskGroup(of: OutputCapturingState.self) { group in - group.addTask { - let stdout = try await self.captureStandardOutput() - return .standardOutputCaptured(stdout) - } - group.addTask { - let stderr = try await self.captureStandardError() - return .standardErrorCaptured(stderr) - } - - var stdout: Data? - var stderror: Data? - while let state = try await group.next() { - switch state { - case .standardOutputCaptured(let output): - stdout = output - case .standardErrorCaptured(let error): - stderror = error - } - } - return (standardOut: stdout, standardError: stderror) - } - } -} diff --git a/Sources/_Subprocess/_LockedState.swift b/Sources/_Subprocess/_LockedState.swift deleted file mode 100644 index da17ccf5..00000000 --- a/Sources/_Subprocess/_LockedState.swift +++ /dev/null @@ -1,159 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2022 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// -//===----------------------------------------------------------------------===// - -#if canImport(os) -internal import os -#if FOUNDATION_FRAMEWORK && canImport(C.os.lock) -internal import C.os.lock -#endif -#elseif canImport(Bionic) -import Bionic -#elseif canImport(Glibc) -import Glibc -#elseif canImport(Musl) -import Musl -#elseif canImport(WinSDK) -import WinSDK -#endif - -package struct LockedState { - - // Internal implementation for a cheap lock to aid sharing code across platforms - private struct _Lock { - #if canImport(os) - typealias Primitive = os_unfair_lock - #elseif canImport(Bionic) || canImport(Glibc) || canImport(Musl) - typealias Primitive = pthread_mutex_t - #elseif canImport(WinSDK) - typealias Primitive = SRWLOCK - #elseif os(WASI) - // WASI is single-threaded, so we don't need a lock. - typealias Primitive = Void - #endif - - typealias PlatformLock = UnsafeMutablePointer - var _platformLock: PlatformLock - - fileprivate static func initialize(_ platformLock: PlatformLock) { - #if canImport(os) - platformLock.initialize(to: os_unfair_lock()) - #elseif canImport(Bionic) || canImport(Glibc) - pthread_mutex_init(platformLock, nil) - #elseif canImport(WinSDK) - InitializeSRWLock(platformLock) - #elseif os(WASI) - // no-op - #endif - } - - fileprivate static func deinitialize(_ platformLock: PlatformLock) { - #if canImport(Bionic) || canImport(Glibc) - pthread_mutex_destroy(platformLock) - #endif - platformLock.deinitialize(count: 1) - } - - static fileprivate func lock(_ platformLock: PlatformLock) { - #if canImport(os) - os_unfair_lock_lock(platformLock) - #elseif canImport(Bionic) || canImport(Glibc) - pthread_mutex_lock(platformLock) - #elseif canImport(WinSDK) - AcquireSRWLockExclusive(platformLock) - #elseif os(WASI) - // no-op - #endif - } - - static fileprivate func unlock(_ platformLock: PlatformLock) { - #if canImport(os) - os_unfair_lock_unlock(platformLock) - #elseif canImport(Bionic) || canImport(Glibc) - pthread_mutex_unlock(platformLock) - #elseif canImport(WinSDK) - ReleaseSRWLockExclusive(platformLock) - #elseif os(WASI) - // no-op - #endif - } - } - - private class _Buffer: ManagedBuffer { - deinit { - withUnsafeMutablePointerToElements { - _Lock.deinitialize($0) - } - } - } - - private let _buffer: ManagedBuffer - - package init(initialState: State) { - _buffer = _Buffer.create( - minimumCapacity: 1, - makingHeaderWith: { buf in - buf.withUnsafeMutablePointerToElements { - _Lock.initialize($0) - } - return initialState - } - ) - } - - package func withLock(_ body: @Sendable (inout State) throws -> T) rethrows -> T { - try withLockUnchecked(body) - } - - package func withLockUnchecked(_ body: (inout State) throws -> T) rethrows -> T { - try _buffer.withUnsafeMutablePointers { state, lock in - _Lock.lock(lock) - defer { _Lock.unlock(lock) } - return try body(&state.pointee) - } - } - - // Ensures the managed state outlives the locked scope. - package func withLockExtendingLifetimeOfState(_ body: @Sendable (inout State) throws -> T) rethrows -> T { - try _buffer.withUnsafeMutablePointers { state, lock in - _Lock.lock(lock) - return try withExtendedLifetime(state.pointee) { - defer { _Lock.unlock(lock) } - return try body(&state.pointee) - } - } - } -} - -extension LockedState where State == Void { - package init() { - self.init(initialState: ()) - } - - package func withLock(_ body: @Sendable () throws -> R) rethrows -> R { - return try withLock { _ in - try body() - } - } - - package func lock() { - _buffer.withUnsafeMutablePointerToElements { lock in - _Lock.lock(lock) - } - } - - package func unlock() { - _buffer.withUnsafeMutablePointerToElements { lock in - _Lock.unlock(lock) - } - } -} - -extension LockedState: @unchecked Sendable where State: Sendable {} diff --git a/Sources/_SubprocessCShims/CMakeLists.txt b/Sources/_SubprocessCShims/CMakeLists.txt deleted file mode 100644 index c078c834..00000000 --- a/Sources/_SubprocessCShims/CMakeLists.txt +++ /dev/null @@ -1,51 +0,0 @@ -##===----------------------------------------------------------------------===## -## -## This source file is part of the Swift.org open source project -## -## Copyright (c) 2024 Apple Inc. and the Swift.org project authors -## Licensed under Apache License v2.0 -## -## See LICENSE.txt for license information -## See CONTRIBUTORS.md for the list of Swift project authors -## -## SPDX-License-Identifier: Apache-2.0 -## -##===----------------------------------------------------------------------===## - -add_library(_SubprocessCShims STATIC - platform_shims.c -# string_shims.c - process_shims.c -# uuid.c -) - -target_include_directories(_SubprocessCShims PUBLIC include) - -set_property(GLOBAL APPEND PROPERTY SWIFT_FOUNDATION_EXPORTS _SubprocessCShims) - -if(BUILD_SHARED_LIBS) - set(install_directory swift) -else() - set(install_directory swift_static) -endif() - -# Copy Headers to known directory for direct client (XCTest) test builds -#file(COPY -# include/ -# DESTINATION -# ${CMAKE_BINARY_DIR}/_CModulesForClients/_SubprocessCShims) - -# Install headers -install(DIRECTORY - include/ - DESTINATION - lib/${install_directory}/_SubprocessCShims) - -if(NOT BUILD_SHARED_LIBS) - get_swift_host_os(swift_os) - install(TARGETS _SubprocessCShims - ARCHIVE DESTINATION lib/${install_directory}/${swift_os} - LIBRARY DESTINATION lib/${install_directory}/${swift_os} - RUNTIME DESTINATION bin) -endif() - diff --git a/Sources/_SubprocessCShims/include/CFUniCharBitmapData.h b/Sources/_SubprocessCShims/include/CFUniCharBitmapData.h deleted file mode 100644 index fd6a92f2..00000000 --- a/Sources/_SubprocessCShims/include/CFUniCharBitmapData.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - CFUniCharBitmapData.h - Copyright (c) 1999-2021, Apple Inc. and the Swift.org project authors. All rights reserved. - This file is generated. Don't touch this file directly. -*/ - -#ifndef _cfunichar_bitmap_data_h -#define _cfunichar_bitmap_data_h - -#include "_CStdlib.h" - -typedef struct { - uint32_t _numPlanes; - uint8_t const * const * const _planes; -} __CFUniCharBitmapData; - -#endif /* _cfunichar_bitmap_data_h */ diff --git a/Sources/_SubprocessCShims/include/CFUniCharBitmapData.inc.h b/Sources/_SubprocessCShims/include/CFUniCharBitmapData.inc.h deleted file mode 100644 index 886508a3..00000000 --- a/Sources/_SubprocessCShims/include/CFUniCharBitmapData.inc.h +++ /dev/null @@ -1,14707 +0,0 @@ -/* - CFUniCharBitmapData.inc.h - Copyright (c) 1999-2021, Apple Inc. and the Swift.org project authors. All rights reserved. - This file is generated. Don't touch this file directly. -*/ -#include "CFUniCharBitmapData.h" - -#include "_CStdlib.h" - -static uint8_t const __CFUniCharLetterCharacterSetBitmapPlane0[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0x07, 0xFE, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x20, 0x04, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC3, 0xFF, 0x03, 0x00, 0x1F, 0x50, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xBC, 0x40, 0xD7, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0x7F, 0x02, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xB6, 0x00, 0xFF, 0xFF, 0xFF, 0x87, 0x07, 0x00, - 0x00, 0x00, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0x9F, 0xFF, 0xFD, 0x00, 0x9C, - 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x24, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0x7E, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0xFE, 0xFF, 0xEF, 0x9F, 0xF9, 0xFF, 0xFF, 0xFD, 0xC5, 0xF3, 0x9F, 0x79, 0x80, 0xB0, 0x0F, 0x00, 0x03, 0x50, - 0xEE, 0x87, 0xF9, 0xFF, 0xFF, 0xFD, 0x6D, 0xD3, 0x87, 0x39, 0x02, 0x5E, 0x00, 0x00, 0x3F, 0x00, 0xEE, 0xBF, 0xFB, 0xFF, 0xFF, 0xFD, 0xED, 0xF3, 0xBF, 0x3B, 0x01, 0x00, 0x0F, 0x00, 0x00, 0xFE, - 0xEE, 0x9F, 0xF9, 0xFF, 0xFF, 0xFD, 0xED, 0xF3, 0x9F, 0x39, 0xE0, 0xB0, 0x0F, 0x00, 0x02, 0x00, 0xEC, 0xC7, 0x3D, 0xD6, 0x18, 0xC7, 0xFF, 0xC3, 0xC7, 0x3D, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xDF, 0xFD, 0xFF, 0xFF, 0xFD, 0xFF, 0xF3, 0xDF, 0x3D, 0x60, 0x27, 0x0F, 0x00, 0x00, 0x00, 0xEF, 0xDF, 0xFD, 0xFF, 0xFF, 0xFD, 0xEF, 0xF3, 0xDF, 0x3D, 0x60, 0x60, 0x0F, 0x00, 0x0E, 0x00, - 0xFF, 0xDF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0x7D, 0xF0, 0x80, 0x0F, 0x00, 0x00, 0xFC, 0xEE, 0xFF, 0x7F, 0xFC, 0xFF, 0xFF, 0xFB, 0x2F, 0x7F, 0x84, 0x5F, 0xFF, 0x00, 0x00, 0x0C, 0x00, - 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD6, 0xF7, 0xFF, 0xFF, 0xAF, 0xFF, 0xFF, 0x3F, 0x5F, 0x7F, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0xA0, 0xC2, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0x1F, 0xFE, 0xFF, 0xDF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0x1F, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x3C, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0x20, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3D, 0x7F, 0x3D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3D, 0xFF, 0xFF, 0xFF, 0xFF, 0x3D, 0x7F, 0x3D, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0x3D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x3F, - 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9F, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFE, 0x01, - 0xFF, 0xFF, 0x3F, 0x80, 0xFF, 0xFF, 0x1F, 0x00, 0xFF, 0xFF, 0x0F, 0x00, 0xFF, 0xDF, 0x0D, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8F, 0x30, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xB8, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, - 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x3F, 0x1F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0x9F, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0xF8, 0x0F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xE0, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0x00, 0x00, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0x3F, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x3F, 0xFF, 0xAA, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0x5F, 0xDC, 0x1F, 0xCF, 0x0F, 0xFF, 0x1F, 0xDC, 0x1F, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x80, 0x00, 0x00, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, - 0x84, 0xFC, 0x2F, 0x3E, 0x50, 0xBD, 0xFF, 0xF3, 0xE0, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xF8, 0x0F, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0x20, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x80, 0xFF, 0xFF, 0x7F, 0x00, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x60, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x3E, 0x18, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xE6, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, - 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0x1F, 0xFF, 0xFF, 0x00, 0x0C, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x03, 0x00, - 0x00, 0x00, 0x80, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xEB, 0x03, 0x00, 0x00, 0xFC, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x10, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xE8, - 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x80, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x7C, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0xFF, 0x3F, 0x00, 0x00, 0xFF, 0xFF, 0x7F, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x38, 0xFF, 0xFF, 0x7C, 0x00, - 0x7E, 0x7E, 0x7E, 0x00, 0x7F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x37, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0xFF, 0xFF, 0x7F, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, - 0x7F, 0x00, 0xF8, 0xE0, 0xFF, 0xFD, 0x7F, 0x5F, 0xDB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x0F, - 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, - 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0x07, 0xFE, 0xFF, 0xFF, 0x07, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFC, 0xFC, 0xFC, 0x1C, 0x00, 0x00, 0x00, 0x00, -}; -static uint8_t const __CFUniCharLetterCharacterSetBitmapPlane1[] = { - 0xFF, 0xEF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xB7, 0xFF, 0x3F, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xE0, 0xFF, 0xFF, 0xFD, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0xFF, 0xF7, 0xFF, 0xF7, 0xB7, 0xFF, 0xFB, 0xFF, 0xFB, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0xFF, 0xFF, 0x3F, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x3F, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0x91, 0xFF, 0xFF, 0x3F, 0x00, 0xFF, 0xFF, 0x7F, 0x00, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x37, 0x00, - 0xFF, 0xFF, 0x3F, 0x00, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x6F, 0xF0, 0xEF, 0xFE, 0xFF, 0xFF, 0x3F, 0x87, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFE, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0xFF, 0xFF, 0x3F, 0x00, 0xFF, 0xFF, 0x07, 0x00, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1B, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, - 0xFF, 0xFF, 0xFF, 0x1F, 0x80, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x7F, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x04, 0x00, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x4F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xDE, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xBD, 0xFF, 0xBF, 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00, - 0xEF, 0x9F, 0xF9, 0xFF, 0xFF, 0xFD, 0xED, 0xFB, 0x9F, 0x39, 0x81, 0xE0, 0xCF, 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0xC0, 0x03, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0x01, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xE7, 0xFF, 0x0F, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x80, - 0x7F, 0xF2, 0x6F, 0xFF, 0xFF, 0xFF, 0xBF, 0xF9, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x1B, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x80, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x23, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFE, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7F, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xB4, 0xFF, 0x00, 0x00, 0x00, 0xBF, 0xFD, 0xFF, 0xFF, 0xFF, 0x7F, 0xFB, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x7F, 0x00, - 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xC7, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x3F, 0x1F, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x0F, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x87, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x03, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEF, 0x6F, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x04, 0x00, 0x00, 0x00, 0x27, 0x00, 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0x1F, 0xFF, 0x01, 0xFF, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xE3, 0x07, 0xF8, 0xE7, 0x0F, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0x64, 0xDE, 0xFF, 0xEB, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xBF, 0xE7, 0xDF, 0xDF, 0xFF, 0xFF, 0xFF, 0x7B, 0x5F, 0xFC, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xF7, 0xFF, 0xFF, 0xFF, 0xF7, - 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xF7, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x20, 0x00, 0x10, 0x00, 0x00, 0xF8, 0xFE, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0x7F, 0xE0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7F, 0xFF, 0xFF, 0xF9, 0xDB, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0x3F, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x6F, 0xFF, 0x7F, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xEF, 0xFF, 0xFF, 0xFF, 0x96, 0xFE, 0xF7, 0x0A, 0x84, 0xEA, 0x96, 0xAA, 0x96, 0xF7, 0xF7, 0x5E, 0xFF, 0xFB, 0xFF, 0x0F, 0xEE, 0xFB, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; -static uint8_t const __CFUniCharLetterCharacterSetBitmapPlane2[] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; -static uint8_t const __CFUniCharLetterCharacterSetBitmapPlane3[] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; -static uint8_t const __CFUniCharLetterCharacterSetBitmapPlane14[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; -static uint8_t const * const __CFUniCharLetterCharacterSetBitmap[] = { - (uint8_t const * const)&__CFUniCharLetterCharacterSetBitmapPlane0, - (uint8_t const * const)&__CFUniCharLetterCharacterSetBitmapPlane1, - (uint8_t const * const)&__CFUniCharLetterCharacterSetBitmapPlane2, - (uint8_t const * const)&__CFUniCharLetterCharacterSetBitmapPlane3, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)&__CFUniCharLetterCharacterSetBitmapPlane14, -}; - -static uint32_t const __CFUniCharLetterCharacterSetBitmapPlaneCount = 15; -static uint8_t const __CFUniCharDecimalDigitCharacterSetBitmapPlane0[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03, 0x00, 0x00, - 0x00, 0x00, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03, 0x00, 0x00, 0xFF, 0x03, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; -static uint8_t const __CFUniCharDecimalDigitCharacterSetBitmapPlane1[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; -static uint8_t const * const __CFUniCharDecimalDigitCharacterSetBitmap[] = { - (uint8_t const * const)&__CFUniCharDecimalDigitCharacterSetBitmapPlane0, - (uint8_t const * const)&__CFUniCharDecimalDigitCharacterSetBitmapPlane1, -}; - -static uint32_t const __CFUniCharDecimalDigitCharacterSetBitmapPlaneCount = 2; -static uint8_t const __CFUniCharLowercaseLetterCharacterSetBitmapPlane0[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x7F, 0xFF, - 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0xAB, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xD4, 0x29, 0x31, 0x24, 0x4E, 0x2A, 0x2D, 0x51, 0xE6, 0x40, 0x52, 0x55, 0xB5, 0xAA, 0xAA, 0x29, 0xAA, - 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xFA, 0x93, 0x85, 0xAA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8A, 0x38, 0x00, 0x00, 0x01, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0xFF, 0x7F, 0xE3, 0xAA, 0xAA, 0xAA, 0x2F, 0x19, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAA, 0xAA, 0xAA, 0xAA, 0x02, 0xA8, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x54, 0xD5, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, - 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xEA, 0xBF, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, - 0xFF, 0x00, 0x3F, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x3F, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x3F, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xDF, 0x40, 0xDC, 0x00, 0xCF, 0x00, 0xFF, 0x00, 0xDC, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xC4, 0x08, 0x00, 0x00, 0x80, 0x10, 0x32, 0xC0, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x62, 0x15, 0xDA, 0x0F, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x1A, 0x50, 0x08, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x2A, 0x00, 0x00, 0xAA, 0xAA, 0xAA, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xA8, 0xAA, 0xAB, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xFE, 0x95, 0xAA, 0x50, 0xBA, 0xAA, 0xAA, 0x82, 0xA0, 0xAA, 0x0A, 0x05, 0xAA, 0x02, 0x00, 0x00, 0x40, 0x04, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7F, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; -static uint8_t const __CFUniCharLowercaseLetterCharacterSetBitmapPlane1[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFB, 0xFF, 0xFB, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0xC0, 0xDF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0xC0, 0xEB, 0xEF, 0xFF, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, - 0x0F, 0x00, 0x00, 0xC0, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0xC0, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0xC0, 0xFF, 0xFF, - 0xFF, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0xC0, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xF7, 0x03, 0x00, 0x00, 0xF0, - 0xFF, 0xFF, 0xDF, 0x0F, 0x00, 0x00, 0xC0, 0xFF, 0xFF, 0x7F, 0x3F, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFD, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xF7, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFB, 0xFF, 0x7F, 0xE0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; -static uint8_t const * const __CFUniCharLowercaseLetterCharacterSetBitmap[] = { - (uint8_t const * const)&__CFUniCharLowercaseLetterCharacterSetBitmapPlane0, - (uint8_t const * const)&__CFUniCharLowercaseLetterCharacterSetBitmapPlane1, -}; - -static uint32_t const __CFUniCharLowercaseLetterCharacterSetBitmapPlaneCount = 2; -static uint8_t const __CFUniCharUppercaseLetterCharacterSetBitmapPlane0[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x7F, 0x7F, 0x00, 0x00, 0x00, 0x00, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0x54, 0x55, 0x55, 0x55, 0x55, 0x55, 0x2B, 0xD6, 0xCE, 0xDB, 0xB1, 0xD5, 0xD2, 0xAE, 0x11, 0xB0, 0xAD, 0xAA, 0x4A, 0x55, 0x55, 0xD6, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x05, 0x6C, 0x7A, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x80, 0x40, 0xD7, 0xFE, 0xFF, 0xFB, 0x0F, 0x00, 0x00, 0x00, 0x80, 0x1C, 0x55, 0x55, 0x55, 0x90, 0xE6, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55, 0x01, 0x54, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xAB, 0x2A, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xFE, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x15, 0x40, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x00, 0xFF, 0x00, 0x3F, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x3F, 0x00, 0xAA, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x1F, 0x00, 0x1F, 0x00, 0x0F, 0x00, 0x1F, 0x00, 0x1F, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x84, 0x38, 0x27, 0x3E, 0x50, 0x3D, 0x0F, 0xC0, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9D, 0xEA, 0x25, 0xC0, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x05, 0x28, 0x04, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55, 0x55, 0x15, 0x00, 0x00, 0x55, 0x55, 0x55, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x54, 0x55, 0x54, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x00, 0x6A, 0x55, 0x28, 0x45, 0x55, 0x55, 0x7D, 0x5F, 0x55, 0xF5, 0x02, 0x41, 0x01, 0x00, 0x00, 0x20, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; -static uint8_t const __CFUniCharUppercaseLetterCharacterSetBitmapPlane1[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xF7, 0xFF, 0xF7, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0xD0, 0x64, 0xDE, 0x3F, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, - 0xB0, 0xE7, 0xDF, 0x1F, 0x00, 0x00, 0x00, 0x7B, 0x5F, 0xFC, 0x01, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0x3F, 0x00, 0x00, - 0x00, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x07, - 0x00, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; -static uint8_t const * const __CFUniCharUppercaseLetterCharacterSetBitmap[] = { - (uint8_t const * const)&__CFUniCharUppercaseLetterCharacterSetBitmapPlane0, - (uint8_t const * const)&__CFUniCharUppercaseLetterCharacterSetBitmapPlane1, -}; - -static uint32_t const __CFUniCharUppercaseLetterCharacterSetBitmapPlaneCount = 2; -static uint8_t const __CFUniCharTitlecaseLetterCharacterSetBitmapPlane0[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x09, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; -static uint8_t const * const __CFUniCharTitlecaseLetterCharacterSetBitmap[] = { - (uint8_t const * const)&__CFUniCharTitlecaseLetterCharacterSetBitmapPlane0, -}; - -static uint32_t const __CFUniCharTitlecaseLetterCharacterSetBitmapPlaneCount = 1; -static uint8_t const __CFUniCharAlphanumericCharacterSetBitmapPlane0[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03, 0xFE, 0xFF, 0xFF, 0x07, 0xFE, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x2C, 0x76, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC3, 0xFF, 0x03, 0x00, 0x1F, 0x50, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xBC, 0x40, 0xD7, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0x7F, 0x02, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xB6, 0x00, 0xFF, 0xFF, 0xFF, 0x87, 0x07, 0x00, - 0x00, 0x00, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0x9F, 0xFF, 0xFD, 0xFF, 0x9F, - 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x24, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0x7E, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCF, 0xFF, 0xFE, 0xFF, 0xEF, 0x9F, 0xF9, 0xFF, 0xFF, 0xFD, 0xC5, 0xF3, 0x9F, 0x79, 0x80, 0xB0, 0xCF, 0xFF, 0xF3, 0x53, - 0xEE, 0x87, 0xF9, 0xFF, 0xFF, 0xFD, 0x6D, 0xD3, 0x87, 0x39, 0x02, 0x5E, 0xC0, 0xFF, 0x3F, 0x00, 0xEE, 0xBF, 0xFB, 0xFF, 0xFF, 0xFD, 0xED, 0xF3, 0xBF, 0x3B, 0x01, 0x00, 0xCF, 0xFF, 0x00, 0xFE, - 0xEE, 0x9F, 0xF9, 0xFF, 0xFF, 0xFD, 0xED, 0xF3, 0x9F, 0x39, 0xE0, 0xB0, 0xCF, 0xFF, 0xFE, 0x00, 0xEC, 0xC7, 0x3D, 0xD6, 0x18, 0xC7, 0xFF, 0xC3, 0xC7, 0x3D, 0x81, 0x00, 0xC0, 0xFF, 0x07, 0x00, - 0xFF, 0xDF, 0xFD, 0xFF, 0xFF, 0xFD, 0xFF, 0xF3, 0xDF, 0x3D, 0x60, 0x27, 0xCF, 0xFF, 0x00, 0x7F, 0xEF, 0xDF, 0xFD, 0xFF, 0xFF, 0xFD, 0xEF, 0xF3, 0xDF, 0x3D, 0x60, 0x60, 0xCF, 0xFF, 0x0E, 0x00, - 0xFF, 0xDF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0x7D, 0xF0, 0xFF, 0xCF, 0xFF, 0xFF, 0xFD, 0xEE, 0xFF, 0x7F, 0xFC, 0xFF, 0xFF, 0xFB, 0x2F, 0x7F, 0x84, 0x5F, 0xFF, 0xC0, 0xFF, 0x0C, 0x00, - 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0x7F, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0xD6, 0xF7, 0xFF, 0xFF, 0xAF, 0xFF, 0xFF, 0x3F, 0x5F, 0x7F, 0xFF, 0xF3, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0xAF, 0xC2, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0x1F, 0xFE, 0xFF, 0xDF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0x1F, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0x20, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3D, 0x7F, 0x3D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3D, 0xFF, 0xFF, 0xFF, 0xFF, 0x3D, 0x7F, 0x3D, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0x3D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0x00, 0xFE, 0xFF, 0x1F, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x3F, - 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9F, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC7, 0xFF, 0x01, - 0xFF, 0xFF, 0x3F, 0x80, 0xFF, 0xFF, 0x1F, 0x00, 0xFF, 0xFF, 0x0F, 0x00, 0xFF, 0xDF, 0x0D, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8F, 0x30, 0xFF, 0x03, 0xFF, 0x03, - 0x00, 0xB8, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, - 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0x0F, 0xFF, 0x0F, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x1F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0x03, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0x9F, 0xFF, 0x03, 0xFF, 0x03, 0x80, 0x00, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0x03, 0x00, 0xF8, 0x0F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xE3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0x00, 0x00, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0x3F, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x3F, 0xFF, 0xAA, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0x5F, 0xDC, 0x1F, 0xCF, 0x0F, 0xFF, 0x1F, 0xDC, 0x1F, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF3, 0x83, 0xFF, 0x03, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, - 0x84, 0xFC, 0x2F, 0x3E, 0x50, 0xBD, 0xFF, 0xF3, 0xE0, 0x43, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xF8, 0x0F, 0x20, - 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0x20, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x80, 0xFF, 0xFF, 0x7F, 0x00, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xE0, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0x3E, 0x1F, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xE6, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, - 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x3C, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03, 0x00, 0x00, 0x00, 0xFF, 0xFE, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0x1F, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, - 0x00, 0x00, 0x80, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xEB, 0x03, 0x00, 0x00, 0xFC, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x10, 0x3F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0xE8, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x80, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0x7F, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0xFF, 0x3F, 0xFF, 0x03, 0xFF, 0xFF, 0x7F, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x38, 0xFF, 0xFF, 0x7C, 0x00, - 0x7E, 0x7E, 0x7E, 0x00, 0x7F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x37, 0xFF, 0x03, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0xFF, 0xFF, 0x7F, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, - 0x7F, 0x00, 0xF8, 0xE0, 0xFF, 0xFD, 0x7F, 0x5F, 0xDB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x0F, - 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, - 0x00, 0x00, 0xFF, 0x03, 0xFE, 0xFF, 0xFF, 0x07, 0xFE, 0xFF, 0xFF, 0x07, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFC, 0xFC, 0xFC, 0x1C, 0x00, 0x00, 0x00, 0x00, -}; -static uint8_t const __CFUniCharAlphanumericCharacterSetBitmapPlane1[] = { - 0xFF, 0xEF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xB7, 0xFF, 0x3F, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, - 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0xFF, 0xFF, 0xFF, 0x0F, - 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xE0, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0xFF, 0xF7, 0xFF, 0xF7, 0xB7, 0xFF, 0xFB, 0xFF, 0xFB, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0xFF, 0xFF, 0x3F, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x3F, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0x91, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0x7F, 0xFE, 0xFF, 0xFF, 0xFF, 0x7F, 0x80, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x37, 0xF8, - 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x6F, 0xF0, 0xEF, 0xFE, 0xFF, 0xFF, 0x3F, 0x87, 0xFF, 0x01, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFE, 0xFF, 0xFF, 0x7F, 0xF8, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFC, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1B, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0xFF, 0xFF, 0x7F, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x3F, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x04, 0x00, 0xFF, 0xFF, 0xFF, 0x01, 0xFF, 0x03, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x4F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xDE, 0xFF, 0x17, 0xFE, 0xFF, 0x1F, 0x00, - 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xBD, 0xFF, 0xBF, 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0x03, - 0xEF, 0x9F, 0xF9, 0xFF, 0xFF, 0xFD, 0xED, 0xFB, 0x9F, 0x39, 0x81, 0xE0, 0xCF, 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xC3, 0x03, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0x00, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0x01, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x11, 0x00, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xE7, 0xFF, 0x0F, 0xFF, 0x0F, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x80, - 0x7F, 0xF2, 0x6F, 0xFF, 0xFF, 0xFF, 0xBF, 0xF9, 0x0F, 0x00, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x1B, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x80, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x23, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0x01, 0x00, 0xFF, 0xFF, 0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFE, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7F, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xB4, 0xFF, 0x00, 0xFF, 0x03, 0xBF, 0xFD, 0xFF, 0xFF, 0xFF, 0x7F, 0xFB, 0x01, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x7F, 0x00, - 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xC7, 0x07, 0x00, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0x3F, 0x1F, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x0F, 0x00, 0xFF, 0xFB, 0xFB, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x87, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x03, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEF, 0x6F, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x04, 0x00, 0x00, 0x00, 0x27, 0x00, 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0x1F, 0xFF, 0x01, 0xFF, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xE3, 0x07, 0xF8, 0xE7, 0x0F, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x0F, 0x00, 0xFF, 0xFF, 0x0F, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0x64, 0xDE, 0xFF, 0xEB, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xBF, 0xE7, 0xDF, 0xDF, 0xFF, 0xFF, 0xFF, 0x7B, 0x5F, 0xFC, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xF7, 0xFF, 0xFF, 0xFF, 0xF7, - 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xF7, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x20, 0x00, 0x10, 0x00, 0x00, 0xF8, 0xFE, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0x7F, 0xE0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7F, 0xFF, 0xFF, 0xF9, 0xDB, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0x3F, 0xFF, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x6F, 0xFF, 0x7F, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9F, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xEF, 0xFF, 0xFF, 0xFF, 0x96, 0xFE, 0xF7, 0x0A, 0x84, 0xEA, 0x96, 0xAA, 0x96, 0xF7, 0xF7, 0x5E, 0xFF, 0xFB, 0xFF, 0x0F, 0xEE, 0xFB, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; -static uint8_t const __CFUniCharAlphanumericCharacterSetBitmapPlane2[] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; -static uint8_t const __CFUniCharAlphanumericCharacterSetBitmapPlane3[] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; -static uint8_t const __CFUniCharAlphanumericCharacterSetBitmapPlane14[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; -static uint8_t const * const __CFUniCharAlphanumericCharacterSetBitmap[] = { - (uint8_t const * const)&__CFUniCharAlphanumericCharacterSetBitmapPlane0, - (uint8_t const * const)&__CFUniCharAlphanumericCharacterSetBitmapPlane1, - (uint8_t const * const)&__CFUniCharAlphanumericCharacterSetBitmapPlane2, - (uint8_t const * const)&__CFUniCharAlphanumericCharacterSetBitmapPlane3, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)&__CFUniCharAlphanumericCharacterSetBitmapPlane14, -}; - -static uint32_t const __CFUniCharAlphanumericCharacterSetBitmapPlaneCount = 15; -static uint8_t const __CFUniCharLegalCharacterSetBitmapPlane0[] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xF0, 0xD7, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0x7F, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0x87, 0x1F, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0x4F, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0x7F, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0x9F, 0xF9, 0xFF, 0xFF, 0xFD, 0xC5, 0xF3, 0x9F, 0x79, 0x80, 0xB0, 0xCF, 0xFF, 0xFF, 0x7F, - 0xEE, 0x87, 0xF9, 0xFF, 0xFF, 0xFD, 0x6D, 0xD3, 0x87, 0x39, 0x02, 0x5E, 0xC0, 0xFF, 0x7F, 0x00, 0xEE, 0xBF, 0xFB, 0xFF, 0xFF, 0xFD, 0xED, 0xF3, 0xBF, 0x3B, 0x01, 0x00, 0xCF, 0xFF, 0x03, 0xFE, - 0xEE, 0x9F, 0xF9, 0xFF, 0xFF, 0xFD, 0xED, 0xF3, 0x9F, 0x39, 0xE0, 0xB0, 0xCF, 0xFF, 0xFF, 0x00, 0xEC, 0xC7, 0x3D, 0xD6, 0x18, 0xC7, 0xFF, 0xC3, 0xC7, 0x3D, 0x81, 0x00, 0xC0, 0xFF, 0xFF, 0x07, - 0xFF, 0xDF, 0xFD, 0xFF, 0xFF, 0xFD, 0xFF, 0xF3, 0xDF, 0x3D, 0x60, 0x27, 0xCF, 0xFF, 0x80, 0xFF, 0xFF, 0xDF, 0xFD, 0xFF, 0xFF, 0xFD, 0xEF, 0xF3, 0xDF, 0x3D, 0x60, 0x60, 0xCF, 0xFF, 0x0E, 0x00, - 0xFF, 0xDF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFD, 0xF0, 0xFF, 0xCF, 0xFF, 0xFF, 0xFF, 0xEE, 0xFF, 0x7F, 0xFC, 0xFF, 0xFF, 0xFB, 0x2F, 0x7F, 0x84, 0x5F, 0xFF, 0xC0, 0xFF, 0x1C, 0x00, - 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x87, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xD6, 0xF7, 0xFF, 0xFF, 0xAF, 0xFF, 0xFF, 0x3F, 0x5F, 0x7F, 0xFF, 0xF3, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0x1F, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0x20, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3D, 0x7F, 0x3D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3D, 0xFF, 0xFF, 0xFF, 0xFF, 0x3D, 0x7F, 0x3D, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0x3D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0xFF, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x3F, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, - 0xFF, 0xFF, 0x3F, 0x80, 0xFF, 0xFF, 0x7F, 0x00, 0xFF, 0xFF, 0x0F, 0x00, 0xFF, 0xDF, 0x0D, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0x03, 0xFF, 0x03, - 0xFF, 0xFF, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, - 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0x0F, 0xFF, 0x0F, 0xF1, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x1F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0x03, 0xFF, 0xC7, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0x9F, 0xFF, 0x03, 0xFF, 0x03, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xF0, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0xFF, 0xE3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0x3F, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x3F, 0xFF, 0xAA, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xCF, 0xEF, 0xFF, 0xFF, 0xDC, 0x7F, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xF3, 0xFF, 0xFF, 0x7F, 0xFF, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0xFF, 0x07, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCF, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFE, - 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0x20, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x01, 0x80, 0xFF, 0xFF, 0x7F, 0x00, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x80, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xEB, 0x03, 0x00, 0x00, 0xFC, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xC0, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x80, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, 0xC3, 0xFF, 0xFF, 0xFF, 0x7F, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0xFF, 0x3F, 0xFF, 0xF3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x7F, 0x00, - 0x7E, 0x7E, 0x7E, 0x00, 0x7F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0x03, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0xFF, 0xFF, 0x7F, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, - 0x7F, 0x00, 0xF8, 0xE0, 0xFF, 0xFF, 0x7F, 0x5F, 0xDB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0xFF, 0x7F, 0x0F, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9F, - 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFC, 0xFC, 0xFC, 0x1C, 0x7F, 0x7F, 0x00, 0x3E, -}; -static uint8_t const __CFUniCharLegalCharacterSetBitmapPlane1[] = { - 0xFF, 0xEF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xB7, 0xFF, 0x3F, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, - 0x87, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0x1F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0xFF, 0xFF, 0xFF, 0x0F, - 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xE0, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x80, 0xFF, 0xF7, 0xFF, 0xF7, 0xB7, 0xFF, 0xFB, 0xFF, 0xFB, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0xFF, 0xFF, 0x3F, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x3F, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0x91, 0xFF, 0xFF, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x80, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x37, 0xF8, - 0xFF, 0xFF, 0xFF, 0x8F, 0xFF, 0xFF, 0xFF, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x6F, 0xF0, 0xEF, 0xFE, 0xFF, 0xFF, 0x3F, 0x87, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xF8, 0x7F, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFE, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0x03, 0x1E, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFC, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3B, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0xFF, 0xFF, 0x7F, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0xFF, 0x3F, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x20, 0xFF, 0xFF, 0xFF, 0x01, 0xFF, 0x03, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0x1F, 0x00, - 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xBD, 0xFF, 0xBF, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0x03, - 0xEF, 0x9F, 0xF9, 0xFF, 0xFF, 0xFD, 0xED, 0xFB, 0x9F, 0x39, 0x81, 0xE0, 0xCF, 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0x03, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0xFF, 0x03, 0xFF, 0x1F, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xE7, 0xFF, 0x0F, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x80, - 0x7F, 0xF2, 0x6F, 0xFF, 0xFF, 0xFF, 0xBF, 0xF9, 0x7F, 0x00, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x1F, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, - 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0x3F, 0x00, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFE, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7F, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xB4, 0xFF, 0x00, 0xFF, 0x03, 0xBF, 0xFD, 0xFF, 0xFF, 0xFF, 0x7F, 0xFB, 0x01, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x01, - 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xC7, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x80, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x1F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xC3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0x3F, 0x3F, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0xFF, 0xFB, 0xFB, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x87, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x03, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEF, 0x6F, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x04, 0x00, 0x00, 0x00, 0x27, 0x00, 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0x1F, 0xFF, 0x01, 0xFF, 0xF3, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0x7F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x0F, 0x00, 0xFF, 0xFF, 0x0F, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0x64, 0xDE, 0xFF, 0xEB, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xBF, 0xE7, 0xDF, 0xDF, 0xFF, 0xFF, 0xFF, 0x7B, 0x5F, 0xFC, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0xF8, 0xFE, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0x7F, 0xE0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7F, 0xFF, 0xFF, 0xF9, 0xDB, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0x3F, 0xFF, 0xC3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x83, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x6F, 0xFF, 0x7F, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9F, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0xC3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xEF, 0xFF, 0xFF, 0xFF, 0x96, 0xFE, 0xF7, 0x0A, 0x84, 0xEA, 0x96, 0xAA, 0x96, 0xF7, 0xF7, 0x5E, 0xFF, 0xFB, 0xFF, 0x0F, 0xEE, 0xFB, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0xFF, 0x7F, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0xFF, 0xFF, - 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0x01, 0x03, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xFF, 0x1F, 0xFF, 0x1F, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xFF, 0x0F, 0x01, 0x00, - 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0x3F, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0xFF, 0x3F, 0xFF, 0x1F, 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0x3F, 0xC0, 0xFF, 0x0F, 0xFF, 0x01, 0xFF, 0x01, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; -static uint8_t const __CFUniCharLegalCharacterSetBitmapPlane2[] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; -static uint8_t const __CFUniCharLegalCharacterSetBitmapPlane3[] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; -static uint8_t const __CFUniCharLegalCharacterSetBitmapPlane14[] = { - 0x02, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; -static uint8_t const * const __CFUniCharLegalCharacterSetBitmap[] = { - (uint8_t const * const)&__CFUniCharLegalCharacterSetBitmapPlane0, - (uint8_t const * const)&__CFUniCharLegalCharacterSetBitmapPlane1, - (uint8_t const * const)&__CFUniCharLegalCharacterSetBitmapPlane2, - (uint8_t const * const)&__CFUniCharLegalCharacterSetBitmapPlane3, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)&__CFUniCharLegalCharacterSetBitmapPlane14, -}; - -static uint32_t const __CFUniCharLegalCharacterSetBitmapPlaneCount = 15; -static uint8_t const __CFUniCharPunctuationCharacterSetBitmapPlane0[] = { - 0x00, 0x00, 0x00, 0x00, 0xEE, 0xF7, 0x00, 0x8C, 0x01, 0x00, 0x00, 0xB8, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x82, 0x08, 0xC0, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, - 0x00, 0x36, 0x00, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xF0, 0xFF, 0x17, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x06, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x07, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x01, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xEF, 0xFF, 0xFB, 0x7F, 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x0F, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x30, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDE, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0E, 0xFF, 0xF3, 0xFF, 0x00, 0x00, 0x01, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x3F, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xFF, 0x03, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0xFF, 0x0B, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xEE, 0xF7, 0x00, 0x8C, 0x01, 0x00, 0x00, 0xB8, 0x00, 0x00, 0x00, 0xA8, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; -static uint8_t const __CFUniCharPunctuationCharacterSetBitmapPlane1[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x03, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x21, 0x00, 0xE8, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0F, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; -static uint8_t const * const __CFUniCharPunctuationCharacterSetBitmap[] = { - (uint8_t const * const)&__CFUniCharPunctuationCharacterSetBitmapPlane0, - (uint8_t const * const)&__CFUniCharPunctuationCharacterSetBitmapPlane1, -}; - -static uint32_t const __CFUniCharPunctuationCharacterSetBitmapPlaneCount = 2; -static uint8_t const __CFUniCharSymbolAndOperatorCharacterSetBitmapPlane0[] = { - 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x70, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xD3, 0x13, 0x01, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0xFC, 0xFF, 0xE0, 0xAF, 0xFF, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xC0, 0xC9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x02, 0x00, 0x60, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xC0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x07, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0E, 0x00, 0xE8, 0xFC, 0x00, 0x00, 0x50, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xBF, 0xDF, 0xE0, 0x01, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x07, 0xF0, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA0, 0x03, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0x60, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7B, 0x03, 0xD0, 0xC1, 0xAF, 0x42, 0x00, 0x0C, 0x1F, 0xBC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xF0, 0xFF, 0xFF, 0xFF, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9F, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0xFF, 0xCF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCF, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x07, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0xFF, 0xFF, - 0x10, 0x00, 0x0C, 0x00, 0x01, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC3, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x80, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x00, 0x01, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0x7F, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xC0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x10, 0x08, 0x00, 0x70, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x7F, 0x00, 0x30, -}; -static uint8_t const __CFUniCharSymbolAndOperatorCharacterSetBitmapPlane1[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0x73, 0xFF, 0x1F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0xFF, 0x03, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x1C, 0x00, 0x00, 0x18, 0xF0, 0xFF, 0xFF, 0xFF, 0xC3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, - 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xDF, 0xFF, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0xFF, 0x7F, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, - 0x00, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0xFF, 0xFF, - 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0x01, 0x03, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xFF, 0x1F, 0xFF, 0x1F, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xFF, 0x0F, 0x01, 0x00, - 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0x3F, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0xFF, 0x3F, 0xFF, 0x1F, 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0x3F, 0xC0, 0xFF, 0x0F, 0xFF, 0x01, 0xFF, 0x01, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; -static uint8_t const * const __CFUniCharSymbolAndOperatorCharacterSetBitmap[] = { - (uint8_t const * const)&__CFUniCharSymbolAndOperatorCharacterSetBitmapPlane0, - (uint8_t const * const)&__CFUniCharSymbolAndOperatorCharacterSetBitmapPlane1, -}; - -static uint32_t const __CFUniCharSymbolAndOperatorCharacterSetBitmapPlaneCount = 2; -static uint8_t const __CFUniCharControlAndFormatterBitmapPlane0[] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x3F, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xF8, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, -}; -static uint8_t const __CFUniCharControlAndFormatterBitmapPlane1[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; -static uint8_t const __CFUniCharControlAndFormatterBitmapPlane14[] = { - 0x02, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; -static uint8_t const * const __CFUniCharControlAndFormatterBitmap[] = { - (uint8_t const * const)&__CFUniCharControlAndFormatterBitmapPlane0, - (uint8_t const * const)&__CFUniCharControlAndFormatterBitmapPlane1, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)&__CFUniCharControlAndFormatterBitmapPlane14, -}; - -static uint32_t const __CFUniCharControlAndFormatterBitmapPlaneCount = 15; -static uint8_t const __CFUniCharHasMirroredMappingBitmapPlane0[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x50, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x1E, 0x3F, 0x62, 0xBC, 0x57, 0xF8, 0x0F, 0xFA, 0xFF, 0x1F, 0x3C, 0x80, 0xF5, 0xCF, 0xFF, 0xFF, 0xFF, 0x9F, 0x07, 0x01, 0xCC, 0xFF, 0xFF, 0xC1, 0x00, 0x3E, 0xC3, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, - 0x00, 0x0F, 0x00, 0x00, 0x03, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x3B, 0x78, 0x70, 0xFC, 0xFF, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0xF9, 0xFD, 0xFF, 0x00, 0x01, 0x3F, 0xC2, 0x37, 0x1F, 0x3A, 0x03, 0xF0, 0x33, - 0x00, 0xFC, 0xFF, 0xDF, 0x53, 0x7A, 0x30, 0x70, 0x00, 0x00, 0x80, 0x01, 0x30, 0xBC, 0x19, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xCF, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x50, 0x7C, 0x70, 0x88, 0x2F, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x3C, 0x36, 0x00, 0x30, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xFF, 0xF3, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0x00, 0x50, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0xA8, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; -static uint8_t const __CFUniCharHasMirroredMappingBitmapPlane1[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; -static uint8_t const * const __CFUniCharHasMirroredMappingBitmap[] = { - (uint8_t const * const)&__CFUniCharHasMirroredMappingBitmapPlane0, - (uint8_t const * const)&__CFUniCharHasMirroredMappingBitmapPlane1, -}; - -static uint32_t const __CFUniCharHasMirroredMappingBitmapPlaneCount = 2; -static uint8_t const __CFUniCharStrongRightToLeftCharacterSetBitmapPlane0[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x49, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x00, 0x29, 0x00, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0xE0, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x60, 0xC0, 0x00, 0xFC, - 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x30, 0xDC, - 0xFF, 0xFF, 0x3F, 0x04, 0x10, 0xC1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xA0, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x1F, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; -static uint8_t const __CFUniCharStrongRightToLeftCharacterSetBitmapPlane1[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x91, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9F, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9F, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x08, 0xFF, 0xC3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xEF, 0xFF, 0xFF, 0xFF, 0x96, 0xFE, 0xF7, 0x0A, 0x84, 0xEA, 0x96, 0xAA, 0x96, 0xF7, 0xF7, 0x5E, 0xFF, 0xFB, 0xFF, 0x0F, 0xEE, 0xFB, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; -static uint8_t const * const __CFUniCharStrongRightToLeftCharacterSetBitmap[] = { - (uint8_t const * const)&__CFUniCharStrongRightToLeftCharacterSetBitmapPlane0, - (uint8_t const * const)&__CFUniCharStrongRightToLeftCharacterSetBitmapPlane1, -}; - -static uint32_t const __CFUniCharStrongRightToLeftCharacterSetBitmapPlaneCount = 2; -static uint8_t const __CFUniCharNonBaseCharacterSetBitmapPlane0[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xB6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x9F, 0x9F, 0x3D, 0x00, 0x00, - 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x0F, 0x20, - 0x00, 0x00, 0xC0, 0xFB, 0xEF, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, - 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0xFF, 0xFF, 0xFE, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD0, 0x9F, 0x39, 0x80, 0x00, 0x0C, 0x00, 0x00, 0x40, - 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD0, 0x87, 0x39, 0x02, 0x00, 0x00, 0x00, 0x23, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD0, 0xBF, 0x3B, 0x00, 0x00, 0x0C, 0x00, 0x00, 0xFC, - 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD0, 0x9F, 0x39, 0xE0, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xC7, 0x3D, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD0, 0xDF, 0x3D, 0x60, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD0, 0xDF, 0x3D, 0x60, 0x00, 0x0C, 0x00, 0x08, 0x00, - 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD8, 0xDF, 0x3D, 0x80, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x5F, 0xFF, 0x00, 0x00, 0x0C, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF2, 0x07, 0x80, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF2, 0x1F, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0xA0, 0xC2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xDF, 0xE0, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0x1F, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0x7F, 0x00, 0x00, 0xC0, 0xC3, 0x9D, 0x3F, 0x1E, 0x00, 0xFC, 0xBF, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0xFF, 0x0F, 0x20, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x7F, 0xFF, 0xFF, 0xFF, 0x9F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x0F, 0x00, 0x07, 0x00, 0x00, 0x00, 0xFE, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0x0F, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF7, 0xFF, 0xFF, 0x21, 0x90, 0x03, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xF7, 0x3F, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x44, 0x08, 0x00, 0x00, 0xF8, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x03, 0x80, - 0x00, 0x00, 0x00, 0x00, 0xC0, 0x3F, 0x00, 0x00, 0x80, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x7F, 0x00, 0x08, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9D, 0xC1, 0x02, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x60, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x37, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; -static uint8_t const __CFUniCharNonBaseCharacterSetBitmapPlane1[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x6E, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x80, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x07, 0x00, 0x00, 0x00, 0x80, 0xFF, 0x1F, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0x01, 0xDE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0x40, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0x07, 0x00, 0x00, - 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD8, 0x9F, 0x39, 0x80, 0x00, 0xCC, 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0x7F, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3F, 0xFF, 0x01, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xE0, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBF, 0x79, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFC, 0x11, 0x00, 0x00, 0x00, - 0xFE, 0x07, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x7B, 0x80, 0x00, 0xFE, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x7F, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFE, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0xB4, 0xBF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, - 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xC7, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xE3, 0x07, 0xF8, 0xE7, 0x0F, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x20, 0x00, 0x10, 0x00, 0x00, 0xF8, 0xFE, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7F, 0xFF, 0xFF, 0xF9, 0xDB, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; -static uint8_t const __CFUniCharNonBaseCharacterSetBitmapPlane14[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; -static uint8_t const * const __CFUniCharNonBaseCharacterSetBitmap[] = { - (uint8_t const * const)&__CFUniCharNonBaseCharacterSetBitmapPlane0, - (uint8_t const * const)&__CFUniCharNonBaseCharacterSetBitmapPlane1, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)&__CFUniCharNonBaseCharacterSetBitmapPlane14, -}; - -static uint32_t const __CFUniCharNonBaseCharacterSetBitmapPlaneCount = 15; -static uint8_t const __CFUniCharCaseIgnorableCharacterSetBitmapPlane0[] = { - 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA1, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x30, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xB6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x3F, 0x00, 0xFF, 0x17, 0x00, 0x00, 0x00, 0x00, 0x01, 0xF8, 0xFF, 0xFF, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xBF, 0xFF, 0x3D, 0x00, 0x00, - 0x00, 0x80, 0x02, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x3F, 0x24, - 0x00, 0x00, 0xC0, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xFE, 0x21, 0xFE, 0x00, 0x0C, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x1E, 0x20, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x40, - 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x86, 0x39, 0x02, 0x00, 0x00, 0x00, 0x23, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xBE, 0x21, 0x00, 0x00, 0x0C, 0x00, 0x00, 0xFC, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x1E, 0x20, 0x60, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD0, 0xC1, 0x3D, 0x60, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x40, 0x30, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x1E, 0x20, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x5C, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF2, 0x07, 0xC0, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF2, 0x1F, 0x40, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0xA0, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x7F, 0xDF, 0xE0, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0x1F, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFD, 0x66, 0x00, 0x00, 0x00, 0xC3, 0x01, 0x00, 0x1E, 0x00, 0x64, 0x20, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB0, 0x3F, 0x40, 0xFE, 0x8F, 0x20, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x87, 0x01, 0x04, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x7F, 0xE5, 0x1F, 0xF8, 0x9F, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD0, 0x17, 0x04, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x0F, 0x00, 0x03, 0x00, 0x00, 0x00, 0x3C, 0x3B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xA3, 0x03, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xCF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF7, 0xFF, 0xFD, 0x21, 0x10, 0x03, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x01, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA0, 0x03, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0x60, - 0x00, 0xF8, 0x00, 0x02, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDF, 0xFF, 0x02, 0x80, 0x00, 0x00, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x20, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x3E, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xF7, 0xBF, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x03, - 0x44, 0x08, 0x00, 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x03, 0x80, - 0x00, 0x00, 0x00, 0x00, 0xC0, 0x3F, 0x00, 0x00, 0x80, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC8, 0x33, 0x00, 0x80, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x66, 0x00, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9D, 0xC1, 0x02, 0x00, 0x00, 0x20, 0x00, 0x30, 0x58, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x21, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x0E, -}; -static uint8_t const __CFUniCharCaseIgnorableCharacterSetBitmapPlane1[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x6E, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x26, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x07, 0x00, 0x00, 0x00, 0x80, 0xEF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x7F, 0x00, 0x9E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xD3, 0x40, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xF8, 0x07, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x01, 0x00, 0x00, 0x00, 0xC0, 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x5C, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x85, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0xB0, 0x01, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xA7, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0xBF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xE0, 0xBC, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x0C, 0x01, 0x00, 0x00, 0x00, - 0xFE, 0x07, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x79, 0x80, 0x00, 0x7E, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x7F, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xBF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFC, 0x6D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0xB4, 0xBF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x07, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x81, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEF, 0x6F, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0xF8, 0xFF, 0xE7, 0x0F, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x20, 0x00, 0x10, 0x00, 0x00, 0xF8, 0xFE, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7F, 0xFF, 0xFF, 0xF9, 0xDB, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; -static uint8_t const __CFUniCharCaseIgnorableCharacterSetBitmapPlane14[] = { - 0x02, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; -static uint8_t const * const __CFUniCharCaseIgnorableCharacterSetBitmap[] = { - (uint8_t const * const)&__CFUniCharCaseIgnorableCharacterSetBitmapPlane0, - (uint8_t const * const)&__CFUniCharCaseIgnorableCharacterSetBitmapPlane1, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)&__CFUniCharCaseIgnorableCharacterSetBitmapPlane14, -}; - -static uint32_t const __CFUniCharCaseIgnorableCharacterSetBitmapPlaneCount = 15; -static uint8_t const __CFUniCharCanonicalDecomposableCharacterSetBitmapPlane0[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBF, 0xFF, 0x7E, 0x3E, 0xBF, 0xFF, 0x7E, 0xBE, - 0xFF, 0xFF, 0xFC, 0xFF, 0x3F, 0xFF, 0xF1, 0x7E, 0xF8, 0xF1, 0xF3, 0xFF, 0x3F, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x01, 0x00, 0x00, 0xE0, 0xFF, 0xDF, 0xCF, 0xFF, 0x31, 0xFF, - 0xFF, 0xFF, 0xFF, 0xCF, 0xC0, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, 0xE0, 0xD7, 0x01, 0x00, 0x00, 0xFC, 0x01, 0x00, 0x00, 0x7C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x8B, 0x70, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x8B, 0x70, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0xCF, 0xFC, 0xFC, 0xFC, 0x3F, 0x03, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x12, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xB0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x4E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x20, 0x84, 0x10, 0x00, 0x02, 0x68, 0x01, 0x02, 0x00, 0x08, 0x20, 0x84, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x40, 0x55, 0x04, 0x00, 0x00, 0x00, 0x00, 0x28, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, - 0xFF, 0xFF, 0x3F, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x3F, 0xFF, 0xAA, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0x5F, 0xDE, 0xFF, 0xCF, 0xEF, 0xFF, 0xFF, 0xDC, 0x3F, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x40, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x40, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x10, 0x12, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x92, 0x02, 0x00, 0x00, 0x05, 0xE0, 0x33, 0x03, 0x33, 0x03, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x3C, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x55, 0x55, 0xA5, 0x02, 0xDB, 0x36, 0x00, 0x00, 0x10, 0x40, 0x00, 0x50, 0x55, 0x55, 0xA5, 0x02, 0xDB, 0x36, 0x00, 0x00, 0x90, 0x47, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0x3F, 0xE5, 0x7F, 0x65, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xA0, 0x00, 0xFC, 0x7F, 0x5F, 0xDB, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; -static uint8_t const __CFUniCharCanonicalDecomposableCharacterSetBitmapPlane1[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; -static uint8_t const __CFUniCharCanonicalDecomposableCharacterSetBitmapPlane2[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; -static uint8_t const * const __CFUniCharCanonicalDecomposableCharacterSetBitmap[] = { - (uint8_t const * const)&__CFUniCharCanonicalDecomposableCharacterSetBitmapPlane0, - (uint8_t const * const)&__CFUniCharCanonicalDecomposableCharacterSetBitmapPlane1, - (uint8_t const * const)&__CFUniCharCanonicalDecomposableCharacterSetBitmapPlane2, -}; - -static uint32_t const __CFUniCharCanonicalDecomposableCharacterSetBitmapPlaneCount = 3; -static uint8_t const __CFUniCharCompatibilityDecomposableCharacterSetBitmapPlane0[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x85, 0x3C, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x80, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x3F, 0x1F, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00, 0x37, 0x02, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xFF, 0xF7, 0xFF, 0xBF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x01, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xFC, 0x07, 0x82, 0x00, 0x70, 0x80, 0xD8, 0x50, 0x80, 0x03, 0x80, 0x80, 0x00, 0x00, 0xF3, 0xFF, 0xFF, 0x7F, 0xFF, 0x1F, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xEF, 0xFE, 0x6F, 0x3E, 0x17, 0xB1, 0xFB, 0xFB, 0xE1, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xB0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFC, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x03, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7F, 0x00, 0xF8, 0x00, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x1F, - 0x00, 0x00, 0xFF, 0x03, 0x00, 0x00, 0xFF, 0xFF, 0x9F, 0xFF, 0xF7, 0xFF, 0x7F, 0x0F, 0xD7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, - 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFC, 0xFC, 0xFC, 0x1C, 0x7F, 0x7F, 0x00, 0x00, -}; -static uint8_t const __CFUniCharCompatibilityDecomposableCharacterSetBitmapPlane1[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0x64, 0xDE, 0xFF, 0xEB, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xBF, 0xE7, 0xDF, 0xDF, 0xFF, 0xFF, 0xFF, 0x7B, 0x5F, 0xFC, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xEF, 0xFF, 0xFF, 0xFF, 0x96, 0xFE, 0xF7, 0x0A, 0x84, 0xEA, 0x96, 0xAA, 0x96, 0xF7, 0xF7, 0x5E, 0xFF, 0xFB, 0xFF, 0x0F, 0xEE, 0xFB, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; -static uint8_t const * const __CFUniCharCompatibilityDecomposableCharacterSetBitmap[] = { - (uint8_t const * const)&__CFUniCharCompatibilityDecomposableCharacterSetBitmapPlane0, - (uint8_t const * const)&__CFUniCharCompatibilityDecomposableCharacterSetBitmapPlane1, -}; - -static uint32_t const __CFUniCharCompatibilityDecomposableCharacterSetBitmapPlaneCount = 2; -static uint8_t const __CFUniCharHasNonSelfUppercaseMappingBitmapPlane0[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x7F, 0xFF, - 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x54, 0x55, 0xAB, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xD4, 0x29, 0x11, 0x24, 0x46, 0x2A, 0x21, 0x51, 0xA2, 0x60, 0x5B, 0x55, 0xB5, 0xAA, 0xAA, 0x2D, 0xAA, - 0xAA, 0xAA, 0xAA, 0xAA, 0xA8, 0xAA, 0x0A, 0x90, 0x85, 0xAA, 0xDF, 0x1A, 0x6B, 0x9F, 0x26, 0x20, 0x8D, 0x1F, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8A, 0x38, 0x00, 0x00, 0x01, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0xFF, 0x7F, 0xE3, 0xAA, 0xAA, 0xAA, 0x2F, 0x09, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAA, 0xAA, 0xAA, 0xAA, 0x02, 0xA8, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x54, 0xD5, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, - 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xEA, 0x0F, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, - 0xFF, 0x00, 0x3F, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x3F, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0x50, 0xDC, 0x10, 0xCF, 0x00, 0xFF, 0x00, 0xDC, 0x10, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x62, 0x15, 0x48, 0x00, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x0A, 0x50, 0x08, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x2A, 0x00, 0x00, 0xAA, 0xAA, 0xAA, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xA8, 0xAA, 0xA8, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x00, 0x94, 0xAA, 0x10, 0x9A, 0xAA, 0xAA, 0x02, 0xA0, 0xAA, 0x0A, 0x05, 0x82, 0x02, 0x00, 0x00, 0x40, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7F, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; -static uint8_t const __CFUniCharHasNonSelfUppercaseMappingBitmapPlane1[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFB, 0xFF, 0xFB, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; -static uint8_t const * const __CFUniCharHasNonSelfUppercaseMappingBitmap[] = { - (uint8_t const * const)&__CFUniCharHasNonSelfUppercaseMappingBitmapPlane0, - (uint8_t const * const)&__CFUniCharHasNonSelfUppercaseMappingBitmapPlane1, -}; - -static uint32_t const __CFUniCharHasNonSelfUppercaseMappingBitmapPlaneCount = 2; -static uint8_t const __CFUniCharHasNonSelfTitlecaseMappingBitmapPlane0[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x7F, 0xFF, - 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x54, 0x55, 0xAB, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xD4, 0x29, 0x11, 0x24, 0x46, 0x2A, 0x21, 0x51, 0xA2, 0xF0, 0x5F, 0x55, 0xB5, 0xAA, 0xAA, 0x2F, 0xAA, - 0xAA, 0xAA, 0xAA, 0xAA, 0xA8, 0xAA, 0x0A, 0x90, 0x85, 0xAA, 0xDF, 0x1A, 0x6B, 0x9F, 0x26, 0x20, 0x8D, 0x1F, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8A, 0x38, 0x00, 0x00, 0x01, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0xFF, 0x7F, 0xE3, 0xAA, 0xAA, 0xAA, 0x2F, 0x09, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAA, 0xAA, 0xAA, 0xAA, 0x02, 0xA8, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x54, 0xD5, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, - 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xEA, 0x0F, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, - 0xFF, 0x00, 0x3F, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x3F, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0x50, 0xDC, 0x10, 0xCF, 0x00, 0xFF, 0x00, 0xDC, 0x10, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x62, 0x15, 0x48, 0x00, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x0A, 0x50, 0x08, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x2A, 0x00, 0x00, 0xAA, 0xAA, 0xAA, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xA8, 0xAA, 0xA8, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x00, 0x94, 0xAA, 0x10, 0x9A, 0xAA, 0xAA, 0x02, 0xA0, 0xAA, 0x0A, 0x05, 0x82, 0x02, 0x00, 0x00, 0x40, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7F, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; -static uint8_t const __CFUniCharHasNonSelfTitlecaseMappingBitmapPlane1[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFB, 0xFF, 0xFB, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; -static uint8_t const * const __CFUniCharHasNonSelfTitlecaseMappingBitmap[] = { - (uint8_t const * const)&__CFUniCharHasNonSelfTitlecaseMappingBitmapPlane0, - (uint8_t const * const)&__CFUniCharHasNonSelfTitlecaseMappingBitmapPlane1, -}; - -static uint32_t const __CFUniCharHasNonSelfTitlecaseMappingBitmapPlaneCount = 2; -static uint8_t const __CFUniCharHasNonSelfLowercaseMappingBitmapPlane0[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x7F, 0x7F, 0x00, 0x00, 0x00, 0x00, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0x54, 0x55, 0x55, 0x55, 0x55, 0x55, 0x2B, 0xD6, 0xCE, 0xDB, 0xB1, 0xD5, 0xD2, 0xAE, 0x11, 0xB0, 0xAD, 0xAA, 0x4A, 0x55, 0x55, 0xD6, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x05, 0x6C, 0x7A, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x80, 0x40, 0xD7, 0xFE, 0xFF, 0xFB, 0x0F, 0x00, 0x00, 0x00, 0x80, 0x00, 0x55, 0x55, 0x55, 0x90, 0xE6, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55, 0x01, 0x54, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xAB, 0x2A, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xFE, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x15, 0x40, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x00, 0xFF, 0x00, 0x3F, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x3F, 0x00, 0xAA, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x1F, 0x00, 0x1F, 0x00, 0x0F, 0x00, 0x1F, 0x00, 0x1F, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x40, 0x0C, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9D, 0xEA, 0x25, 0xC0, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x05, 0x28, 0x04, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55, 0x55, 0x15, 0x00, 0x00, 0x55, 0x55, 0x55, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x54, 0x55, 0x54, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x00, 0x6A, 0x55, 0x28, 0x45, 0x55, 0x55, 0x7D, 0x5F, 0x55, 0xF5, 0x02, 0x41, 0x01, 0x00, 0x00, 0x20, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; -static uint8_t const __CFUniCharHasNonSelfLowercaseMappingBitmapPlane1[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xF7, 0xFF, 0xF7, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; -static uint8_t const * const __CFUniCharHasNonSelfLowercaseMappingBitmap[] = { - (uint8_t const * const)&__CFUniCharHasNonSelfLowercaseMappingBitmapPlane0, - (uint8_t const * const)&__CFUniCharHasNonSelfLowercaseMappingBitmapPlane1, -}; - -static uint32_t const __CFUniCharHasNonSelfLowercaseMappingBitmapPlaneCount = 2; -static uint8_t const __CFUniCharHasNonSelfCaseFoldingMappingBitmapPlane0[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x63, 0x00, 0x00, 0x00, 0x23, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x4F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDC, 0x50, 0xDC, 0x10, 0xCC, 0x00, 0xDC, 0x00, 0xDC, 0x10, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7F, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; -static uint8_t const * const __CFUniCharHasNonSelfCaseFoldingMappingBitmap[] = { - (uint8_t const * const)&__CFUniCharHasNonSelfCaseFoldingMappingBitmapPlane0, -}; - -static uint32_t const __CFUniCharHasNonSelfCaseFoldingMappingBitmapPlaneCount = 1; -static uint8_t const __CFUniCharGraphemeExtendCharacterSetBitmapPlane0[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xB6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x9F, 0x9F, 0x3D, 0x00, 0x00, - 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x0F, 0x20, - 0x00, 0x00, 0xC0, 0xFB, 0xEF, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, - 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xFE, 0x21, 0xFE, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x1E, 0x20, 0x80, 0x00, 0x0C, 0x00, 0x00, 0x40, - 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x86, 0x39, 0x02, 0x00, 0x00, 0x00, 0x23, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xBE, 0x21, 0x00, 0x00, 0x0C, 0x00, 0x00, 0xFC, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD0, 0x1E, 0x20, 0xE0, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0x20, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD0, 0xC1, 0x3D, 0x60, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x44, 0x30, 0x60, 0x00, 0x0C, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x1E, 0x20, 0x80, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x5C, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF2, 0x07, 0x80, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF2, 0x1F, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0xA0, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x7F, 0xDF, 0xE0, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0x1F, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFD, 0x66, 0x00, 0x00, 0x00, 0xC3, 0x01, 0x00, 0x1E, 0x00, 0x64, 0x20, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB0, 0x3F, 0x40, 0xFE, 0x0F, 0x20, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x87, 0x01, 0x04, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x7F, 0xE5, 0x1F, 0xF8, 0x9F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x17, 0x04, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x0F, 0x00, 0x03, 0x00, 0x00, 0x00, 0x3C, 0x3B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xA3, 0x03, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xCF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF7, 0xFF, 0xFD, 0x21, 0x10, 0x03, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xF7, 0x3F, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x44, 0x08, 0x00, 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x03, 0x80, - 0x00, 0x00, 0x00, 0x00, 0xC0, 0x3F, 0x00, 0x00, 0x80, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC8, 0x33, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x66, 0x00, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9D, 0xC1, 0x02, 0x00, 0x00, 0x00, 0x00, 0x30, 0x40, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x21, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; -static uint8_t const __CFUniCharGraphemeExtendCharacterSetBitmapPlane1[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x6E, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x06, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x07, 0x00, 0x00, 0x00, 0x80, 0xEF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x7F, 0x00, 0x9E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xD3, 0x40, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xF8, 0x07, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x01, 0x00, 0x80, 0x00, 0xC0, 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x5C, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF9, 0xA5, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3C, 0xB0, 0x01, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xA7, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0xBF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xE0, 0xBC, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x58, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x0C, 0x01, 0x00, 0x00, 0x00, - 0xFE, 0x07, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x79, 0x80, 0x00, 0x7E, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x7F, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xBF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFC, 0x6D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0xB4, 0xBF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x07, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA0, 0xC3, 0x07, 0xF8, 0xE7, 0x0F, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x20, 0x00, 0x10, 0x00, 0x00, 0xF8, 0xFE, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7F, 0xFF, 0xFF, 0xF9, 0xDB, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; -static uint8_t const __CFUniCharGraphemeExtendCharacterSetBitmapPlane14[] = { - 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; -static uint8_t const * const __CFUniCharGraphemeExtendCharacterSetBitmap[] = { - (uint8_t const * const)&__CFUniCharGraphemeExtendCharacterSetBitmapPlane0, - (uint8_t const * const)&__CFUniCharGraphemeExtendCharacterSetBitmapPlane1, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)NULL, - (uint8_t const * const)&__CFUniCharGraphemeExtendCharacterSetBitmapPlane14, -}; - -static uint32_t const __CFUniCharGraphemeExtendCharacterSetBitmapPlaneCount = 15; -static uint8_t const __CFUniCharHfsPlusDecomposableCharacterSetBitmapPlane0[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBF, 0xFF, 0x7E, 0x3E, 0xBF, 0xFF, 0x7E, 0xBE, - 0xFF, 0xFF, 0xFC, 0xFF, 0x3F, 0xFF, 0xF1, 0x7E, 0xF8, 0xF1, 0xF3, 0xFF, 0x3F, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x01, 0x00, 0x00, 0xE0, 0xFF, 0xDF, 0xCF, 0xFF, 0x31, 0xFF, - 0xFF, 0xFF, 0xFF, 0xCF, 0xC0, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, 0xE0, 0xD7, 0x01, 0x00, 0x00, 0xFC, 0x01, 0x00, 0x00, 0x7C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x8B, 0x70, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x8B, 0x70, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0xCF, 0xFC, 0xFC, 0xFC, 0x3F, 0x03, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x12, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xB0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x4E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x20, 0x84, 0x10, 0x00, 0x02, 0x68, 0x01, 0x02, 0x00, 0x08, 0x20, 0x84, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x40, 0x55, 0x04, 0x00, 0x00, 0x00, 0x00, 0x28, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, - 0xFF, 0xFF, 0x3F, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x3F, 0xFF, 0xAA, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0x5F, 0xDE, 0xFF, 0xCF, 0xEF, 0xFF, 0xFF, 0xDC, 0x3F, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x55, 0x55, 0xA5, 0x02, 0xDB, 0x36, 0x00, 0x00, 0x10, 0x40, 0x00, 0x50, 0x55, 0x55, 0xA5, 0x02, 0xDB, 0x36, 0x00, 0x00, 0x90, 0x47, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xA0, 0x00, 0xFC, 0x7F, 0x5F, 0xDB, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; -static uint8_t const __CFUniCharHfsPlusDecomposableCharacterSetBitmapPlane1[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; -static uint8_t const * const __CFUniCharHfsPlusDecomposableCharacterSetBitmap[] = { - (uint8_t const * const)&__CFUniCharHfsPlusDecomposableCharacterSetBitmapPlane0, - (uint8_t const * const)&__CFUniCharHfsPlusDecomposableCharacterSetBitmapPlane1, -}; - -static uint32_t const __CFUniCharHfsPlusDecomposableCharacterSetBitmapPlaneCount = 2; -static char const * const __CFUniCharUnicodeVersionString = "15.1.0"; - -static uint32_t const __CFUniCharNumberOfBitmaps = 22; -static __CFUniCharBitmapData const __CFUniCharBitmapDataArray[] = { - { ._numPlanes = __CFUniCharDecimalDigitCharacterSetBitmapPlaneCount, ._planes = __CFUniCharDecimalDigitCharacterSetBitmap }, - { ._numPlanes = __CFUniCharLetterCharacterSetBitmapPlaneCount, ._planes = __CFUniCharLetterCharacterSetBitmap }, - { ._numPlanes = __CFUniCharLowercaseLetterCharacterSetBitmapPlaneCount, ._planes = __CFUniCharLowercaseLetterCharacterSetBitmap }, - { ._numPlanes = __CFUniCharUppercaseLetterCharacterSetBitmapPlaneCount, ._planes = __CFUniCharUppercaseLetterCharacterSetBitmap }, - { ._numPlanes = __CFUniCharNonBaseCharacterSetBitmapPlaneCount, ._planes = __CFUniCharNonBaseCharacterSetBitmap }, - { ._numPlanes = __CFUniCharCanonicalDecomposableCharacterSetBitmapPlaneCount, ._planes = __CFUniCharCanonicalDecomposableCharacterSetBitmap }, - { ._numPlanes = __CFUniCharAlphanumericCharacterSetBitmapPlaneCount, ._planes = __CFUniCharAlphanumericCharacterSetBitmap }, - { ._numPlanes = __CFUniCharPunctuationCharacterSetBitmapPlaneCount, ._planes = __CFUniCharPunctuationCharacterSetBitmap }, - { ._numPlanes = __CFUniCharLegalCharacterSetBitmapPlaneCount, ._planes = __CFUniCharLegalCharacterSetBitmap }, - { ._numPlanes = __CFUniCharTitlecaseLetterCharacterSetBitmapPlaneCount, ._planes = __CFUniCharTitlecaseLetterCharacterSetBitmap }, - { ._numPlanes = __CFUniCharSymbolAndOperatorCharacterSetBitmapPlaneCount, ._planes = __CFUniCharSymbolAndOperatorCharacterSetBitmap }, - { ._numPlanes = __CFUniCharCompatibilityDecomposableCharacterSetBitmapPlaneCount, ._planes = __CFUniCharCompatibilityDecomposableCharacterSetBitmap }, - { ._numPlanes = __CFUniCharHfsPlusDecomposableCharacterSetBitmapPlaneCount, ._planes = __CFUniCharHfsPlusDecomposableCharacterSetBitmap }, - { ._numPlanes = __CFUniCharStrongRightToLeftCharacterSetBitmapPlaneCount, ._planes = __CFUniCharStrongRightToLeftCharacterSetBitmap }, - { ._numPlanes = __CFUniCharHasNonSelfLowercaseMappingBitmapPlaneCount, ._planes = __CFUniCharHasNonSelfLowercaseMappingBitmap }, - { ._numPlanes = __CFUniCharHasNonSelfUppercaseMappingBitmapPlaneCount, ._planes = __CFUniCharHasNonSelfUppercaseMappingBitmap }, - { ._numPlanes = __CFUniCharHasNonSelfTitlecaseMappingBitmapPlaneCount, ._planes = __CFUniCharHasNonSelfTitlecaseMappingBitmap }, - { ._numPlanes = __CFUniCharHasNonSelfCaseFoldingMappingBitmapPlaneCount, ._planes = __CFUniCharHasNonSelfCaseFoldingMappingBitmap }, - { ._numPlanes = __CFUniCharHasMirroredMappingBitmapPlaneCount, ._planes = __CFUniCharHasMirroredMappingBitmap }, - { ._numPlanes = __CFUniCharControlAndFormatterBitmapPlaneCount, ._planes = __CFUniCharControlAndFormatterBitmap }, - { ._numPlanes = __CFUniCharCaseIgnorableCharacterSetBitmapPlaneCount, ._planes = __CFUniCharCaseIgnorableCharacterSetBitmap }, - { ._numPlanes = __CFUniCharGraphemeExtendCharacterSetBitmapPlaneCount, ._planes = __CFUniCharGraphemeExtendCharacterSetBitmap }, -}; - diff --git a/Sources/_SubprocessCShims/include/_CShimsMacros.h b/Sources/_SubprocessCShims/include/_CShimsMacros.h deleted file mode 100644 index b537e937..00000000 --- a/Sources/_SubprocessCShims/include/_CShimsMacros.h +++ /dev/null @@ -1,24 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2021 - 2022 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// - -#ifndef _C_SHIMS_MACROS_H -#define _C_SHIMS_MACROS_H - -#if FOUNDATION_FRAMEWORK -// This macro prevents the symbol from being exported from the framework, where library evolution is enabled. -#define INTERNAL __attribute__((__visibility__("hidden"))) -#else -// This macro makes the symbol available for package users. With library evolution disabled, it is possible for clients to end up referencing these normally-internal symbols. -#define INTERNAL extern -#endif - -#endif diff --git a/Sources/_SubprocessCShims/include/_CShimsTargetConditionals.h b/Sources/_SubprocessCShims/include/_CShimsTargetConditionals.h deleted file mode 100644 index d6db4bf7..00000000 --- a/Sources/_SubprocessCShims/include/_CShimsTargetConditionals.h +++ /dev/null @@ -1,56 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2021 - 2022 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// - -#ifndef _C_SHIMS_TARGET_CONDITIONALS_H -#define _C_SHIMS_TARGET_CONDITIONALS_H - -#if __has_include() -#include -#endif - -#if (defined(__APPLE__) && defined(__MACH__)) -#define TARGET_OS_MAC 1 -#else -#define TARGET_OS_MAC 0 -#endif - -#if defined(__linux__) -#define TARGET_OS_LINUX 1 -#else -#define TARGET_OS_LINUX 0 -#endif - -#if defined(__unix__) -#define TARGET_OS_BSD 1 -#else -#define TARGET_OS_BSD 0 -#endif - -#if defined(_WIN32) -#define TARGET_OS_WINDOWS 1 -#else -#define TARGET_OS_WINDOWS 0 -#endif - -#if defined(__wasi__) -#define TARGET_OS_WASI 1 -#else -#define TARGET_OS_WASI 0 -#endif - -#if defined(__ANDROID__) -#define TARGET_OS_ANDROID 1 -#else -#define TARGET_OS_ANDROID 0 -#endif - -#endif // _C_SHIMS_TARGET_CONDITIONALS_H diff --git a/Sources/_SubprocessCShims/include/_CStdlib.h b/Sources/_SubprocessCShims/include/_CStdlib.h deleted file mode 100644 index 4a92b3a5..00000000 --- a/Sources/_SubprocessCShims/include/_CStdlib.h +++ /dev/null @@ -1,156 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2022 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// - -#ifndef FOUNDATION_CSTDLIB -#define FOUNDATION_CSTDLIB - -#include "_CShimsTargetConditionals.h" - -#if __has_include() -#include -#endif - -#if __has_include() -#include -#endif - -#if __has_include() -#include -#endif - -#if __has_include() -#include -#endif - -#if __has_include() -#include -#endif - -#if __has_include() -#include -#endif - -#if __has_include() -#include -#endif - -#if __has_include() -#include -#endif - -#if __has_include() -#include -#endif - -#if __has_include() -#include -#endif - -#if __has_include() -#include -#endif - -#if __has_include() -#include -#endif - -#if __has_include() -#include -#endif - -#if __has_include() -#include -#endif - -#if __has_include() -#include -#endif - -#if __has_include() -#include -#endif - -#if __has_include() -#include -#endif - -#if __has_include() -#include -#endif - -#if __has_include() -#include -#endif - -#if __has_include() -#include -#endif - -#if __has_include() -#include -#endif - -#if !defined(_WIN32) -#if __has_include() -#include -#endif -#endif - -#if __has_include() -#include -#endif - -#if __has_include() -#include -#endif - -#if __has_include() -#include -#endif - - -#if __has_include() -#include -#endif - -#if __has_include() -#include -#endif - -#if __has_include() -#include -#endif - -#if __has_include() -#include -#endif - -#if __has_include() -#include -#endif - -#if __has_include() -#include -#else - -#ifndef TZDIR -#define TZDIR "/usr/share/zoneinfo/" /* Time zone object file directory */ -#endif /* !defined TZDIR */ - -#ifndef TZDEFAULT -#define TZDEFAULT "/etc/localtime" -#endif /* !defined TZDEFAULT */ - -#endif - -#endif // FOUNDATION_CSTDLIB - diff --git a/Sources/_SubprocessCShims/include/_SubprocessCShims.h b/Sources/_SubprocessCShims/include/_SubprocessCShims.h deleted file mode 100644 index 17beeaa8..00000000 --- a/Sources/_SubprocessCShims/include/_SubprocessCShims.h +++ /dev/null @@ -1,32 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2023 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// - -#ifndef _CShims_h -#define _CShims_h - -#include "_CShimsTargetConditionals.h" -#include "_CStdlib.h" -#include "CFUniCharBitmapData.inc.h" -#include "CFUniCharBitmapData.h" -#include "string_shims.h" -#include "bplist_shims.h" -#include "io_shims.h" -#include "platform_shims.h" -#include "process_shims.h" -#include "filemanager_shims.h" -#include "uuid.h" - -#if FOUNDATION_FRAMEWORK && !TARGET_OS_EXCLAVEKIT -#include "sandbox_shims.h" -#endif - -#endif /* _CShims_h */ diff --git a/Sources/_SubprocessCShims/include/bplist_shims.h b/Sources/_SubprocessCShims/include/bplist_shims.h deleted file mode 100644 index 150dd8c7..00000000 --- a/Sources/_SubprocessCShims/include/bplist_shims.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - bplist.h - Copyright (c) 2023, Apple Inc. and the Swift.org project authors. All rights reserved. -*/ - -#ifndef _bplist_h -#define _bplist_h - -typedef struct { - uint8_t _unused[5]; - uint8_t _sortVersion; - uint8_t _offsetIntSize; - uint8_t _objectRefSize; - uint64_t _numObjects; - uint64_t _topObject; - uint64_t _offsetTableOffset; -} BPlistTrailer; - -#endif /* _bplist_h */ diff --git a/Sources/_SubprocessCShims/include/filemanager_shims.h b/Sources/_SubprocessCShims/include/filemanager_shims.h deleted file mode 100644 index 49f8ffd5..00000000 --- a/Sources/_SubprocessCShims/include/filemanager_shims.h +++ /dev/null @@ -1,49 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2023 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// - -#ifndef CSHIMS_FILEMANAGER_H -#define CSHIMS_FILEMANAGER_H - -#include "_CShimsMacros.h" - -#if __has_include() -#include -#endif - -#if __has_include() -#include -#endif - -#if __has_include() -#include -#endif - -#if __has_include() -#include -#endif - -#if __has_include() -#include -#endif - -#if __has_include() -#include -#endif // __has_include() - -#if FOUNDATION_FRAMEWORK && __has_include() -#include -// Darwin-specific API that is implemented but not declared in any header -// This function behaves exactly like the public mkpath_np(3) API, but it also returns the first directory it actually created, which helps us make sure we set the given attributes on the right directories. -extern int _mkpath_np(const char *path, mode_t omode, const char **firstdir); -#endif - -#endif // CSHIMS_FILEMANAGER_H diff --git a/Sources/_SubprocessCShims/include/io_shims.h b/Sources/_SubprocessCShims/include/io_shims.h deleted file mode 100644 index 1186a4b6..00000000 --- a/Sources/_SubprocessCShims/include/io_shims.h +++ /dev/null @@ -1,89 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2022 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// - - -#ifndef IOShims_h -#define IOShims_h - -#include "_CShimsTargetConditionals.h" - -#if TARGET_OS_MAC && (!defined(TARGET_OS_EXCLAVEKIT) || !TARGET_OS_EXCLAVEKIT) - -#include -#include - -// See getattrlist for an explanation of the layout of these structs. - -#pragma pack(push, 1) -typedef struct PreRenameAttributes { - u_int32_t length; - fsobj_type_t fileType; - u_int32_t mode; - attrreference_t fullPathAttr; - u_int32_t nlink; - char fullPathBuf[PATH_MAX]; -} PreRenameAttributes; -#pragma pack(pop) - -#pragma pack(push, 1) -typedef struct FullPathAttributes { - u_int32_t length; - attrreference_t fullPathAttr; - char fullPathBuf[PATH_MAX]; -} FullPathAttributes; -#pragma pack(pop) - -#endif // TARGET_OS_EXCLAVEKIT - -#if TARGET_OS_WINDOWS - -#include - -// Replicated from ntifs.h -// https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/ntifs/ns-ntifs-_reparse_data_buffer - -typedef struct _REPARSE_DATA_BUFFER { - unsigned long ReparseTag; - unsigned short ReparseDataLength; - unsigned short Reserved; - union { - struct { - unsigned short SubstituteNameOffset; - unsigned short SubstituteNameLength; - unsigned short PrintNameOffset; - unsigned short PrintNameLength; - unsigned long Flags; - short PathBuffer[1]; - } SymbolicLinkReparseBuffer; - struct { - unsigned short SubstituteNameOffset; - unsigned short SubstituteNameLength; - unsigned short PrintNameOffset; - unsigned short PrintNameLength; - short PathBuffer[1]; - } MountPointReparseBuffer; - struct { - unsigned char DataBuffer[1]; - } GenericReparseBuffer; - }; -} REPARSE_DATA_BUFFER; - -static inline intptr_t _ioshims_reparse_data_buffer_symboliclinkreparsebuffer_pathbuffer_offset(void) { - return offsetof(struct _REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer); -} - -static inline intptr_t _ioshims_reparse_data_buffer_mountpointreparsebuffer_pathbuffer_offset(void) { - return offsetof(struct _REPARSE_DATA_BUFFER, MountPointReparseBuffer.PathBuffer); -} - -#endif -#endif /* IOShims_h */ diff --git a/Sources/_SubprocessCShims/include/module.modulemap b/Sources/_SubprocessCShims/include/module.modulemap deleted file mode 100644 index 724a69f6..00000000 --- a/Sources/_SubprocessCShims/include/module.modulemap +++ /dev/null @@ -1,5 +0,0 @@ -module _SubprocessCShims { - header "_SubprocessCShims.h" - - export * -} diff --git a/Sources/_SubprocessCShims/include/platform_shims.h b/Sources/_SubprocessCShims/include/platform_shims.h deleted file mode 100644 index ab488849..00000000 --- a/Sources/_SubprocessCShims/include/platform_shims.h +++ /dev/null @@ -1,71 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2022 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// - -#ifndef CSHIMS_PLATFORM_SHIMS -#define CSHIMS_PLATFORM_SHIMS - -#include "_CShimsTargetConditionals.h" -#include "_CShimsMacros.h" - -#if __has_include() -#include -#endif - -#if __has_include() -#include -#endif - -// Workaround for inability to import `security.h` as a module in WinSDK -#if defined(_WIN32) -#include -#define SECURITY_WIN32 -#include -#endif - -INTERNAL char * _Nullable * _Nullable _platform_shims_get_environ(); - -INTERNAL void _platform_shims_lock_environ(); -INTERNAL void _platform_shims_unlock_environ(); - -#if __has_include() -#include -INTERNAL vm_size_t _platform_shims_vm_size(); -#endif - -#if __has_include() -#include -INTERNAL mach_port_t _platform_mach_task_self(); -#endif - -#if __has_include() -typedef enum { -#if TARGET_OS_OSX || TARGET_OS_MACCATALYST - _kOSThermalPressureLevelNominal = kOSThermalPressureLevelNominal, - _kOSThermalPressureLevelModerate = kOSThermalPressureLevelModerate, - _kOSThermalPressureLevelHeavy = kOSThermalPressureLevelHeavy, - _kOSThermalPressureLevelTrapping = kOSThermalPressureLevelTrapping, - _kOSThermalPressureLevelSleeping = kOSThermalPressureLevelSleeping -#else - _kOSThermalPressureLevelNominal = kOSThermalPressureLevelNominal, - _kOSThermalPressureLevelLight = kOSThermalPressureLevelLight, - _kOSThermalPressureLevelModerate = kOSThermalPressureLevelModerate, - _kOSThermalPressureLevelHeavy = kOSThermalPressureLevelHeavy, - _kOSThermalPressureLevelTrapping = kOSThermalPressureLevelTrapping, - _kOSThermalPressureLevelSleeping = kOSThermalPressureLevelSleeping -#endif -} _platform_shims_OSThermalPressureLevel; - - -INTERNAL const char * _Nonnull _platform_shims_kOSThermalNotificationPressureLevelName(); -#endif - -#endif /* CSHIMS_PLATFORM_SHIMS */ diff --git a/Sources/_SubprocessCShims/include/process_shims.h b/Sources/_SubprocessCShims/include/process_shims.h deleted file mode 100644 index cf921da8..00000000 --- a/Sources/_SubprocessCShims/include/process_shims.h +++ /dev/null @@ -1,64 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// -//===----------------------------------------------------------------------===// - -#ifndef process_shims_h -#define process_shims_h - -#include -#include "_CShimsTargetConditionals.h" - -#if TARGET_OS_MAC -#include - -int _subprocess_spawn( - pid_t * _Nonnull pid, - const char * _Nonnull exec_path, - const posix_spawn_file_actions_t _Nullable * _Nonnull file_actions, - const posix_spawnattr_t _Nullable * _Nonnull spawn_attrs, - char * _Nullable const args[_Nonnull], - char * _Nullable const env[_Nullable], - uid_t * _Nullable uid, - gid_t * _Nullable gid, - int number_of_sgroups, const gid_t * _Nullable sgroups, - int create_session -); -#endif // TARGET_OS_MAC - -int _subprocess_fork_exec( - pid_t * _Nonnull pid, - const char * _Nonnull exec_path, - const char * _Nullable working_directory, - const int file_descriptors[_Nonnull], - char * _Nullable const args[_Nonnull], - char * _Nullable const env[_Nullable], - uid_t * _Nullable uid, - gid_t * _Nullable gid, - int number_of_sgroups, const gid_t * _Nullable sgroups, - int create_session, - int create_process_group -); - -int _was_process_exited(int status); -int _get_exit_code(int status); -int _was_process_signaled(int status); -int _get_signal_code(int status); - -#if TARGET_OS_LINUX -int _shims_snprintf( - char * _Nonnull str, - int len, - const char * _Nonnull format, - char * _Nonnull str1, - char * _Nonnull str2 -); -#endif - -#endif /* process_shims_h */ diff --git a/Sources/_SubprocessCShims/include/string_shims.h b/Sources/_SubprocessCShims/include/string_shims.h deleted file mode 100644 index 90c05621..00000000 --- a/Sources/_SubprocessCShims/include/string_shims.h +++ /dev/null @@ -1,49 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2022 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// - -#ifndef CSHIMS_STRING_H -#define CSHIMS_STRING_H - -#include "_CShimsMacros.h" - -#if __has_include() -#include -#endif -#include - -#if __has_include() -#include -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -#if defined(_WIN32) -#define locale_t _locale_t -#endif - -#if defined(TARGET_OS_EXCLAVEKIT) && TARGET_OS_EXCLAVEKIT -#define locale_t void * -#endif - -INTERNAL int _stringshims_strncasecmp_l(const char * _Nullable s1, const char * _Nullable s2, size_t n, locale_t _Nullable loc); - -INTERNAL double _stringshims_strtod_l(const char * _Nullable __restrict nptr, char * _Nullable * _Nullable __restrict endptr, locale_t _Nullable loc); - -INTERNAL float _stringshims_strtof_l(const char * _Nullable __restrict nptr, char * _Nullable * _Nullable __restrict endptr, locale_t _Nullable loc); - -#ifdef __cplusplus -} -#endif - -#endif /* CSHIMS_STRING_H */ diff --git a/Sources/_SubprocessCShims/include/uuid.h b/Sources/_SubprocessCShims/include/uuid.h deleted file mode 100644 index d2e1c156..00000000 --- a/Sources/_SubprocessCShims/include/uuid.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. - * - * %Begin-Header% - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, and the entire permission notice in its entirety, - * including the disclaimer of warranties. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF - * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * %End-Header% - */ - -#ifndef _CSHIMS_UUID_UUID_H -#define _CSHIMS_UUID_UUID_H - -#include "_CShimsTargetConditionals.h" -#include "_CShimsMacros.h" - -#if TARGET_OS_MAC -#include -#else -#include -typedef unsigned char __darwin_uuid_t[16]; -typedef char __darwin_uuid_string_t[37]; -#ifdef uuid_t -#undef uuid_t -#endif -typedef __darwin_uuid_t uuid_t; -typedef __darwin_uuid_string_t uuid_string_t; - -#define UUID_DEFINE(name,u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,u13,u14,u15) \ - static const uuid_t name __attribute__ ((unused)) = {u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,u13,u14,u15} -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -INTERNAL void _foundation_uuid_clear(uuid_t uu); - -INTERNAL int _foundation_uuid_compare(const uuid_t uu1, const uuid_t uu2); - -INTERNAL void _foundation_uuid_copy(uuid_t dst, const uuid_t src); - -INTERNAL void _foundation_uuid_generate(uuid_t out); -INTERNAL void _foundation_uuid_generate_random(uuid_t out); -INTERNAL void _foundation_uuid_generate_time(uuid_t out); - -INTERNAL int _foundation_uuid_is_null(const uuid_t uu); - -INTERNAL int _foundation_uuid_parse(const uuid_string_t in, uuid_t uu); - -INTERNAL void _foundation_uuid_unparse(const uuid_t uu, uuid_string_t out); -INTERNAL void _foundation_uuid_unparse_lower(const uuid_t uu, uuid_string_t out); -INTERNAL void _foundation_uuid_unparse_upper(const uuid_t uu, uuid_string_t out); - -#ifdef __cplusplus -} -#endif - -#endif /* _CSHIMS_UUID_UUID_H */ diff --git a/Sources/_SubprocessCShims/platform_shims.c b/Sources/_SubprocessCShims/platform_shims.c deleted file mode 100644 index 3990c588..00000000 --- a/Sources/_SubprocessCShims/platform_shims.c +++ /dev/null @@ -1,69 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2023 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// - -#include "include/platform_shims.h" - -#if __has_include() -#include -#elif defined(_WIN32) -#include -#elif __has_include() -#include -extern char **environ; -#endif - -#if __has_include() -#import -void _platform_shims_lock_environ() { - environ_lock_np(); -} - -void _platform_shims_unlock_environ() { - environ_unlock_np(); -} -#else -void _platform_shims_lock_environ() { /* noop */ } -void _platform_shims_unlock_environ() { /* noop */ } -#endif - -char ** _platform_shims_get_environ() { -#if __has_include() - return *_NSGetEnviron(); -#elif defined(_WIN32) - return _environ; -#elif TARGET_OS_WASI - return __wasilibc_get_environ(); -#elif __has_include() - return environ; -#endif -} - -#if __has_include() -const char * _platform_shims_kOSThermalNotificationPressureLevelName() { - return kOSThermalNotificationPressureLevelName; -} -#endif - -#if __has_include() -vm_size_t _platform_shims_vm_size() { - // This shim exists because vm_page_size is not marked const, and therefore looks like global mutable state to Swift. - return vm_page_size; -} -#endif - -#if __has_include() -mach_port_t _platform_mach_task_self() { - // This shim exists because mach_task_self_ is not marked const, and therefore looks like global mutable state to Swift. - return mach_task_self(); -} -#endif - diff --git a/Sources/_SubprocessCShims/process_shims.c b/Sources/_SubprocessCShims/process_shims.c deleted file mode 100644 index 61348a2d..00000000 --- a/Sources/_SubprocessCShims/process_shims.c +++ /dev/null @@ -1,301 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// -//===----------------------------------------------------------------------===// - -#include "include/_CShimsTargetConditionals.h" -#include "include/process_shims.h" -#include -#include -#include - -int _was_process_exited(int status) { - return WIFEXITED(status); -} - -int _get_exit_code(int status) { - return WEXITSTATUS(status); -} - -int _was_process_signaled(int status) { - return WIFSIGNALED(status); -} - -int _get_signal_code(int status) { - return WTERMSIG(status); -} - -#if TARGET_OS_LINUX -#include - -int _shims_snprintf( - char * _Nonnull str, - int len, - const char * _Nonnull format, - char * _Nonnull str1, - char * _Nonnull str2 -) { - return snprintf(str, len, format, str1, str2); -} -#endif - -// MARK: - Darwin (posix_spawn) -#if TARGET_OS_MAC - -int _subprocess_spawn( - pid_t * _Nonnull pid, - const char * _Nonnull exec_path, - const posix_spawn_file_actions_t _Nullable * _Nonnull file_actions, - const posix_spawnattr_t _Nullable * _Nonnull spawn_attrs, - char * _Nullable const args[_Nonnull], - char * _Nullable const env[_Nullable], - uid_t * _Nullable uid, - gid_t * _Nullable gid, - int number_of_sgroups, const gid_t * _Nullable sgroups, - int create_session -) { - int require_pre_fork = uid != NULL || - gid != NULL || - number_of_sgroups > 0 || - create_session > 0; - - if (require_pre_fork != 0) { - pid_t childPid = fork(); - if (childPid != 0) { - *pid = childPid; - return childPid < 0 ? errno : 0; - } - - if (uid != NULL) { - if (setuid(*uid) != 0) { - return errno; - } - } - - if (gid != NULL) { - if (setgid(*gid) != 0) { - return errno; - } - } - - if (number_of_sgroups > 0 && sgroups != NULL) { - if (setgroups(number_of_sgroups, sgroups) != 0) { - return errno; - } - } - - if (create_session != 0) { - (void)setsid(); - } - } - - // Set POSIX_SPAWN_SETEXEC if we already forked - if (require_pre_fork) { - short flags = 0; - int rc = posix_spawnattr_getflags(spawn_attrs, &flags); - if (rc != 0) { - return rc; - } - - rc = posix_spawnattr_setflags( - (posix_spawnattr_t *)spawn_attrs, flags | POSIX_SPAWN_SETEXEC); - if (rc != 0) { - return rc; - } - } - - // Spawn - return posix_spawn(pid, exec_path, file_actions, spawn_attrs, args, env); -} - -#endif // TARGET_OS_MAC - -// MARK: - Linux (fork/exec + posix_spawn fallback) - -#if _POSIX_SPAWN -static int _subprocess_posix_spawn_fallback( - pid_t * _Nonnull pid, - const char * _Nonnull exec_path, - const char * _Nullable working_directory, - const int file_descriptors[_Nonnull], - char * _Nullable const args[_Nonnull], - char * _Nullable const env[_Nullable], - int create_process_group -) { - // Setup stdin, stdout, and stderr - posix_spawn_file_actions_t file_actions; - - int rc = posix_spawn_file_actions_init(&file_actions); - if (rc != 0) { return rc; } - rc = posix_spawn_file_actions_adddup2( - &file_actions, file_descriptors[0], STDIN_FILENO); - if (rc != 0) { return rc; } - rc = posix_spawn_file_actions_adddup2( - &file_actions, file_descriptors[2], STDOUT_FILENO); - if (rc != 0) { return rc; } - rc = posix_spawn_file_actions_adddup2( - &file_actions, file_descriptors[4], STDERR_FILENO); - if (rc != 0) { return rc; } - if (file_descriptors[1] != 0) { - rc = posix_spawn_file_actions_addclose(&file_actions, file_descriptors[1]); - if (rc != 0) { return rc; } - } - if (file_descriptors[3] != 0) { - rc = posix_spawn_file_actions_addclose(&file_actions, file_descriptors[3]); - if (rc != 0) { return rc; } - } - if (file_descriptors[5] != 0) { - rc = posix_spawn_file_actions_addclose(&file_actions, file_descriptors[5]); - if (rc != 0) { return rc; } - } - - // Setup spawnattr - posix_spawnattr_t spawn_attr; - rc = posix_spawnattr_init(&spawn_attr); - if (rc != 0) { return rc; } - // Masks - sigset_t no_signals; - sigset_t all_signals; - sigemptyset(&no_signals); - sigfillset(&all_signals); - rc = posix_spawnattr_setsigmask(&spawn_attr, &no_signals); - if (rc != 0) { return rc; } - rc = posix_spawnattr_setsigdefault(&spawn_attr, &all_signals); - if (rc != 0) { return rc; } - // Flags - short flags = POSIX_SPAWN_SETSIGMASK | POSIX_SPAWN_SETSIGDEF; - if (create_process_group) { - flags |= POSIX_SPAWN_SETPGROUP; - } - rc = posix_spawnattr_setflags(&spawn_attr, flags); - - // Spawn! - rc = posix_spawn( - pid, exec_path, - &file_actions, &spawn_attr, - args, env - ); - posix_spawn_file_actions_destroy(&file_actions); - posix_spawnattr_destroy(&spawn_attr); - return rc; -} -#endif // _POSIX_SPAWN - -int _subprocess_fork_exec( - pid_t * _Nonnull pid, - const char * _Nonnull exec_path, - const char * _Nullable working_directory, - const int file_descriptors[_Nonnull], - char * _Nullable const args[_Nonnull], - char * _Nullable const env[_Nullable], - uid_t * _Nullable uid, - gid_t * _Nullable gid, - int number_of_sgroups, const gid_t * _Nullable sgroups, - int create_session, - int create_process_group -) { - int require_pre_fork = working_directory != NULL || - uid != NULL || - gid != NULL || - (number_of_sgroups > 0 && sgroups != NULL) || - create_session; - -#if _POSIX_SPAWN - // If posix_spawn is available on this platform and - // we do not require prefork, use posix_spawn if possible. - // - // (Glibc's posix_spawn does not support - // `POSIX_SPAWN_SETEXEC` therefore we have to keep - // using fork/exec if `require_pre_fork` is true. - if (require_pre_fork == 0) { - return _subprocess_posix_spawn_fallback( - pid, exec_path, - working_directory, - file_descriptors, - args, env, - create_process_group - ); - } -#endif - - pid_t child_pid = fork(); - if (child_pid != 0) { - *pid = child_pid; - return child_pid < 0 ? errno : 0; - } - - if (working_directory != NULL) { - if (chdir(working_directory) != 0) { - return errno; - } - } - - if (uid != NULL) { - if (setuid(*uid) != 0) { - return errno; - } - } - - if (gid != NULL) { - if (setgid(*gid) != 0) { - return errno; - } - } - - if (number_of_sgroups > 0 && sgroups != NULL) { - if (setgroups(number_of_sgroups, sgroups) != 0) { - return errno; - } - } - - if (create_session != 0) { - (void)setsid(); - } - - if (create_process_group != 0) { - (void)setpgid(0, 0); - } - - // Bind stdin, stdout, and stderr - int rc = 0; - if (file_descriptors[0] != 0) { - rc = dup2(file_descriptors[0], STDIN_FILENO); - if (rc != 0) { return rc; } - } - if (file_descriptors[2] != 0) { - rc = dup2(file_descriptors[2], STDOUT_FILENO); - if (rc != 0) { return rc; } - } - - if (file_descriptors[4] != 0) { - rc = dup2(file_descriptors[4], STDERR_FILENO); - if (rc != 0) { return rc; } - } - -#warning Shold close all and then return error no early return - // Close parent side - if (file_descriptors[1] != 0) { - rc = close(file_descriptors[1]); - if (rc != 0) { return rc; } - } - if (file_descriptors[3] != 0) { - rc = close(file_descriptors[3]); - if (rc != 0) { return rc; } - } - if (file_descriptors[4] != 0) { - rc = close(file_descriptors[5]); - if (rc != 0) { return rc; } - } - - // Finally, exec - execve(exec_path, args, env); - // If we got here, something went wrong - return errno; -} - diff --git a/Sources/_SubprocessCShims/string_shims.c b/Sources/_SubprocessCShims/string_shims.c deleted file mode 100644 index e69de29b..00000000 diff --git a/Sources/_SubprocessCShims/uuid.c b/Sources/_SubprocessCShims/uuid.c deleted file mode 100644 index e69de29b..00000000 diff --git a/Tests/JExtractSwiftTests/FuncImportTests.swift b/Tests/JExtractSwiftTests/FuncImportTests.swift index 4c210b3e..aa441487 100644 --- a/Tests/JExtractSwiftTests/FuncImportTests.swift +++ b/Tests/JExtractSwiftTests/FuncImportTests.swift @@ -61,14 +61,14 @@ final class MethodImportTests { } """ - @Test func method_helloWorld() async throws { + @Test func method_helloWorld() throws { let st = Swift2JavaTranslator( javaPackage: "com.example.swift", swiftModuleName: "__FakeModule" ) st.log.logLevel = .trace - try await st.analyze(swiftInterfacePath: "/fake/Fake.swiftinterface", text: class_interfaceFile) + try st.analyze(swiftInterfacePath: "/fake/Fake.swiftinterface", text: class_interfaceFile) let funcDecl = st.importedGlobalFuncs.first { $0.baseIdentifier == "helloWorld" }! @@ -100,14 +100,14 @@ final class MethodImportTests { ) } - @Test func method_globalTakeInt() async throws { + @Test func method_globalTakeInt() throws { let st = Swift2JavaTranslator( javaPackage: "com.example.swift", swiftModuleName: "__FakeModule" ) st.log.logLevel = .trace - try await st.analyze(swiftInterfacePath: "/fake/__FakeModule/SwiftFile.swiftinterface", text: class_interfaceFile) + try st.analyze(swiftInterfacePath: "/fake/__FakeModule/SwiftFile.swiftinterface", text: class_interfaceFile) let funcDecl = st.importedGlobalFuncs.first { $0.baseIdentifier == "globalTakeInt" @@ -141,14 +141,14 @@ final class MethodImportTests { ) } - @Test func method_globalTakeIntLongString() async throws { + @Test func method_globalTakeIntLongString() throws { let st = Swift2JavaTranslator( javaPackage: "com.example.swift", swiftModuleName: "__FakeModule" ) st.log.logLevel = .trace - try await st.analyze(swiftInterfacePath: "/fake/__FakeModule/SwiftFile.swiftinterface", text: class_interfaceFile) + try st.analyze(swiftInterfacePath: "/fake/__FakeModule/SwiftFile.swiftinterface", text: class_interfaceFile) let funcDecl = st.importedGlobalFuncs.first { $0.baseIdentifier == "globalTakeIntLongString" @@ -182,14 +182,14 @@ final class MethodImportTests { ) } - @Test func method_class_helloMemberFunction_self_memorySegment() async throws { + @Test func method_class_helloMemberFunction_self_memorySegment() throws { let st = Swift2JavaTranslator( javaPackage: "com.example.swift", swiftModuleName: "__FakeModule" ) st.log.logLevel = .trace - try await st.analyze(swiftInterfacePath: "/fake/__FakeModule/SwiftFile.swiftinterface", text: class_interfaceFile) + try st.analyze(swiftInterfacePath: "/fake/__FakeModule/SwiftFile.swiftinterface", text: class_interfaceFile) let funcDecl: ImportedFunc = st.importedTypes["MySwiftClass"]!.methods.first { $0.baseIdentifier == "helloMemberFunction" @@ -223,14 +223,14 @@ final class MethodImportTests { ) } - @Test func method_class_helloMemberFunction_self_wrapper() async throws { + @Test func method_class_helloMemberFunction_self_wrapper() throws { let st = Swift2JavaTranslator( javaPackage: "com.example.swift", swiftModuleName: "__FakeModule" ) st.log.logLevel = .trace - try await st.analyze(swiftInterfacePath: "/fake/__FakeModule/SwiftFile.swiftinterface", text: class_interfaceFile) + try st.analyze(swiftInterfacePath: "/fake/__FakeModule/SwiftFile.swiftinterface", text: class_interfaceFile) let funcDecl: ImportedFunc = st.importedTypes["MySwiftClass"]!.methods.first { $0.baseIdentifier == "helloMemberInExtension" @@ -264,14 +264,14 @@ final class MethodImportTests { ) } - func test_method_class_helloMemberFunction_self_wrapper() async throws { + @Test func test_method_class_helloMemberFunction_self_wrapper() throws { let st = Swift2JavaTranslator( javaPackage: "com.example.swift", swiftModuleName: "__FakeModule" ) st.log.logLevel = .trace - try await st.analyze(swiftInterfacePath: "/fake/__FakeModule/SwiftFile.swiftinterface", text: class_interfaceFile) + try st.analyze(swiftInterfacePath: "/fake/__FakeModule/SwiftFile.swiftinterface", text: class_interfaceFile) let funcDecl: ImportedFunc = st.importedTypes["MySwiftClass"]!.methods.first { $0.baseIdentifier == "helloMemberFunction" @@ -305,14 +305,14 @@ final class MethodImportTests { ) } - @Test func method_class_helloMemberFunction_wrapper() async throws { + @Test func method_class_helloMemberFunction_wrapper() throws { let st = Swift2JavaTranslator( javaPackage: "com.example.swift", swiftModuleName: "__FakeModule" ) st.log.logLevel = .trace - try await st.analyze(swiftInterfacePath: "/fake/__FakeModule/SwiftFile.swiftinterface", text: class_interfaceFile) + try st.analyze(swiftInterfacePath: "/fake/__FakeModule/SwiftFile.swiftinterface", text: class_interfaceFile) let funcDecl: ImportedFunc = st.importedTypes["MySwiftClass"]!.methods.first { $0.baseIdentifier == "helloMemberFunction" @@ -338,14 +338,14 @@ final class MethodImportTests { ) } - @Test func method_class_makeInt_wrapper() async throws { + @Test func method_class_makeInt_wrapper() throws { let st = Swift2JavaTranslator( javaPackage: "com.example.swift", swiftModuleName: "__FakeModule" ) st.log.logLevel = .trace - try await st.analyze(swiftInterfacePath: "/fake/__FakeModule/SwiftFile.swiftinterface", text: class_interfaceFile) + try st.analyze(swiftInterfacePath: "/fake/__FakeModule/SwiftFile.swiftinterface", text: class_interfaceFile) let funcDecl: ImportedFunc = st.importedTypes["MySwiftClass"]!.methods.first { $0.baseIdentifier == "makeInt" @@ -371,14 +371,14 @@ final class MethodImportTests { ) } - @Test func class_constructor() async throws { + @Test func class_constructor() throws { let st = Swift2JavaTranslator( javaPackage: "com.example.swift", swiftModuleName: "__FakeModule" ) st.log.logLevel = .trace - try await st.analyze(swiftInterfacePath: "/fake/__FakeModule/SwiftFile.swiftinterface", text: class_interfaceFile) + try st.analyze(swiftInterfacePath: "/fake/__FakeModule/SwiftFile.swiftinterface", text: class_interfaceFile) let initDecl: ImportedFunc = st.importedTypes["MySwiftClass"]!.initializers.first { $0.identifier == "init(len:cap:)" diff --git a/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift b/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift index 064672e1..4fddc965 100644 --- a/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift +++ b/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift @@ -52,15 +52,15 @@ final class FunctionDescriptorTests { javaPackage: String = "com.example.swift", swiftModuleName: String = "SwiftModule", logLevel: Logger.Level = .trace, - body: (String) async throws -> () - ) async throws { + body: (String) throws -> () + ) throws { let st = Swift2JavaTranslator( javaPackage: javaPackage, swiftModuleName: swiftModuleName ) st.log.logLevel = logLevel - try await st.analyze(swiftInterfacePath: "/fake/Sample.swiftinterface", text: interfaceFile) + try st.analyze(swiftInterfacePath: "/fake/Sample.swiftinterface", text: interfaceFile) let funcDecl = st.importedGlobalFuncs.first { $0.baseIdentifier == methodIdentifier @@ -70,12 +70,12 @@ final class FunctionDescriptorTests { st.printFunctionDescriptorValue(&printer, funcDecl) } - try await body(output) + try body(output) } @Test - func FunctionDescriptor_globalTakeInt() async throws { - try await functionDescriptorTest("globalTakeInt") { output in + func FunctionDescriptor_globalTakeInt() throws { + try functionDescriptorTest("globalTakeInt") { output in assertOutput( output, expected: @@ -89,8 +89,8 @@ final class FunctionDescriptorTests { } @Test - func FunctionDescriptor_globalTakeLongIntString() async throws { - try await functionDescriptorTest("globalTakeLongInt") { output in + func FunctionDescriptor_globalTakeLongIntString() throws { + try functionDescriptorTest("globalTakeLongInt") { output in assertOutput( output, expected: @@ -105,8 +105,8 @@ final class FunctionDescriptorTests { } @Test - func FunctionDescriptor_echoInt() async throws { - try await functionDescriptorTest("echoInt") { output in + func FunctionDescriptor_echoInt() throws { + try functionDescriptorTest("echoInt") { output in assertOutput( output, expected: diff --git a/Tests/JExtractSwiftTests/SwiftDylibTests.swift b/Tests/JExtractSwiftTests/SwiftDylibTests.swift deleted file mode 100644 index 09dbb166..00000000 --- a/Tests/JExtractSwiftTests/SwiftDylibTests.swift +++ /dev/null @@ -1,35 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -import JExtractSwift -import Testing - -final class SwiftDylibTests { - - @Test - func test_nm() async throws { - let dylib = SwiftDylib(path: ".build/arm64-apple-macosx/debug/libJavaKitExample.dylib")! - - let names = try await dylib.nmSymbolNames(grepDemangled: ["MySwiftClass", "len"]) - - #expect( - names.contains { - $0.descriptiveName.contains("JavaKitExample.MySwiftClass.len.getter") - } - ) - - let getter = names.findPropertyGetter() - #expect(getter?.mangledName == "$s14JavaKitExample12MySwiftClassC3lenSivg") - #expect(getter?.descriptiveName == "JavaKitExample.MySwiftClass.len.getter : Swift.Int") - } -} diff --git a/Tests/JavaKitTests/BasicRuntimeTests.swift b/Tests/JavaKitTests/BasicRuntimeTests.swift index e133970c..162a97b0 100644 --- a/Tests/JavaKitTests/BasicRuntimeTests.swift +++ b/Tests/JavaKitTests/BasicRuntimeTests.swift @@ -50,7 +50,7 @@ struct BasicRuntimeTests { } @Test("Java exceptions") - func javaExceptionsInSwift() async throws { + func javaExceptionsInSwift() throws { do { _ = try URL("bad url", environment: jvm.environment) } catch { diff --git a/WIP.md b/WIP.md index d5efd30c..c8a6255d 100644 --- a/WIP.md +++ b/WIP.md @@ -57,9 +57,6 @@ Importer: - [x] import global functions into the `Module.theFunction` on Java side - [x] import functions with parameters - [x] import functions return values -- [x] HACK: use dylib to find mangled names of methods -- [x] HACK: use dylib to find mangled names of initializers -- [x] HACK: use dylib to find mangled names of imported types (`TYPE_METADATA_NAME`) - [ ] import instance member functions using "wrapper" pattern - [ ] handle types like `[any Thing]?`, we can't parse them right now even - [ ] support nested types in Swift From 1e60cadb5129cdbec65ac4a431014d4619dc168d Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Mon, 30 Sep 2024 21:36:08 -0700 Subject: [PATCH 016/426] Chomp newline at the end of JAVA_HOME when reading from ~/.java_home --- Package.swift | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Package.swift b/Package.swift index 1e47f8cd..1e4c03d1 100644 --- a/Package.swift +++ b/Package.swift @@ -19,6 +19,10 @@ func findJavaHome() -> String { // picking up env variables during the build process let path = "\(FileManager.default.homeDirectoryForCurrentUser.path()).java_home" if let home = try? String(contentsOfFile: path) { + if let lastChar = home.last, lastChar.isNewline { + return String(home.dropLast()) + } + return home } From e9bb0bc401f317ce5ce7a814aa3191ac4242bb9b Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Mon, 30 Sep 2024 21:36:08 -0700 Subject: [PATCH 017/426] Chomp newline at the end of JAVA_HOME when reading from ~/.java_home --- Package.swift | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Package.swift b/Package.swift index a4869eec..cf6158d1 100644 --- a/Package.swift +++ b/Package.swift @@ -19,6 +19,10 @@ func findJavaHome() -> String { // picking up env variables during the build process let path = "\(FileManager.default.homeDirectoryForCurrentUser.path()).java_home" if let home = try? String(contentsOfFile: path) { + if let lastChar = home.last, lastChar.isNewline { + return String(home.dropLast()) + } + return home } From 14612af4ce4d9d0136046009084d093303ac4d7c Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Wed, 2 Oct 2024 10:52:49 +0900 Subject: [PATCH 018/426] add CONTRIBUTING and explain how to run gh actions locally (#36) --- CONTRIBUTING.md | 109 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..05b02de7 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,109 @@ +## Legal + +By submitting a pull request, you represent that you have the right to license +your contribution to Apple and the community, and agree by submitting the patch +that your contributions are licensed under the Apache 2.0 license (see +`LICENSE.txt`). + +## How to submit a bug report + +Please ensure to specify the following: + +* Commit hash +* Contextual information (e.g. what you were trying to achieve with swift-java) +* Simplest possible steps to reproduce + * More complex the steps are, lower the priority will be. + * A pull request with failing test case is preferred, but it's just fine to paste the test case into the issue description. +* Anything that might be relevant in your opinion, such as: + * Swift version or the output of `swift --version` + * OS version and the output of `uname -a` + +### Example + +``` +Commit hash: b17a8a9f0f814c01a56977680cb68d8a779c951f + +Context: +While testing my application that uses with swift-openapi-generator, I noticed that ... + +Steps to reproduce: +1. ... +2. ... +3. ... +4. ... + +$ swift --version +Swift version 4.0.2 (swift-4.0.2-RELEASE) +Target: x86_64-unknown-linux-gnu + +Operating system: Ubuntu Linux 16.04 64-bit + +$ uname -a +Linux beefy.machine 4.4.0-101-generic #124-Ubuntu SMP Fri Nov 10 18:29:59 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux + +My system has IPv6 disabled. +``` + +## Writing a Patch + +A good patch is: + +1. Concise, and contains as few changes as needed to achieve the end result. +2. Tested, ensuring that any tests provided failed before the patch and pass after it. +3. Documented, adding API documentation as needed to cover new functions and properties. +4. Accompanied by a great commit message, using our commit message template. + +### Run CI checks locally + +You can run the Github Actions workflows locally using +[act](https://github.com/nektos/act). To run all the jobs that run on a pull +request, use the following command: + +``` +% act pull_request +``` + +To run just a single job, use `workflow_call -j `, and specify the inputs +the job expects. For example, to run just shellcheck: + +``` +% act workflow_call -j soundness --input shell_check_enabled=true +``` + +To bind-mount the working directory to the container, rather than a copy, use +`--bind`. For example, to run just the formatting, and have the results +reflected in your working directory: + +``` +% act --bind workflow_call -j soundness --input format_check_enabled=true +``` + +If you'd like `act` to always run with certain flags, these can be be placed in +an `.actrc` file either in the current working directory or your home +directory, for example: + +``` +--container-architecture=linux/amd64 +--remote-name upstream +--action-offline-mode +``` + +For frequent contributors, we recommend adding the script as a [git pre-push hook](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks), which you can do via executing the following command in the project root directory: + +```bash +cat << EOF > .git/hooks/pre-push + +if [[ -f "scripts/soundness.sh" ]]; then + scripts/soundness.sh +fi +EOF +``` + +Which makes the script execute, and only allow the `git push` to complete if the check has passed. + +In the case of formatting issues, you can then `git add` the formatting changes, and attempt the push again. + +## How to contribute your work + +Please open a pull request at https://github.com/swiftlang/swift-java. Make sure the CI passes, and then wait for code review. + From 080c2aee8c028f639b3f8e71ff3f2edf03814f1d Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Thu, 3 Oct 2024 00:06:49 +0900 Subject: [PATCH 019/426] Prepare for Linux build and CI (#14) Co-authored-by: Mishal Shah --- .github/workflows/pull_request.yml | 73 ++ .gitignore | 1 + .licenseignore | 46 + BuildLogic/build.gradle.kts | 1 + BuildLogic/settings.gradle.kts | 1 + ...ic.java-application-conventions.gradle.kts | 1 + ...d-logic.java-common-conventions.gradle.kts | 1 + ...-logic.java-library-conventions.gradle.kts | 1 + JavaSwiftKitDemo/build.gradle.kts | 1 + .../java/com/example/swift/HelloSubclass.java | 2 + .../java/com/example/swift/HelloSwift.java | 2 + .../src/main/java/org/example/CallMe.java | 1 + .../java/org/example/HelloJava2Swift.java | 1 + .../example/swift/ManualJavaKitExample.java | 6 +- .../org/example/swift/ManualMySwiftClass.java | 1 + .../example/swift/Manual_MySwiftClass.java | 1 + .../org/swift/javakit/ManagedSwiftType.java | 1 + .../main/java/org/swift/javakit/SwiftKit.java | 1 + .../java/org/swift/swiftkit/SwiftArena.java | 1 + .../org/swift/swiftkit/SwiftHeapObject.java | 1 + .../example/swift/GlobalFunctionsTest.java | 1 + .../java/org/example/swift/JavaKitTest.java | 1 + .../java/org/example/swift/SwiftKitTest.java | 1 + Makefile | 27 +- Package.swift | 26 +- README.md | 30 + Sources/JExtractSwift/CodePrinter.swift | 1 + .../Convenience/Collection+Extensions.swift | 1 + .../Convenience/SwiftSyntax+Extensions.swift | 1 + Sources/JExtractSwift/ImportedDecls.swift | 1 + .../JavaConstants/ForeignValueLayouts.swift | 1 + Sources/JExtractSwift/JavaTypes.swift | 1 + Sources/JExtractSwift/Logger.swift | 1 + .../JExtractSwift/NominalTypeResolution.swift | 1 + Sources/JExtractSwift/Swift2Java.swift | 1 + .../Swift2JavaTranslator+MemoryLayouts.swift | 1 + .../Swift2JavaTranslator+Printing.swift | 3 +- .../JExtractSwift/Swift2JavaTranslator.swift | 1 + Sources/JExtractSwift/Swift2JavaVisitor.swift | 1 + Sources/JExtractSwift/SwiftDylib.swift | 8 + Sources/JExtractSwift/TerminalColors.swift | 1 + Sources/JExtractSwift/TranslatedType.swift | 1 + .../JExtractSwiftTool/JExtractSwiftTool.swift | 1 + Sources/Java2Swift/JavaToSwift.swift | 1 + .../JavaTranslator+TranslationManifest.swift | 1 + Sources/Java2Swift/JavaTranslator.swift | 1 + Sources/Java2Swift/StringExtras.swift | 1 + Sources/Java2Swift/TranslationError.swift | 1 + Sources/Java2Swift/TranslationManifest.swift | 1 + Sources/JavaKit/AnyJavaObject.swift | 1 + .../BridgedValues/JavaValue+Array.swift | 1 + .../BridgedValues/JavaValue+Bool.swift | 1 + .../JavaValue+FloatingPoint.swift | 1 + .../BridgedValues/JavaValue+Integers.swift | 1 + .../BridgedValues/JavaValue+String.swift | 1 + .../JavaKit/Exceptions/Exception+Error.swift | 1 + .../Exceptions/ExceptionHandling.swift | 1 + .../JavaKit/Exceptions/Throwable+Error.swift | 1 + Sources/JavaKit/JavaClass.swift | 1 + .../JavaKit/JavaEnumeration+Sequence.swift | 1 + Sources/JavaKit/JavaEnvironment.swift | 1 + Sources/JavaKit/JavaObject+Inheritance.swift | 1 + Sources/JavaKit/JavaObject+MethodCalls.swift | 1 + Sources/JavaKit/JavaObjectHolder.swift | 1 + Sources/JavaKit/JavaValue.swift | 1 + Sources/JavaKit/Macros.swift | 1 + Sources/JavaKit/Optional+JavaObject.swift | 1 + Sources/JavaKitExample/JavaKitExample.swift | 1 + Sources/JavaKitExample/MySwiftLibrary.swift | 1 + Sources/JavaKitExample/SwiftKit.swift | 1 + .../JavaKitMacros/ImplementsJavaMacro.swift | 1 + Sources/JavaKitMacros/JavaClassMacro.swift | 2 + Sources/JavaKitMacros/JavaFieldMacro.swift | 1 + Sources/JavaKitMacros/JavaMethodMacro.swift | 1 + Sources/JavaKitMacros/MacroErrors.swift | 1 + .../JavaKitMacros/SwiftJNIMacrosPlugin.swift | 1 + Sources/JavaKitMacros/SwiftSyntaxUtils.swift | 1 + .../Constructor+Utilities.swift | 1 + .../Executable+Utilities.swift | 1 + .../JavaClass+Reflection.swift | 1 + .../JavaKitReflection/Method+Utilities.swift | 1 + Sources/JavaKitVM/JavaVirtualMachine.swift | 1 + Sources/JavaRuntime/dummy.c | 1 + Sources/JavaRuntime/include/JavaRuntime.h | 1 + Sources/JavaTypes/JavaDemanglingError.swift | 1 + Sources/JavaTypes/JavaType+JNI.swift | 1 + Sources/JavaTypes/JavaType+JavaSource.swift | 1 + Sources/JavaTypes/JavaType+SwiftNames.swift | 1 + Sources/JavaTypes/JavaType.swift | 1 + Sources/JavaTypes/Mangling.swift | 1 + Sources/JavaTypes/MethodSignature.swift | 1 + Sources/_Subprocess/LockedState.swift | 158 +++ .../Platforms/Subprocess+Darwin.swift | 447 ++++---- .../Platforms/Subprocess+Linux.swift | 292 +++-- .../Platforms/Subprocess+Unix.swift | 471 ++++---- Sources/_Subprocess/Subprocess+API.swift | 441 ++++---- .../_Subprocess/Subprocess+AsyncBytes.swift | 161 +-- .../Subprocess+Configuration.swift | 1000 ++++++++--------- Sources/_Subprocess/Subprocess+IO.swift | 662 +++++------ Sources/_Subprocess/Subprocess.swift | 358 +++--- Sources/_Subprocess/_LockedState.swift | 159 --- .../include/_CShimsTargetConditionals.h | 14 +- .../_SubprocessCShims/include/process_shims.h | 7 +- Sources/_SubprocessCShims/process_shims.c | 118 +- SwiftJavaKitExample/build.gradle.kts | 1 + SwiftKit/build.gradle.kts | 1 + .../Asserts/TextAssertions.swift | 1 + .../JExtractSwiftTests/FuncImportTests.swift | 1 + .../FunctionDescriptorImportTests.swift | 1 + .../NominalTypeResolutionTests.swift | 1 + .../JExtractSwiftTests/SwiftDylibTests.swift | 5 + Tests/JavaKitTests/BasicRuntimeTests.swift | 11 +- Tests/JavaTypesTests/ManglingTests.swift | 1 + docker/Dockerfile | 22 + docker/docker-compose.2204.main.yaml | 23 + docker/docker-compose.yaml | 47 + docker/install_jdk.sh | 86 ++ scripts/check-license-header.sh | 79 -- settings.gradle.kts | 1 + 119 files changed, 2709 insertions(+), 2165 deletions(-) create mode 100644 .github/workflows/pull_request.yml create mode 100644 .licenseignore create mode 100644 Sources/_Subprocess/LockedState.swift delete mode 100644 Sources/_Subprocess/_LockedState.swift create mode 100644 docker/Dockerfile create mode 100644 docker/docker-compose.2204.main.yaml create mode 100644 docker/docker-compose.yaml create mode 100755 docker/install_jdk.sh delete mode 100755 scripts/check-license-header.sh diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml new file mode 100644 index 00000000..0114da27 --- /dev/null +++ b/.github/workflows/pull_request.yml @@ -0,0 +1,73 @@ +name: pull_request + +on: + pull_request: + types: [ opened, reopened, synchronize ] + +jobs: + soundness: + uses: swiftlang/github-workflows/.github/workflows/soundness.yml@main + with: + api_breakage_check_enabled: false + # FIXME: Something is off with the format task and it gets "stuck", need to investigate + format_check_enabled: false + license_header_check_project_name: Swift.org + # FIXME: we're about to remove _Subprocess immediately anyway, so rather than fixing it one by one remove this adjusted list and use the default again ASAP + # swift-subprocess includes the word "kill" because SIGKILL signal handling so we allow it + unacceptable_language_check_word_list: "blacklist whitelist slave master sane sanity insane insanity killed killing hang hung hanged hanging" #ignore-unacceptable-language + + test-java: + name: Java tests (swift:${{ matrix.swift_version }} jdk:${{matrix.jdk_vendor}} os:${{ matrix.os_version }}) + runs-on: ubuntu-latest + strategy: + fail-fast: true + matrix: + swift_version: [ 'nightly-main' ] + os_version: [ 'jammy' ] + jdk_vendor: [ 'Corretto' ] + container: + image: ${{ (contains(matrix.swift_version, 'nightly') && 'swiftlang/swift') || 'swift' }}:${{ matrix.swift_version }}-${{ matrix.os_version }} + env: + JAVA_HOME: "/usr/lib/jvm/default-jdk" + steps: + - uses: actions/checkout@v4 + - name: Install Make + run: apt-get -qq update && apt-get -qq install -y make + - name: Install JDK + run: "bash -xc 'JDK_VENDOR=${{ matrix.jdk_vendor }} ./docker/install_jdk.sh'" + # TODO: not using setup-java since incompatible with the swiftlang/swift base image + # - uses: actions/setup-java@v4 + # with: + # distribution: 'zulu' + # java-version: '22' + # cache: 'gradle' + - name: Generate sources (make) (Temporary) + # TODO: this should be triggered by the respective builds + run: make jextract-run + - name: Gradle build + run: ./gradlew build --no-daemon + + test-swift: + name: Swift tests (swift:${{ matrix.swift_version }} jdk:${{matrix.jdk_vendor}} os:${{ matrix.os_version }}) + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + swift_version: [ 'nightly-main' ] + os_version: [ 'jammy' ] + jdk_vendor: [ 'Corretto' ] + container: + image: ${{ (contains(matrix.swift_version, 'nightly') && 'swiftlang/swift') || 'swift' }}:${{ matrix.swift_version }}-${{ matrix.os_version }} + env: + JAVA_HOME: "/usr/lib/jvm/default-jdk" + steps: + - uses: actions/checkout@v4 + - name: Install Make + run: apt-get -qq update && apt-get -qq install -y make + - name: Install JDK + run: "bash -xc 'JDK_VENDOR=${{ matrix.jdk_vendor }} ./docker/install_jdk.sh'" + - name: Generate sources (make) (Temporary) + # TODO: this should be triggered by the respective builds + run: "make jextract-run" + - name: Test Swift + run: "swift test" diff --git a/.gitignore b/.gitignore index b9c1eadb..416f253f 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ DerivedData/ .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata .netrc *.class +bin/ # Ignore gradle build artifacts .gradle diff --git a/.licenseignore b/.licenseignore new file mode 100644 index 00000000..86afc57b --- /dev/null +++ b/.licenseignore @@ -0,0 +1,46 @@ +.gitignore +.licenseignore +.swiftformatignore +.spi.yml +.swift-format +.github/* +*.md +CONTRIBUTORS.txt +LICENSE.txt +NOTICE.txt +Package.swift +Package.resolved +README.md +SECURITY.md +scripts/unacceptable-language.txt +docker/* +**/*.docc/* +**/.gitignore +**/Package.swift +**/Package.resolved +**/*.md +**/openapi.yml +**/petstore.yaml +**/openapi-generator-config.yaml +**/openapi-generator-config.yml +**/docker-compose.yaml +**/docker/* +**/.dockerignore +JavaSwiftKitDemo/src/main/java/com/example/swift/generated/* +Makefile +**/Makefile +**/*.html +**/CMakeLists.txt +**/*.jar +gradle/wrapper/gradle-wrapper.properties +gradlew +gradlew.bat +**/*.swift2java +Sources/JavaKit/generated/* +Sources/JavaKitJar/generated/* +Sources/JavaKitNetwork/generated/* +Sources/JavaKitReflection/generated/* +Sources/_Subprocess/* +Sources/_Subprocess/**/* +Sources/_SubprocessCShims/* +Sources/_SubprocessCShims/**/* diff --git a/BuildLogic/build.gradle.kts b/BuildLogic/build.gradle.kts index 5efdc8c8..142b7f7c 100644 --- a/BuildLogic/build.gradle.kts +++ b/BuildLogic/build.gradle.kts @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/BuildLogic/settings.gradle.kts b/BuildLogic/settings.gradle.kts index 045cfa06..44b13a6b 100644 --- a/BuildLogic/settings.gradle.kts +++ b/BuildLogic/settings.gradle.kts @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/BuildLogic/src/main/kotlin/build-logic.java-application-conventions.gradle.kts b/BuildLogic/src/main/kotlin/build-logic.java-application-conventions.gradle.kts index 0ab89662..4bd9b815 100644 --- a/BuildLogic/src/main/kotlin/build-logic.java-application-conventions.gradle.kts +++ b/BuildLogic/src/main/kotlin/build-logic.java-application-conventions.gradle.kts @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/BuildLogic/src/main/kotlin/build-logic.java-common-conventions.gradle.kts b/BuildLogic/src/main/kotlin/build-logic.java-common-conventions.gradle.kts index 67e91248..85142bd9 100644 --- a/BuildLogic/src/main/kotlin/build-logic.java-common-conventions.gradle.kts +++ b/BuildLogic/src/main/kotlin/build-logic.java-common-conventions.gradle.kts @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/BuildLogic/src/main/kotlin/build-logic.java-library-conventions.gradle.kts b/BuildLogic/src/main/kotlin/build-logic.java-library-conventions.gradle.kts index 0ab89662..4bd9b815 100644 --- a/BuildLogic/src/main/kotlin/build-logic.java-library-conventions.gradle.kts +++ b/BuildLogic/src/main/kotlin/build-logic.java-library-conventions.gradle.kts @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/JavaSwiftKitDemo/build.gradle.kts b/JavaSwiftKitDemo/build.gradle.kts index dd325591..84c0b924 100644 --- a/JavaSwiftKitDemo/build.gradle.kts +++ b/JavaSwiftKitDemo/build.gradle.kts @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/JavaSwiftKitDemo/src/main/java/com/example/swift/HelloSubclass.java b/JavaSwiftKitDemo/src/main/java/com/example/swift/HelloSubclass.java index 29258d3b..25cc9245 100644 --- a/JavaSwiftKitDemo/src/main/java/com/example/swift/HelloSubclass.java +++ b/JavaSwiftKitDemo/src/main/java/com/example/swift/HelloSubclass.java @@ -6,12 +6,14 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// package com.example.swift; + import com.example.swift.HelloSwift; public class HelloSubclass extends HelloSwift { diff --git a/JavaSwiftKitDemo/src/main/java/com/example/swift/HelloSwift.java b/JavaSwiftKitDemo/src/main/java/com/example/swift/HelloSwift.java index a6c9bbd7..652d230b 100644 --- a/JavaSwiftKitDemo/src/main/java/com/example/swift/HelloSwift.java +++ b/JavaSwiftKitDemo/src/main/java/com/example/swift/HelloSwift.java @@ -6,12 +6,14 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// package com.example.swift; + import com.example.swift.HelloSubclass; public class HelloSwift { diff --git a/JavaSwiftKitDemo/src/main/java/org/example/CallMe.java b/JavaSwiftKitDemo/src/main/java/org/example/CallMe.java index fc7f0373..4af50f91 100644 --- a/JavaSwiftKitDemo/src/main/java/org/example/CallMe.java +++ b/JavaSwiftKitDemo/src/main/java/org/example/CallMe.java @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/JavaSwiftKitDemo/src/main/java/org/example/HelloJava2Swift.java b/JavaSwiftKitDemo/src/main/java/org/example/HelloJava2Swift.java index 4aa00b25..00264946 100644 --- a/JavaSwiftKitDemo/src/main/java/org/example/HelloJava2Swift.java +++ b/JavaSwiftKitDemo/src/main/java/org/example/HelloJava2Swift.java @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/JavaSwiftKitDemo/src/main/java/org/example/swift/ManualJavaKitExample.java b/JavaSwiftKitDemo/src/main/java/org/example/swift/ManualJavaKitExample.java index a3499b15..f11c5637 100644 --- a/JavaSwiftKitDemo/src/main/java/org/example/swift/ManualJavaKitExample.java +++ b/JavaSwiftKitDemo/src/main/java/org/example/swift/ManualJavaKitExample.java @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // @@ -199,14 +200,13 @@ public static void globalCallJavaCallback(Runnable callMe) { var mh$ = globalCallJavaCallback.HANDLE; try { + // signature of 'void run()' FunctionDescriptor callMe_run_desc = FunctionDescriptor.ofVoid( - // replicate signature of run() ); MethodHandle callMe_run_handle = MethodHandles.lookup() .findVirtual(Runnable.class, "run", - callMe_run_desc.toMethodType() - ); + callMe_run_desc.toMethodType()); callMe_run_handle = callMe_run_handle.bindTo(callMe); // set the first parameter to the Runnable as the "this" of the callback pretty much try (Arena arena = Arena.ofConfined()) { diff --git a/JavaSwiftKitDemo/src/main/java/org/example/swift/ManualMySwiftClass.java b/JavaSwiftKitDemo/src/main/java/org/example/swift/ManualMySwiftClass.java index b7994665..53b21e8a 100644 --- a/JavaSwiftKitDemo/src/main/java/org/example/swift/ManualMySwiftClass.java +++ b/JavaSwiftKitDemo/src/main/java/org/example/swift/ManualMySwiftClass.java @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/JavaSwiftKitDemo/src/main/java/org/example/swift/Manual_MySwiftClass.java b/JavaSwiftKitDemo/src/main/java/org/example/swift/Manual_MySwiftClass.java index d9f39034..9ef51038 100644 --- a/JavaSwiftKitDemo/src/main/java/org/example/swift/Manual_MySwiftClass.java +++ b/JavaSwiftKitDemo/src/main/java/org/example/swift/Manual_MySwiftClass.java @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/JavaSwiftKitDemo/src/main/java/org/swift/javakit/ManagedSwiftType.java b/JavaSwiftKitDemo/src/main/java/org/swift/javakit/ManagedSwiftType.java index c5a3aa97..117a0a09 100644 --- a/JavaSwiftKitDemo/src/main/java/org/swift/javakit/ManagedSwiftType.java +++ b/JavaSwiftKitDemo/src/main/java/org/swift/javakit/ManagedSwiftType.java @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/JavaSwiftKitDemo/src/main/java/org/swift/javakit/SwiftKit.java b/JavaSwiftKitDemo/src/main/java/org/swift/javakit/SwiftKit.java index 0c43db5a..07765a08 100644 --- a/JavaSwiftKitDemo/src/main/java/org/swift/javakit/SwiftKit.java +++ b/JavaSwiftKitDemo/src/main/java/org/swift/javakit/SwiftKit.java @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/JavaSwiftKitDemo/src/main/java/org/swift/swiftkit/SwiftArena.java b/JavaSwiftKitDemo/src/main/java/org/swift/swiftkit/SwiftArena.java index 5f24a3ef..2c60dc3f 100644 --- a/JavaSwiftKitDemo/src/main/java/org/swift/swiftkit/SwiftArena.java +++ b/JavaSwiftKitDemo/src/main/java/org/swift/swiftkit/SwiftArena.java @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/JavaSwiftKitDemo/src/main/java/org/swift/swiftkit/SwiftHeapObject.java b/JavaSwiftKitDemo/src/main/java/org/swift/swiftkit/SwiftHeapObject.java index 21152cf8..5d1945dd 100644 --- a/JavaSwiftKitDemo/src/main/java/org/swift/swiftkit/SwiftHeapObject.java +++ b/JavaSwiftKitDemo/src/main/java/org/swift/swiftkit/SwiftHeapObject.java @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/JavaSwiftKitDemo/src/test/java/org/example/swift/GlobalFunctionsTest.java b/JavaSwiftKitDemo/src/test/java/org/example/swift/GlobalFunctionsTest.java index f3b15e7b..7faff6b0 100644 --- a/JavaSwiftKitDemo/src/test/java/org/example/swift/GlobalFunctionsTest.java +++ b/JavaSwiftKitDemo/src/test/java/org/example/swift/GlobalFunctionsTest.java @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/JavaSwiftKitDemo/src/test/java/org/example/swift/JavaKitTest.java b/JavaSwiftKitDemo/src/test/java/org/example/swift/JavaKitTest.java index 89b5350c..404dca42 100644 --- a/JavaSwiftKitDemo/src/test/java/org/example/swift/JavaKitTest.java +++ b/JavaSwiftKitDemo/src/test/java/org/example/swift/JavaKitTest.java @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/JavaSwiftKitDemo/src/test/java/org/example/swift/SwiftKitTest.java b/JavaSwiftKitDemo/src/test/java/org/example/swift/SwiftKitTest.java index 5eda123a..390b1ceb 100644 --- a/JavaSwiftKitDemo/src/test/java/org/example/swift/SwiftKitTest.java +++ b/JavaSwiftKitDemo/src/test/java/org/example/swift/SwiftKitTest.java @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Makefile b/Makefile index 0e5b4817..a0baff12 100644 --- a/Makefile +++ b/Makefile @@ -15,23 +15,38 @@ .PHONY: run clean all ARCH := $(shell arch) +UNAME := $(shell uname) + +ifeq ($(UNAME), Linux) +ifeq ($(ARCH), 'i386') + ARCH_SUBDIR := x86_64 +else + ARCH_SUBDIR := aarch64 +endif +BUILD_DIR := .build/$(ARCH_SUBDIR)-unknown-linux-gnu +LIB_SUFFIX := so +endif + +ifeq ($(UNAME), Darwin) ifeq ($(ARCH), 'i386') ARCH_SUBDIR := x86_64 else ARCH_SUBDIR := arm64 endif +BUILD_DIR := .build/$(ARCH_SUBDIR)-apple-macosx +LIB_SUFFIX := dylib +endif -BUILD_DIR=".build/$(ARCH_SUBDIR)-apple-macosx" all: generate-all -$(BUILD_DIR)/debug/libJavaKit.dylib $(BUILD_DIR)/debug/libJavaKitExample.dylib $(BUILD_DIR)/debug/Java2Swift: +$(BUILD_DIR)/debug/libJavaKit.$(LIB_SUFFIX) $(BUILD_DIR)/debug/libJavaKitExample.$(LIB_SUFFIX) $(BUILD_DIR)/debug/Java2Swift: swift build ./JavaSwiftKitDemo/build/classes/java/main/com/example/swift/HelloSubclass.class: JavaSwiftKitDemo/src/main/java/com/example/swift ./gradlew build -run: $(BUILD_DIR)/debug/libJavaKit.dylib $(BUILD_DIR)/debug/libJavaKitExample.dylib JavaSwiftKitDemo/src/main/java/com/example/swift +run: $(BUILD_DIR)/debug/libJavaKit.$(LIB_SUFFIX) $(BUILD_DIR)/debug/libJavaKitExample.$(LIB_SUFFIX) JavaSwiftKitDemo/src/main/java/com/example/swift java -cp JavaSwiftKitDemo/build/classes/java/main -Djava.library.path=$(BUILD_DIR)/debug/ com.example.swift.HelloSwift Java2Swift: $(BUILD_DIR)/debug/Java2Swift @@ -82,7 +97,7 @@ endef jextract-swift: generate-JExtract-interface-files swift build -generate-JExtract-interface-files: $(BUILD_DIR)/debug/libJavaKit.dylib +generate-JExtract-interface-files: $(BUILD_DIR)/debug/libJavaKit.$(LIB_SUFFIX) echo "Generate .swiftinterface files..." @$(call make_swiftinterface, "JavaKitExample", "MySwiftLibrary") @$(call make_swiftinterface, "JavaKitExample", "SwiftKit") @@ -92,8 +107,8 @@ jextract-run: jextract-swift generate-JExtract-interface-files --package-name com.example.swift.generated \ --swift-module JavaKitExample \ --output-directory JavaSwiftKitDemo/src/main/java \ - .build/arm64-apple-macosx/jextract/JavaKitExample/MySwiftLibrary.swiftinterface \ - .build/arm64-apple-macosx/jextract/JavaKitExample/SwiftKit.swiftinterface + $(BUILD_DIR)/jextract/JavaKitExample/MySwiftLibrary.swiftinterface \ + $(BUILD_DIR)/jextract/JavaKitExample/SwiftKit.swiftinterface jextract-run-java: jextract-swift generate-JExtract-interface-files diff --git a/Package.swift b/Package.swift index cf6158d1..705ab731 100644 --- a/Package.swift +++ b/Package.swift @@ -30,6 +30,16 @@ func findJavaHome() -> String { } let javaHome = findJavaHome() +let javaIncludePath = "\(javaHome)/include" +#if os(Linux) + let javaPlatformIncludePath = "\(javaIncludePath)/linux" +#elseif os(macOS) + let javaPlatformIncludePath = "\(javaIncludePath)/darwin" +#else + #error("Currently only macOS and Linux platforms are supported, this may change in the future.") +// TODO: Handle windows as well +#endif + let package = Package( name: "JavaKit", platforms: [ @@ -119,7 +129,7 @@ let package = Package( dependencies: ["JavaRuntime", "JavaKitMacros", "JavaTypes"], exclude: ["generated/JavaKit.swift2java"], swiftSettings: [ - .unsafeFlags(["-I\(javaHome)/include", "-I\(javaHome)/include/darwin"]) + .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) ] ), .target( @@ -127,7 +137,7 @@ let package = Package( dependencies: ["JavaKit"], exclude: ["generated/JavaKitJar.swift2java"], swiftSettings: [ - .unsafeFlags(["-I\(javaHome)/include", "-I\(javaHome)/include/darwin"]) + .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) ] ), .target( @@ -135,7 +145,7 @@ let package = Package( dependencies: ["JavaKit"], exclude: ["generated/JavaKitNetwork.swift2java"], swiftSettings: [ - .unsafeFlags(["-I\(javaHome)/include", "-I\(javaHome)/include/darwin"]) + .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) ] ), .target( @@ -143,14 +153,14 @@ let package = Package( dependencies: ["JavaKit"], exclude: ["generated/JavaKitReflection.swift2java"], swiftSettings: [ - .unsafeFlags(["-I\(javaHome)/include", "-I\(javaHome)/include/darwin"]) + .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) ] ), .target( name: "JavaKitVM", dependencies: ["JavaKit"], swiftSettings: [ - .unsafeFlags(["-I\(javaHome)/include", "-I\(javaHome)/include/darwin"]) + .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) ], linkerSettings: [ .unsafeFlags( @@ -169,14 +179,14 @@ let package = Package( name: "JavaKitExample", dependencies: ["JavaKit"], swiftSettings: [ - .unsafeFlags(["-I\(javaHome)/include", "-I\(javaHome)/include/darwin"]) + .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) ] ), .target( name: "JavaRuntime", swiftSettings: [ - .unsafeFlags(["-I\(javaHome)/include", "-I\(javaHome)/include/darwin"]) + .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) ] ), @@ -253,7 +263,7 @@ let package = Package( "JExtractSwift" ], swiftSettings: [ - .unsafeFlags(["-I\(javaHome)/include", "-I\(javaHome)/include/darwin"]) + .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) ] ), ] diff --git a/README.md b/README.md index cc208d40..a2facd6a 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,23 @@ Parts of this project are incomplete, not fleshed out, and subject to change wit The primary purpose of this repository is to create an environment for collaboration and joint exploration of the Swift/Java interoperability story. The project will transition to a more structured approach once key goals have been outlined. +## Dependencies + +This project consists of different modules which have different Swift and Java runtime requirements. + +**JavaKit** – the Swift macros allowing the invocation of Java libraries from Swift + +- **JDK 17+**, any recent JDK installation should be sufficient, as only general reflection and JNI APIs are used by this integration +- **Swift 6.0+**, because the library uses modern Swift macros + +**jextract-swift** – the source generator that ingests .swiftinterface files and makes them available to be called from generated Java sources + +- **Swift 6.x development snapshots**, because of dependence on rich swift interface files +- **JDK 22+** because of dependence on [JEP-454: Foreign Function & Memory API](https://openjdk.org/jeps/454) + - We are validating the implementation using the currently supported non-LTE release, which at present means JDK-23. + +The extract tool may become able to generate legacy compatible sources, which would not require JEP-454 and would instead rely on existing JNI facilities. Currently though, efforts are focused on the forward-looking implementation using modern foreign function and memory APIs. + ## Development and Testing This project contains quite a few builds, Swift, Java, and depends on some custom steps. @@ -26,6 +43,19 @@ swift test # test all Swift code, e.g. jextract-swift ./gradlew test # test all Java code, including integration tests that actually use jextract-ed sources ``` +To test on Linux using Docker you can: + +```bash +# run only Swift tests (i.e. swift test) +docker-compose -f docker/docker-compose.yaml -f docker/docker-compose.2204.main.yaml run test-swift + +# run only Java tests (i.e. gradle test) +docker-compose -f docker/docker-compose.yaml -f docker/docker-compose.2204.main.yaml run test-java + +# run all tests +docker-compose -f docker/docker-compose.yaml -f docker/docker-compose.2204.main.yaml run test +``` + ### Examples #### JavaKit (Swift -> Java) diff --git a/Sources/JExtractSwift/CodePrinter.swift b/Sources/JExtractSwift/CodePrinter.swift index 80fdd79d..56a61a42 100644 --- a/Sources/JExtractSwift/CodePrinter.swift +++ b/Sources/JExtractSwift/CodePrinter.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Sources/JExtractSwift/Convenience/Collection+Extensions.swift b/Sources/JExtractSwift/Convenience/Collection+Extensions.swift index 1f8cb0e6..ca23435c 100644 --- a/Sources/JExtractSwift/Convenience/Collection+Extensions.swift +++ b/Sources/JExtractSwift/Convenience/Collection+Extensions.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Sources/JExtractSwift/Convenience/SwiftSyntax+Extensions.swift b/Sources/JExtractSwift/Convenience/SwiftSyntax+Extensions.swift index b175482e..0a8f5533 100644 --- a/Sources/JExtractSwift/Convenience/SwiftSyntax+Extensions.swift +++ b/Sources/JExtractSwift/Convenience/SwiftSyntax+Extensions.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Sources/JExtractSwift/ImportedDecls.swift b/Sources/JExtractSwift/ImportedDecls.swift index a1254d51..c8cdd8fa 100644 --- a/Sources/JExtractSwift/ImportedDecls.swift +++ b/Sources/JExtractSwift/ImportedDecls.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Sources/JExtractSwift/JavaConstants/ForeignValueLayouts.swift b/Sources/JExtractSwift/JavaConstants/ForeignValueLayouts.swift index a63f565d..292b7182 100644 --- a/Sources/JExtractSwift/JavaConstants/ForeignValueLayouts.swift +++ b/Sources/JExtractSwift/JavaConstants/ForeignValueLayouts.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Sources/JExtractSwift/JavaTypes.swift b/Sources/JExtractSwift/JavaTypes.swift index e38df600..01a69aaf 100644 --- a/Sources/JExtractSwift/JavaTypes.swift +++ b/Sources/JExtractSwift/JavaTypes.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Sources/JExtractSwift/Logger.swift b/Sources/JExtractSwift/Logger.swift index 41c0a96a..7309c3d7 100644 --- a/Sources/JExtractSwift/Logger.swift +++ b/Sources/JExtractSwift/Logger.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Sources/JExtractSwift/NominalTypeResolution.swift b/Sources/JExtractSwift/NominalTypeResolution.swift index c655598c..e3cc18a1 100644 --- a/Sources/JExtractSwift/NominalTypeResolution.swift +++ b/Sources/JExtractSwift/NominalTypeResolution.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Sources/JExtractSwift/Swift2Java.swift b/Sources/JExtractSwift/Swift2Java.swift index ab97da2a..5c6d8a69 100644 --- a/Sources/JExtractSwift/Swift2Java.swift +++ b/Sources/JExtractSwift/Swift2Java.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Sources/JExtractSwift/Swift2JavaTranslator+MemoryLayouts.swift b/Sources/JExtractSwift/Swift2JavaTranslator+MemoryLayouts.swift index 5109446b..4e8f6aa7 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator+MemoryLayouts.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator+MemoryLayouts.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift b/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift index 46274c35..7f238c75 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // @@ -116,7 +117,7 @@ extension Swift2JavaTranslator { printer.print( """ // FIXME: this detecting is somewhat off - public static final String TYPE_METADATA_NAME = "\(decl.swiftMangledName!)"; + public static final String TYPE_METADATA_NAME = "\(decl.swiftMangledName ?? "")"; static final MemorySegment TYPE_METADATA = SwiftKit.getTypeByMangledNameInEnvironment(TYPE_METADATA_NAME); """ ) diff --git a/Sources/JExtractSwift/Swift2JavaTranslator.swift b/Sources/JExtractSwift/Swift2JavaTranslator.swift index d66e23c2..e942ff9b 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Sources/JExtractSwift/Swift2JavaVisitor.swift b/Sources/JExtractSwift/Swift2JavaVisitor.swift index e4524461..c6c9bb56 100644 --- a/Sources/JExtractSwift/Swift2JavaVisitor.swift +++ b/Sources/JExtractSwift/Swift2JavaVisitor.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Sources/JExtractSwift/SwiftDylib.swift b/Sources/JExtractSwift/SwiftDylib.swift index 486aa3ab..28ddcb90 100644 --- a/Sources/JExtractSwift/SwiftDylib.swift +++ b/Sources/JExtractSwift/SwiftDylib.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // @@ -109,6 +110,13 @@ package struct SwiftDylib { // FIXME: remove this entire utility; replace with /// So not even trying to make this very efficient. We find the symbols from the dylib and some /// heuristic matching. package func nmSymbolNames(grepDemangled: [String]) async throws -> [SwiftSymbolName] { + #if os(Linux) + #warning("Obtaining symbols with 'nm' is not supported on Linux and about to be removed in any case") + return [] + #endif + + // ----- + let nmResult = try await Subprocess.run( .named("nm"), arguments: ["-gU", path] diff --git a/Sources/JExtractSwift/TerminalColors.swift b/Sources/JExtractSwift/TerminalColors.swift index e36de1c7..fcef5a3c 100644 --- a/Sources/JExtractSwift/TerminalColors.swift +++ b/Sources/JExtractSwift/TerminalColors.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Sources/JExtractSwift/TranslatedType.swift b/Sources/JExtractSwift/TranslatedType.swift index 8262aff4..c759b3af 100644 --- a/Sources/JExtractSwift/TranslatedType.swift +++ b/Sources/JExtractSwift/TranslatedType.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Sources/JExtractSwiftTool/JExtractSwiftTool.swift b/Sources/JExtractSwiftTool/JExtractSwiftTool.swift index 2e3c339f..b9853b82 100644 --- a/Sources/JExtractSwiftTool/JExtractSwiftTool.swift +++ b/Sources/JExtractSwiftTool/JExtractSwiftTool.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Sources/Java2Swift/JavaToSwift.swift b/Sources/Java2Swift/JavaToSwift.swift index c43c7e04..87fcc7e7 100644 --- a/Sources/Java2Swift/JavaToSwift.swift +++ b/Sources/Java2Swift/JavaToSwift.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Sources/Java2Swift/JavaTranslator+TranslationManifest.swift b/Sources/Java2Swift/JavaTranslator+TranslationManifest.swift index d839053e..244cefd4 100644 --- a/Sources/Java2Swift/JavaTranslator+TranslationManifest.swift +++ b/Sources/Java2Swift/JavaTranslator+TranslationManifest.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Sources/Java2Swift/JavaTranslator.swift b/Sources/Java2Swift/JavaTranslator.swift index f416cf14..c83e5c85 100644 --- a/Sources/Java2Swift/JavaTranslator.swift +++ b/Sources/Java2Swift/JavaTranslator.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Sources/Java2Swift/StringExtras.swift b/Sources/Java2Swift/StringExtras.swift index a066eec0..34729883 100644 --- a/Sources/Java2Swift/StringExtras.swift +++ b/Sources/Java2Swift/StringExtras.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Sources/Java2Swift/TranslationError.swift b/Sources/Java2Swift/TranslationError.swift index b4839c3e..d44fd2d7 100644 --- a/Sources/Java2Swift/TranslationError.swift +++ b/Sources/Java2Swift/TranslationError.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Sources/Java2Swift/TranslationManifest.swift b/Sources/Java2Swift/TranslationManifest.swift index c24c171e..aa03eae6 100644 --- a/Sources/Java2Swift/TranslationManifest.swift +++ b/Sources/Java2Swift/TranslationManifest.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Sources/JavaKit/AnyJavaObject.swift b/Sources/JavaKit/AnyJavaObject.swift index 209dd3ae..aaddaa9a 100644 --- a/Sources/JavaKit/AnyJavaObject.swift +++ b/Sources/JavaKit/AnyJavaObject.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Sources/JavaKit/BridgedValues/JavaValue+Array.swift b/Sources/JavaKit/BridgedValues/JavaValue+Array.swift index f09aaf2f..dce723d1 100644 --- a/Sources/JavaKit/BridgedValues/JavaValue+Array.swift +++ b/Sources/JavaKit/BridgedValues/JavaValue+Array.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Sources/JavaKit/BridgedValues/JavaValue+Bool.swift b/Sources/JavaKit/BridgedValues/JavaValue+Bool.swift index 5a1149b5..c1599076 100644 --- a/Sources/JavaKit/BridgedValues/JavaValue+Bool.swift +++ b/Sources/JavaKit/BridgedValues/JavaValue+Bool.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Sources/JavaKit/BridgedValues/JavaValue+FloatingPoint.swift b/Sources/JavaKit/BridgedValues/JavaValue+FloatingPoint.swift index 53c46bbf..f90c5019 100644 --- a/Sources/JavaKit/BridgedValues/JavaValue+FloatingPoint.swift +++ b/Sources/JavaKit/BridgedValues/JavaValue+FloatingPoint.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Sources/JavaKit/BridgedValues/JavaValue+Integers.swift b/Sources/JavaKit/BridgedValues/JavaValue+Integers.swift index ba3e9803..39dca985 100644 --- a/Sources/JavaKit/BridgedValues/JavaValue+Integers.swift +++ b/Sources/JavaKit/BridgedValues/JavaValue+Integers.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Sources/JavaKit/BridgedValues/JavaValue+String.swift b/Sources/JavaKit/BridgedValues/JavaValue+String.swift index 016bdc23..028cf390 100644 --- a/Sources/JavaKit/BridgedValues/JavaValue+String.swift +++ b/Sources/JavaKit/BridgedValues/JavaValue+String.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Sources/JavaKit/Exceptions/Exception+Error.swift b/Sources/JavaKit/Exceptions/Exception+Error.swift index 7071bce8..688ae9d0 100644 --- a/Sources/JavaKit/Exceptions/Exception+Error.swift +++ b/Sources/JavaKit/Exceptions/Exception+Error.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Sources/JavaKit/Exceptions/ExceptionHandling.swift b/Sources/JavaKit/Exceptions/ExceptionHandling.swift index d9c4129b..44f1897c 100644 --- a/Sources/JavaKit/Exceptions/ExceptionHandling.swift +++ b/Sources/JavaKit/Exceptions/ExceptionHandling.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Sources/JavaKit/Exceptions/Throwable+Error.swift b/Sources/JavaKit/Exceptions/Throwable+Error.swift index c6eb99d8..bae53123 100644 --- a/Sources/JavaKit/Exceptions/Throwable+Error.swift +++ b/Sources/JavaKit/Exceptions/Throwable+Error.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Sources/JavaKit/JavaClass.swift b/Sources/JavaKit/JavaClass.swift index 8db54bae..8cb2e3c2 100644 --- a/Sources/JavaKit/JavaClass.swift +++ b/Sources/JavaKit/JavaClass.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Sources/JavaKit/JavaEnumeration+Sequence.swift b/Sources/JavaKit/JavaEnumeration+Sequence.swift index b096dbc8..742bfc91 100644 --- a/Sources/JavaKit/JavaEnumeration+Sequence.swift +++ b/Sources/JavaKit/JavaEnumeration+Sequence.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Sources/JavaKit/JavaEnvironment.swift b/Sources/JavaKit/JavaEnvironment.swift index 4e92d635..d74146ab 100644 --- a/Sources/JavaKit/JavaEnvironment.swift +++ b/Sources/JavaKit/JavaEnvironment.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Sources/JavaKit/JavaObject+Inheritance.swift b/Sources/JavaKit/JavaObject+Inheritance.swift index 46e0aab2..8d6b68fa 100644 --- a/Sources/JavaKit/JavaObject+Inheritance.swift +++ b/Sources/JavaKit/JavaObject+Inheritance.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Sources/JavaKit/JavaObject+MethodCalls.swift b/Sources/JavaKit/JavaObject+MethodCalls.swift index 3e625b77..62a5617e 100644 --- a/Sources/JavaKit/JavaObject+MethodCalls.swift +++ b/Sources/JavaKit/JavaObject+MethodCalls.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Sources/JavaKit/JavaObjectHolder.swift b/Sources/JavaKit/JavaObjectHolder.swift index 29529ef5..173991c9 100644 --- a/Sources/JavaKit/JavaObjectHolder.swift +++ b/Sources/JavaKit/JavaObjectHolder.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Sources/JavaKit/JavaValue.swift b/Sources/JavaKit/JavaValue.swift index ab7bc50d..310b54df 100644 --- a/Sources/JavaKit/JavaValue.swift +++ b/Sources/JavaKit/JavaValue.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Sources/JavaKit/Macros.swift b/Sources/JavaKit/Macros.swift index 24383dc8..24ce8d32 100644 --- a/Sources/JavaKit/Macros.swift +++ b/Sources/JavaKit/Macros.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Sources/JavaKit/Optional+JavaObject.swift b/Sources/JavaKit/Optional+JavaObject.swift index d66f54fd..0444b4f1 100644 --- a/Sources/JavaKit/Optional+JavaObject.swift +++ b/Sources/JavaKit/Optional+JavaObject.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Sources/JavaKitExample/JavaKitExample.swift b/Sources/JavaKitExample/JavaKitExample.swift index 3253637b..7252d648 100644 --- a/Sources/JavaKitExample/JavaKitExample.swift +++ b/Sources/JavaKitExample/JavaKitExample.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Sources/JavaKitExample/MySwiftLibrary.swift b/Sources/JavaKitExample/MySwiftLibrary.swift index 115a281d..bd76fcf1 100644 --- a/Sources/JavaKitExample/MySwiftLibrary.swift +++ b/Sources/JavaKitExample/MySwiftLibrary.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Sources/JavaKitExample/SwiftKit.swift b/Sources/JavaKitExample/SwiftKit.swift index df4a258f..e034f6d0 100644 --- a/Sources/JavaKitExample/SwiftKit.swift +++ b/Sources/JavaKitExample/SwiftKit.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Sources/JavaKitMacros/ImplementsJavaMacro.swift b/Sources/JavaKitMacros/ImplementsJavaMacro.swift index 5b1ca607..2d6d7159 100644 --- a/Sources/JavaKitMacros/ImplementsJavaMacro.swift +++ b/Sources/JavaKitMacros/ImplementsJavaMacro.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Sources/JavaKitMacros/JavaClassMacro.swift b/Sources/JavaKitMacros/JavaClassMacro.swift index 6dd8f307..b1da49dd 100644 --- a/Sources/JavaKitMacros/JavaClassMacro.swift +++ b/Sources/JavaKitMacros/JavaClassMacro.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // @@ -14,6 +15,7 @@ import SwiftSyntax import SwiftSyntaxBuilder import SwiftSyntaxMacros +import Foundation // for e.g. replacingOccurrences enum JavaClassMacro {} diff --git a/Sources/JavaKitMacros/JavaFieldMacro.swift b/Sources/JavaKitMacros/JavaFieldMacro.swift index 86c819b1..10f06ad3 100644 --- a/Sources/JavaKitMacros/JavaFieldMacro.swift +++ b/Sources/JavaKitMacros/JavaFieldMacro.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Sources/JavaKitMacros/JavaMethodMacro.swift b/Sources/JavaKitMacros/JavaMethodMacro.swift index 35dc67fe..7996fc8c 100644 --- a/Sources/JavaKitMacros/JavaMethodMacro.swift +++ b/Sources/JavaKitMacros/JavaMethodMacro.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Sources/JavaKitMacros/MacroErrors.swift b/Sources/JavaKitMacros/MacroErrors.swift index f9b02303..7a9622c9 100644 --- a/Sources/JavaKitMacros/MacroErrors.swift +++ b/Sources/JavaKitMacros/MacroErrors.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Sources/JavaKitMacros/SwiftJNIMacrosPlugin.swift b/Sources/JavaKitMacros/SwiftJNIMacrosPlugin.swift index 80be6237..f8841ef0 100644 --- a/Sources/JavaKitMacros/SwiftJNIMacrosPlugin.swift +++ b/Sources/JavaKitMacros/SwiftJNIMacrosPlugin.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Sources/JavaKitMacros/SwiftSyntaxUtils.swift b/Sources/JavaKitMacros/SwiftSyntaxUtils.swift index 0d405495..08607056 100644 --- a/Sources/JavaKitMacros/SwiftSyntaxUtils.swift +++ b/Sources/JavaKitMacros/SwiftSyntaxUtils.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Sources/JavaKitReflection/Constructor+Utilities.swift b/Sources/JavaKitReflection/Constructor+Utilities.swift index 694df7d5..4979abbc 100644 --- a/Sources/JavaKitReflection/Constructor+Utilities.swift +++ b/Sources/JavaKitReflection/Constructor+Utilities.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Sources/JavaKitReflection/Executable+Utilities.swift b/Sources/JavaKitReflection/Executable+Utilities.swift index 6041c329..2b0a8a2d 100644 --- a/Sources/JavaKitReflection/Executable+Utilities.swift +++ b/Sources/JavaKitReflection/Executable+Utilities.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Sources/JavaKitReflection/JavaClass+Reflection.swift b/Sources/JavaKitReflection/JavaClass+Reflection.swift index c1324c85..5191a7b7 100644 --- a/Sources/JavaKitReflection/JavaClass+Reflection.swift +++ b/Sources/JavaKitReflection/JavaClass+Reflection.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Sources/JavaKitReflection/Method+Utilities.swift b/Sources/JavaKitReflection/Method+Utilities.swift index 588d3cde..8f981369 100644 --- a/Sources/JavaKitReflection/Method+Utilities.swift +++ b/Sources/JavaKitReflection/Method+Utilities.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Sources/JavaKitVM/JavaVirtualMachine.swift b/Sources/JavaKitVM/JavaVirtualMachine.swift index 9ab0c873..1d144157 100644 --- a/Sources/JavaKitVM/JavaVirtualMachine.swift +++ b/Sources/JavaKitVM/JavaVirtualMachine.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Sources/JavaRuntime/dummy.c b/Sources/JavaRuntime/dummy.c index c1dd7e37..33600881 100644 --- a/Sources/JavaRuntime/dummy.c +++ b/Sources/JavaRuntime/dummy.c @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Sources/JavaRuntime/include/JavaRuntime.h b/Sources/JavaRuntime/include/JavaRuntime.h index 30bdcc85..02bf548e 100644 --- a/Sources/JavaRuntime/include/JavaRuntime.h +++ b/Sources/JavaRuntime/include/JavaRuntime.h @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Sources/JavaTypes/JavaDemanglingError.swift b/Sources/JavaTypes/JavaDemanglingError.swift index 85daa3b4..445957d4 100644 --- a/Sources/JavaTypes/JavaDemanglingError.swift +++ b/Sources/JavaTypes/JavaDemanglingError.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Sources/JavaTypes/JavaType+JNI.swift b/Sources/JavaTypes/JavaType+JNI.swift index 6f797168..41a93d25 100644 --- a/Sources/JavaTypes/JavaType+JNI.swift +++ b/Sources/JavaTypes/JavaType+JNI.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Sources/JavaTypes/JavaType+JavaSource.swift b/Sources/JavaTypes/JavaType+JavaSource.swift index fc90eae1..e1fa8129 100644 --- a/Sources/JavaTypes/JavaType+JavaSource.swift +++ b/Sources/JavaTypes/JavaType+JavaSource.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Sources/JavaTypes/JavaType+SwiftNames.swift b/Sources/JavaTypes/JavaType+SwiftNames.swift index 088cb545..4bef1e75 100644 --- a/Sources/JavaTypes/JavaType+SwiftNames.swift +++ b/Sources/JavaTypes/JavaType+SwiftNames.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Sources/JavaTypes/JavaType.swift b/Sources/JavaTypes/JavaType.swift index d11973ee..80364b5b 100644 --- a/Sources/JavaTypes/JavaType.swift +++ b/Sources/JavaTypes/JavaType.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Sources/JavaTypes/Mangling.swift b/Sources/JavaTypes/Mangling.swift index 694f2219..c4774dbb 100644 --- a/Sources/JavaTypes/Mangling.swift +++ b/Sources/JavaTypes/Mangling.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Sources/JavaTypes/MethodSignature.swift b/Sources/JavaTypes/MethodSignature.swift index 834e1450..3e2b6613 100644 --- a/Sources/JavaTypes/MethodSignature.swift +++ b/Sources/JavaTypes/MethodSignature.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Sources/_Subprocess/LockedState.swift b/Sources/_Subprocess/LockedState.swift new file mode 100644 index 00000000..0cde3b94 --- /dev/null +++ b/Sources/_Subprocess/LockedState.swift @@ -0,0 +1,158 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2022 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// + +#if canImport(os) +internal import os +#if FOUNDATION_FRAMEWORK && canImport(C.os.lock) +internal import C.os.lock +#endif +#elseif canImport(Bionic) +import Bionic +#elseif canImport(Glibc) +import Glibc +#elseif canImport(Musl) +import Musl +#elseif canImport(WinSDK) +import WinSDK +#endif + +package struct LockedState { + + // Internal implementation for a cheap lock to aid sharing code across platforms + private struct _Lock { +#if canImport(os) + typealias Primitive = os_unfair_lock +#elseif canImport(Bionic) || canImport(Glibc) || canImport(Musl) + typealias Primitive = pthread_mutex_t +#elseif canImport(WinSDK) + typealias Primitive = SRWLOCK +#elseif os(WASI) + // WASI is single-threaded, so we don't need a lock. + typealias Primitive = Void +#endif + + typealias PlatformLock = UnsafeMutablePointer + var _platformLock: PlatformLock + + fileprivate static func initialize(_ platformLock: PlatformLock) { +#if canImport(os) + platformLock.initialize(to: os_unfair_lock()) +#elseif canImport(Bionic) || canImport(Glibc) + pthread_mutex_init(platformLock, nil) +#elseif canImport(WinSDK) + InitializeSRWLock(platformLock) +#elseif os(WASI) + // no-op +#endif + } + + fileprivate static func deinitialize(_ platformLock: PlatformLock) { +#if canImport(Bionic) || canImport(Glibc) + pthread_mutex_destroy(platformLock) +#endif + platformLock.deinitialize(count: 1) + } + + static fileprivate func lock(_ platformLock: PlatformLock) { +#if canImport(os) + os_unfair_lock_lock(platformLock) +#elseif canImport(Bionic) || canImport(Glibc) + pthread_mutex_lock(platformLock) +#elseif canImport(WinSDK) + AcquireSRWLockExclusive(platformLock) +#elseif os(WASI) + // no-op +#endif + } + + static fileprivate func unlock(_ platformLock: PlatformLock) { +#if canImport(os) + os_unfair_lock_unlock(platformLock) +#elseif canImport(Bionic) || canImport(Glibc) + pthread_mutex_unlock(platformLock) +#elseif canImport(WinSDK) + ReleaseSRWLockExclusive(platformLock) +#elseif os(WASI) + // no-op +#endif + } + } + + private class _Buffer: ManagedBuffer { + deinit { + withUnsafeMutablePointerToElements { + _Lock.deinitialize($0) + } + } + } + + private let _buffer: ManagedBuffer + + package init(initialState: State) { + _buffer = _Buffer.create(minimumCapacity: 1, makingHeaderWith: { buf in + buf.withUnsafeMutablePointerToElements { + _Lock.initialize($0) + } + return initialState + }) + } + + package func withLock(_ body: @Sendable (inout State) throws -> T) rethrows -> T { + try withLockUnchecked(body) + } + + package func withLockUnchecked(_ body: (inout State) throws -> T) rethrows -> T { + try _buffer.withUnsafeMutablePointers { state, lock in + _Lock.lock(lock) + defer { _Lock.unlock(lock) } + return try body(&state.pointee) + } + } + + // Ensures the managed state outlives the locked scope. + package func withLockExtendingLifetimeOfState(_ body: @Sendable (inout State) throws -> T) rethrows -> T { + try _buffer.withUnsafeMutablePointers { state, lock in + _Lock.lock(lock) + return try withExtendedLifetime(state.pointee) { + defer { _Lock.unlock(lock) } + return try body(&state.pointee) + } + } + } +} + +extension LockedState where State == Void { + package init() { + self.init(initialState: ()) + } + + package func withLock(_ body: @Sendable () throws -> R) rethrows -> R { + return try withLock { _ in + try body() + } + } + + package func lock() { + _buffer.withUnsafeMutablePointerToElements { lock in + _Lock.lock(lock) + } + } + + package func unlock() { + _buffer.withUnsafeMutablePointerToElements { lock in + _Lock.unlock(lock) + } + } +} + +extension LockedState: @unchecked Sendable where State: Sendable {} + diff --git a/Sources/_Subprocess/Platforms/Subprocess+Darwin.swift b/Sources/_Subprocess/Platforms/Subprocess+Darwin.swift index 746ba51c..823052ff 100644 --- a/Sources/_Subprocess/Platforms/Subprocess+Darwin.swift +++ b/Sources/_Subprocess/Platforms/Subprocess+Darwin.swift @@ -11,241 +11,268 @@ #if canImport(Darwin) -import Darwin +#if canImport(FoundationEssentials) +import FoundationEssentials +#elseif canImport(Foundation) import Foundation +#endif + +import Darwin +import Dispatch import SystemPackage #if FOUNDATION_FRAMEWORK -@_implementationOnly import _SubprocessCShims +@_implementationOnly import _FoundationCShims #else internal import _SubprocessCShims #endif // Darwin specific implementation extension Subprocess.Configuration { - internal typealias StringOrRawBytes = Subprocess.StringOrRawBytes - - internal func spawn( - withInput input: Subprocess.ExecutionInput, - output: Subprocess.ExecutionOutput, - error: Subprocess.ExecutionOutput - ) throws -> Subprocess { - let ( - executablePath, - env, argv, - intendedWorkingDir, - uidPtr, gidPtr, supplementaryGroups - ) = try self.preSpawn() - defer { - for ptr in env { ptr?.deallocate() } - for ptr in argv { ptr?.deallocate() } - uidPtr?.deallocate() - gidPtr?.deallocate() - } + internal typealias StringOrRawBytes = Subprocess.StringOrRawBytes - // Setup file actions and spawn attributes - var fileActions: posix_spawn_file_actions_t? = nil - var spawnAttributes: posix_spawnattr_t? = nil - // Setup stdin, stdout, and stderr - posix_spawn_file_actions_init(&fileActions) - defer { - posix_spawn_file_actions_destroy(&fileActions) - } - // Input - var result: Int32 = -1 - if let inputRead = input.getReadFileDescriptor() { - result = posix_spawn_file_actions_adddup2(&fileActions, inputRead.rawValue, 0) - guard result == 0 else { - try self.cleanupAll(input: input, output: output, error: error) - throw POSIXError(.init(rawValue: result) ?? .ENODEV) - } - } - if let inputWrite = input.getWriteFileDescriptor() { - // Close parent side - result = posix_spawn_file_actions_addclose(&fileActions, inputWrite.rawValue) - guard result == 0 else { - try self.cleanupAll(input: input, output: output, error: error) - throw POSIXError(.init(rawValue: result) ?? .ENODEV) - } - } - // Output - if let outputWrite = output.getWriteFileDescriptor() { - result = posix_spawn_file_actions_adddup2(&fileActions, outputWrite.rawValue, 1) - guard result == 0 else { - try self.cleanupAll(input: input, output: output, error: error) - throw POSIXError(.init(rawValue: result) ?? .ENODEV) - } - } - if let outputRead = output.getReadFileDescriptor() { - // Close parent side - result = posix_spawn_file_actions_addclose(&fileActions, outputRead.rawValue) - guard result == 0 else { - try self.cleanupAll(input: input, output: output, error: error) - throw POSIXError(.init(rawValue: result) ?? .ENODEV) - } - } - // Error - if let errorWrite = error.getWriteFileDescriptor() { - result = posix_spawn_file_actions_adddup2(&fileActions, errorWrite.rawValue, 2) - guard result == 0 else { - try self.cleanupAll(input: input, output: output, error: error) - throw POSIXError(.init(rawValue: result) ?? .ENODEV) - } - } - if let errorRead = error.getReadFileDescriptor() { - // Close parent side - result = posix_spawn_file_actions_addclose(&fileActions, errorRead.rawValue) - guard result == 0 else { - try self.cleanupAll(input: input, output: output, error: error) - throw POSIXError(.init(rawValue: result) ?? .ENODEV) - } - } - // Setup spawnAttributes - posix_spawnattr_init(&spawnAttributes) - defer { - posix_spawnattr_destroy(&spawnAttributes) - } - var noSignals = sigset_t() - var allSignals = sigset_t() - sigemptyset(&noSignals) - sigfillset(&allSignals) - posix_spawnattr_setsigmask(&spawnAttributes, &noSignals) - posix_spawnattr_setsigdefault(&spawnAttributes, &allSignals) - // Configure spawnattr - var flags: Int32 = POSIX_SPAWN_CLOEXEC_DEFAULT | POSIX_SPAWN_SETSIGMASK | POSIX_SPAWN_SETSIGDEF - if self.platformOptions.createProcessGroup { - flags |= POSIX_SPAWN_SETPGROUP - } - var spawnAttributeError = posix_spawnattr_setflags(&spawnAttributes, Int16(flags)) - // Set QualityOfService - // spanattr_qos seems to only accept `QOS_CLASS_UTILITY` or `QOS_CLASS_BACKGROUND` - // and returns an error of `EINVAL` if anything else is provided - if spawnAttributeError == 0 && self.platformOptions.qualityOfService == .utility { - spawnAttributeError = posix_spawnattr_set_qos_class_np(&spawnAttributes, QOS_CLASS_UTILITY) - } else if spawnAttributeError == 0 && self.platformOptions.qualityOfService == .background { - spawnAttributeError = posix_spawnattr_set_qos_class_np(&spawnAttributes, QOS_CLASS_BACKGROUND) - } + internal func spawn( + withInput input: Subprocess.ExecutionInput, + output: Subprocess.ExecutionOutput, + error: Subprocess.ExecutionOutput + ) throws -> Subprocess { + let (executablePath, + env, argv, + intendedWorkingDir, + uidPtr, gidPtr, supplementaryGroups + ) = try self.preSpawn() + defer { + for ptr in env { ptr?.deallocate() } + for ptr in argv { ptr?.deallocate() } + uidPtr?.deallocate() + gidPtr?.deallocate() + } - // Setup cwd - var chdirError: Int32 = 0 - if intendedWorkingDir != .currentWorkingDirectory { - chdirError = intendedWorkingDir.withPlatformString { workDir in - return posix_spawn_file_actions_addchdir_np(&fileActions, workDir) - } - } + // Setup file actions and spawn attributes + var fileActions: posix_spawn_file_actions_t? = nil + var spawnAttributes: posix_spawnattr_t? = nil + // Setup stdin, stdout, and stderr + posix_spawn_file_actions_init(&fileActions) + defer { + posix_spawn_file_actions_destroy(&fileActions) + } + // Input + var result: Int32 = -1 + if let inputRead = input.getReadFileDescriptor() { + result = posix_spawn_file_actions_adddup2(&fileActions, inputRead.rawValue, 0) + guard result == 0 else { + try self.cleanupAll(input: input, output: output, error: error) + throw POSIXError(.init(rawValue: result) ?? .ENODEV) + } + } + if let inputWrite = input.getWriteFileDescriptor() { + // Close parent side + result = posix_spawn_file_actions_addclose(&fileActions, inputWrite.rawValue) + guard result == 0 else { + try self.cleanupAll(input: input, output: output, error: error) + throw POSIXError(.init(rawValue: result) ?? .ENODEV) + } + } + // Output + if let outputWrite = output.getWriteFileDescriptor() { + result = posix_spawn_file_actions_adddup2(&fileActions, outputWrite.rawValue, 1) + guard result == 0 else { + try self.cleanupAll(input: input, output: output, error: error) + throw POSIXError(.init(rawValue: result) ?? .ENODEV) + } + } + if let outputRead = output.getReadFileDescriptor() { + // Close parent side + result = posix_spawn_file_actions_addclose(&fileActions, outputRead.rawValue) + guard result == 0 else { + try self.cleanupAll(input: input, output: output, error: error) + throw POSIXError(.init(rawValue: result) ?? .ENODEV) + } + } + // Error + if let errorWrite = error.getWriteFileDescriptor() { + result = posix_spawn_file_actions_adddup2(&fileActions, errorWrite.rawValue, 2) + guard result == 0 else { + try self.cleanupAll(input: input, output: output, error: error) + throw POSIXError(.init(rawValue: result) ?? .ENODEV) + } + } + if let errorRead = error.getReadFileDescriptor() { + // Close parent side + result = posix_spawn_file_actions_addclose(&fileActions, errorRead.rawValue) + guard result == 0 else { + try self.cleanupAll(input: input, output: output, error: error) + throw POSIXError(.init(rawValue: result) ?? .ENODEV) + } + } + // Setup spawnAttributes + posix_spawnattr_init(&spawnAttributes) + defer { + posix_spawnattr_destroy(&spawnAttributes) + } + var noSignals = sigset_t() + var allSignals = sigset_t() + sigemptyset(&noSignals) + sigfillset(&allSignals) + posix_spawnattr_setsigmask(&spawnAttributes, &noSignals) + posix_spawnattr_setsigdefault(&spawnAttributes, &allSignals) + // Configure spawnattr + var spawnAttributeError: Int32 = 0 + var flags: Int32 = POSIX_SPAWN_CLOEXEC_DEFAULT | + POSIX_SPAWN_SETSIGMASK | POSIX_SPAWN_SETSIGDEF + if let pgid = self.platformOptions.processGroupID { + flags |= POSIX_SPAWN_SETPGROUP + spawnAttributeError = posix_spawnattr_setpgroup(&spawnAttributes, pid_t(pgid)) + } + spawnAttributeError = posix_spawnattr_setflags(&spawnAttributes, Int16(flags)) + // Set QualityOfService + // spanattr_qos seems to only accept `QOS_CLASS_UTILITY` or `QOS_CLASS_BACKGROUND` + // and returns an error of `EINVAL` if anything else is provided + if spawnAttributeError == 0 && self.platformOptions.qualityOfService == .utility{ + spawnAttributeError = posix_spawnattr_set_qos_class_np(&spawnAttributes, QOS_CLASS_UTILITY) + } else if spawnAttributeError == 0 && self.platformOptions.qualityOfService == .background { + spawnAttributeError = posix_spawnattr_set_qos_class_np(&spawnAttributes, QOS_CLASS_BACKGROUND) + } - // Error handling - if chdirError != 0 || spawnAttributeError != 0 { - try self.cleanupAll(input: input, output: output, error: error) - if spawnAttributeError != 0 { - throw POSIXError(.init(rawValue: result) ?? .ENODEV) - } - - if chdirError != 0 { - throw CocoaError( - .fileNoSuchFile, - userInfo: [ - .debugDescriptionErrorKey: - "Cannot failed to change the working directory to \(intendedWorkingDir) with errno \(chdirError)" - ] - ) - } - } - // Run additional config - if let spawnConfig = self.platformOptions.preSpawnAttributeConfigurator { - try spawnConfig(&spawnAttributes) - } - if let fileAttributeConfig = self.platformOptions.preSpawnFileAttributeConfigurator { - try fileAttributeConfig(&fileActions) - } - // Spawn - var pid: pid_t = 0 - let spawnError: CInt = executablePath.withCString { exePath in - return supplementaryGroups.withOptionalUnsafeBufferPointer { sgroups in - return _subprocess_spawn( - &pid, - exePath, - &fileActions, - &spawnAttributes, - argv, - env, - uidPtr, - gidPtr, - Int32(supplementaryGroups?.count ?? 0), - sgroups?.baseAddress, - self.platformOptions.createSession ? 1 : 0 + // Setup cwd + var chdirError: Int32 = 0 + if intendedWorkingDir != .currentWorkingDirectory { + chdirError = intendedWorkingDir.withPlatformString { workDir in + return posix_spawn_file_actions_addchdir_np(&fileActions, workDir) + } + } + + // Error handling + if chdirError != 0 || spawnAttributeError != 0 { + try self.cleanupAll(input: input, output: output, error: error) + if spawnAttributeError != 0 { + throw POSIXError(.init(rawValue: result) ?? .ENODEV) + } + + if chdirError != 0 { + throw CocoaError(.fileNoSuchFile, userInfo: [ + .debugDescriptionErrorKey: "Cannot failed to change the working directory to \(intendedWorkingDir) with errno \(chdirError)" + ]) + } + } + // Run additional config + if let spawnConfig = self.platformOptions.preSpawnAttributeConfigurator { + try spawnConfig(&spawnAttributes) + } + if let fileAttributeConfig = self.platformOptions.preSpawnFileAttributeConfigurator { + try fileAttributeConfig(&fileActions) + } + // Spawn + var pid: pid_t = 0 + let spawnError: CInt = executablePath.withCString { exePath in + return supplementaryGroups.withOptionalUnsafeBufferPointer { sgroups in + return _subprocess_spawn( + &pid, exePath, + &fileActions, &spawnAttributes, + argv, env, + uidPtr, gidPtr, + Int32(supplementaryGroups?.count ?? 0), sgroups?.baseAddress, + self.platformOptions.createSession ? 1 : 0 + ) + } + } + // Spawn error + if spawnError != 0 { + try self.cleanupAll(input: input, output: output, error: error) + throw POSIXError(.init(rawValue: spawnError) ?? .ENODEV) + } + return Subprocess( + processIdentifier: .init(value: pid), + executionInput: input, + executionOutput: output, + executionError: error ) - } - } - // Spawn error - if spawnError != 0 { - try self.cleanupAll(input: input, output: output, error: error) - throw POSIXError(.init(rawValue: spawnError) ?? .ENODEV) } - return Subprocess( - processIdentifier: .init(value: pid), - executionInput: input, - executionOutput: output, - executionError: error - ) - } } // Special keys used in Error's user dictionary extension String { - static let debugDescriptionErrorKey = "NSDebugDescription" + static let debugDescriptionErrorKey = "NSDebugDescription" } // MARK: - Platform Specific Options extension Subprocess { - /// The collection of platform-specific configurations - public struct PlatformOptions: Sendable { - public var qualityOfService: QualityOfService = .default - // Set user ID for the subprocess - public var userID: Int? = nil - // Set group ID for the subprocess - public var groupID: Int? = nil - // Set list of supplementary group IDs for the subprocess - public var supplementaryGroups: [Int]? = nil - // Creates a session and sets the process group ID - // i.e. Detach from the terminal. - public var createSession: Bool = false - // Create a new process group - public var createProcessGroup: Bool = false - public var launchRequirementData: Data? = nil - public var preSpawnAttributeConfigurator: (@Sendable (inout posix_spawnattr_t?) throws -> Void)? - public var preSpawnFileAttributeConfigurator: (@Sendable (inout posix_spawn_file_actions_t?) throws -> Void)? - - public init( - qualityOfService: QualityOfService, - userID: Int?, - groupID: Int?, - supplementaryGroups: [Int]?, - createSession: Bool, - createProcessGroup: Bool, - launchRequirementData: Data? - ) { - self.qualityOfService = qualityOfService - self.userID = userID - self.groupID = groupID - self.supplementaryGroups = supplementaryGroups - self.createSession = createSession - self.createProcessGroup = createProcessGroup - self.launchRequirementData = launchRequirementData + /// The collection of platform-specific configurations + public struct PlatformOptions: Sendable { + public var qualityOfService: QualityOfService = .default + // Set user ID for the subprocess + public var userID: Int? = nil + // Set group ID for the subprocess + public var groupID: Int? = nil + // Set list of supplementary group IDs for the subprocess + public var supplementaryGroups: [Int]? = nil + // Set process group ID for the subprocess + public var processGroupID: Int? = nil + // Creates a session and sets the process group ID + // i.e. Detach from the terminal. + public var createSession: Bool = false + public var launchRequirementData: Data? = nil + public var preSpawnAttributeConfigurator: (@Sendable (inout posix_spawnattr_t?) throws -> Void)? + public var preSpawnFileAttributeConfigurator: (@Sendable (inout posix_spawn_file_actions_t?) throws -> Void)? + + public init( + qualityOfService: QualityOfService, + userID: Int?, + groupID: Int?, + supplementaryGroups: [Int]?, + processGroupID: Int?, + createSession: Bool, + launchRequirementData: Data? + ) { + self.qualityOfService = qualityOfService + self.userID = userID + self.groupID = groupID + self.supplementaryGroups = supplementaryGroups + self.createSession = createSession + self.processGroupID = processGroupID + self.launchRequirementData = launchRequirementData + } + + public static var `default`: Self { + return .init( + qualityOfService: .default, + userID: nil, + groupID: nil, + supplementaryGroups: nil, + processGroupID: nil, + createSession: false, + launchRequirementData: nil + ) + } } +} - public static var `default`: Self { - return .init( - qualityOfService: .default, - userID: nil, - groupID: nil, - supplementaryGroups: nil, - createSession: false, - createProcessGroup: false, - launchRequirementData: nil - ) +// MARK: - Process Monitoring +@Sendable +internal func monitorProcessTermination( + forProcessWithIdentifier pid: Subprocess.ProcessIdentifier +) async -> Subprocess.TerminationStatus { + return await withCheckedContinuation { continuation in + let source = DispatchSource.makeProcessSource( + identifier: pid.value, + eventMask: [.exit, .signal] + ) + source.setEventHandler { + source.cancel() + var status: Int32 = -1 + waitpid(pid.value, &status, 0) + if _was_process_exited(status) != 0 { + continuation.resume(returning: .exited(_get_exit_code(status))) + return + } + if _was_process_signaled(status) != 0 { + continuation.resume(returning: .unhandledException(_get_signal_code(status))) + return + } + fatalError("Unexpected exit status type: \(status)") + } + source.resume() } - } } -#endif // canImport(Darwin) +#endif // canImport(Darwin) diff --git a/Sources/_Subprocess/Platforms/Subprocess+Linux.swift b/Sources/_Subprocess/Platforms/Subprocess+Linux.swift index 2f92ed50..1f62dc8b 100644 --- a/Sources/_Subprocess/Platforms/Subprocess+Linux.swift +++ b/Sources/_Subprocess/Platforms/Subprocess+Linux.swift @@ -12,130 +12,212 @@ #if canImport(Glibc) import Glibc -import Foundation import SystemPackage import FoundationEssentials package import _SubprocessCShims // Linux specific implementations extension Subprocess.Configuration { - internal typealias StringOrRawBytes = Subprocess.StringOrRawBytes - - internal func spawn( - withInput input: Subprocess.ExecutionInput, - output: Subprocess.ExecutionOutput, - error: Subprocess.ExecutionOutput - ) throws -> Subprocess { - let ( - executablePath, - env, argv, - intendedWorkingDir, - uidPtr, gidPtr, - supplementaryGroups - ) = try self.preSpawn() - defer { - for ptr in env { ptr?.deallocate() } - for ptr in argv { ptr?.deallocate() } - uidPtr?.deallocate() - gidPtr?.deallocate() - } + internal typealias StringOrRawBytes = Subprocess.StringOrRawBytes - let fileDescriptors: [CInt] = [ - input.getReadFileDescriptor().rawValue, input.getWriteFileDescriptor()?.rawValue ?? 0, - output.getWriteFileDescriptor().rawValue, output.getReadFileDescriptor()?.rawValue ?? 0, - error.getWriteFileDescriptor().rawValue, error.getReadFileDescriptor()?.rawValue ?? 0, - ] + internal func spawn( + withInput input: Subprocess.ExecutionInput, + output: Subprocess.ExecutionOutput, + error: Subprocess.ExecutionOutput + ) throws -> Subprocess { + // Setup signal handler to minitor SIGCHLD + _setupMonitorSignalHandler() - var workingDirectory: String? - if intendedWorkingDir != FilePath.currentWorkingDirectory { - // Only pass in working directory if it's different - workingDirectory = intendedWorkingDir.string - } - // Spawn - var pid: pid_t = 0 - let spawnError: CInt = executablePath.withCString { exePath in - return workingDirectory.withOptionalCString { workingDir in - return supplementaryGroups.withOptionalUnsafeBufferPointer { sgroups in - return fileDescriptors.withUnsafeBufferPointer { fds in - return _subprocess_fork_exec( - &pid, - exePath, - workingDir, - fds.baseAddress!, - argv, - env, - uidPtr, - gidPtr, - CInt(supplementaryGroups?.count ?? 0), - sgroups?.baseAddress, - self.platformOptions.createSession ? 1 : 0, - self.platformOptions.createProcessGroup ? 1 : 0 - ) - } + let (executablePath, + env, argv, + intendedWorkingDir, + uidPtr, gidPtr, + supplementaryGroups + ) = try self.preSpawn() + var processGroupIDPtr: UnsafeMutablePointer? = nil + if let processGroupID = self.platformOptions.processGroupID { + processGroupIDPtr = .allocate(capacity: 1) + processGroupIDPtr?.pointee = gid_t(processGroupID) } - } - } - // Spawn error - if spawnError != 0 { - try self.cleanupAll(input: input, output: output, error: error) - throw POSIXError(.init(rawValue: spawnError) ?? .ENODEV) + defer { + for ptr in env { ptr?.deallocate() } + for ptr in argv { ptr?.deallocate() } + uidPtr?.deallocate() + gidPtr?.deallocate() + processGroupIDPtr?.deallocate() + } + + let fileDescriptors: [CInt] = [ + input.getReadFileDescriptor()?.rawValue ?? -1, + input.getWriteFileDescriptor()?.rawValue ?? -1, + output.getWriteFileDescriptor()?.rawValue ?? -1, + output.getReadFileDescriptor()?.rawValue ?? -1, + error.getWriteFileDescriptor()?.rawValue ?? -1, + error.getReadFileDescriptor()?.rawValue ?? -1 + ] + + var workingDirectory: String? + if intendedWorkingDir != FilePath.currentWorkingDirectory { + // Only pass in working directory if it's different + workingDirectory = intendedWorkingDir.string + } + // Spawn + var pid: pid_t = 0 + let spawnError: CInt = executablePath.withCString { exePath in + return workingDirectory.withOptionalCString { workingDir in + return supplementaryGroups.withOptionalUnsafeBufferPointer { sgroups in + return fileDescriptors.withUnsafeBufferPointer { fds in + return _subprocess_fork_exec( + &pid, exePath, workingDir, + fds.baseAddress!, + argv, env, + uidPtr, gidPtr, + processGroupIDPtr, + CInt(supplementaryGroups?.count ?? 0), sgroups?.baseAddress, + self.platformOptions.createSession ? 1 : 0, + self.platformOptions.preSpawnProcessConfigurator + ) + } + } + } + } + // Spawn error + if spawnError != 0 { + try self.cleanupAll(input: input, output: output, error: error) + throw POSIXError(.init(rawValue: spawnError) ?? .ENODEV) + } + return Subprocess( + processIdentifier: .init(value: pid), + executionInput: input, + executionOutput: output, + executionError: error + ) } - return Subprocess( - processIdentifier: .init(value: pid), - executionInput: input, - executionOutput: output, - executionError: error - ) - } } // MARK: - Platform Specific Options extension Subprocess { - public struct PlatformOptions: Sendable { - // Set user ID for the subprocess - public var userID: Int? = nil - // Set group ID for the subprocess - public var groupID: Int? = nil - // Set list of supplementary group IDs for the subprocess - public var supplementaryGroups: [Int]? = nil - // Creates a session and sets the process group ID - // i.e. Detach from the terminal. - public var createSession: Bool = false - // Create a new process group - public var createProcessGroup: Bool = false - // This callback is run after `fork` but before `exec`. - // Use it to perform any custom process setup - public var customProcessConfigurator: (@Sendable () -> Void)? = nil - - public init( - userID: Int?, - groupID: Int?, - supplementaryGroups: [Int]?, - createSession: Bool, - createProcessGroup: Bool - ) { - self.userID = userID - self.groupID = groupID - self.supplementaryGroups = supplementaryGroups - self.createSession = createSession - self.createProcessGroup = createProcessGroup - } + public struct PlatformOptions: Sendable { + // Set user ID for the subprocess + public var userID: Int? = nil + // Set group ID for the subprocess + public var groupID: Int? = nil + // Set list of supplementary group IDs for the subprocess + public var supplementaryGroups: [Int]? = nil + // Set process group ID for the subprocess + public var processGroupID: Int? = nil + // Creates a session and sets the process group ID + // i.e. Detach from the terminal. + public var createSession: Bool = false + // This callback is run after `fork` but before `exec`. + // Use it to perform any custom process setup + // This callback *must not* capture any global variables + public var preSpawnProcessConfigurator: (@convention(c) @Sendable () -> Void)? = nil - public static var `default`: Self { - return .init( - userID: nil, - groupID: nil, - supplementaryGroups: nil, - createSession: false, - createProcessGroup: false - ) + public init( + userID: Int?, + groupID: Int?, + supplementaryGroups: [Int]?, + processGroupID: Int?, + createSession: Bool + ) { + self.userID = userID + self.groupID = groupID + self.supplementaryGroups = supplementaryGroups + self.processGroupID = processGroupID + self.createSession = createSession + } + + public static var `default`: Self { + return .init( + userID: nil, + groupID: nil, + supplementaryGroups: nil, + processGroupID: nil, + createSession: false + ) + } } - } } // Special keys used in Error's user dictionary extension String { - static let debugDescriptionErrorKey = "DebugDescription" + static let debugDescriptionErrorKey = "DebugDescription" } -#endif // canImport(Glibc) +// MARK: - Process Monitoring +@Sendable +internal func monitorProcessTermination( + forProcessWithIdentifier pid: Subprocess.ProcessIdentifier +) async -> Subprocess.TerminationStatus { + return await withCheckedContinuation { continuation in + _childProcessContinuations.withLock { continuations in + if let existing = continuations.removeValue(forKey: pid.value), + case .status(let existingStatus) = existing { + // We already have existing status to report + if _was_process_exited(existingStatus) != 0 { + continuation.resume(returning: .exited(_get_exit_code(existingStatus))) + return + } + if _was_process_signaled(existingStatus) != 0 { + continuation.resume(returning: .unhandledException(_get_signal_code(existingStatus))) + return + } + fatalError("Unexpected exit status type: \(existingStatus)") + } else { + // Save the continuation for handler + continuations[pid.value] = .continuation(continuation) + } + } + } +} + +private enum ContinuationOrStatus { + case continuation(CheckedContinuation) + case status(Int32) +} + +private let _childProcessContinuations: LockedState< + [pid_t: ContinuationOrStatus] +> = LockedState(initialState: [:]) + +// Callback for sigaction +private func _childProcessMonitorHandler(_ singnal: Int32) { + _childProcessContinuations.withLock { continuations in + var status: Int32 = -1 + let childPid = waitpid(-1, &status, 0) + if let existing = continuations.removeValue(forKey: childPid), + case .continuation(let c) = existing { + // We already have continuations saved + if _was_process_exited(status) != 0 { + c.resume(returning: .exited(_get_exit_code(status))) + return + } + if _was_process_signaled(status) != 0 { + c.resume(returning: .unhandledException(_get_signal_code(status))) + return + } + fatalError("Unexpected exit status type: \(status)") + } else { + // We don't have continuation yet, just save the state + continuations[childPid] = .status(status) + } + } +} + +private func _setupMonitorSignalHandler() { + // Only executed once + let setup = { + var action: sigaction = sigaction() + action.__sigaction_handler.sa_handler = _childProcessMonitorHandler + action.sa_flags = SA_RESTART + sigemptyset(&action.sa_mask) + if sigaction(SIGCHLD, &action, nil) != 0 { + fatalError("Failed to setup signal handler") + } + }() + setup +} + +#endif // canImport(Glibc) + diff --git a/Sources/_Subprocess/Platforms/Subprocess+Unix.swift b/Sources/_Subprocess/Platforms/Subprocess+Unix.swift index 40551261..e07f9127 100644 --- a/Sources/_Subprocess/Platforms/Subprocess+Unix.swift +++ b/Sources/_Subprocess/Platforms/Subprocess+Unix.swift @@ -11,311 +11,276 @@ #if canImport(Darwin) || canImport(Glibc) +#if canImport(FoundationEssentials) +import FoundationEssentials +#elseif canImport(Foundation) +import Foundation +#endif + #if canImport(Darwin) import Darwin #elseif canImport(Glibc) import Glibc #endif -import Foundation -import SystemPackage - #if FOUNDATION_FRAMEWORK -@_implementationOnly import _SubprocessCShims +@_implementationOnly import _FoundationCShims #else -package import _SubprocessCShims +internal import _SubprocessCShims #endif -import Dispatch +import SystemPackage // MARK: - Signals extension Subprocess { - public struct Signal: Hashable, Sendable { - public let rawValue: Int32 + public struct Signal : Hashable, Sendable { + public let rawValue: Int32 - private init(rawValue: Int32) { - self.rawValue = rawValue - } + private init(rawValue: Int32) { + self.rawValue = rawValue + } - public static var interrupt: Self { .init(rawValue: SIGINT) } - public static var terminate: Self { .init(rawValue: SIGTERM) } - public static var suspend: Self { .init(rawValue: SIGSTOP) } - public static var resume: Self { .init(rawValue: SIGCONT) } - public static var kill: Self { .init(rawValue: SIGKILL) } - public static var terminalClosed: Self { .init(rawValue: SIGHUP) } - public static var quit: Self { .init(rawValue: SIGQUIT) } - public static var userDefinedOne: Self { .init(rawValue: SIGUSR1) } - public static var userDefinedTwo: Self { .init(rawValue: SIGUSR2) } - public static var alarm: Self { .init(rawValue: SIGALRM) } - public static var windowSizeChange: Self { .init(rawValue: SIGWINCH) } - } + public static var interrupt: Self { .init(rawValue: SIGINT) } + public static var terminate: Self { .init(rawValue: SIGTERM) } + public static var suspend: Self { .init(rawValue: SIGSTOP) } + public static var resume: Self { .init(rawValue: SIGCONT) } + public static var kill: Self { .init(rawValue: SIGKILL) } + public static var terminalClosed: Self { .init(rawValue: SIGHUP) } + public static var quit: Self { .init(rawValue: SIGQUIT) } + public static var userDefinedOne: Self { .init(rawValue: SIGUSR1) } + public static var userDefinedTwo: Self { .init(rawValue: SIGUSR2) } + public static var alarm: Self { .init(rawValue: SIGALRM) } + public static var windowSizeChange: Self { .init(rawValue: SIGWINCH) } + } - public func sendSignal(_ signal: Signal, toProcessGroup shouldSendToProcessGroup: Bool) throws { - let pid = shouldSendToProcessGroup ? -(self.processIdentifier.value) : self.processIdentifier.value - guard kill(pid, signal.rawValue) == 0 else { - throw POSIXError(.init(rawValue: errno)!) + public func sendSignal(_ signal: Signal, toProcessGroup shouldSendToProcessGroup: Bool) throws { + let pid = shouldSendToProcessGroup ? -(self.processIdentifier.value) : self.processIdentifier.value + guard kill(pid, signal.rawValue) == 0 else { + throw POSIXError(.init(rawValue: errno)!) + } } - } } // MARK: Environment Resolution extension Subprocess.Environment { - internal static let pathEnvironmentVariableName = "PATH" - - internal func pathValue() -> String? { - switch self.config { - case .inherit(let overrides): - // If PATH value exists in overrides, use it - if let value = overrides[.string(Self.pathEnvironmentVariableName)] { - return value.stringValue - } - // Fall back to current process - return ProcessInfo.processInfo.environment[Self.pathEnvironmentVariableName] - case .custom(let fullEnvironment): - if let value = fullEnvironment[.string(Self.pathEnvironmentVariableName)] { - return value.stringValue - } - return nil - } - } + internal static let pathEnvironmentVariableName = "PATH" - // This method follows the standard "create" rule: `env` needs to be - // manually deallocated - internal func createEnv() -> [UnsafeMutablePointer?] { - func createFullCString( - fromKey keyContainer: Subprocess.StringOrRawBytes, - value valueContainer: Subprocess.StringOrRawBytes - ) -> UnsafeMutablePointer { - let rawByteKey: UnsafeMutablePointer = keyContainer.createRawBytes() - let rawByteValue: UnsafeMutablePointer = valueContainer.createRawBytes() - defer { - rawByteKey.deallocate() - rawByteValue.deallocate() - } - /// length = `key` + `=` + `value` + `\null` - let totalLength = keyContainer.count + 1 + valueContainer.count + 1 - let fullString: UnsafeMutablePointer = .allocate(capacity: totalLength) - #if canImport(Darwin) - _ = snprintf(ptr: fullString, totalLength, "%s=%s", rawByteKey, rawByteValue) - #else - _ = _shims_snprintf(fullString, CInt(totalLength), "%s=%s", rawByteKey, rawByteValue) - #endif - return fullString + internal func pathValue() -> String? { + switch self.config { + case .inherit(let overrides): + // If PATH value exists in overrides, use it + if let value = overrides[.string(Self.pathEnvironmentVariableName)] { + return value.stringValue + } + // Fall back to current process + return ProcessInfo.processInfo.environment[Self.pathEnvironmentVariableName] + case .custom(let fullEnvironment): + if let value = fullEnvironment[.string(Self.pathEnvironmentVariableName)] { + return value.stringValue + } + return nil + } } - var env: [UnsafeMutablePointer?] = [] - switch self.config { - case .inherit(let updates): - var current = ProcessInfo.processInfo.environment - for (keyContainer, valueContainer) in updates { - if let stringKey = keyContainer.stringValue { - // Remove the value from current to override it - current.removeValue(forKey: stringKey) - } - // Fast path - if case .string(let stringKey) = keyContainer, - case .string(let stringValue) = valueContainer - { - let fullString = "\(stringKey)=\(stringValue)" - env.append(strdup(fullString)) - continue + // This method follows the standard "create" rule: `env` needs to be + // manually deallocated + internal func createEnv() -> [UnsafeMutablePointer?] { + func createFullCString( + fromKey keyContainer: Subprocess.StringOrRawBytes, + value valueContainer: Subprocess.StringOrRawBytes + ) -> UnsafeMutablePointer { + let rawByteKey: UnsafeMutablePointer = keyContainer.createRawBytes() + let rawByteValue: UnsafeMutablePointer = valueContainer.createRawBytes() + defer { + rawByteKey.deallocate() + rawByteValue.deallocate() + } + /// length = `key` + `=` + `value` + `\null` + let totalLength = keyContainer.count + 1 + valueContainer.count + 1 + let fullString: UnsafeMutablePointer = .allocate(capacity: totalLength) + #if canImport(Darwin) + _ = snprintf(ptr: fullString, totalLength, "%s=%s", rawByteKey, rawByteValue) + #else + _ = _shims_snprintf(fullString, CInt(totalLength), "%s=%s", rawByteKey, rawByteValue) + #endif + return fullString } - env.append(createFullCString(fromKey: keyContainer, value: valueContainer)) - } - // Add the rest of `current` to env - for (key, value) in current { - let fullString = "\(key)=\(value)" - env.append(strdup(fullString)) - } - case .custom(let customValues): - for (keyContainer, valueContainer) in customValues { - // Fast path - if case .string(let stringKey) = keyContainer, - case .string(let stringValue) = valueContainer - { - let fullString = "\(stringKey)=\(stringValue)" - env.append(strdup(fullString)) - continue + var env: [UnsafeMutablePointer?] = [] + switch self.config { + case .inherit(let updates): + var current = ProcessInfo.processInfo.environment + for (keyContainer, valueContainer) in updates { + if let stringKey = keyContainer.stringValue { + // Remove the value from current to override it + current.removeValue(forKey: stringKey) + } + // Fast path + if case .string(let stringKey) = keyContainer, + case .string(let stringValue) = valueContainer { + let fullString = "\(stringKey)=\(stringValue)" + env.append(strdup(fullString)) + continue + } + + env.append(createFullCString(fromKey: keyContainer, value: valueContainer)) + } + // Add the rest of `current` to env + for (key, value) in current { + let fullString = "\(key)=\(value)" + env.append(strdup(fullString)) + } + case .custom(let customValues): + for (keyContainer, valueContainer) in customValues { + // Fast path + if case .string(let stringKey) = keyContainer, + case .string(let stringValue) = valueContainer { + let fullString = "\(stringKey)=\(stringValue)" + env.append(strdup(fullString)) + continue + } + env.append(createFullCString(fromKey: keyContainer, value: valueContainer)) + } } - env.append(createFullCString(fromKey: keyContainer, value: valueContainer)) - } + env.append(nil) + return env } - env.append(nil) - return env - } } // MARK: Args Creation extension Subprocess.Arguments { - // This method follows the standard "create" rule: `args` needs to be - // manually deallocated - internal func createArgs(withExecutablePath executablePath: String) -> [UnsafeMutablePointer?] { - var argv: [UnsafeMutablePointer?] = self.storage.map { $0.createRawBytes() } - // argv[0] = executable path - if let override = self.executablePathOverride { - argv.insert(override.createRawBytes(), at: 0) - } else { - argv.insert(strdup(executablePath), at: 0) + // This method follows the standard "create" rule: `args` needs to be + // manually deallocated + internal func createArgs(withExecutablePath executablePath: String) -> [UnsafeMutablePointer?] { + var argv: [UnsafeMutablePointer?] = self.storage.map { $0.createRawBytes() } + // argv[0] = executable path + if let override = self.executablePathOverride { + argv.insert(override.createRawBytes(), at: 0) + } else { + argv.insert(strdup(executablePath), at: 0) + } + argv.append(nil) + return argv } - argv.append(nil) - return argv - } } // MARK: - Executable Searching extension Subprocess.Executable { - internal static var defaultSearchPaths: Set { - return Set([ - "/usr/bin", - "/bin", - "/usr/sbin", - "/sbin", - "/usr/local/bin", - ]) - } + internal static var defaultSearchPaths: Set { + return Set([ + "/usr/bin", + "/bin", + "/usr/sbin", + "/sbin", + "/usr/local/bin" + ]) + } - internal func resolveExecutablePath(withPathValue pathValue: String?) -> String? { - switch self.storage { - case .executable(let executableName): - // If the executableName in is already a full path, return it directly - if Subprocess.Configuration.pathAccessible(executableName, mode: X_OK) { - return executableName - } - // Get $PATH from environment - let searchPaths: Set - if let pathValue = pathValue { - let localSearchPaths = pathValue.split(separator: ":").map { String($0) } - searchPaths = Set(localSearchPaths).union(Self.defaultSearchPaths) - } else { - searchPaths = Self.defaultSearchPaths - } + internal func resolveExecutablePath(withPathValue pathValue: String?) -> String? { + switch self.storage { + case .executable(let executableName): + // If the executableName in is already a full path, return it directly + if Subprocess.Configuration.pathAccessible(executableName, mode: X_OK) { + return executableName + } + // Get $PATH from environment + let searchPaths: Set + if let pathValue = pathValue { + let localSearchPaths = pathValue.split(separator: ":").map { String($0) } + searchPaths = Set(localSearchPaths).union(Self.defaultSearchPaths) + } else { + searchPaths = Self.defaultSearchPaths + } - for path in searchPaths { - let fullPath = "\(path)/\(executableName)" - let fileExists = Subprocess.Configuration.pathAccessible(fullPath, mode: X_OK) - if fileExists { - return fullPath + for path in searchPaths { + let fullPath = "\(path)/\(executableName)" + let fileExists = Subprocess.Configuration.pathAccessible(fullPath, mode: X_OK) + if fileExists { + return fullPath + } + } + case .path(let executablePath): + // Use path directly + return executablePath.string } - } - case .path(let executablePath): - // Use path directly - return executablePath.string + return nil } - return nil - } } // MARK: - Configuration extension Subprocess.Configuration { - internal func preSpawn() throws -> ( - executablePath: String, - env: [UnsafeMutablePointer?], - argv: [UnsafeMutablePointer?], - intendedWorkingDir: FilePath, - uidPtr: UnsafeMutablePointer?, - gidPtr: UnsafeMutablePointer?, - supplementaryGroups: [gid_t]? - ) { - // Prepare environment - let env = self.environment.createEnv() - // Prepare executable path - guard - let executablePath = self.executable.resolveExecutablePath( - withPathValue: self.environment.pathValue() - ) - else { - for ptr in env { ptr?.deallocate() } - throw CocoaError( - .executableNotLoadable, - userInfo: [ - "description": "\(self.executable.description) is not an executable" - ] - ) - } - // Prepare arguments - let argv: [UnsafeMutablePointer?] = self.arguments.createArgs(withExecutablePath: executablePath) - // Prepare workingDir - let intendedWorkingDir = self.workingDirectory - guard Self.pathAccessible(intendedWorkingDir.string, mode: F_OK) else { - for ptr in env { ptr?.deallocate() } - for ptr in argv { ptr?.deallocate() } - throw CocoaError( - .fileNoSuchFile, - userInfo: [ - "description": "Failed to set working directory to \(intendedWorkingDir)" - ] - ) - } - - var uidPtr: UnsafeMutablePointer? = nil - if let userID = self.platformOptions.userID { - uidPtr = .allocate(capacity: 1) - uidPtr?.pointee = uid_t(userID) - } - var gidPtr: UnsafeMutablePointer? = nil - if let groupID = self.platformOptions.groupID { - gidPtr = .allocate(capacity: 1) - gidPtr?.pointee = gid_t(groupID) - } - var supplementaryGroups: [gid_t]? - if let groupsValue = self.platformOptions.supplementaryGroups { - supplementaryGroups = groupsValue.map { gid_t($0) } - } - return ( - executablePath: executablePath, - env: env, argv: argv, - intendedWorkingDir: intendedWorkingDir, - uidPtr: uidPtr, gidPtr: gidPtr, - supplementaryGroups: supplementaryGroups - ) - } + internal func preSpawn() throws -> ( + executablePath: String, + env: [UnsafeMutablePointer?], + argv: [UnsafeMutablePointer?], + intendedWorkingDir: FilePath, + uidPtr: UnsafeMutablePointer?, + gidPtr: UnsafeMutablePointer?, + supplementaryGroups: [gid_t]? + ) { + // Prepare environment + let env = self.environment.createEnv() + // Prepare executable path + guard let executablePath = self.executable.resolveExecutablePath( + withPathValue: self.environment.pathValue()) else { + for ptr in env { ptr?.deallocate() } + throw CocoaError(.executableNotLoadable, userInfo: [ + .debugDescriptionErrorKey : "\(self.executable.description) is not an executable" + ]) + } + // Prepare arguments + let argv: [UnsafeMutablePointer?] = self.arguments.createArgs(withExecutablePath: executablePath) + // Prepare workingDir + let intendedWorkingDir = self.workingDirectory + guard Self.pathAccessible(intendedWorkingDir.string, mode: F_OK) else { + for ptr in env { ptr?.deallocate() } + for ptr in argv { ptr?.deallocate() } + throw CocoaError(.fileNoSuchFile, userInfo: [ + .debugDescriptionErrorKey : "Failed to set working directory to \(intendedWorkingDir)" + ]) + } - internal static func pathAccessible(_ path: String, mode: Int32) -> Bool { - return path.withCString { - return access($0, mode) == 0 + var uidPtr: UnsafeMutablePointer? = nil + if let userID = self.platformOptions.userID { + uidPtr = .allocate(capacity: 1) + uidPtr?.pointee = uid_t(userID) + } + var gidPtr: UnsafeMutablePointer? = nil + if let groupID = self.platformOptions.groupID { + gidPtr = .allocate(capacity: 1) + gidPtr?.pointee = gid_t(groupID) + } + var supplementaryGroups: [gid_t]? + if let groupsValue = self.platformOptions.supplementaryGroups { + supplementaryGroups = groupsValue.map { gid_t($0) } + } + return ( + executablePath: executablePath, + env: env, argv: argv, + intendedWorkingDir: intendedWorkingDir, + uidPtr: uidPtr, gidPtr: gidPtr, + supplementaryGroups: supplementaryGroups + ) } - } -} -// MARK: - Process Monitoring -@Sendable -internal func monitorProcessTermination( - forProcessWithIdentifier pid: Subprocess.ProcessIdentifier -) async -> Subprocess.TerminationStatus { - return await withCheckedContinuation { continuation in - let source = DispatchSource.makeProcessSource( - identifier: pid.value, - eventMask: [.exit, .signal] - ) - source.setEventHandler { - source.cancel() - var status: Int32 = -1 - waitpid(pid.value, &status, 0) - if _was_process_exited(status) != 0 { - continuation.resume(returning: .exited(_get_exit_code(status))) - return - } - if _was_process_signaled(status) != 0 { - continuation.resume(returning: .unhandledException(_get_signal_code(status))) - return - } - fatalError("Unexpected exit status type: \(status)") + internal static func pathAccessible(_ path: String, mode: Int32) -> Bool { + return path.withCString { + return access($0, mode) == 0 + } } - source.resume() - } } // MARK: - Read Buffer Size extension Subprocess { - @inline(__always) - internal static var readBufferSize: Int { - #if canImport(Darwin) - return 16384 - #else - return Platform.pageSize - #endif // canImport(Darwin) - } + @inline(__always) + internal static var readBufferSize: Int { +#if canImport(Darwin) + return 16384 +#else + // FIXME: Use Platform.pageSize here + return 4096 +#endif // canImport(Darwin) + } } -#endif // canImport(Darwin) || canImport(Glibc) +#endif // canImport(Darwin) || canImport(Glibc) diff --git a/Sources/_Subprocess/Subprocess+API.swift b/Sources/_Subprocess/Subprocess+API.swift index 63872ee1..5fb87ba1 100644 --- a/Sources/_Subprocess/Subprocess+API.swift +++ b/Sources/_Subprocess/Subprocess+API.swift @@ -9,220 +9,271 @@ // //===----------------------------------------------------------------------===// -import Foundation import SystemPackage +#if canImport(FoundationEssentials) +import FoundationEssentials +#elseif canImport(Foundation) +import Foundation +#endif extension Subprocess { - public static func run( - _ executable: Executable, - arguments: Arguments = [], - environment: Environment = .inherit, - workingDirectory: FilePath? = nil, - platformOptions: PlatformOptions = .default, - input: InputMethod = .noInput, - output: CollectedOutputMethod = .collect, - error: CollectedOutputMethod = .collect - ) async throws -> CollectedResult { - let result = try await self.run( - executable, - arguments: arguments, - environment: environment, - workingDirectory: workingDirectory, - platformOptions: platformOptions, - input: input, - output: .init(method: output.method), - error: .init(method: error.method) - ) { subprocess in - let (standardOutput, standardError) = try await subprocess.captureIOs() - return ( - processIdentifier: subprocess.processIdentifier, - standardOutput: standardOutput, - standardError: standardError - ) + public static func run( + _ executable: Executable, + arguments: Arguments = [], + environment: Environment = .inherit, + workingDirectory: FilePath? = nil, + platformOptions: PlatformOptions = .default, + input: InputMethod = .noInput, + output: CollectedOutputMethod = .collect, + error: CollectedOutputMethod = .collect + ) async throws -> CollectedResult { + let result = try await self.run( + executable, + arguments: arguments, + environment: environment, + workingDirectory: workingDirectory, + platformOptions: platformOptions, + input: input, + output: .init(method: output.method), + error: .init(method: error.method) + ) { subprocess in + let (standardOutput, standardError) = try await subprocess.captureIOs() + return ( + processIdentifier: subprocess.processIdentifier, + standardOutput: standardOutput, + standardError: standardError + ) + } + return CollectedResult( + processIdentifier: result.value.processIdentifier, + terminationStatus: result.terminationStatus, + standardOutput: result.value.standardOutput, + standardError: result.value.standardError + ) } - return CollectedResult( - processIdentifier: result.value.processIdentifier, - terminationStatus: result.terminationStatus, - standardOutput: result.value.standardOutput, - standardError: result.value.standardError - ) - } - public static func run( - _ executable: Executable, - arguments: Arguments = [], - environment: Environment = .inherit, - workingDirectory: FilePath? = nil, - platformOptions: PlatformOptions = .default, - input: some Sequence, - output: CollectedOutputMethod = .collect, - error: CollectedOutputMethod = .collect - ) async throws -> CollectedResult { - let result = try await self.run( - executable, - arguments: arguments, - environment: environment, - workingDirectory: workingDirectory, - platformOptions: platformOptions, - output: .init(method: output.method), - error: .init(method: output.method) - ) { subprocess, writer in - try await writer.write(input) - try await writer.finish() - let (standardOutput, standardError) = try await subprocess.captureIOs() - return ( - processIdentifier: subprocess.processIdentifier, - standardOutput: standardOutput, - standardError: standardError - ) + public static func run( + _ executable: Executable, + arguments: Arguments = [], + environment: Environment = .inherit, + workingDirectory: FilePath? = nil, + platformOptions: PlatformOptions = .default, + input: some Sequence, + output: CollectedOutputMethod = .collect, + error: CollectedOutputMethod = .collect + ) async throws -> CollectedResult { + let result = try await self.run( + executable, + arguments: arguments, + environment: environment, + workingDirectory: workingDirectory, + platformOptions: platformOptions, + output: .init(method: output.method), + error: .init(method: output.method) + ) { subprocess, writer in + return try await withThrowingTaskGroup(of: CapturedIOs?.self) { group in + group.addTask { + try await writer.write(input) + try await writer.finish() + return nil + } + group.addTask { + return try await subprocess.captureIOs() + } + var capturedIOs: CapturedIOs! + while let result = try await group.next() { + capturedIOs = result + } + return ( + processIdentifier: subprocess.processIdentifier, + standardOutput: capturedIOs.standardOutput, + standardError: capturedIOs.standardError + ) + } + } + return CollectedResult( + processIdentifier: result.value.processIdentifier, + terminationStatus: result.terminationStatus, + standardOutput: result.value.standardOutput, + standardError: result.value.standardError + ) } - return CollectedResult( - processIdentifier: result.value.processIdentifier, - terminationStatus: result.terminationStatus, - standardOutput: result.value.standardOutput, - standardError: result.value.standardError - ) - } - public static func run( - _ executable: Executable, - arguments: Arguments = [], - environment: Environment = .inherit, - workingDirectory: FilePath? = nil, - platformOptions: PlatformOptions = .default, - input: S, - output: CollectedOutputMethod = .collect, - error: CollectedOutputMethod = .collect - ) async throws -> CollectedResult where S.Element == UInt8 { - let result = try await self.run( - executable, - arguments: arguments, - environment: environment, - workingDirectory: workingDirectory, - platformOptions: platformOptions, - output: .init(method: output.method), - error: .init(method: output.method) - ) { subprocess, writer in - try await writer.write(input) - try await writer.finish() - let (standardOutput, standardError) = try await subprocess.captureIOs() - return ( - processIdentifier: subprocess.processIdentifier, - standardOutput: standardOutput, - standardError: standardError - ) + public static func run( + _ executable: Executable, + arguments: Arguments = [], + environment: Environment = .inherit, + workingDirectory: FilePath? = nil, + platformOptions: PlatformOptions = .default, + input: S, + output: CollectedOutputMethod = .collect, + error: CollectedOutputMethod = .collect + ) async throws -> CollectedResult where S.Element == UInt8 { + let result = try await self.run( + executable, + arguments: arguments, + environment: environment, + workingDirectory: workingDirectory, + platformOptions: platformOptions, + output: .init(method: output.method), + error: .init(method: output.method) + ) { subprocess, writer in + return try await withThrowingTaskGroup(of: CapturedIOs?.self) { group in + group.addTask { + try await writer.write(input) + try await writer.finish() + return nil + } + group.addTask { + return try await subprocess.captureIOs() + } + var capturedIOs: CapturedIOs! + while let result = try await group.next() { + capturedIOs = result + } + return ( + processIdentifier: subprocess.processIdentifier, + standardOutput: capturedIOs.standardOutput, + standardError: capturedIOs.standardError + ) + } + } + return CollectedResult( + processIdentifier: result.value.processIdentifier, + terminationStatus: result.terminationStatus, + standardOutput: result.value.standardOutput, + standardError: result.value.standardError + ) } - return CollectedResult( - processIdentifier: result.value.processIdentifier, - terminationStatus: result.terminationStatus, - standardOutput: result.value.standardOutput, - standardError: result.value.standardError - ) - } } // MARK: Custom Execution Body extension Subprocess { - public static func run( - _ executable: Executable, - arguments: Arguments = [], - environment: Environment = .inherit, - workingDirectory: FilePath? = nil, - platformOptions: PlatformOptions = .default, - input: InputMethod = .noInput, - output: RedirectedOutputMethod = .redirectToSequence, - error: RedirectedOutputMethod = .redirectToSequence, - _ body: (@Sendable @escaping (Subprocess) async throws -> R) - ) async throws -> ExecutionResult { - return try await Configuration( - executable: executable, - arguments: arguments, - environment: environment, - workingDirectory: workingDirectory, - platformOptions: platformOptions - ) - .run(input: input, output: output, error: error, body) - } + public static func run( + _ executable: Executable, + arguments: Arguments = [], + environment: Environment = .inherit, + workingDirectory: FilePath? = nil, + platformOptions: PlatformOptions = .default, + input: InputMethod = .noInput, + output: RedirectedOutputMethod = .redirectToSequence, + error: RedirectedOutputMethod = .redirectToSequence, + _ body: (@Sendable @escaping (Subprocess) async throws -> R) + ) async throws -> ExecutionResult { + return try await Configuration( + executable: executable, + arguments: arguments, + environment: environment, + workingDirectory: workingDirectory, + platformOptions: platformOptions + ) + .run(input: input, output: output, error: error, body) + } - public static func run( - _ executable: Executable, - arguments: Arguments = [], - environment: Environment = .inherit, - workingDirectory: FilePath? = nil, - platformOptions: PlatformOptions, - input: some Sequence, - output: RedirectedOutputMethod = .redirectToSequence, - error: RedirectedOutputMethod = .redirectToSequence, - _ body: (@Sendable @escaping (Subprocess) async throws -> R) - ) async throws -> ExecutionResult { - return try await Configuration( - executable: executable, - arguments: arguments, - environment: environment, - workingDirectory: workingDirectory, - platformOptions: platformOptions - ) - .run(output: output, error: error) { execution, writer in - try await writer.write(input) - try await writer.finish() - return try await body(execution) + public static func run( + _ executable: Executable, + arguments: Arguments = [], + environment: Environment = .inherit, + workingDirectory: FilePath? = nil, + platformOptions: PlatformOptions = .default, + input: some Sequence, + output: RedirectedOutputMethod = .redirectToSequence, + error: RedirectedOutputMethod = .redirectToSequence, + _ body: (@Sendable @escaping (Subprocess) async throws -> R) + ) async throws -> ExecutionResult { + return try await Configuration( + executable: executable, + arguments: arguments, + environment: environment, + workingDirectory: workingDirectory, + platformOptions: platformOptions + ) + .run(output: output, error: error) { execution, writer in + return try await withThrowingTaskGroup(of: R?.self) { group in + group.addTask { + try await writer.write(input) + try await writer.finish() + return nil + } + group.addTask { + return try await body(execution) + } + var result: R! + while let next = try await group.next() { + result = next + } + return result + } + } } - } - public static func run( - _ executable: Executable, - arguments: Arguments = [], - environment: Environment = .inherit, - workingDirectory: FilePath? = nil, - platformOptions: PlatformOptions = .default, - input: S, - output: RedirectedOutputMethod = .redirectToSequence, - error: RedirectedOutputMethod = .redirectToSequence, - _ body: (@Sendable @escaping (Subprocess) async throws -> R) - ) async throws -> ExecutionResult where S.Element == UInt8 { - return try await Configuration( - executable: executable, - arguments: arguments, - environment: environment, - workingDirectory: workingDirectory, - platformOptions: platformOptions - ) - .run(output: output, error: error) { execution, writer in - try await writer.write(input) - try await writer.finish() - return try await body(execution) + public static func run( + _ executable: Executable, + arguments: Arguments = [], + environment: Environment = .inherit, + workingDirectory: FilePath? = nil, + platformOptions: PlatformOptions = .default, + input: S, + output: RedirectedOutputMethod = .redirectToSequence, + error: RedirectedOutputMethod = .redirectToSequence, + _ body: (@Sendable @escaping (Subprocess) async throws -> R) + ) async throws -> ExecutionResult where S.Element == UInt8 { + return try await Configuration( + executable: executable, + arguments: arguments, + environment: environment, + workingDirectory: workingDirectory, + platformOptions: platformOptions + ) + .run(output: output, error: error) { execution, writer in + return try await withThrowingTaskGroup(of: R?.self) { group in + group.addTask { + try await writer.write(input) + try await writer.finish() + return nil + } + group.addTask { + return try await body(execution) + } + var result: R! + while let next = try await group.next() { + result = next + } + return result + } + } } - } - public static func run( - _ executable: Executable, - arguments: Arguments = [], - environment: Environment = .inherit, - workingDirectory: FilePath? = nil, - platformOptions: PlatformOptions = .default, - output: RedirectedOutputMethod = .redirectToSequence, - error: RedirectedOutputMethod = .redirectToSequence, - _ body: (@Sendable @escaping (Subprocess, StandardInputWriter) async throws -> R) - ) async throws -> ExecutionResult { - return try await Configuration( - executable: executable, - arguments: arguments, - environment: environment, - workingDirectory: workingDirectory, - platformOptions: platformOptions - ) - .run(output: output, error: error, body) - } + public static func run( + _ executable: Executable, + arguments: Arguments = [], + environment: Environment = .inherit, + workingDirectory: FilePath? = nil, + platformOptions: PlatformOptions = .default, + output: RedirectedOutputMethod = .redirectToSequence, + error: RedirectedOutputMethod = .redirectToSequence, + _ body: (@Sendable @escaping (Subprocess, StandardInputWriter) async throws -> R) + ) async throws -> ExecutionResult { + return try await Configuration( + executable: executable, + arguments: arguments, + environment: environment, + workingDirectory: workingDirectory, + platformOptions: platformOptions + ) + .run(output: output, error: error, body) + } } // MARK: - Configuration Based extension Subprocess { - public static func run( - using configuration: Configuration, - output: RedirectedOutputMethod = .redirectToSequence, - error: RedirectedOutputMethod = .redirectToSequence, - _ body: (@Sendable @escaping (Subprocess, StandardInputWriter) async throws -> R) - ) async throws -> ExecutionResult { - return try await configuration.run(output: output, error: error, body) - } + public static func run( + using configuration: Configuration, + output: RedirectedOutputMethod = .redirectToSequence, + error: RedirectedOutputMethod = .redirectToSequence, + _ body: (@Sendable @escaping (Subprocess, StandardInputWriter) async throws -> R) + ) async throws -> ExecutionResult { + return try await configuration.run(output: output, error: error, body) + } } + diff --git a/Sources/_Subprocess/Subprocess+AsyncBytes.swift b/Sources/_Subprocess/Subprocess+AsyncBytes.swift index bdd08caa..f80fc315 100644 --- a/Sources/_Subprocess/Subprocess+AsyncBytes.swift +++ b/Sources/_Subprocess/Subprocess+AsyncBytes.swift @@ -9,107 +9,110 @@ // //===----------------------------------------------------------------------===// +import SystemPackage import Dispatch + +#if canImport(FoundationEssentials) +import FoundationEssentials +#elseif canImport(Foundation) import Foundation -import SystemPackage +#endif extension Subprocess { - public struct AsyncBytes: AsyncSequence, Sendable, _AsyncSequence { - public typealias Error = any Swift.Error + public struct AsyncBytes: AsyncSequence, Sendable, _AsyncSequence { + public typealias Error = any Swift.Error - public typealias Element = UInt8 + public typealias Element = UInt8 - @_nonSendable - public struct Iterator: AsyncIteratorProtocol { - public typealias Element = UInt8 + @_nonSendable + public struct Iterator: AsyncIteratorProtocol { + public typealias Element = UInt8 - private let fileDescriptor: FileDescriptor - private var buffer: [UInt8] - private var currentPosition: Int - private var finished: Bool + private let fileDescriptor: FileDescriptor + private var buffer: [UInt8] + private var currentPosition: Int + private var finished: Bool - internal init(fileDescriptor: FileDescriptor) { - self.fileDescriptor = fileDescriptor - self.buffer = [] - self.currentPosition = 0 - self.finished = false - } + internal init(fileDescriptor: FileDescriptor) { + self.fileDescriptor = fileDescriptor + self.buffer = [] + self.currentPosition = 0 + self.finished = false + } - private mutating func reloadBufferAndNext() async throws -> UInt8? { - if self.finished { - return nil - } - try Task.checkCancellation() - do { - self.buffer = try await self.fileDescriptor.read( - upToLength: Subprocess.readBufferSize - ) - self.currentPosition = 0 - if self.buffer.count < Subprocess.readBufferSize { - self.finished = true - } - } catch { - self.finished = true - throw error - } - return try await self.next() - } + private mutating func reloadBufferAndNext() async throws -> UInt8? { + if self.finished { + return nil + } + try Task.checkCancellation() + do { + self.buffer = try await self.fileDescriptor.read( + upToLength: Subprocess.readBufferSize) + self.currentPosition = 0 + if self.buffer.isEmpty { + self.finished = true + } + } catch { + self.finished = true + throw error + } + return try await self.next() + } - public mutating func next() async throws -> UInt8? { - if currentPosition < buffer.count { - let value = buffer[currentPosition] - self.currentPosition += 1 - return value - } - return try await self.reloadBufferAndNext() - } + public mutating func next() async throws -> UInt8? { + if currentPosition < buffer.count { + let value = buffer[currentPosition] + self.currentPosition += 1 + return value + } + return try await self.reloadBufferAndNext() + } - private func read(from fileDescriptor: FileDescriptor, maxLength: Int) async throws -> [UInt8] { - return try await withCheckedThrowingContinuation { continuation in - DispatchIO.read( - fromFileDescriptor: fileDescriptor.rawValue, - maxLength: maxLength, - runningHandlerOn: .main - ) { data, error in - guard error == 0 else { - continuation.resume( - throwing: POSIXError( - .init(rawValue: error) ?? .ENODEV - ) - ) - return + private func read(from fileDescriptor: FileDescriptor, maxLength: Int) async throws -> [UInt8] { + return try await withCheckedThrowingContinuation { continuation in + DispatchIO.read( + fromFileDescriptor: fileDescriptor.rawValue, + maxLength: maxLength, + runningHandlerOn: .main + ) { data, error in + guard error == 0 else { + continuation.resume( + throwing: POSIXError( + .init(rawValue: error) ?? .ENODEV) + ) + return + } + continuation.resume(returning: Array(data)) + } + } } - continuation.resume(returning: Array(data)) - } } - } - } - private let fileDescriptor: FileDescriptor + private let fileDescriptor: FileDescriptor - init(fileDescriptor: FileDescriptor) { - self.fileDescriptor = fileDescriptor - } + init(fileDescriptor: FileDescriptor) { + self.fileDescriptor = fileDescriptor + } - public func makeAsyncIterator() -> Iterator { - return Iterator(fileDescriptor: self.fileDescriptor) + public func makeAsyncIterator() -> Iterator { + return Iterator(fileDescriptor: self.fileDescriptor) + } } - } } extension RangeReplaceableCollection { - /// Creates a new instance of a collection containing the elements of an asynchronous sequence. - /// - /// - Parameter source: The asynchronous sequence of elements for the new collection. - @inlinable - public init(_ source: Source) async rethrows where Source.Element == Element { - self.init() - for try await item in source { - append(item) + /// Creates a new instance of a collection containing the elements of an asynchronous sequence. + /// + /// - Parameter source: The asynchronous sequence of elements for the new collection. + @inlinable + public init(_ source: Source) async rethrows where Source.Element == Element { + self.init() + for try await item in source { + append(item) + } } - } } public protocol _AsyncSequence: AsyncSequence { - associatedtype Error + associatedtype Error } diff --git a/Sources/_Subprocess/Subprocess+Configuration.swift b/Sources/_Subprocess/Subprocess+Configuration.swift index a50f1fc5..2c4e6ae6 100644 --- a/Sources/_Subprocess/Subprocess+Configuration.swift +++ b/Sources/_Subprocess/Subprocess+Configuration.swift @@ -9,11 +9,10 @@ // //===----------------------------------------------------------------------===// -import Foundation @preconcurrency import SystemPackage #if FOUNDATION_FRAMEWORK -@_implementationOnly import _SubprocessCShims +@_implementationOnly import _FoundationCShims #else package import _SubprocessCShims #endif @@ -24,598 +23,599 @@ import Darwin import Glibc #endif +#if canImport(FoundationEssentials) +import FoundationEssentials +#elseif canImport(Foundation) +import Foundation +#endif + extension Subprocess { - public struct Configuration: Sendable { + public struct Configuration: Sendable { - internal enum RunState: Sendable { - case workBody(Result) - case monitorChildProcess(TerminationStatus) - } + internal enum RunState: Sendable { + case workBody(Result) + case monitorChildProcess(TerminationStatus) + } - // Configurable properties - public var executable: Executable - public var arguments: Arguments - public var environment: Environment - public var workingDirectory: FilePath - public var platformOptions: PlatformOptions - - public init( - executable: Executable, - arguments: Arguments = [], - environment: Environment = .inherit, - workingDirectory: FilePath? = nil, - platformOptions: PlatformOptions = .default - ) { - self.executable = executable - self.arguments = arguments - self.environment = environment - self.workingDirectory = workingDirectory ?? .currentWorkingDirectory - self.platformOptions = platformOptions - } + // Configurable properties + public var executable: Executable + public var arguments: Arguments + public var environment: Environment + public var workingDirectory: FilePath + public var platformOptions: PlatformOptions + + public init( + executable: Executable, + arguments: Arguments = [], + environment: Environment = .inherit, + workingDirectory: FilePath? = nil, + platformOptions: PlatformOptions = .default + ) { + self.executable = executable + self.arguments = arguments + self.environment = environment + self.workingDirectory = workingDirectory ?? .currentWorkingDirectory + self.platformOptions = platformOptions + } - /// Close each input individually, and throw the first error if there's multiple errors thrown - @Sendable - private func cleanup( - process: Subprocess, - childSide: Bool, - parentSide: Bool, - attemptToTerminateSubProcess: Bool - ) throws { - guard childSide || parentSide || attemptToTerminateSubProcess else { - return - } - - let inputCloseFunc: () throws -> Void - let outputCloseFunc: () throws -> Void - let errorCloseFunc: () throws -> Void - if childSide && parentSide { - // Close all - inputCloseFunc = process.executionInput.closeAll - outputCloseFunc = process.executionOutput.closeAll - errorCloseFunc = process.executionError.closeAll - } else if childSide { - // Close child only - inputCloseFunc = process.executionInput.closeChildSide - outputCloseFunc = process.executionOutput.closeChildSide - errorCloseFunc = process.executionError.closeChildSide - } else { - // Close parent only - inputCloseFunc = process.executionInput.closeParentSide - outputCloseFunc = process.executionOutput.closeParentSide - errorCloseFunc = process.executionError.closeParentSide - } - - var inputError: Error? - var outputError: Error? - var errorError: Error? // lol - do { - try inputCloseFunc() - } catch { - inputError = error - } - - do { - try outputCloseFunc() - } catch { - outputError = error - } - - do { - try errorCloseFunc() - } catch { - errorError = error // lolol - } - - // Attempt to kill the subprocess - var killError: Error? - if attemptToTerminateSubProcess { - do { - try process.sendSignal(.kill, toProcessGroup: true) - } catch { - guard let posixError: POSIXError = error as? POSIXError else { - killError = error - return - } - // Ignore ESRCH (no such process) - if posixError.code != .ESRCH { - killError = error - } - } - } - - if let inputError = inputError { - throw inputError - } - - if let outputError = outputError { - throw outputError - } - - if let errorError = errorError { - throw errorError - } - - if let killError = killError { - throw killError - } - } + /// Close each input individually, and throw the first error if there's multiple errors thrown + @Sendable + private func cleanup( + process: Subprocess, + childSide: Bool, parentSide: Bool, + attemptToTerminateSubProcess: Bool + ) throws { + guard childSide || parentSide || attemptToTerminateSubProcess else { + return + } - /// Close each input individually, and throw the first error if there's multiple errors thrown - @Sendable - internal func cleanupAll( - input: ExecutionInput, - output: ExecutionOutput, - error: ExecutionOutput - ) throws { - var inputError: Error? - var outputError: Error? - var errorError: Error? - - do { - try input.closeAll() - } catch { - inputError = error - } - - do { - try output.closeAll() - } catch { - outputError = error - } - - do { - try error.closeAll() - } catch { - errorError = error - } - - if let inputError = inputError { - throw inputError - } - if let outputError = outputError { - throw outputError - } - if let errorError = errorError { - throw errorError - } - } + let inputCloseFunc: () throws -> Void + let outputCloseFunc: () throws -> Void + let errorCloseFunc: () throws -> Void + if childSide && parentSide { + // Close all + inputCloseFunc = process.executionInput.closeAll + outputCloseFunc = process.executionOutput.closeAll + errorCloseFunc = process.executionError.closeAll + } else if childSide { + // Close child only + inputCloseFunc = process.executionInput.closeChildSide + outputCloseFunc = process.executionOutput.closeChildSide + errorCloseFunc = process.executionError.closeChildSide + } else { + // Close parent only + inputCloseFunc = process.executionInput.closeParentSide + outputCloseFunc = process.executionOutput.closeParentSide + errorCloseFunc = process.executionError.closeParentSide + } - internal func run( - output: RedirectedOutputMethod, - error: RedirectedOutputMethod, - _ body: @Sendable @escaping (Subprocess, StandardInputWriter) async throws -> R - ) async throws -> ExecutionResult { - let (readFd, writeFd) = try FileDescriptor.pipe() - let executionInput: ExecutionInput = .init(storage: .customWrite(readFd, writeFd)) - let executionOutput: ExecutionOutput = try output.createExecutionOutput() - let executionError: ExecutionOutput = try error.createExecutionOutput() - let process: Subprocess = try self.spawn( - withInput: executionInput, - output: executionOutput, - error: executionError - ) - // After spawn, cleanup child side fds - try self.cleanup( - process: process, - childSide: true, - parentSide: false, - attemptToTerminateSubProcess: false - ) - return try await withTaskCancellationHandler { - return try await withThrowingTaskGroup(of: RunState.self) { group in - group.addTask { - let status = await monitorProcessTermination( - forProcessWithIdentifier: process.processIdentifier - ) - return .monitorChildProcess(status) - } - group.addTask { + var inputError: Error? + var outputError: Error? + var errorError: Error? // lol do { - let result = try await body(process, .init(input: executionInput)) - try self.cleanup( - process: process, - childSide: false, - parentSide: true, - attemptToTerminateSubProcess: false - ) - return .workBody(result) + try inputCloseFunc() } catch { - // Cleanup everything - try self.cleanup( - process: process, - childSide: true, - parentSide: true, - attemptToTerminateSubProcess: true - ) - throw error + inputError = error } - } - - var result: R! - var terminationStatus: TerminationStatus! - while let state = try await group.next() { - switch state { - case .monitorChildProcess(let status): - // We don't really care about termination status here - terminationStatus = status - case .workBody(let workResult): - result = workResult + + do { + try outputCloseFunc() + } catch { + outputError = error } - } - return ExecutionResult(terminationStatus: terminationStatus, value: result) - } - } onCancel: { - // Attempt to terminate the child process - // Since the task has already been cancelled, - // this is the best we can do - try? self.cleanup( - process: process, - childSide: true, - parentSide: true, - attemptToTerminateSubProcess: true - ) - } - } - internal func run( - input: InputMethod, - output: RedirectedOutputMethod, - error: RedirectedOutputMethod, - _ body: (@Sendable @escaping (Subprocess) async throws -> R) - ) async throws -> ExecutionResult { - let executionInput = try input.createExecutionInput() - let executionOutput = try output.createExecutionOutput() - let executionError = try error.createExecutionOutput() - let process = try self.spawn( - withInput: executionInput, - output: executionOutput, - error: executionError - ) - // After spawn, clean up child side - try self.cleanup( - process: process, - childSide: true, - parentSide: false, - attemptToTerminateSubProcess: false - ) - return try await withTaskCancellationHandler { - return try await withThrowingTaskGroup(of: RunState.self) { group in - group.addTask { - let status = await monitorProcessTermination( - forProcessWithIdentifier: process.processIdentifier - ) - return .monitorChildProcess(status) - } - group.addTask { do { - let result = try await body(process) - try self.cleanup( - process: process, - childSide: false, - parentSide: true, - attemptToTerminateSubProcess: false - ) - return .workBody(result) + try errorCloseFunc() + } catch { + errorError = error // lolol + } + + // Attempt to kill the subprocess + var killError: Error? + if attemptToTerminateSubProcess { + do { + try process.sendSignal(.kill, toProcessGroup: true) + } catch { + guard let posixError: POSIXError = error as? POSIXError else { + killError = error + return + } + // Ignore ESRCH (no such process) + if posixError.code != .ESRCH { + killError = error + } + } + } + + if let inputError = inputError { + throw inputError + } + + if let outputError = outputError { + throw outputError + } + + if let errorError = errorError { + throw errorError + } + + if let killError = killError { + throw killError + } + } + + /// Close each input individually, and throw the first error if there's multiple errors thrown + @Sendable + internal func cleanupAll( + input: ExecutionInput, + output: ExecutionOutput, + error: ExecutionOutput + ) throws { + var inputError: Error? + var outputError: Error? + var errorError: Error? + + do { + try input.closeAll() + } catch { + inputError = error + } + + do { + try output.closeAll() } catch { - try self.cleanup( + outputError = error + } + + do { + try error.closeAll() + } catch { + errorError = error + } + + if let inputError = inputError { + throw inputError + } + if let outputError = outputError { + throw outputError + } + if let errorError = errorError { + throw errorError + } + } + + internal func run( + output: RedirectedOutputMethod, + error: RedirectedOutputMethod, + _ body: @Sendable @escaping (Subprocess, StandardInputWriter) async throws -> R + ) async throws -> ExecutionResult { + let (readFd, writeFd) = try FileDescriptor.pipe() + let executionInput: ExecutionInput = .init(storage: .customWrite(readFd, writeFd)) + let executionOutput: ExecutionOutput = try output.createExecutionOutput() + let executionError: ExecutionOutput = try error.createExecutionOutput() + let process: Subprocess = try self.spawn( + withInput: executionInput, + output: executionOutput, + error: executionError) + // After spawn, cleanup child side fds + try self.cleanup( process: process, childSide: true, - parentSide: true, - attemptToTerminateSubProcess: true - ) - throw error + parentSide: false, + attemptToTerminateSubProcess: false + ) + return try await withTaskCancellationHandler { + return try await withThrowingTaskGroup(of: RunState.self) { group in + group.addTask { + let status = await monitorProcessTermination( + forProcessWithIdentifier: process.processIdentifier) + return .monitorChildProcess(status) + } + group.addTask { + do { + let result = try await body(process, .init(input: executionInput)) + try self.cleanup( + process: process, + childSide: false, + parentSide: true, + attemptToTerminateSubProcess: false + ) + return .workBody(result) + } catch { + // Cleanup everything + try self.cleanup( + process: process, + childSide: true, + parentSide: true, + attemptToTerminateSubProcess: true + ) + throw error + } + } + + var result: R! + var terminationStatus: TerminationStatus! + while let state = try await group.next() { + switch state { + case .monitorChildProcess(let status): + // We don't really care about termination status here + terminationStatus = status + case .workBody(let workResult): + result = workResult + } + } + return ExecutionResult(terminationStatus: terminationStatus, value: result) + } + } onCancel: { + // Attempt to terminate the child process + // Since the task has already been cancelled, + // this is the best we can do + try? self.cleanup( + process: process, + childSide: true, + parentSide: true, + attemptToTerminateSubProcess: true + ) } - } - - var result: R! - var terminationStatus: TerminationStatus! - while let state = try await group.next() { - switch state { - case .monitorChildProcess(let status): - terminationStatus = status - case .workBody(let workResult): - result = workResult + } + + internal func run( + input: InputMethod, + output: RedirectedOutputMethod, + error: RedirectedOutputMethod, + _ body: (@Sendable @escaping (Subprocess) async throws -> R) + ) async throws -> ExecutionResult { + let executionInput = try input.createExecutionInput() + let executionOutput = try output.createExecutionOutput() + let executionError = try error.createExecutionOutput() + let process = try self.spawn( + withInput: executionInput, + output: executionOutput, + error: executionError) + // After spawn, clean up child side + try self.cleanup( + process: process, + childSide: true, + parentSide: false, + attemptToTerminateSubProcess: false + ) + return try await withTaskCancellationHandler { + return try await withThrowingTaskGroup(of: RunState.self) { group in + group.addTask { + let status = await monitorProcessTermination( + forProcessWithIdentifier: process.processIdentifier) + return .monitorChildProcess(status) + } + group.addTask { + do { + let result = try await body(process) + try self.cleanup( + process: process, + childSide: false, + parentSide: true, + attemptToTerminateSubProcess: false + ) + return .workBody(result) + } catch { + try self.cleanup( + process: process, + childSide: true, + parentSide: true, + attemptToTerminateSubProcess: true + ) + throw error + } + } + + var result: R! + var terminationStatus: TerminationStatus! + while let state = try await group.next() { + switch state { + case .monitorChildProcess(let status): + terminationStatus = status + case .workBody(let workResult): + result = workResult + } + } + return ExecutionResult(terminationStatus: terminationStatus, value: result) + } + } onCancel: { + // Attempt to terminate the child process + // Since the task has already been cancelled, + // this is the best we can do + try? self.cleanup( + process: process, + childSide: true, + parentSide: true, + attemptToTerminateSubProcess: true + ) } - } - return ExecutionResult(terminationStatus: terminationStatus, value: result) - } - } onCancel: { - // Attempt to terminate the child process - // Since the task has already been cancelled, - // this is the best we can do - try? self.cleanup( - process: process, - childSide: true, - parentSide: true, - attemptToTerminateSubProcess: true - ) - } + } } - } } // MARK: - Executable extension Subprocess { - public struct Executable: Sendable, CustomStringConvertible, Hashable { - internal enum Configuration: Sendable, Hashable { - case executable(String) - case path(FilePath) - } + public struct Executable: Sendable, CustomStringConvertible, Hashable { + internal enum Configuration: Sendable, Hashable { + case executable(String) + case path(FilePath) + } - internal let storage: Configuration + internal let storage: Configuration - public var description: String { - switch storage { - case .executable(let executableName): - return executableName - case .path(let filePath): - return filePath.string - } - } + public var description: String { + switch storage { + case .executable(let executableName): + return executableName + case .path(let filePath): + return filePath.string + } + } - private init(_config: Configuration) { - self.storage = _config - } + private init(_config: Configuration) { + self.storage = _config + } - public static func named(_ executableName: String) -> Self { - return .init(_config: .executable(executableName)) - } + public static func named(_ executableName: String) -> Self { + return .init(_config: .executable(executableName)) + } - public static func at(_ filePath: FilePath) -> Self { - return .init(_config: .path(filePath)) - } + public static func at(_ filePath: FilePath) -> Self { + return .init(_config: .path(filePath)) + } - public func resolveExecutablePath(in environment: Environment) -> FilePath? { - if let path = self.resolveExecutablePath(withPathValue: environment.pathValue()) { - return FilePath(path) - } - return nil + public func resolveExecutablePath(in environment: Environment) -> FilePath? { + if let path = self.resolveExecutablePath(withPathValue: environment.pathValue()) { + return FilePath(path) + } + return nil + } } - } } // MARK: - Arguments extension Subprocess { - public struct Arguments: Sendable, ExpressibleByArrayLiteral { - public typealias ArrayLiteralElement = String + public struct Arguments: Sendable, ExpressibleByArrayLiteral { + public typealias ArrayLiteralElement = String - internal let storage: [StringOrRawBytes] - internal let executablePathOverride: StringOrRawBytes? + internal let storage: [StringOrRawBytes] + internal let executablePathOverride: StringOrRawBytes? - public init(arrayLiteral elements: String...) { - self.storage = elements.map { .string($0) } - self.executablePathOverride = nil - } + public init(arrayLiteral elements: String...) { + self.storage = elements.map { .string($0) } + self.executablePathOverride = nil + } - public init(executablePathOverride: String?, remainingValues: [String]) { - self.storage = remainingValues.map { .string($0) } - if let executablePathOverride = executablePathOverride { - self.executablePathOverride = .string(executablePathOverride) - } else { - self.executablePathOverride = nil - } - } + public init(executablePathOverride: String?, remainingValues: [String]) { + self.storage = remainingValues.map { .string($0) } + if let executablePathOverride = executablePathOverride { + self.executablePathOverride = .string(executablePathOverride) + } else { + self.executablePathOverride = nil + } + } - public init(executablePathOverride: Data?, remainingValues: [Data]) { - self.storage = remainingValues.map { .rawBytes($0.toArray()) } - if let override = executablePathOverride { - self.executablePathOverride = .rawBytes(override.toArray()) - } else { - self.executablePathOverride = nil - } + public init(executablePathOverride: Data?, remainingValues: [Data]) { + self.storage = remainingValues.map { .rawBytes($0.toArray()) } + if let override = executablePathOverride { + self.executablePathOverride = .rawBytes(override.toArray()) + } else { + self.executablePathOverride = nil + } + } } - } } // MARK: - Environment extension Subprocess { - public struct Environment: Sendable { - internal enum Configuration { - case inherit([StringOrRawBytes: StringOrRawBytes]) - case custom([StringOrRawBytes: StringOrRawBytes]) - } + public struct Environment: Sendable { + internal enum Configuration { + case inherit([StringOrRawBytes : StringOrRawBytes]) + case custom([StringOrRawBytes : StringOrRawBytes]) + } - internal let config: Configuration + internal let config: Configuration - init(config: Configuration) { - self.config = config - } + init(config: Configuration) { + self.config = config + } - public static var inherit: Self { - return .init(config: .inherit([:])) - } + public static var inherit: Self { + return .init(config: .inherit([:])) + } - public func updating(_ newValue: [String: String]) -> Self { - return .init(config: .inherit(newValue.wrapToStringOrRawBytes())) - } + public func updating(_ newValue: [String : String]) -> Self { + return .init(config: .inherit(newValue.wrapToStringOrRawBytes())) + } - public func updating(_ newValue: [Data: Data]) -> Self { - return .init(config: .inherit(newValue.wrapToStringOrRawBytes())) - } + public func updating(_ newValue: [Data : Data]) -> Self { + return .init(config: .inherit(newValue.wrapToStringOrRawBytes())) + } - public static func custom(_ newValue: [String: String]) -> Self { - return .init(config: .custom(newValue.wrapToStringOrRawBytes())) - } + public static func custom(_ newValue: [String : String]) -> Self { + return .init(config: .custom(newValue.wrapToStringOrRawBytes())) + } - public static func custom(_ newValue: [Data: Data]) -> Self { - return .init(config: .custom(newValue.wrapToStringOrRawBytes())) + public static func custom(_ newValue: [Data : Data]) -> Self { + return .init(config: .custom(newValue.wrapToStringOrRawBytes())) + } } - } } fileprivate extension Dictionary where Key == String, Value == String { - func wrapToStringOrRawBytes() -> [Subprocess.StringOrRawBytes: Subprocess.StringOrRawBytes] { - var result = Dictionary< - Subprocess.StringOrRawBytes, - Subprocess.StringOrRawBytes - >(minimumCapacity: self.count) - for (key, value) in self { - result[.string(key)] = .string(value) + func wrapToStringOrRawBytes() -> [Subprocess.StringOrRawBytes : Subprocess.StringOrRawBytes] { + var result = Dictionary< + Subprocess.StringOrRawBytes, + Subprocess.StringOrRawBytes + >(minimumCapacity: self.count) + for (key, value) in self { + result[.string(key)] = .string(value) + } + return result } - return result - } } fileprivate extension Dictionary where Key == Data, Value == Data { - func wrapToStringOrRawBytes() -> [Subprocess.StringOrRawBytes: Subprocess.StringOrRawBytes] { - var result = Dictionary< - Subprocess.StringOrRawBytes, - Subprocess.StringOrRawBytes - >(minimumCapacity: self.count) - for (key, value) in self { - result[.rawBytes(key.toArray())] = .rawBytes(value.toArray()) + func wrapToStringOrRawBytes() -> [Subprocess.StringOrRawBytes : Subprocess.StringOrRawBytes] { + var result = Dictionary< + Subprocess.StringOrRawBytes, + Subprocess.StringOrRawBytes + >(minimumCapacity: self.count) + for (key, value) in self { + result[.rawBytes(key.toArray())] = .rawBytes(value.toArray()) + } + return result } - return result - } } fileprivate extension Data { - func toArray() -> [T] { - return self.withUnsafeBytes { ptr in - return Array(ptr.bindMemory(to: T.self)) + func toArray() -> [T] { + return self.withUnsafeBytes { ptr in + return Array(ptr.bindMemory(to: T.self)) + } } - } } // MARK: - ProcessIdentifier extension Subprocess { - public struct ProcessIdentifier: Sendable, Hashable { - let value: pid_t + public struct ProcessIdentifier: Sendable, Hashable { + let value: pid_t - internal init(value: pid_t) { - self.value = value + internal init(value: pid_t) { + self.value = value + } } - } } // MARK: - TerminationStatus extension Subprocess { - public enum TerminationStatus: Sendable, Hashable, Codable { - #if canImport(WinSDK) - public typealias Code = DWORD - #else - public typealias Code = CInt - #endif - - #if canImport(WinSDK) - case stillActive - #endif - - case exited(Code) - case unhandledException(Code) - - public var isSuccess: Bool { - switch self { - case .exited(let exitCode): - return exitCode == 0 - case .unhandledException(_): - return false - } - } + public enum TerminationStatus: Sendable, Hashable, Codable { + #if canImport(WinSDK) + public typealias Code = DWORD + #else + public typealias Code = CInt + #endif + + #if canImport(WinSDK) + case stillActive + #endif + + case exited(Code) + case unhandledException(Code) + + public var isSuccess: Bool { + switch self { + case .exited(let exitCode): + return exitCode == 0 + case .unhandledException(_): + return false + } + } - public var isUnhandledException: Bool { - switch self { - case .exited(_): - return false - case .unhandledException(_): - return true - } + public var isUnhandledException: Bool { + switch self { + case .exited(_): + return false + case .unhandledException(_): + return true + } + } } - } } // MARK: - Internal extension Subprocess { - internal enum StringOrRawBytes: Sendable, Hashable { - case string(String) - case rawBytes([CChar]) - - // Return value needs to be deallocated manually by callee - func createRawBytes() -> UnsafeMutablePointer { - switch self { - case .string(let string): - return strdup(string) - case .rawBytes(let rawBytes): - return strdup(rawBytes) - } - } + internal enum StringOrRawBytes: Sendable, Hashable { + case string(String) + case rawBytes([CChar]) + + // Return value needs to be deallocated manually by callee + func createRawBytes() -> UnsafeMutablePointer { + switch self { + case .string(let string): + return strdup(string) + case .rawBytes(let rawBytes): + return strdup(rawBytes) + } + } - var stringValue: String? { - switch self { - case .string(let string): - return string - case .rawBytes(let rawBytes): - return String(validatingUTF8: rawBytes) - } - } + var stringValue: String? { + switch self { + case .string(let string): + return string + case .rawBytes(let rawBytes): + return String(validatingUTF8: rawBytes) + } + } - var count: Int { - switch self { - case .string(let string): - return string.count - case .rawBytes(let rawBytes): - return strnlen(rawBytes, Int.max) - } - } + var count: Int { + switch self { + case .string(let string): + return string.count + case .rawBytes(let rawBytes): + return strnlen(rawBytes, Int.max) + } + } - func hash(into hasher: inout Hasher) { - // If Raw bytes is valid UTF8, hash it as so - switch self { - case .string(let string): - hasher.combine(string) - case .rawBytes(let bytes): - if let stringValue = self.stringValue { - hasher.combine(stringValue) - } else { - hasher.combine(bytes) - } - } + func hash(into hasher: inout Hasher) { + // If Raw bytes is valid UTF8, hash it as so + switch self { + case .string(let string): + hasher.combine(string) + case .rawBytes(let bytes): + if let stringValue = self.stringValue { + hasher.combine(stringValue) + } else { + hasher.combine(bytes) + } + } + } } - } } extension FilePath { - static var currentWorkingDirectory: Self { - let path = getcwd(nil, 0)! - defer { free(path) } - return .init(String(cString: path)) - } + static var currentWorkingDirectory: Self { + let path = getcwd(nil, 0)! + defer { free(path) } + return .init(String(cString: path)) + } } -extension Optional where Wrapped: Collection { - func withOptionalUnsafeBufferPointer(_ body: ((UnsafeBufferPointer)?) throws -> R) rethrows -> R { - switch self { - case .some(let wrapped): - guard let array: Array = wrapped as? Array else { - return try body(nil) - } - return try array.withUnsafeBufferPointer { ptr in - return try body(ptr) - } - case .none: - return try body(nil) +extension Optional where Wrapped : Collection { + func withOptionalUnsafeBufferPointer(_ body: ((UnsafeBufferPointer)?) throws -> R) rethrows -> R { + switch self { + case .some(let wrapped): + guard let array: Array = wrapped as? Array else { + return try body(nil) + } + return try array.withUnsafeBufferPointer { ptr in + return try body(ptr) + } + case .none: + return try body(nil) + } } - } } extension Optional where Wrapped == String { - func withOptionalCString(_ body: ((UnsafePointer)?) throws -> R) rethrows -> R { - switch self { - case .none: - return try body(nil) - case .some(let wrapped): - return try wrapped.withCString { - return try body($0) - } + func withOptionalCString(_ body: ((UnsafePointer)?) throws -> R) rethrows -> R { + switch self { + case .none: + return try body(nil) + case .some(let wrapped): + return try wrapped.withCString { + return try body($0) + } + } } - } } // MARK: - Stubs for the one from Foundation public enum QualityOfService: Int, Sendable { - case userInteractive = 0x21 - case userInitiated = 0x19 - case utility = 0x11 - case background = 0x09 - case `default` = -1 + case userInteractive = 0x21 + case userInitiated = 0x19 + case utility = 0x11 + case background = 0x09 + case `default` = -1 } diff --git a/Sources/_Subprocess/Subprocess+IO.swift b/Sources/_Subprocess/Subprocess+IO.swift index f71bb2dc..73b1f99e 100644 --- a/Sources/_Subprocess/Subprocess+IO.swift +++ b/Sources/_Subprocess/Subprocess+IO.swift @@ -9,392 +9,396 @@ // //===----------------------------------------------------------------------===// -import Dispatch +#if canImport(FoundationEssentials) +import FoundationEssentials +#elseif canImport(Foundation) import Foundation +#endif + +import Dispatch import SystemPackage +import Synchronization // MARK: - Input extension Subprocess { - public struct InputMethod: Sendable, Hashable { - internal enum Storage: Sendable, Hashable { - case noInput - case fileDescriptor(FileDescriptor, Bool) - } + public struct InputMethod: Sendable, Hashable { + internal enum Storage: Sendable, Hashable { + case noInput + case fileDescriptor(FileDescriptor, Bool) + } - internal let method: Storage + internal let method: Storage - internal init(method: Storage) { - self.method = method - } + internal init(method: Storage) { + self.method = method + } - internal func createExecutionInput() throws -> ExecutionInput { - switch self.method { - case .noInput: - let devnull: FileDescriptor = try .open("/dev/null", .readOnly) - return .init(storage: .noInput(devnull)) - case .fileDescriptor(let fileDescriptor, let closeWhenDone): - return .init(storage: .fileDescriptor(fileDescriptor, closeWhenDone)) - } - } + internal func createExecutionInput() throws -> ExecutionInput { + switch self.method { + case .noInput: + let devnull: FileDescriptor = try .open("/dev/null", .readOnly) + return .init(storage: .noInput(devnull)) + case .fileDescriptor(let fileDescriptor, let closeWhenDone): + return .init(storage: .fileDescriptor(fileDescriptor, closeWhenDone)) + } + } - public static var noInput: Self { - return .init(method: .noInput) - } + public static var noInput: Self { + return .init(method: .noInput) + } - public static func readFrom(_ fd: FileDescriptor, closeAfterProcessSpawned: Bool) -> Self { - return .init(method: .fileDescriptor(fd, closeAfterProcessSpawned)) + public static func readFrom(_ fd: FileDescriptor, closeAfterProcessSpawned: Bool) -> Self { + return .init(method: .fileDescriptor(fd, closeAfterProcessSpawned)) + } } - } } extension Subprocess { - public struct CollectedOutputMethod: Sendable, Hashable { - internal enum Storage: Sendable, Hashable { - case discarded - case fileDescriptor(FileDescriptor, Bool) - case collected(Int) - } + public struct CollectedOutputMethod: Sendable, Hashable { + internal enum Storage: Sendable, Hashable { + case discarded + case fileDescriptor(FileDescriptor, Bool) + case collected(Int) + } - internal let method: Storage + internal let method: Storage - internal init(method: Storage) { - self.method = method - } + internal init(method: Storage) { + self.method = method + } - public static var discard: Self { - return .init(method: .discarded) - } + public static var discard: Self { + return .init(method: .discarded) + } - public static var collect: Self { - return .init(method: .collected(128 * 1024)) - } + public static var collect: Self { + return .init(method: .collected(128 * 1024)) + } - public static func writeTo(_ fd: FileDescriptor, closeAfterProcessSpawned: Bool) -> Self { - return .init(method: .fileDescriptor(fd, closeAfterProcessSpawned)) - } + public static func writeTo(_ fd: FileDescriptor, closeAfterProcessSpawned: Bool) -> Self { + return .init(method: .fileDescriptor(fd, closeAfterProcessSpawned)) + } - public static func collect(limit: Int) -> Self { - return .init(method: .collected(limit)) - } + public static func collect(limit: Int) -> Self { + return .init(method: .collected(limit)) + } - internal func createExecutionOutput() throws -> ExecutionOutput { - switch self.method { - case .discarded: - // Bind to /dev/null - let devnull: FileDescriptor = try .open("/dev/null", .writeOnly) - return .init(storage: .discarded(devnull)) - case .fileDescriptor(let fileDescriptor, let closeWhenDone): - return .init(storage: .fileDescriptor(fileDescriptor, closeWhenDone)) - case .collected(let limit): - let (readFd, writeFd) = try FileDescriptor.pipe() - return .init(storage: .collected(limit, readFd, writeFd)) - } + internal func createExecutionOutput() throws -> ExecutionOutput { + switch self.method { + case .discarded: + // Bind to /dev/null + let devnull: FileDescriptor = try .open("/dev/null", .writeOnly) + return .init(storage: .discarded(devnull)) + case .fileDescriptor(let fileDescriptor, let closeWhenDone): + return .init(storage: .fileDescriptor(fileDescriptor, closeWhenDone)) + case .collected(let limit): + let (readFd, writeFd) = try FileDescriptor.pipe() + return .init(storage: .collected(limit, readFd, writeFd)) + } + } } - } - public struct RedirectedOutputMethod: Sendable, Hashable { - typealias Storage = CollectedOutputMethod.Storage + public struct RedirectedOutputMethod: Sendable, Hashable { + typealias Storage = CollectedOutputMethod.Storage - internal let method: Storage + internal let method: Storage - internal init(method: Storage) { - self.method = method - } + internal init(method: Storage) { + self.method = method + } - public static var discard: Self { - return .init(method: .discarded) - } + public static var discard: Self { + return .init(method: .discarded) + } - public static var redirectToSequence: Self { - return .init(method: .collected(128 * 1024)) - } + public static var redirectToSequence: Self { + return .init(method: .collected(128 * 1024)) + } - public static func writeTo(_ fd: FileDescriptor, closeAfterProcessSpawned: Bool) -> Self { - return .init(method: .fileDescriptor(fd, closeAfterProcessSpawned)) - } + public static func writeTo(_ fd: FileDescriptor, closeAfterProcessSpawned: Bool) -> Self { + return .init(method: .fileDescriptor(fd, closeAfterProcessSpawned)) + } - internal func createExecutionOutput() throws -> ExecutionOutput { - switch self.method { - case .discarded: - // Bind to /dev/null - let devnull: FileDescriptor = try .open("/dev/null", .writeOnly) - return .init(storage: .discarded(devnull)) - case .fileDescriptor(let fileDescriptor, let closeWhenDone): - return .init(storage: .fileDescriptor(fileDescriptor, closeWhenDone)) - case .collected(let limit): - let (readFd, writeFd) = try FileDescriptor.pipe() - return .init(storage: .collected(limit, readFd, writeFd)) - } + internal func createExecutionOutput() throws -> ExecutionOutput { + switch self.method { + case .discarded: + // Bind to /dev/null + let devnull: FileDescriptor = try .open("/dev/null", .writeOnly) + return .init(storage: .discarded(devnull)) + case .fileDescriptor(let fileDescriptor, let closeWhenDone): + return .init(storage: .fileDescriptor(fileDescriptor, closeWhenDone)) + case .collected(let limit): + let (readFd, writeFd) = try FileDescriptor.pipe() + return .init(storage: .collected(limit, readFd, writeFd)) + } + } } - } } // MARK: - Execution IO extension Subprocess { - internal final class ExecutionInput: Sendable { - - internal enum Storage: Sendable { - case noInput(FileDescriptor?) - case customWrite(FileDescriptor?, FileDescriptor?) - case fileDescriptor(FileDescriptor?, Bool) - } + internal final class ExecutionInput: Sendable { - let storage: LockedState - - internal init(storage: Storage) { - self.storage = .init(initialState: storage) - } + internal enum Storage: Sendable { + case noInput(FileDescriptor?) + case customWrite(FileDescriptor?, FileDescriptor?) + case fileDescriptor(FileDescriptor?, Bool) + } + + let storage: Mutex - internal func getReadFileDescriptor() -> FileDescriptor? { - return self.storage.withLock { - switch $0 { - case .noInput(let readFd): - return readFd - case .customWrite(let readFd, _): - return readFd - case .fileDescriptor(let readFd, _): - return readFd - } - } - } + internal init(storage: Storage) { + self.storage = .init(storage) + } - internal func getWriteFileDescriptor() -> FileDescriptor? { - return self.storage.withLock { - switch $0 { - case .noInput(_), .fileDescriptor(_, _): - return nil - case .customWrite(_, let writeFd): - return writeFd + internal func getReadFileDescriptor() -> FileDescriptor? { + return self.storage.withLock { + switch $0 { + case .noInput(let readFd): + return readFd + case .customWrite(let readFd, _): + return readFd + case .fileDescriptor(let readFd, _): + return readFd + } + } } - } - } - internal func closeChildSide() throws { - try self.storage.withLock { - switch $0 { - case .noInput(let devnull): - try devnull?.close() - $0 = .noInput(nil) - case .customWrite(let readFd, let writeFd): - try readFd?.close() - $0 = .customWrite(nil, writeFd) - case .fileDescriptor(let fd, let closeWhenDone): - // User passed in fd - if closeWhenDone { - try fd?.close() - $0 = .fileDescriptor(nil, closeWhenDone) - } - } - } - } + internal func getWriteFileDescriptor() -> FileDescriptor? { + return self.storage.withLock { + switch $0 { + case .noInput(_), .fileDescriptor(_, _): + return nil + case .customWrite(_, let writeFd): + return writeFd + } + } + } - internal func closeParentSide() throws { - try self.storage.withLock { - switch $0 { - case .noInput(_), .fileDescriptor(_, _): - break - case .customWrite(let readFd, let writeFd): - // The parent fd should have been closed - // in the `body` when writer.finish() is called - // But in case it isn't call it agian - try writeFd?.close() - $0 = .customWrite(readFd, nil) - } - } - } + internal func closeChildSide() throws { + try self.storage.withLock { + switch $0 { + case .noInput(let devnull): + try devnull?.close() + $0 = .noInput(nil) + case .customWrite(let readFd, let writeFd): + try readFd?.close() + $0 = .customWrite(nil, writeFd) + case .fileDescriptor(let fd, let closeWhenDone): + // User passed in fd + if closeWhenDone { + try fd?.close() + $0 = .fileDescriptor(nil, closeWhenDone) + } + } + } + } - internal func closeAll() throws { - try self.storage.withLock { - switch $0 { - case .noInput(let readFd): - try readFd?.close() - $0 = .noInput(nil) - case .customWrite(let readFd, let writeFd): - var readFdCloseError: Error? - var writeFdCloseError: Error? - do { - try readFd?.close() - } catch { - readFdCloseError = error - } - do { - try writeFd?.close() - } catch { - writeFdCloseError = error - } - $0 = .customWrite(nil, nil) - if let readFdCloseError { - throw readFdCloseError - } - if let writeFdCloseError { - throw writeFdCloseError - } - case .fileDescriptor(let fd, let closeWhenDone): - try fd?.close() - $0 = .fileDescriptor(nil, closeWhenDone) - } - } - } - } + internal func closeParentSide() throws { + try self.storage.withLock { + switch $0 { + case .noInput(_), .fileDescriptor(_, _): + break + case .customWrite(let readFd, let writeFd): + // The parent fd should have been closed + // in the `body` when writer.finish() is called + // But in case it isn't call it agian + try writeFd?.close() + $0 = .customWrite(readFd, nil) + } + } + } - internal final class ExecutionOutput: Sendable { - internal enum Storage: Sendable { - case discarded(FileDescriptor?) - case fileDescriptor(FileDescriptor?, Bool) - case collected(Int, FileDescriptor?, FileDescriptor?) + internal func closeAll() throws { + try self.storage.withLock { + switch $0 { + case .noInput(let readFd): + try readFd?.close() + $0 = .noInput(nil) + case .customWrite(let readFd, let writeFd): + var readFdCloseError: Error? + var writeFdCloseError: Error? + do { + try readFd?.close() + } catch { + readFdCloseError = error + } + do { + try writeFd?.close() + } catch { + writeFdCloseError = error + } + $0 = .customWrite(nil, nil) + if let readFdCloseError { + throw readFdCloseError + } + if let writeFdCloseError { + throw writeFdCloseError + } + case .fileDescriptor(let fd, let closeWhenDone): + try fd?.close() + $0 = .fileDescriptor(nil, closeWhenDone) + } + } + } } - private let storage: LockedState - - internal init(storage: Storage) { - self.storage = .init(initialState: storage) - } + internal final class ExecutionOutput: Sendable { + internal enum Storage: Sendable { + case discarded(FileDescriptor?) + case fileDescriptor(FileDescriptor?, Bool) + case collected(Int, FileDescriptor?, FileDescriptor?) + } + + private let storage: Mutex - internal func getWriteFileDescriptor() -> FileDescriptor? { - return self.storage.withLock { - switch $0 { - case .discarded(let writeFd): - return writeFd - case .fileDescriptor(let writeFd, _): - return writeFd - case .collected(_, _, let writeFd): - return writeFd - } - } - } + internal init(storage: Storage) { + self.storage = .init(storage) + } - internal func getReadFileDescriptor() -> FileDescriptor? { - return self.storage.withLock { - switch $0 { - case .discarded(_), .fileDescriptor(_, _): - return nil - case .collected(_, let readFd, _): - return readFd + internal func getWriteFileDescriptor() -> FileDescriptor? { + return self.storage.withLock { + switch $0 { + case .discarded(let writeFd): + return writeFd + case .fileDescriptor(let writeFd, _): + return writeFd + case .collected(_, _, let writeFd): + return writeFd + } + } } - } - } - internal func consumeCollectedFileDescriptor() -> (limit: Int, fd: FileDescriptor?)? { - return self.storage.withLock { - switch $0 { - case .discarded(_), .fileDescriptor(_, _): - // The output has been written somewhere else - return nil - case .collected(let limit, let readFd, let writeFd): - $0 = .collected(limit, nil, writeFd) - return (limit, readFd) - } - } - } + internal func getReadFileDescriptor() -> FileDescriptor? { + return self.storage.withLock { + switch $0 { + case .discarded(_), .fileDescriptor(_, _): + return nil + case .collected(_, let readFd, _): + return readFd + } + } + } + + internal func consumeCollectedFileDescriptor() -> (limit: Int, fd: FileDescriptor?)? { + return self.storage.withLock { + switch $0 { + case .discarded(_), .fileDescriptor(_, _): + // The output has been written somewhere else + return nil + case .collected(let limit, let readFd, let writeFd): + $0 = .collected(limit, nil, writeFd) + return (limit, readFd) + } + } + } - internal func closeChildSide() throws { - try self.storage.withLock { - switch $0 { - case .discarded(let writeFd): - try writeFd?.close() - $0 = .discarded(nil) - case .fileDescriptor(let fd, let closeWhenDone): - // User passed fd - if closeWhenDone { - try fd?.close() - $0 = .fileDescriptor(nil, closeWhenDone) - } - case .collected(let limit, let readFd, let writeFd): - try writeFd?.close() - $0 = .collected(limit, readFd, nil) - } - } - } + internal func closeChildSide() throws { + try self.storage.withLock { + switch $0 { + case .discarded(let writeFd): + try writeFd?.close() + $0 = .discarded(nil) + case .fileDescriptor(let fd, let closeWhenDone): + // User passed fd + if closeWhenDone { + try fd?.close() + $0 = .fileDescriptor(nil, closeWhenDone) + } + case .collected(let limit, let readFd, let writeFd): + try writeFd?.close() + $0 = .collected(limit, readFd, nil) + } + } + } - internal func closeParentSide() throws { - try self.storage.withLock { - switch $0 { - case .discarded(_), .fileDescriptor(_, _): - break - case .collected(let limit, let readFd, let writeFd): - try readFd?.close() - $0 = .collected(limit, nil, writeFd) + internal func closeParentSide() throws { + try self.storage.withLock { + switch $0 { + case .discarded(_), .fileDescriptor(_, _): + break + case .collected(let limit, let readFd, let writeFd): + try readFd?.close() + $0 = .collected(limit, nil, writeFd) + } + } } - } - } - internal func closeAll() throws { - try self.storage.withLock { - switch $0 { - case .discarded(let writeFd): - try writeFd?.close() - $0 = .discarded(nil) - case .fileDescriptor(let fd, let closeWhenDone): - try fd?.close() - $0 = .fileDescriptor(nil, closeWhenDone) - case .collected(let limit, let readFd, let writeFd): - var readFdCloseError: Error? - var writeFdCloseError: Error? - do { - try readFd?.close() - } catch { - readFdCloseError = error - } - do { - try writeFd?.close() - } catch { - writeFdCloseError = error - } - $0 = .collected(limit, nil, nil) - if let readFdCloseError { - throw readFdCloseError - } - if let writeFdCloseError { - throw writeFdCloseError - } - } - } + internal func closeAll() throws { + try self.storage.withLock { + switch $0 { + case .discarded(let writeFd): + try writeFd?.close() + $0 = .discarded(nil) + case .fileDescriptor(let fd, let closeWhenDone): + try fd?.close() + $0 = .fileDescriptor(nil, closeWhenDone) + case .collected(let limit, let readFd, let writeFd): + var readFdCloseError: Error? + var writeFdCloseError: Error? + do { + try readFd?.close() + } catch { + readFdCloseError = error + } + do { + try writeFd?.close() + } catch { + writeFdCloseError = error + } + $0 = .collected(limit, nil, nil) + if let readFdCloseError { + throw readFdCloseError + } + if let writeFdCloseError { + throw writeFdCloseError + } + } + } + } } - } } // MARK: - Private Helpers extension FileDescriptor { - internal func read(upToLength maxLength: Int) async throws -> [UInt8] { - return try await withCheckedThrowingContinuation { continuation in - DispatchIO.read( - fromFileDescriptor: self.rawValue, - maxLength: maxLength, - runningHandlerOn: .main - ) { data, error in - guard error == 0 else { - continuation.resume( - throwing: POSIXError( - .init(rawValue: error) ?? .ENODEV - ) - ) - return - } - continuation.resume(returning: Array(data)) - } + internal func read(upToLength maxLength: Int) async throws -> [UInt8] { + return try await withCheckedThrowingContinuation { continuation in + DispatchIO.read( + fromFileDescriptor: self.rawValue, + maxLength: maxLength, + runningHandlerOn: .main + ) { data, error in + guard error == 0 else { + continuation.resume( + throwing: POSIXError( + .init(rawValue: error) ?? .ENODEV) + ) + return + } + continuation.resume(returning: Array(data)) + } + } } - } - - internal func write(_ data: S) async throws where S.Element == UInt8 { - try await withCheckedThrowingContinuation { (continuation: CheckedContinuation) -> Void in - let dispatchData: DispatchData = Array(data).withUnsafeBytes { - return DispatchData(bytes: $0) - } - DispatchIO.write( - toFileDescriptor: self.rawValue, - data: dispatchData, - runningHandlerOn: .main - ) { _, error in - guard error == 0 else { - continuation.resume( - throwing: POSIXError( - .init(rawValue: error) ?? .ENODEV - ) - ) - return - } - continuation.resume() - } + + internal func write(_ data: S) async throws where S.Element == UInt8 { + try await withCheckedThrowingContinuation { (continuation: CheckedContinuation) -> Void in + let dispatchData: DispatchData = Array(data).withUnsafeBytes { + return DispatchData(bytes: $0) + } + DispatchIO.write( + toFileDescriptor: self.rawValue, + data: dispatchData, + runningHandlerOn: .main + ) { _, error in + guard error == 0 else { + continuation.resume( + throwing: POSIXError( + .init(rawValue: error) ?? .ENODEV) + ) + return + } + continuation.resume() + } + } } - } } diff --git a/Sources/_Subprocess/Subprocess.swift b/Sources/_Subprocess/Subprocess.swift index fe61ba81..56758bcf 100644 --- a/Sources/_Subprocess/Subprocess.swift +++ b/Sources/_Subprocess/Subprocess.swift @@ -9,9 +9,14 @@ // //===----------------------------------------------------------------------===// -import Foundation import SystemPackage +#if canImport(FoundationEssentials) +import FoundationEssentials +#elseif canImport(Foundation) +import Foundation +#endif + /// An object that represents a subprocess of the current process. /// /// Using `Subprocess`, your program can run another program as a subprocess @@ -19,215 +24,208 @@ import SystemPackage /// **separate executable** entity; it’s different from `Thread` because it doesn’t /// share memory space with the process that creates it. public struct Subprocess: Sendable { - /// The process identifier of the current subprocess - public let processIdentifier: ProcessIdentifier - - internal let executionInput: ExecutionInput - internal let executionOutput: ExecutionOutput - internal let executionError: ExecutionOutput - internal var extracted: Bool = false - - internal init( - processIdentifier: ProcessIdentifier, - executionInput: ExecutionInput, - executionOutput: ExecutionOutput, - executionError: ExecutionOutput - ) { - self.processIdentifier = processIdentifier - self.executionInput = executionInput - self.executionOutput = executionOutput - self.executionError = executionError - } - - /// The standard output of the subprocess. - /// Accessing this property will **fatalError** if - /// - `.output` wasn't set to `.redirectToSequence` when the subprocess was spawned; - /// - This property was accessed multiple times. Subprocess communicates with - /// parent process via pipe under the hood and each pipe can only be consumed ones. - public var standardOutput: some _AsyncSequence { - guard - let (_, fd) = self.executionOutput - .consumeCollectedFileDescriptor() - else { - fatalError("The standard output was not redirected") - } - guard let fd = fd else { - fatalError("The standard output has already been closed") - } - return AsyncBytes(fileDescriptor: fd) - } - - /// The standard error of the subprocess. - /// Accessing this property will **fatalError** if - /// - `.error` wasn't set to `.redirectToSequence` when the subprocess was spawned; - /// - This property was accessed multiple times. Subprocess communicates with - /// parent process via pipe under the hood and each pipe can only be consumed ones. - public var standardError: some _AsyncSequence { - guard - let (_, fd) = self.executionError - .consumeCollectedFileDescriptor() - else { - fatalError("The standard error was not redirected") - } - guard let fd = fd else { - fatalError("The standard error has already been closed") + /// The process identifier of the current subprocess + public let processIdentifier: ProcessIdentifier + + internal let executionInput: ExecutionInput + internal let executionOutput: ExecutionOutput + internal let executionError: ExecutionOutput + internal var extracted: Bool = false + + internal init( + processIdentifier: ProcessIdentifier, + executionInput: ExecutionInput, + executionOutput: ExecutionOutput, + executionError: ExecutionOutput + ) { + self.processIdentifier = processIdentifier + self.executionInput = executionInput + self.executionOutput = executionOutput + self.executionError = executionError + } + + /// The standard output of the subprocess. + /// Accessing this property will **fatalError** if + /// - `.output` wasn't set to `.redirectToSequence` when the subprocess was spawned; + /// - This property was accessed multiple times. Subprocess communicates with + /// parent process via pipe under the hood and each pipe can only be consumed ones. + public var standardOutput: some _AsyncSequence { + guard let (_, fd) = self.executionOutput + .consumeCollectedFileDescriptor() else { + fatalError("The standard output was not redirected") + } + guard let fd = fd else { + fatalError("The standard output has already been closed") + } + return AsyncBytes(fileDescriptor: fd) + } + + /// The standard error of the subprocess. + /// Accessing this property will **fatalError** if + /// - `.error` wasn't set to `.redirectToSequence` when the subprocess was spawned; + /// - This property was accessed multiple times. Subprocess communicates with + /// parent process via pipe under the hood and each pipe can only be consumed ones. + public var standardError: some _AsyncSequence { + guard let (_, fd) = self.executionError + .consumeCollectedFileDescriptor() else { + fatalError("The standard error was not redirected") + } + guard let fd = fd else { + fatalError("The standard error has already been closed") + } + return AsyncBytes(fileDescriptor: fd) } - return AsyncBytes(fileDescriptor: fd) - } } // MARK: - StandardInputWriter extension Subprocess { - @_nonSendable - public struct StandardInputWriter { + @_nonSendable + public struct StandardInputWriter { - private let input: ExecutionInput + private let input: ExecutionInput - init(input: ExecutionInput) { - self.input = input - } + init(input: ExecutionInput) { + self.input = input + } - public func write(_ sequence: S) async throws where S: Sequence, S.Element == UInt8 { - guard let fd: FileDescriptor = self.input.getWriteFileDescriptor() else { - fatalError("Attempting to write to a file descriptor that's already closed") - } - try await fd.write(sequence) - } + public func write(_ sequence: S) async throws where S : Sequence, S.Element == UInt8 { + guard let fd: FileDescriptor = self.input.getWriteFileDescriptor() else { + fatalError("Attempting to write to a file descriptor that's already closed") + } + try await fd.write(sequence) + } - public func write(_ sequence: S) async throws where S: Sequence, S.Element == CChar { - try await self.write(sequence.map { UInt8($0) }) - } + public func write(_ sequence: S) async throws where S : Sequence, S.Element == CChar { + try await self.write(sequence.map { UInt8($0) }) + } - public func write(_ asyncSequence: S) async throws where S.Element == CChar { - let sequence = try await Array(asyncSequence).map { UInt8($0) } - try await self.write(sequence) - } + public func write(_ asyncSequence: S) async throws where S.Element == CChar { + let sequence = try await Array(asyncSequence).map { UInt8($0) } + try await self.write(sequence) + } - public func write(_ asyncSequence: S) async throws where S.Element == UInt8 { - let sequence = try await Array(asyncSequence) - try await self.write(sequence) - } + public func write(_ asyncSequence: S) async throws where S.Element == UInt8 { + let sequence = try await Array(asyncSequence) + try await self.write(sequence) + } - public func finish() async throws { - try self.input.closeParentSide() + public func finish() async throws { + try self.input.closeParentSide() + } } - } } // MARK: - Result extension Subprocess { - public struct ExecutionResult: Sendable { - public let terminationStatus: TerminationStatus - public let value: T + public struct ExecutionResult: Sendable { + public let terminationStatus: TerminationStatus + public let value: T - internal init(terminationStatus: TerminationStatus, value: T) { - self.terminationStatus = terminationStatus - self.value = value + internal init(terminationStatus: TerminationStatus, value: T) { + self.terminationStatus = terminationStatus + self.value = value + } } - } - public struct CollectedResult: Sendable, Hashable { - public let processIdentifier: ProcessIdentifier - public let terminationStatus: TerminationStatus - private let _standardOutput: Data? - private let _standardError: Data? - public var standardOutput: Data { - guard let output = self._standardOutput else { - fatalError("standardOutput is only available if the Subprocess was ran with .collect as output") - } - return output - } - public var standardError: Data { - guard let output = self._standardError else { - fatalError("standardError is only available if the Subprocess was ran with .collect as error ") - } - return output - } + public struct CollectedResult: Sendable, Hashable { + public let processIdentifier: ProcessIdentifier + public let terminationStatus: TerminationStatus + private let _standardOutput: Data? + private let _standardError: Data? + public var standardOutput: Data { + guard let output = self._standardOutput else { + fatalError("standardOutput is only available if the Subprocess was ran with .collect as output") + } + return output + } + public var standardError: Data { + guard let output = self._standardError else { + fatalError("standardError is only available if the Subprocess was ran with .collect as error ") + } + return output + } - internal init( - processIdentifier: ProcessIdentifier, - terminationStatus: TerminationStatus, - standardOutput: Data?, - standardError: Data? - ) { - self.processIdentifier = processIdentifier - self.terminationStatus = terminationStatus - self._standardOutput = standardOutput - self._standardError = standardError + internal init( + processIdentifier: ProcessIdentifier, + terminationStatus: TerminationStatus, + standardOutput: Data?, + standardError: Data?) { + self.processIdentifier = processIdentifier + self.terminationStatus = terminationStatus + self._standardOutput = standardOutput + self._standardError = standardError + } } - } } -extension Subprocess.ExecutionResult: Equatable where T: Equatable {} +extension Subprocess.ExecutionResult: Equatable where T : Equatable {} -extension Subprocess.ExecutionResult: Hashable where T: Hashable {} +extension Subprocess.ExecutionResult: Hashable where T : Hashable {} -extension Subprocess.ExecutionResult: Codable where T: Codable {} +extension Subprocess.ExecutionResult: Codable where T : Codable {} // MARK: Internal extension Subprocess { - internal enum OutputCapturingState { - case standardOutputCaptured(Data?) - case standardErrorCaptured(Data?) - } - - private func capture(fileDescriptor: FileDescriptor, maxLength: Int) async throws -> Data { - let chunkSize: Int = min(Subprocess.readBufferSize, maxLength) - var buffer: [UInt8] = [] - while buffer.count <= maxLength { - let captured = try await fileDescriptor.read(upToLength: chunkSize) - buffer += captured - if captured.count < chunkSize { - break - } - } - return Data(buffer) - } - - internal func captureStandardOutput() async throws -> Data? { - guard - let (limit, readFd) = self.executionOutput - .consumeCollectedFileDescriptor(), - let readFd = readFd - else { - return nil + internal enum OutputCapturingState { + case standardOutputCaptured(Data?) + case standardErrorCaptured(Data?) + } + + internal typealias CapturedIOs = (standardOutput: Data?, standardError: Data?) + + private func capture(fileDescriptor: FileDescriptor, maxLength: Int) async throws -> Data{ + let chunkSize: Int = min(Subprocess.readBufferSize, maxLength) + var buffer: [UInt8] = [] + while buffer.count <= maxLength { + let captured = try await fileDescriptor.read(upToLength: chunkSize) + buffer += captured + if captured.count < chunkSize { + break + } + } + return Data(buffer) } - return try await self.capture(fileDescriptor: readFd, maxLength: limit) - } - - internal func captureStandardError() async throws -> Data? { - guard - let (limit, readFd) = self.executionError - .consumeCollectedFileDescriptor(), - let readFd = readFd - else { - return nil + + internal func captureStandardOutput() async throws -> Data? { + guard let (limit, readFd) = self.executionOutput + .consumeCollectedFileDescriptor(), + let readFd = readFd else { + return nil + } + return try await self.capture(fileDescriptor: readFd, maxLength: limit) } - return try await self.capture(fileDescriptor: readFd, maxLength: limit) - } - - internal func captureIOs() async throws -> (standardOut: Data?, standardError: Data?) { - return try await withThrowingTaskGroup(of: OutputCapturingState.self) { group in - group.addTask { - let stdout = try await self.captureStandardOutput() - return .standardOutputCaptured(stdout) - } - group.addTask { - let stderr = try await self.captureStandardError() - return .standardErrorCaptured(stderr) - } - - var stdout: Data? - var stderror: Data? - while let state = try await group.next() { - switch state { - case .standardOutputCaptured(let output): - stdout = output - case .standardErrorCaptured(let error): - stderror = error - } - } - return (standardOut: stdout, standardError: stderror) + + internal func captureStandardError() async throws -> Data? { + guard let (limit, readFd) = self.executionError + .consumeCollectedFileDescriptor(), + let readFd = readFd else { + return nil + } + return try await self.capture(fileDescriptor: readFd, maxLength: limit) + } + + internal func captureIOs() async throws -> CapturedIOs { + return try await withThrowingTaskGroup(of: OutputCapturingState.self) { group in + group.addTask { + let stdout = try await self.captureStandardOutput() + return .standardOutputCaptured(stdout) + } + group.addTask { + let stderr = try await self.captureStandardError() + return .standardErrorCaptured(stderr) + } + + var stdout: Data? + var stderror: Data? + while let state = try await group.next() { + switch state { + case .standardOutputCaptured(let output): + stdout = output + case .standardErrorCaptured(let error): + stderror = error + } + } + return (standardOutput: stdout, standardError: stderror) + } } - } } diff --git a/Sources/_Subprocess/_LockedState.swift b/Sources/_Subprocess/_LockedState.swift deleted file mode 100644 index da17ccf5..00000000 --- a/Sources/_Subprocess/_LockedState.swift +++ /dev/null @@ -1,159 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2022 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// -//===----------------------------------------------------------------------===// - -#if canImport(os) -internal import os -#if FOUNDATION_FRAMEWORK && canImport(C.os.lock) -internal import C.os.lock -#endif -#elseif canImport(Bionic) -import Bionic -#elseif canImport(Glibc) -import Glibc -#elseif canImport(Musl) -import Musl -#elseif canImport(WinSDK) -import WinSDK -#endif - -package struct LockedState { - - // Internal implementation for a cheap lock to aid sharing code across platforms - private struct _Lock { - #if canImport(os) - typealias Primitive = os_unfair_lock - #elseif canImport(Bionic) || canImport(Glibc) || canImport(Musl) - typealias Primitive = pthread_mutex_t - #elseif canImport(WinSDK) - typealias Primitive = SRWLOCK - #elseif os(WASI) - // WASI is single-threaded, so we don't need a lock. - typealias Primitive = Void - #endif - - typealias PlatformLock = UnsafeMutablePointer - var _platformLock: PlatformLock - - fileprivate static func initialize(_ platformLock: PlatformLock) { - #if canImport(os) - platformLock.initialize(to: os_unfair_lock()) - #elseif canImport(Bionic) || canImport(Glibc) - pthread_mutex_init(platformLock, nil) - #elseif canImport(WinSDK) - InitializeSRWLock(platformLock) - #elseif os(WASI) - // no-op - #endif - } - - fileprivate static func deinitialize(_ platformLock: PlatformLock) { - #if canImport(Bionic) || canImport(Glibc) - pthread_mutex_destroy(platformLock) - #endif - platformLock.deinitialize(count: 1) - } - - static fileprivate func lock(_ platformLock: PlatformLock) { - #if canImport(os) - os_unfair_lock_lock(platformLock) - #elseif canImport(Bionic) || canImport(Glibc) - pthread_mutex_lock(platformLock) - #elseif canImport(WinSDK) - AcquireSRWLockExclusive(platformLock) - #elseif os(WASI) - // no-op - #endif - } - - static fileprivate func unlock(_ platformLock: PlatformLock) { - #if canImport(os) - os_unfair_lock_unlock(platformLock) - #elseif canImport(Bionic) || canImport(Glibc) - pthread_mutex_unlock(platformLock) - #elseif canImport(WinSDK) - ReleaseSRWLockExclusive(platformLock) - #elseif os(WASI) - // no-op - #endif - } - } - - private class _Buffer: ManagedBuffer { - deinit { - withUnsafeMutablePointerToElements { - _Lock.deinitialize($0) - } - } - } - - private let _buffer: ManagedBuffer - - package init(initialState: State) { - _buffer = _Buffer.create( - minimumCapacity: 1, - makingHeaderWith: { buf in - buf.withUnsafeMutablePointerToElements { - _Lock.initialize($0) - } - return initialState - } - ) - } - - package func withLock(_ body: @Sendable (inout State) throws -> T) rethrows -> T { - try withLockUnchecked(body) - } - - package func withLockUnchecked(_ body: (inout State) throws -> T) rethrows -> T { - try _buffer.withUnsafeMutablePointers { state, lock in - _Lock.lock(lock) - defer { _Lock.unlock(lock) } - return try body(&state.pointee) - } - } - - // Ensures the managed state outlives the locked scope. - package func withLockExtendingLifetimeOfState(_ body: @Sendable (inout State) throws -> T) rethrows -> T { - try _buffer.withUnsafeMutablePointers { state, lock in - _Lock.lock(lock) - return try withExtendedLifetime(state.pointee) { - defer { _Lock.unlock(lock) } - return try body(&state.pointee) - } - } - } -} - -extension LockedState where State == Void { - package init() { - self.init(initialState: ()) - } - - package func withLock(_ body: @Sendable () throws -> R) rethrows -> R { - return try withLock { _ in - try body() - } - } - - package func lock() { - _buffer.withUnsafeMutablePointerToElements { lock in - _Lock.lock(lock) - } - } - - package func unlock() { - _buffer.withUnsafeMutablePointerToElements { lock in - _Lock.unlock(lock) - } - } -} - -extension LockedState: @unchecked Sendable where State: Sendable {} diff --git a/Sources/_SubprocessCShims/include/_CShimsTargetConditionals.h b/Sources/_SubprocessCShims/include/_CShimsTargetConditionals.h index d6db4bf7..fef2eaf2 100644 --- a/Sources/_SubprocessCShims/include/_CShimsTargetConditionals.h +++ b/Sources/_SubprocessCShims/include/_CShimsTargetConditionals.h @@ -2,7 +2,7 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2021 - 2022 Apple Inc. and the Swift.org project authors +// Copyright (c) 2021 - 2022 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See https://swift.org/LICENSE.txt for license information @@ -10,8 +10,8 @@ // //===----------------------------------------------------------------------===// -#ifndef _C_SHIMS_TARGET_CONDITIONALS_H -#define _C_SHIMS_TARGET_CONDITIONALS_H +#ifndef _SHIMS_TARGET_CONDITIONALS_H +#define _SHIMS_TARGET_CONDITIONALS_H #if __has_include() #include @@ -47,10 +47,4 @@ #define TARGET_OS_WASI 0 #endif -#if defined(__ANDROID__) -#define TARGET_OS_ANDROID 1 -#else -#define TARGET_OS_ANDROID 0 -#endif - -#endif // _C_SHIMS_TARGET_CONDITIONALS_H +#endif // _SHIMS_TARGET_CONDITIONALS_H diff --git a/Sources/_SubprocessCShims/include/process_shims.h b/Sources/_SubprocessCShims/include/process_shims.h index cf921da8..560bdf0f 100644 --- a/Sources/_SubprocessCShims/include/process_shims.h +++ b/Sources/_SubprocessCShims/include/process_shims.h @@ -15,9 +15,11 @@ #include #include "_CShimsTargetConditionals.h" -#if TARGET_OS_MAC +#if _POSIX_SPAWN #include +#endif +#if TARGET_OS_MAC int _subprocess_spawn( pid_t * _Nonnull pid, const char * _Nonnull exec_path, @@ -41,9 +43,10 @@ int _subprocess_fork_exec( char * _Nullable const env[_Nullable], uid_t * _Nullable uid, gid_t * _Nullable gid, + gid_t * _Nullable process_group_id, int number_of_sgroups, const gid_t * _Nullable sgroups, int create_session, - int create_process_group + void (* _Nullable configurator)(void) ); int _was_process_exited(int status); diff --git a/Sources/_SubprocessCShims/process_shims.c b/Sources/_SubprocessCShims/process_shims.c index 61348a2d..8f708a58 100644 --- a/Sources/_SubprocessCShims/process_shims.c +++ b/Sources/_SubprocessCShims/process_shims.c @@ -11,9 +11,16 @@ #include "include/_CShimsTargetConditionals.h" #include "include/process_shims.h" +#include #include +#include +#include #include #include +#include +#include + +#include int _was_process_exited(int status) { return WIFEXITED(status); @@ -61,31 +68,34 @@ int _subprocess_spawn( int create_session ) { int require_pre_fork = uid != NULL || - gid != NULL || - number_of_sgroups > 0 || + gid != NULL || + number_of_sgroups > 0 || create_session > 0; if (require_pre_fork != 0) { - pid_t childPid = fork(); +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated" + pid_t childPid = vfork(); +#pragma GCC diagnostic pop if (childPid != 0) { *pid = childPid; return childPid < 0 ? errno : 0; } - if (uid != NULL) { - if (setuid(*uid) != 0) { + if (number_of_sgroups > 0 && sgroups != NULL) { + if (setgroups(number_of_sgroups, sgroups) != 0) { return errno; } } - if (gid != NULL) { - if (setgid(*gid) != 0) { + if (uid != NULL) { + if (setuid(*uid) != 0) { return errno; } } - if (number_of_sgroups > 0 && sgroups != NULL) { - if (setgroups(number_of_sgroups, sgroups) != 0) { + if (gid != NULL) { + if (setgid(*gid) != 0) { return errno; } } @@ -104,7 +114,8 @@ int _subprocess_spawn( } rc = posix_spawnattr_setflags( - (posix_spawnattr_t *)spawn_attrs, flags | POSIX_SPAWN_SETEXEC); + (posix_spawnattr_t *)spawn_attrs, flags | POSIX_SPAWN_SETEXEC + ); if (rc != 0) { return rc; } @@ -126,31 +137,42 @@ static int _subprocess_posix_spawn_fallback( const int file_descriptors[_Nonnull], char * _Nullable const args[_Nonnull], char * _Nullable const env[_Nullable], - int create_process_group + gid_t * _Nullable process_group_id ) { // Setup stdin, stdout, and stderr posix_spawn_file_actions_t file_actions; int rc = posix_spawn_file_actions_init(&file_actions); if (rc != 0) { return rc; } - rc = posix_spawn_file_actions_adddup2( - &file_actions, file_descriptors[0], STDIN_FILENO); - if (rc != 0) { return rc; } - rc = posix_spawn_file_actions_adddup2( - &file_actions, file_descriptors[2], STDOUT_FILENO); - if (rc != 0) { return rc; } - rc = posix_spawn_file_actions_adddup2( - &file_actions, file_descriptors[4], STDERR_FILENO); - if (rc != 0) { return rc; } - if (file_descriptors[1] != 0) { + if (file_descriptors[0] >= 0) { + rc = posix_spawn_file_actions_adddup2( + &file_actions, file_descriptors[0], STDIN_FILENO + ); + if (rc != 0) { return rc; } + } + if (file_descriptors[2] >= 0) { + rc = posix_spawn_file_actions_adddup2( + &file_actions, file_descriptors[2], STDOUT_FILENO + ); + if (rc != 0) { return rc; } + } + if (file_descriptors[4] >= 0) { + rc = posix_spawn_file_actions_adddup2( + &file_actions, file_descriptors[4], STDERR_FILENO + ); + if (rc != 0) { return rc; } + } + + // Close parent side + if (file_descriptors[1] >= 0) { rc = posix_spawn_file_actions_addclose(&file_actions, file_descriptors[1]); if (rc != 0) { return rc; } } - if (file_descriptors[3] != 0) { + if (file_descriptors[3] >= 0) { rc = posix_spawn_file_actions_addclose(&file_actions, file_descriptors[3]); if (rc != 0) { return rc; } } - if (file_descriptors[5] != 0) { + if (file_descriptors[5] >= 0) { rc = posix_spawn_file_actions_addclose(&file_actions, file_descriptors[5]); if (rc != 0) { return rc; } } @@ -170,8 +192,10 @@ static int _subprocess_posix_spawn_fallback( if (rc != 0) { return rc; } // Flags short flags = POSIX_SPAWN_SETSIGMASK | POSIX_SPAWN_SETSIGDEF; - if (create_process_group) { + if (process_group_id != NULL) { flags |= POSIX_SPAWN_SETPGROUP; + rc = posix_spawnattr_setpgroup(&spawn_attr, *process_group_id); + if (rc != 0) { return rc; } } rc = posix_spawnattr_setflags(&spawn_attr, flags); @@ -196,15 +220,18 @@ int _subprocess_fork_exec( char * _Nullable const env[_Nullable], uid_t * _Nullable uid, gid_t * _Nullable gid, + gid_t * _Nullable process_group_id, int number_of_sgroups, const gid_t * _Nullable sgroups, int create_session, - int create_process_group + void (* _Nullable configurator)(void) ) { int require_pre_fork = working_directory != NULL || uid != NULL || gid != NULL || + process_group_id != NULL || (number_of_sgroups > 0 && sgroups != NULL) || - create_session; + create_session || + configurator != NULL; #if _POSIX_SPAWN // If posix_spawn is available on this platform and @@ -219,7 +246,7 @@ int _subprocess_fork_exec( working_directory, file_descriptors, args, env, - create_process_group + process_group_id ); } #endif @@ -236,6 +263,7 @@ int _subprocess_fork_exec( } } + if (uid != NULL) { if (setuid(*uid) != 0) { return errno; @@ -258,41 +286,41 @@ int _subprocess_fork_exec( (void)setsid(); } - if (create_process_group != 0) { - (void)setpgid(0, 0); + if (process_group_id != NULL) { + (void)setpgid(0, *process_group_id); } // Bind stdin, stdout, and stderr int rc = 0; - if (file_descriptors[0] != 0) { + if (file_descriptors[0] >= 0) { rc = dup2(file_descriptors[0], STDIN_FILENO); - if (rc != 0) { return rc; } + if (rc < 0) { return errno; } } - if (file_descriptors[2] != 0) { + if (file_descriptors[2] >= 0) { rc = dup2(file_descriptors[2], STDOUT_FILENO); - if (rc != 0) { return rc; } + if (rc < 0) { return errno; } } - - if (file_descriptors[4] != 0) { + if (file_descriptors[4] >= 0) { rc = dup2(file_descriptors[4], STDERR_FILENO); - if (rc != 0) { return rc; } + if (rc < 0) { return errno; } } - -#warning Shold close all and then return error no early return // Close parent side - if (file_descriptors[1] != 0) { + if (file_descriptors[1] >= 0) { rc = close(file_descriptors[1]); - if (rc != 0) { return rc; } } - if (file_descriptors[3] != 0) { + if (file_descriptors[3] >= 0) { rc = close(file_descriptors[3]); - if (rc != 0) { return rc; } } - if (file_descriptors[4] != 0) { + if (file_descriptors[4] >= 0) { rc = close(file_descriptors[5]); - if (rc != 0) { return rc; } } - + if (rc != 0) { + return errno; + } + // Run custom configuratior + if (configurator != NULL) { + configurator(); + } // Finally, exec execve(exec_path, args, env); // If we got here, something went wrong diff --git a/SwiftJavaKitExample/build.gradle.kts b/SwiftJavaKitExample/build.gradle.kts index 13ed70fd..4c77db83 100644 --- a/SwiftJavaKitExample/build.gradle.kts +++ b/SwiftJavaKitExample/build.gradle.kts @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/SwiftKit/build.gradle.kts b/SwiftKit/build.gradle.kts index b7ecb6a8..3842620b 100644 --- a/SwiftKit/build.gradle.kts +++ b/SwiftKit/build.gradle.kts @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift b/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift index b03d3d74..8017822f 100644 --- a/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift +++ b/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Tests/JExtractSwiftTests/FuncImportTests.swift b/Tests/JExtractSwiftTests/FuncImportTests.swift index 4c210b3e..ed71c14d 100644 --- a/Tests/JExtractSwiftTests/FuncImportTests.swift +++ b/Tests/JExtractSwiftTests/FuncImportTests.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift b/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift index 064672e1..b6f93eb2 100644 --- a/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift +++ b/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Tests/JExtractSwiftTests/NominalTypeResolutionTests.swift b/Tests/JExtractSwiftTests/NominalTypeResolutionTests.swift index bb8fce6c..01b507df 100644 --- a/Tests/JExtractSwiftTests/NominalTypeResolutionTests.swift +++ b/Tests/JExtractSwiftTests/NominalTypeResolutionTests.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Tests/JExtractSwiftTests/SwiftDylibTests.swift b/Tests/JExtractSwiftTests/SwiftDylibTests.swift index 09dbb166..2cf8894b 100644 --- a/Tests/JExtractSwiftTests/SwiftDylibTests.swift +++ b/Tests/JExtractSwiftTests/SwiftDylibTests.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // @@ -16,7 +17,11 @@ import Testing final class SwiftDylibTests { + #if os(Linux) + @Test(.disabled("Dylib.nm approach to getting symbol names not supported on Linux")) + #else @Test + #endif func test_nm() async throws { let dylib = SwiftDylib(path: ".build/arm64-apple-macosx/debug/libJavaKitExample.dylib")! diff --git a/Tests/JavaKitTests/BasicRuntimeTests.swift b/Tests/JavaKitTests/BasicRuntimeTests.swift index e133970c..33a93fd4 100644 --- a/Tests/JavaKitTests/BasicRuntimeTests.swift +++ b/Tests/JavaKitTests/BasicRuntimeTests.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // @@ -23,7 +24,11 @@ let jvm = try! JavaVirtualMachine(vmOptions: []) @Suite @MainActor struct BasicRuntimeTests { - @Test("Object management") + #if os(Linux) + @Test("Object management", .disabled("Attempts to refcount a null pointer on Linux")) + #else + @Test("Object management", .disabled("Bad pointer de-reference on Linux")) + #endif func javaObjectManagement() throws { let sneakyJavaThis: jobject do { @@ -49,7 +54,11 @@ struct BasicRuntimeTests { #expect(url.javaHolder === urlAgain.javaHolder) } + #if os(Linux) + @Test("Java exceptions", .disabled("Attempts to refcount a null pointer on Linux")) + #else @Test("Java exceptions") + #endif func javaExceptionsInSwift() async throws { do { _ = try URL("bad url", environment: jvm.environment) diff --git a/Tests/JavaTypesTests/ManglingTests.swift b/Tests/JavaTypesTests/ManglingTests.swift index 6be75d6b..778360cd 100644 --- a/Tests/JavaTypesTests/ManglingTests.swift +++ b/Tests/JavaTypesTests/ManglingTests.swift @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 00000000..170619e1 --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,22 @@ +ARG swift_version=nightly-main +ARG ubuntu_version=jammy +ARG base_image=docker.io/swiftlang/swift:$swift_version-$ubuntu_version +FROM $base_image +# needed to do again after FROM due to docker limitation +ARG swift_version +ARG ubuntu_version + +# set as UTF-8 +RUN apt-get update && apt-get install -y \ + locales locales-all \ + make \ + libc6-dev +ENV LC_ALL=en_US.UTF-8 +ENV LANG=en_US.UTF-8 +ENV LANGUAGE=en_US.UTF-8 + +# JDK dependency +COPY install_jdk.sh . +RUN bash -xc 'JDK_VENDOR=Corretto ./install_jdk.sh' +ENV JAVA_HOME="/usr/lib/jvm/default-jdk" +ENV PATH="$PATH:/usr/lib/jvm/default-jdk/bin" \ No newline at end of file diff --git a/docker/docker-compose.2204.main.yaml b/docker/docker-compose.2204.main.yaml new file mode 100644 index 00000000..f06b576a --- /dev/null +++ b/docker/docker-compose.2204.main.yaml @@ -0,0 +1,23 @@ +services: + + runtime-setup: + image: swift-java:22.04-main + build: + args: + base_image: "swiftlang/swift:nightly-main-jammy" + + unit-tests: + image: swift-java:22.04-main + + integration-tests: + image: swift-java:22.04-main + + documentation-check: + image: swift-java:22.04-main + + test-swift: + image: swift-java:22.04-main + test-java: + image: swift-java:22.04-main + test: + image: swift-java:22.04-main diff --git a/docker/docker-compose.yaml b/docker/docker-compose.yaml new file mode 100644 index 00000000..a2097226 --- /dev/null +++ b/docker/docker-compose.yaml @@ -0,0 +1,47 @@ +# this file is not designed to be run directly +# instead, use the docker-compose.. files +# eg docker-compose -f docker/docker-compose.yaml -f docker/docker-compose.1604.41.yaml run test +services: + + runtime-setup: + image: swift-java:default + build: + context: . + dockerfile: Dockerfile + + common: &common + image: swift-java:default + depends_on: [runtime-setup] + volumes: + - ~/.ssh:/root/.ssh + - ..:/swift-java:z + working_dir: /swift-java + environment: + JAVA_HOME: /jdk + + soundness: + <<: *common + command: /bin/bash -xcl "swift -version && uname -a && ./scripts/soundness.sh" + + unit-tests: + <<: *common + command: /bin/bash -xcl "swift $${SWIFT_TEST_VERB-test} $${WARN_AS_ERROR_ARG-} $${IMPORT_CHECK_ARG-}" + + test-swift: + <<: *common + command: /bin/bash -xcl "uname -a && swift -version && /jdk/bin/java -version && swift $${SWIFT_TEST_VERB-test} $${WARN_AS_ERROR_ARG-} $${SANITIZER_ARG-} $${IMPORT_CHECK_ARG-}" + + test-java: + <<: *common + command: /bin/bash -xcl "uname -a && swift -version && /jdk/bin/java -version && make jextract-run && ./gradlew test --debug" + + test: + <<: *common + command: /bin/bash -xcl "uname -a && swift -version && /jdk/bin/java -version && make jextract-run && swift $${SWIFT_TEST_VERB-test} $${WARN_AS_ERROR_ARG-} $${SANITIZER_ARG-} $${IMPORT_CHECK_ARG-} && ./gradlew test --debug" + + # util + + shell: + <<: *common + entrypoint: /bin/bash + diff --git a/docker/install_jdk.sh b/docker/install_jdk.sh new file mode 100755 index 00000000..0d63eaf9 --- /dev/null +++ b/docker/install_jdk.sh @@ -0,0 +1,86 @@ +#!/bin/bash +##===----------------------------------------------------------------------===## +## +## This source file is part of the Swift.org open source project +## +## Copyright (c) 2024 Apple Inc. and the Swift.org project authors +## Licensed under Apache License v2.0 +## +## See LICENSE.txt for license information +## See CONTRIBUTORS.txt for the list of Swift.org project authors +## +## SPDX-License-Identifier: Apache-2.0 +## +##===----------------------------------------------------------------------===## +set -euo pipefail + +# Supported JDKs: Corretto or OpenJDK +if [ "$JDK_VENDOR" = "" ]; then +declare -r JDK_VENDOR="Corretto" +fi +echo "Installing $JDK_VENDOR JDK..." + +apt-get update && apt-get install -y wget + +echo "Download JDK for: $(uname -m)" + +if [ "$JDK_VENDOR" = 'OpenJDK' ]; then + if [ "$(uname -m)" = 'aarch64' ]; then + declare -r JDK_URL="https://download.java.net/java/GA/jdk23/3c5b90190c68498b986a97f276efd28a/37/GPL/openjdk-23_linux-aarch64_bin.tar.gz" + declare -r EXPECT_JDK_SHA="076dcf7078cdf941951587bf92733abacf489a6570f1df97ee35945ffebec5b7" + else + declare -r JDK_URL="https://download.java.net/java/GA/jdk23/3c5b90190c68498b986a97f276efd28a/37/GPL/$JDK_NAME" + declare -r EXPECT_JDK_SHA="08fea92724127c6fa0f2e5ea0b07ff4951ccb1e2f22db3c21eebbd7347152a67" + fi + + wget -q -O jdk.tar.gz "$JDK_URL" + + declare JDK_SHA # on separate lines due to: SC2155 (warning): Declare and assign separately to avoid masking return values. + JDK_SHA="$(sha256sum jdk.tar.gz | cut -d ' ' -f 1)" + if [ "$JDK_SHA" != "$EXPECT_JDK_SHA" ]; then + echo "Downloaded JDK SHA does not match expected!" + echo "Expected: $EXPECT_JDK_SHA" + echo " Was: $JDK_SHA" + exit 1; + else + echo "JDK SHA is correct."; + fi +elif [ "$JDK_VENDOR" = 'Corretto' ]; then + if [ "$(uname -m)" = 'aarch64' ]; then + declare -r JDK_URL="https://corretto.aws/downloads/latest/amazon-corretto-22-aarch64-linux-jdk.tar.gz" + declare -r EXPECT_JDK_MD5="1ebe5f5229bb18bc784a1e0f54d3fe39" + else + declare -r JDK_URL="https://corretto.aws/downloads/latest/amazon-corretto-22-x64-linux-jdk.tar.gz" + declare -r EXPECT_JDK_MD5="5bd7fe30eb063699a3b4db7a00455841" + fi + + wget -q -O jdk.tar.gz "$JDK_URL" + + declare JDK_MD5 # on separate lines due to: SC2155 (warning): Declare and assign separately to avoid masking return values. + JDK_MD5="$(md5sum jdk.tar.gz | cut -d ' ' -f 1)" + if [ "$JDK_MD5" != "$EXPECT_JDK_MD5" ]; then + echo "Downloaded JDK MD5 does not match expected!" + echo "Expected: $EXPECT_JDK_MD5" + echo " Was: $JDK_MD5" + exit 1; + else + echo "JDK MD5 is correct."; + fi +else + echo "Unsupported JDK vendor: '$JDK_VENDOR'" + exit 1 +fi + +# Extract and verify the JDK installation + +mkdir -p /usr/lib/jvm/ +mv jdk.tar.gz /usr/lib/jvm/ +cd /usr/lib/jvm/ +ls +tar xzvf jdk.tar.gz && rm jdk.tar.gz +ls +find . -depth -maxdepth 1 -type d +mv "$(find . -depth -maxdepth 1 -type d | head -n1)" default-jdk + +echo "JAVA_HOME = /usr/lib/jvm/default-jdk" +/usr/lib/jvm/default-jdk/bin/java -version \ No newline at end of file diff --git a/scripts/check-license-header.sh b/scripts/check-license-header.sh deleted file mode 100755 index afdeb30d..00000000 --- a/scripts/check-license-header.sh +++ /dev/null @@ -1,79 +0,0 @@ -#!/bin/bash -##===----------------------------------------------------------------------===## -## -## This source file is part of the Swift.org open source project -## -## Copyright (c) 2024 Apple Inc. and the Swift.org project authors -## Licensed under Apache License v2.0 -## -## See LICENSE.txt for license information -## -## SPDX-License-Identifier: Apache-2.0 -## -##===----------------------------------------------------------------------===## -set -euo pipefail - -log() { printf -- "** %s\n" "$*" >&2; } -error() { printf -- "** ERROR: %s\n" "$*" >&2; } -fatal() { error "$@"; exit 1; } - -declare -r PROJECT_NAME="Swift.org" - -test -n "${PROJECT_NAME:-}" || fatal "PROJECT_NAME unset" - -expected_file_header_template="@@===----------------------------------------------------------------------===@@ -@@ -@@ This source file is part of the ${PROJECT_NAME} open source project -@@ -@@ Copyright (c) YEARS Apple Inc. and the ${PROJECT_NAME} project authors -@@ Licensed under Apache License v2.0 -@@ -@@ See LICENSE.txt for license information -@@ -@@ SPDX-License-Identifier: Apache-2.0 -@@ -@@===----------------------------------------------------------------------===@@" - -paths_with_missing_license=( ) - -file_paths=$(tr '\n' '\0' < .licenseignore | xargs -0 -I% printf '":(exclude)%" ' | xargs git ls-files) - -while IFS= read -r file_path; do - file_basename=$(basename -- "${file_path}") - file_extension="${file_basename##*.}" - - # shellcheck disable=SC2001 # We prefer to use sed here instead of bash search/replace - case "${file_extension}" in - swift) expected_file_header=$(sed -e 's|@@|//|g' <<<"${expected_file_header_template}") ;; - java) expected_file_header=$(sed -e 's|@@|//|g' <<<"${expected_file_header_template}") ;; - kts) expected_file_header=$(sed -e 's|@@|//|g' <<<"${expected_file_header_template}") ;; - h) expected_file_header=$(sed -e 's|@@|//|g' <<<"${expected_file_header_template}") ;; - c) expected_file_header=$(sed -e 's|@@|//|g' <<<"${expected_file_header_template}") ;; - sh) expected_file_header=$(cat <(echo '#!/bin/bash') <(sed -e 's|@@|##|g' <<<"${expected_file_header_template}")) ;; - py) expected_file_header=$(cat <(echo '#!/usr/bin/env python3') <(sed -e 's|@@|##|g' <<<"${expected_file_header_template}")) ;; - rb) expected_file_header=$(cat <(echo '#!/usr/bin/env ruby') <(sed -e 's|@@|##|g' <<<"${expected_file_header_template}")) ;; - in) expected_file_header=$(sed -e 's|@@|##|g' <<<"${expected_file_header_template}") ;; - cmake) expected_file_header=$(sed -e 's|@@|##|g' <<<"${expected_file_header_template}") ;; - *) echo "Unsupported file extension for file (exclude or update this script): ${file_path}" ;; - esac - expected_file_header_linecount=$(wc -l <<<"${expected_file_header}") - - file_header=$(head -n "${expected_file_header_linecount}" "${file_path}") - normalized_file_header=$( - echo "${file_header}" \ - | sed -e 's/20[12][0123456789]-20[12][0123456789]/YEARS/' -e 's/20[12][0123456789]/YEARS/' \ - ) - - if ! diff -u \ - --label "Expected header" <(echo "${expected_file_header}") \ - --label "${file_path}" <(echo "${normalized_file_header}") - then - paths_with_missing_license+=("${file_path} ") - fi -done <<< "$file_paths" - -if [ "${#paths_with_missing_license[@]}" -gt 0 ]; then - fatal "❌ Found missing license header in files: ${paths_with_missing_license[*]}." -fi - -log "✅ Found no files with missing license header." \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index 87616cf3..04c6b6ed 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -6,6 +6,7 @@ // Licensed under Apache License v2.0 // // See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors // // SPDX-License-Identifier: Apache-2.0 // From 980940428993d56b95f16ed12b394680d0f0dbd1 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Wed, 2 Oct 2024 15:53:03 -0700 Subject: [PATCH 020/426] Introduce the @JavaStaticMethod and use it for calling static Java methods The use of the `@JavaMethod` macro within an extension of `JavaClass` to represent static Java methods on that class didn't quite work, because JavaClass is itself an AnyJavaObject with its own methods. Introduce a `@JavaStaticMethod` macro that will be used for this purpose, and have it call through a separate API (`dynamicJavaStaticMethodCall`). Thank you to Lokesh for reporting this bug! --- Sources/Java2Swift/JavaTranslator.swift | 3 ++- Sources/JavaKit/JavaObject+MethodCalls.swift | 13 +++++++------ Sources/JavaKit/Macros.swift | 14 +++++++++++++- Sources/JavaKitMacros/JavaMethodMacro.swift | 3 ++- .../JavaKitNetwork/generated/URLConnection.swift | 2 +- Tests/JavaKitTests/BasicRuntimeTests.swift | 10 ++++++++++ 6 files changed, 35 insertions(+), 10 deletions(-) diff --git a/Sources/Java2Swift/JavaTranslator.swift b/Sources/Java2Swift/JavaTranslator.swift index c83e5c85..bc2140a0 100644 --- a/Sources/Java2Swift/JavaTranslator.swift +++ b/Sources/Java2Swift/JavaTranslator.swift @@ -416,8 +416,9 @@ extension JavaTranslator { let throwsStr = javaMethod.throwsCheckedException ? "throws" : "" + let methodAttribute: AttributeSyntax = javaMethod.isStatic ? "@JavaStaticMethod" : "@JavaMethod"; return """ - @JavaMethod + \(methodAttribute) public func \(raw: javaMethod.getName())\(raw: genericParameterClause)(\(raw: parametersStr))\(raw: throwsStr)\(raw: resultTypeStr)\(raw: whereClause) """ } diff --git a/Sources/JavaKit/JavaObject+MethodCalls.swift b/Sources/JavaKit/JavaObject+MethodCalls.swift index 62a5617e..ad091943 100644 --- a/Sources/JavaKit/JavaObject+MethodCalls.swift +++ b/Sources/JavaKit/JavaObject+MethodCalls.swift @@ -301,9 +301,10 @@ extension AnyJavaObject { extension JavaClass { /// Call a Java static method with the given name and arguments, which must be /// of the correct type, that produces the given result type. - public func dynamicJavaMethodCall( + public func dynamicJavaStaticMethodCall( methodName: String, - args: repeat each Param + arguments: repeat each Param, + resultType: Result.Type ) throws -> Result { let thisClass = javaThis let environment = javaEnvironment @@ -325,7 +326,7 @@ extension JavaClass { // Retrieve the method that performs this call, then let jniMethod = Result.jniStaticMethodCall(in: environment) - let jniArgs = getJValues(repeat each args, in: environment) + let jniArgs = getJValues(repeat each arguments, in: environment) let jniResult = try environment.translatingJNIExceptions { jniMethod(environment, thisClass, methodID, jniArgs) } @@ -335,9 +336,9 @@ extension JavaClass { /// Call a Java static method with the given name and arguments, which must be /// of the correct type, that produces the given result type. - public func dynamicJavaMethodCall( + public func dynamicJavaStaticMethodCall( methodName: String, - args: repeat each Param + arguments: repeat each Param ) throws { let thisClass = javaThis let environment = javaEnvironment @@ -359,7 +360,7 @@ extension JavaClass { // Retrieve the method that performs this call, then let jniMethod = environment.interface.CallStaticVoidMethodA - let jniArgs = getJValues(repeat each args, in: environment) + let jniArgs = getJValues(repeat each arguments, in: environment) try environment.translatingJNIExceptions { jniMethod!(environment, thisClass, methodID, jniArgs) } diff --git a/Sources/JavaKit/Macros.swift b/Sources/JavaKit/Macros.swift index 24ce8d32..772138f8 100644 --- a/Sources/JavaKit/Macros.swift +++ b/Sources/JavaKit/Macros.swift @@ -95,7 +95,7 @@ public macro JavaField(_ javaFieldName: String? = nil) = #externalMacro(module: /// Attached macro that turns a Swift method into one that wraps a Java method on the underlying Java object. /// -/// The macro must be used within either a AnyJavaObject-conforming type or a specific JavaClass instance. +/// The macro must be used in an AnyJavaObject-conforming type. /// /// ```swift /// @JavaMethod @@ -115,6 +115,18 @@ public macro JavaField(_ javaFieldName: String? = nil) = #externalMacro(module: @attached(body) public macro JavaMethod() = #externalMacro(module: "JavaKitMacros", type: "JavaMethodMacro") +/// Attached macro that turns a Swift method on JavaClass into one that wraps +/// a Java static method on the underlying Java class object. +/// +/// The macro must be used within a specific JavaClass instance. +/// +/// ```swift +/// @JavaMethod +/// func sayHelloBack(_ i: Int32) -> Double +/// ``` +@attached(body) +public macro JavaStaticMethod() = #externalMacro(module: "JavaKitMacros", type: "JavaMethodMacro") + /// Macro that exposes the given Swift method as a native method in Java. /// /// The macro must be used within a struct type marked with `@JavaClass`, and there diff --git a/Sources/JavaKitMacros/JavaMethodMacro.swift b/Sources/JavaKitMacros/JavaMethodMacro.swift index 7996fc8c..b16d8ab2 100644 --- a/Sources/JavaKitMacros/JavaMethodMacro.swift +++ b/Sources/JavaKitMacros/JavaMethodMacro.swift @@ -34,6 +34,7 @@ extension JavaMethodMacro: BodyMacro { fatalError("not a function") } + let isStatic = node.attributeName.trimmedDescription == "JavaStaticMethod" let funcName = funcDecl.name.text let params = funcDecl.signature.parameterClause.parameters let resultType: String = @@ -54,7 +55,7 @@ extension JavaMethodMacro: BodyMacro { ? "try" : "try!" return [ - "return \(raw: tryKeyword) dynamicJavaMethodCall(methodName: \(literal: funcName)\(raw: parametersAsArgs)\(raw: resultType))" + "return \(raw: tryKeyword) dynamicJava\(raw: isStatic ? "Static" : "")MethodCall(methodName: \(literal: funcName)\(raw: parametersAsArgs)\(raw: resultType))" ] } diff --git a/Sources/JavaKitNetwork/generated/URLConnection.swift b/Sources/JavaKitNetwork/generated/URLConnection.swift index f229b8be..94fd6f52 100644 --- a/Sources/JavaKitNetwork/generated/URLConnection.swift +++ b/Sources/JavaKitNetwork/generated/URLConnection.swift @@ -146,7 +146,7 @@ extension JavaClass { @JavaMethod public func setDefaultAllowUserInteraction(_ arg0: Bool) - @JavaMethod + @JavaStaticMethod public func getDefaultAllowUserInteraction() -> Bool @JavaMethod diff --git a/Tests/JavaKitTests/BasicRuntimeTests.swift b/Tests/JavaKitTests/BasicRuntimeTests.swift index 33a93fd4..e182c453 100644 --- a/Tests/JavaKitTests/BasicRuntimeTests.swift +++ b/Tests/JavaKitTests/BasicRuntimeTests.swift @@ -66,4 +66,14 @@ struct BasicRuntimeTests { #expect(String(describing: error) == "no protocol: bad url") } } + + @Test("Static methods") + func staticMethods() { + let urlConnectionClass = JavaClass( + javaThis: URLConnection.getJNIClass(in: jvm.environment)!, + environment: jvm.environment + ) + + #expect(urlConnectionClass.getDefaultAllowUserInteraction() == false) + } } From c749211239a66c9b49eb65da4d1731599169d769 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Wed, 2 Oct 2024 16:00:10 -0700 Subject: [PATCH 021/426] Regenerate JavaKit module sources using @JavaStaticMethod --- Sources/JavaKitNetwork/generated/URI.swift | 2 +- Sources/JavaKitNetwork/generated/URLClassLoader.swift | 6 +++--- Sources/JavaKitReflection/generated/AccessibleObject.swift | 2 +- Sources/JavaKitReflection/generated/Constructor.swift | 2 +- Sources/JavaKitReflection/generated/Executable.swift | 2 +- Sources/JavaKitReflection/generated/Method.swift | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Sources/JavaKitNetwork/generated/URI.swift b/Sources/JavaKitNetwork/generated/URI.swift index 2f035938..6fdad52c 100644 --- a/Sources/JavaKitNetwork/generated/URI.swift +++ b/Sources/JavaKitNetwork/generated/URI.swift @@ -125,6 +125,6 @@ public struct URI { public func wait() throws } extension JavaClass { - @JavaMethod + @JavaStaticMethod public func create(_ arg0: String) -> URI? } diff --git a/Sources/JavaKitNetwork/generated/URLClassLoader.swift b/Sources/JavaKitNetwork/generated/URLClassLoader.swift index db46e5e0..849d5715 100644 --- a/Sources/JavaKitNetwork/generated/URLClassLoader.swift +++ b/Sources/JavaKitNetwork/generated/URLClassLoader.swift @@ -74,12 +74,12 @@ public struct URLClassLoader { public func wait() throws } extension JavaClass { - @JavaMethod + @JavaStaticMethod public func newInstance(_ arg0: [URL?]) -> URLClassLoader? - @JavaMethod + @JavaStaticMethod public func getSystemResource(_ arg0: String) -> URL? - @JavaMethod + @JavaStaticMethod public func getSystemResources(_ arg0: String) throws -> Enumeration? } diff --git a/Sources/JavaKitReflection/generated/AccessibleObject.swift b/Sources/JavaKitReflection/generated/AccessibleObject.swift index 8cbc33a5..c54fd33a 100644 --- a/Sources/JavaKitReflection/generated/AccessibleObject.swift +++ b/Sources/JavaKitReflection/generated/AccessibleObject.swift @@ -65,6 +65,6 @@ public struct AccessibleObject { public func wait() throws } extension JavaClass { - @JavaMethod + @JavaStaticMethod public func setAccessible(_ arg0: [AccessibleObject?], _ arg1: Bool) } diff --git a/Sources/JavaKitReflection/generated/Constructor.swift b/Sources/JavaKitReflection/generated/Constructor.swift index d7806d24..e7ea0476 100644 --- a/Sources/JavaKitReflection/generated/Constructor.swift +++ b/Sources/JavaKitReflection/generated/Constructor.swift @@ -122,6 +122,6 @@ public struct Constructor { public func wait() throws } extension JavaClass { - @JavaMethod + @JavaStaticMethod public func setAccessible(_ arg0: [AccessibleObject?], _ arg1: Bool) where ObjectType == Constructor } diff --git a/Sources/JavaKitReflection/generated/Executable.swift b/Sources/JavaKitReflection/generated/Executable.swift index 55e2911d..76b34325 100644 --- a/Sources/JavaKitReflection/generated/Executable.swift +++ b/Sources/JavaKitReflection/generated/Executable.swift @@ -119,6 +119,6 @@ public struct Executable { public func wait() throws } extension JavaClass { - @JavaMethod + @JavaStaticMethod public func setAccessible(_ arg0: [AccessibleObject?], _ arg1: Bool) } diff --git a/Sources/JavaKitReflection/generated/Method.swift b/Sources/JavaKitReflection/generated/Method.swift index c8ae49b4..84d0b90a 100644 --- a/Sources/JavaKitReflection/generated/Method.swift +++ b/Sources/JavaKitReflection/generated/Method.swift @@ -137,6 +137,6 @@ public struct Method { public func wait() throws } extension JavaClass { - @JavaMethod + @JavaStaticMethod public func setAccessible(_ arg0: [AccessibleObject?], _ arg1: Bool) } From 2d89c14ae9c6af9d6d48a16ddd83919ec8bb8ff8 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Wed, 2 Oct 2024 16:12:55 -0700 Subject: [PATCH 022/426] Unbreak macOS build because Mutex requires macOS 15 --- Sources/_Subprocess/Subprocess+IO.swift | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Sources/_Subprocess/Subprocess+IO.swift b/Sources/_Subprocess/Subprocess+IO.swift index 73b1f99e..b085a991 100644 --- a/Sources/_Subprocess/Subprocess+IO.swift +++ b/Sources/_Subprocess/Subprocess+IO.swift @@ -145,10 +145,10 @@ extension Subprocess { case fileDescriptor(FileDescriptor?, Bool) } - let storage: Mutex + let storage: LockedState internal init(storage: Storage) { - self.storage = .init(storage) + self.storage = .init(initialState: storage) } internal func getReadFileDescriptor() -> FileDescriptor? { @@ -250,10 +250,10 @@ extension Subprocess { case collected(Int, FileDescriptor?, FileDescriptor?) } - private let storage: Mutex + private let storage: LockedState internal init(storage: Storage) { - self.storage = .init(storage) + self.storage = .init(initialState: storage) } internal func getWriteFileDescriptor() -> FileDescriptor? { From 8c69803753695d8529221ddb79828ebf55350a5d Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Fri, 4 Oct 2024 12:50:23 -0700 Subject: [PATCH 023/426] Model Swift's type metadata and value witness table for memory layout information Extend the Java SwiftKit with the ability to query the memory layout of an arbitrary Swift type given its Swift type metadata pointer (e.g., `Any.Type` in the Swift world). Use this to show the size, stride, and alignment of `Int?` from the Java side, which produces: Memory layout for Swift.Int?: size = 9 stride = 16 alignment = 8 --- .../java/org/example/HelloJava2Swift.java | 6 + .../main/java/org/swift/javakit/SwiftKit.java | 120 +++++++++++++++++- 2 files changed, 125 insertions(+), 1 deletion(-) diff --git a/JavaSwiftKitDemo/src/main/java/org/example/HelloJava2Swift.java b/JavaSwiftKitDemo/src/main/java/org/example/HelloJava2Swift.java index 00264946..6d9c2de0 100644 --- a/JavaSwiftKitDemo/src/main/java/org/example/HelloJava2Swift.java +++ b/JavaSwiftKitDemo/src/main/java/org/example/HelloJava2Swift.java @@ -68,5 +68,11 @@ static void tests() { obj.voidMethod(); obj.takeIntMethod(42); + + MemorySegment swiftType = SwiftKit.getTypeByMangledNameInEnvironment("SiSg"); + System.out.println("Memory layout for Swift.Int?:"); + System.out.println(" size = " + SwiftKit.sizeOfSwiftType(swiftType)); + System.out.println(" stride = " + SwiftKit.strideOfSwiftType(swiftType)); + System.out.println(" alignment = " + SwiftKit.alignmentOfSwiftType(swiftType)); } } diff --git a/JavaSwiftKitDemo/src/main/java/org/swift/javakit/SwiftKit.java b/JavaSwiftKitDemo/src/main/java/org/swift/javakit/SwiftKit.java index 07765a08..9e818690 100644 --- a/JavaSwiftKitDemo/src/main/java/org/swift/javakit/SwiftKit.java +++ b/JavaSwiftKitDemo/src/main/java/org/swift/javakit/SwiftKit.java @@ -17,6 +17,7 @@ import org.swift.swiftkit.SwiftHeapObject; import java.lang.foreign.*; +import java.lang.foreign.MemoryLayout.PathElement; import java.lang.invoke.MethodHandle; import java.util.Arrays; import java.util.stream.Collectors; @@ -200,7 +201,7 @@ public static MemorySegment getTypeByName(String string) { */ private static class swift_getTypeByMangledNameInEnvironment { public static final FunctionDescriptor DESC = FunctionDescriptor.of( - /*returns=*/ValueLayout.ADDRESS, + /*returns=*/SWIFT_POINTER, ValueLayout.ADDRESS, ValueLayout.JAVA_INT, ValueLayout.ADDRESS, @@ -230,4 +231,121 @@ public static MemorySegment getTypeByMangledNameInEnvironment(String string) { throw new AssertionError("should not reach here", ex$); } } + + /** + * The value layout for Swift's Int type, which is a signed type that follows + * the size of a pointer (aka C's ptrdiff_t). + */ + public static ValueLayout SWIFT_INT = (ValueLayout.ADDRESS.byteSize() == 4) ? + ValueLayout.JAVA_INT : ValueLayout.JAVA_LONG; + + /** + * The value layout for Swift's UInt type, which is an unsigned type that follows + * the size of a pointer (aka C's size_t). Java does not have unsigned integer + * types in general, so we use the layout for Swift's Int. + */ + public static ValueLayout SWIFT_UINT = SWIFT_INT; + + /** + * Read a Swift.Int value from memory at the given offset and translate it into a Java long. + * + * This function copes with the fact that a Swift.Int might be 32 or 64 bits. + */ + public static final long getSwiftInt(MemorySegment memorySegment, long offset) { + if (SWIFT_INT == ValueLayout.JAVA_LONG) { + return memorySegment.get(ValueLayout.JAVA_LONG, offset); + } else { + return memorySegment.get(ValueLayout.JAVA_INT, offset); + } + } + + /** + * Value witness table layout. + */ + public static final MemoryLayout valueWitnessTableLayout = MemoryLayout.structLayout( + ValueLayout.ADDRESS.withName("initializeBufferWithCopyOfBuffer"), + ValueLayout.ADDRESS.withName("destroy"), + ValueLayout.ADDRESS.withName("initializeWithCopy"), + ValueLayout.ADDRESS.withName("assignWithCopy"), + ValueLayout.ADDRESS.withName("initializeWithTake"), + ValueLayout.ADDRESS.withName("assignWithTake"), + ValueLayout.ADDRESS.withName("getEnumTagSinglePayload"), + ValueLayout.ADDRESS.withName("storeEnumTagSinglePayload"), + SwiftKit.SWIFT_INT.withName("size"), + SwiftKit.SWIFT_INT.withName("stride"), + SwiftKit.SWIFT_UINT.withName("flags"), + SwiftKit.SWIFT_UINT.withName("extraInhabitantCount") + ).withName("SwiftValueWitnessTable"); + + /** + * Offset for the "size" field within the value witness table. + */ + static final long valueWitnessTable$size$offset = + valueWitnessTableLayout.byteOffset(PathElement.groupElement("size")); + + /** + * Offset for the "stride" field within the value witness table. + */ + static final long valueWitnessTable$stride$offset = + valueWitnessTableLayout.byteOffset(PathElement.groupElement("stride")); + + /** + * Offset for the "flags" field within the value witness table. + */ + static final long valueWitnessTable$flags$offset = + valueWitnessTableLayout.byteOffset(PathElement.groupElement("flags")); + + /** + * Type metadata pointer. + */ + public static final StructLayout fullTypeMetadataLayout = MemoryLayout.structLayout( + SWIFT_POINTER.withName("vwt") + ).withName("SwiftFullTypeMetadata"); + + /** + * Offset for the "vwt" field within the full type metadata. + */ + static final long fullTypeMetadata$vwt$offset = + fullTypeMetadataLayout.byteOffset(PathElement.groupElement("vwt")); + + /** + * Given the address of Swift type metadata for a type, return the addres + * of the "full" type metadata that can be accessed via fullTypeMetadataLayout. + */ + public static MemorySegment fullTypeMetadata(MemorySegment typeMetadata) { + return MemorySegment.ofAddress(typeMetadata.address() - SWIFT_POINTER.byteSize()) + .reinterpret(fullTypeMetadataLayout.byteSize()); + } + + /** + * Given the address of Swift type's metadata, return the address that + * references the value witness table for the type. + */ + public static MemorySegment valueWitnessTable(MemorySegment typeMetadata) { + return fullTypeMetadata(typeMetadata).get(SWIFT_POINTER, fullTypeMetadata$vwt$offset); + } + + /** + * Determine the size of a Swift type given its type metadata. + */ + public static long sizeOfSwiftType(MemorySegment typeMetadata) { + return getSwiftInt(valueWitnessTable(typeMetadata), valueWitnessTable$size$offset); + } + + /** + * Determine the stride of a Swift type given its type metadata, which is + * how many bytes are between successive elements of this type within an + * array. It is >= the size. + */ + public static long strideOfSwiftType(MemorySegment typeMetadata) { + return getSwiftInt(valueWitnessTable(typeMetadata), valueWitnessTable$stride$offset); + } + + /** + * Determine the alignment of the given Swift type. + */ + public static long alignmentOfSwiftType(MemorySegment typeMetadata) { + long flags = getSwiftInt(valueWitnessTable(typeMetadata), valueWitnessTable$flags$offset); + return (flags & 0xFF) + 1; + } } From 968b3bcad732b8e9005e6ead9eac85d742f2eb25 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Fri, 4 Oct 2024 21:48:08 -0700 Subject: [PATCH 024/426] [jextract-swift] Add an API to produce a MemoryLayout for a given Swift type Given Swift type metadata, inspect the metadata to produce a memory layout for the Swift type that covers its size/alignment and can be used to refer to memory containing a Swift value of that type. --- .../java/org/example/HelloJava2Swift.java | 1 + .../main/java/org/swift/javakit/SwiftKit.java | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/JavaSwiftKitDemo/src/main/java/org/example/HelloJava2Swift.java b/JavaSwiftKitDemo/src/main/java/org/example/HelloJava2Swift.java index 6d9c2de0..95870989 100644 --- a/JavaSwiftKitDemo/src/main/java/org/example/HelloJava2Swift.java +++ b/JavaSwiftKitDemo/src/main/java/org/example/HelloJava2Swift.java @@ -74,5 +74,6 @@ static void tests() { System.out.println(" size = " + SwiftKit.sizeOfSwiftType(swiftType)); System.out.println(" stride = " + SwiftKit.strideOfSwiftType(swiftType)); System.out.println(" alignment = " + SwiftKit.alignmentOfSwiftType(swiftType)); + System.out.println(" Java layout = " + SwiftKit.layoutOfSwiftType(swiftType)); } } diff --git a/JavaSwiftKitDemo/src/main/java/org/swift/javakit/SwiftKit.java b/JavaSwiftKitDemo/src/main/java/org/swift/javakit/SwiftKit.java index 9e818690..cc859d00 100644 --- a/JavaSwiftKitDemo/src/main/java/org/swift/javakit/SwiftKit.java +++ b/JavaSwiftKitDemo/src/main/java/org/swift/javakit/SwiftKit.java @@ -348,4 +348,23 @@ public static long alignmentOfSwiftType(MemorySegment typeMetadata) { long flags = getSwiftInt(valueWitnessTable(typeMetadata), valueWitnessTable$flags$offset); return (flags & 0xFF) + 1; } + + /** + * Produce a layout that describes a Swift type based on its + * type metadata. The resulting layout is completely opaque to Java, but + * has appropriate size/alignment to model the memory associated with a + * Swift type. + * + * In the future, this layout could be extended to provide more detail, + * such as the fields of a Swift struct. + */ + public static MemoryLayout layoutOfSwiftType(MemorySegment typeMetadata) { + long size = sizeOfSwiftType(typeMetadata); + long stride = strideOfSwiftType(typeMetadata); + return MemoryLayout.structLayout( + MemoryLayout.sequenceLayout(size, JAVA_BYTE) + .withByteAlignment(alignmentOfSwiftType(typeMetadata)), + MemoryLayout.paddingLayout(stride - size) + ); + } } From 7dd04a5e1fffac94441b1f9d05abc8382e86521b Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Fri, 4 Oct 2024 22:32:11 -0700 Subject: [PATCH 025/426] Add SwiftKit.nameOfSwiftType() to get the name from Swift type metadata Use this new API to give a name to the memory layout we create for a Swift type. --- .../main/java/org/swift/javakit/SwiftKit.java | 43 ++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/JavaSwiftKitDemo/src/main/java/org/swift/javakit/SwiftKit.java b/JavaSwiftKitDemo/src/main/java/org/swift/javakit/SwiftKit.java index cc859d00..edb95cff 100644 --- a/JavaSwiftKitDemo/src/main/java/org/swift/javakit/SwiftKit.java +++ b/JavaSwiftKitDemo/src/main/java/org/swift/javakit/SwiftKit.java @@ -22,6 +22,7 @@ import java.util.Arrays; import java.util.stream.Collectors; +import static java.lang.foreign.ValueLayout.ADDRESS; import static java.lang.foreign.ValueLayout.JAVA_BYTE; public class SwiftKit { @@ -349,6 +350,46 @@ public static long alignmentOfSwiftType(MemorySegment typeMetadata) { return (flags & 0xFF) + 1; } + /** + * Descriptor for the swift_getTypeName runtime function. + */ + public static final FunctionDescriptor swift_getTypeName$descriptor = FunctionDescriptor.of( + /*returns=*/MemoryLayout.structLayout( + SWIFT_POINTER.withName("utf8Chars"), + SWIFT_INT.withName("length") + ), + ValueLayout.ADDRESS, + ValueLayout.JAVA_BOOLEAN + ); + + /** + * Address of the swift_getTypeName runtime function. + */ + public static final MemorySegment swift_getTypeName$addr = findOrThrow("swift_getTypeName"); + + /** + * Handle for the swift_getTypeName runtime function. + */ + public static final MethodHandle swift_getTypeName$handle = Linker.nativeLinker().downcallHandle(swift_getTypeName$addr, swift_getTypeName$descriptor); + + /** + * Produce the name of the Swift type given its Swift type metadata. + * + * If 'qualified' is true, leave all of the qualification in place to + * disambiguate the type, producing a more complete (but longer) type name. + */ + public static String nameOfSwiftType(MemorySegment typeMetadata, boolean qualified) { + try { + try (Arena arena = Arena.ofConfined()) { + MemorySegment charsAndLength = (MemorySegment)swift_getTypeName$handle.invokeExact((SegmentAllocator)arena, typeMetadata, qualified); + MemorySegment utf8Chars = charsAndLength.get(SWIFT_POINTER, 0); + return utf8Chars.getString(0); + } + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + /** * Produce a layout that describes a Swift type based on its * type metadata. The resulting layout is completely opaque to Java, but @@ -365,6 +406,6 @@ public static MemoryLayout layoutOfSwiftType(MemorySegment typeMetadata) { MemoryLayout.sequenceLayout(size, JAVA_BYTE) .withByteAlignment(alignmentOfSwiftType(typeMetadata)), MemoryLayout.paddingLayout(stride - size) - ); + ).withName(nameOfSwiftType(typeMetadata, true)); } } From 8cb407e25b634714dd724ea3ac1b07c27124a84e Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Fri, 4 Oct 2024 22:40:25 -0700 Subject: [PATCH 026/426] Free the memory the Swift runtime allocated in swift_getTypeName(). --- .../main/java/org/swift/javakit/SwiftKit.java | 34 ++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/JavaSwiftKitDemo/src/main/java/org/swift/javakit/SwiftKit.java b/JavaSwiftKitDemo/src/main/java/org/swift/javakit/SwiftKit.java index edb95cff..ba76232b 100644 --- a/JavaSwiftKitDemo/src/main/java/org/swift/javakit/SwiftKit.java +++ b/JavaSwiftKitDemo/src/main/java/org/swift/javakit/SwiftKit.java @@ -63,6 +63,36 @@ static MemorySegment findOrThrow(String symbol) { .orElseThrow(() -> new UnsatisfiedLinkError("unresolved symbol: %s".formatted(symbol))); } + // ==== ------------------------------------------------------------------------------------------------------------ + // free + /** + * Descriptor for the free C runtime function. + */ + public static final FunctionDescriptor free$descriptor = FunctionDescriptor.ofVoid( + ValueLayout.ADDRESS + ); + + /** + * Address of the free C runtime function. + */ + public static final MemorySegment free$addr = findOrThrow("free"); + + /** + * Handle for the free C runtime function. + */ + public static final MethodHandle free$handle = Linker.nativeLinker().downcallHandle(free$addr, free$descriptor); + + /** + * free the given pointer + */ + public static void cFree(MemorySegment pointer) { + try { + free$handle.invokeExact(pointer); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + // ==== ------------------------------------------------------------------------------------------------------------ // swift_retainCount @@ -383,7 +413,9 @@ public static String nameOfSwiftType(MemorySegment typeMetadata, boolean qualifi try (Arena arena = Arena.ofConfined()) { MemorySegment charsAndLength = (MemorySegment)swift_getTypeName$handle.invokeExact((SegmentAllocator)arena, typeMetadata, qualified); MemorySegment utf8Chars = charsAndLength.get(SWIFT_POINTER, 0); - return utf8Chars.getString(0); + String typeName = utf8Chars.getString(0); + cFree(utf8Chars); + return typeName; } } catch (Throwable ex$) { throw new AssertionError("should not reach here", ex$); From 83a194560f44763091af39108649589c09119e84 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Mon, 7 Oct 2024 14:38:15 +0900 Subject: [PATCH 027/426] build: require swift 6 toolchain Since we require swift 6 anyway, we should reflect this in the package.swift so it's more obvious when using an older swift to attempt to build. --- Package.swift | 41 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 37 insertions(+), 4 deletions(-) diff --git a/Package.swift b/Package.swift index 705ab731..dea2b000 100644 --- a/Package.swift +++ b/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version: 5.9 +// swift-tools-version: 6.0 // The swift-tools-version declares the minimum version of Swift required to build this package. import CompilerPluginSupport @@ -119,16 +119,23 @@ let package = Package( dependencies: [ .product(name: "SwiftSyntaxMacros", package: "swift-syntax"), .product(name: "SwiftCompilerPlugin", package: "swift-syntax"), + ], + swiftSettings: [ + .swiftLanguageMode(.v5) ] ), .target( - name: "JavaTypes" + name: "JavaTypes", + swiftSettings: [ + .swiftLanguageMode(.v5) + ] ), .target( name: "JavaKit", dependencies: ["JavaRuntime", "JavaKitMacros", "JavaTypes"], exclude: ["generated/JavaKit.swift2java"], swiftSettings: [ + .swiftLanguageMode(.v5), .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) ] ), @@ -137,6 +144,7 @@ let package = Package( dependencies: ["JavaKit"], exclude: ["generated/JavaKitJar.swift2java"], swiftSettings: [ + .swiftLanguageMode(.v5), .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) ] ), @@ -145,6 +153,7 @@ let package = Package( dependencies: ["JavaKit"], exclude: ["generated/JavaKitNetwork.swift2java"], swiftSettings: [ + .swiftLanguageMode(.v5), .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) ] ), @@ -153,6 +162,7 @@ let package = Package( dependencies: ["JavaKit"], exclude: ["generated/JavaKitReflection.swift2java"], swiftSettings: [ + .swiftLanguageMode(.v5), .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) ] ), @@ -160,6 +170,7 @@ let package = Package( name: "JavaKitVM", dependencies: ["JavaKit"], swiftSettings: [ + .swiftLanguageMode(.v5), .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) ], linkerSettings: [ @@ -179,6 +190,7 @@ let package = Package( name: "JavaKitExample", dependencies: ["JavaKit"], swiftSettings: [ + .swiftLanguageMode(.v5), .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) ] ), @@ -186,6 +198,7 @@ let package = Package( .target( name: "JavaRuntime", swiftSettings: [ + .swiftLanguageMode(.v5), .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) ] ), @@ -205,6 +218,7 @@ let package = Package( "JavaTypes", ], swiftSettings: [ + .swiftLanguageMode(.v5), .enableUpcomingFeature("BareSlashRegexLiterals") ] ), @@ -216,6 +230,9 @@ let package = Package( dependencies: [ "_SubprocessCShims", .product(name: "SystemPackage", package: "swift-system"), + ], + swiftSettings: [ + .swiftLanguageMode(.v5) ] ), .target( @@ -225,6 +242,9 @@ let package = Package( "_CRT_SECURE_NO_WARNINGS", .when(platforms: [.windows]) ) + ], + swiftSettings: [ + .swiftLanguageMode(.v5) ] ), @@ -237,6 +257,9 @@ let package = Package( .product(name: "ArgumentParser", package: "swift-argument-parser"), "_Subprocess", "JavaTypes", + ], + swiftSettings: [ + .swiftLanguageMode(.v5) ] ), @@ -244,17 +267,26 @@ let package = Package( name: "JExtractSwiftTool", dependencies: [ "JExtractSwift", + ], + swiftSettings: [ + .swiftLanguageMode(.v5) ] ), .testTarget( name: "JavaKitTests", - dependencies: ["JavaKit", "JavaKitNetwork", "JavaKitVM"] + dependencies: ["JavaKit", "JavaKitNetwork", "JavaKitVM"], + swiftSettings: [ + .swiftLanguageMode(.v5) + ] ), .testTarget( name: "JavaTypesTests", - dependencies: ["JavaTypes"] + dependencies: ["JavaTypes"], + swiftSettings: [ + .swiftLanguageMode(.v5) + ] ), .testTarget( @@ -263,6 +295,7 @@ let package = Package( "JExtractSwift" ], swiftSettings: [ + .swiftLanguageMode(.v5), .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) ] ), From 82f20e75658c3df91afe640c0eb5faab57fc8e94 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Mon, 7 Oct 2024 16:02:49 +0900 Subject: [PATCH 028/426] fix java test syntax; init -> constructor --- .../src/test/java/org/example/swift/SwiftKitTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/JavaSwiftKitDemo/src/test/java/org/example/swift/SwiftKitTest.java b/JavaSwiftKitDemo/src/test/java/org/example/swift/SwiftKitTest.java index 390b1ceb..acc1f372 100644 --- a/JavaSwiftKitDemo/src/test/java/org/example/swift/SwiftKitTest.java +++ b/JavaSwiftKitDemo/src/test/java/org/example/swift/SwiftKitTest.java @@ -42,7 +42,7 @@ static void beforeAll() { @Test void call_retain_retainCount_release() { - var obj = MySwiftClass.init(1, 2); + var obj = new MySwiftClass(1, 2); assertEquals(1, SwiftKit.retainCount(obj.$memorySegment())); // TODO: test directly on SwiftHeapObject inheriting obj From ed67b7399571f718daa365dba7c3c4b748275417 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Mon, 7 Oct 2024 09:27:39 -0700 Subject: [PATCH 029/426] Use a computed variable `isLinux` for disabling some tests The `#if`s around `@Test` confuse some IDE tooling for tests, so replace it. --- Tests/JavaKitTests/BasicRuntimeTests.swift | 23 +++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/Tests/JavaKitTests/BasicRuntimeTests.swift b/Tests/JavaKitTests/BasicRuntimeTests.swift index e182c453..4dd5d196 100644 --- a/Tests/JavaKitTests/BasicRuntimeTests.swift +++ b/Tests/JavaKitTests/BasicRuntimeTests.swift @@ -24,11 +24,7 @@ let jvm = try! JavaVirtualMachine(vmOptions: []) @Suite @MainActor struct BasicRuntimeTests { - #if os(Linux) - @Test("Object management", .disabled("Attempts to refcount a null pointer on Linux")) - #else - @Test("Object management", .disabled("Bad pointer de-reference on Linux")) - #endif + @Test("Object management", .disabled(if: isLinux, "Attempts to refcount a null pointer on Linux")) func javaObjectManagement() throws { let sneakyJavaThis: jobject do { @@ -54,12 +50,8 @@ struct BasicRuntimeTests { #expect(url.javaHolder === urlAgain.javaHolder) } - #if os(Linux) - @Test("Java exceptions", .disabled("Attempts to refcount a null pointer on Linux")) - #else - @Test("Java exceptions") - #endif - func javaExceptionsInSwift() async throws { + @Test("Java exceptions", .disabled(if: isLinux, "Attempts to refcount a null pointer on Linux")) + func javaExceptionsInSwift() throws { do { _ = try URL("bad url", environment: jvm.environment) } catch { @@ -77,3 +69,12 @@ struct BasicRuntimeTests { #expect(urlConnectionClass.getDefaultAllowUserInteraction() == false) } } + +/// Whether we're running on Linux. +var isLinux: Bool { + #if os(Linux) + return true + #else + return false + #endif +} From 4508462ee15a76e529d53407da39767e13c5d6f5 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Mon, 7 Oct 2024 10:50:20 -0700 Subject: [PATCH 030/426] Re-export JavaRuntime from the JavaKit module There's no way to use JavaKit without the JavaRuntime module, so ensure that it's always available. --- Sources/Java2Swift/JavaToSwift.swift | 1 - .../JavaKit/BridgedValues/JavaValue+Array.swift | 1 - .../JavaKit/BridgedValues/JavaValue+Bool.swift | 1 - .../BridgedValues/JavaValue+FloatingPoint.swift | 1 - .../BridgedValues/JavaValue+Integers.swift | 1 - .../JavaKit/BridgedValues/JavaValue+String.swift | 1 - Sources/JavaKit/JavaRuntime+Reexport.swift | 15 +++++++++++++++ Sources/JavaKitVM/JavaVirtualMachine.swift | 1 - Tests/JavaKitTests/BasicRuntimeTests.swift | 1 - USER_GUIDE.md | 2 -- 10 files changed, 15 insertions(+), 10 deletions(-) create mode 100644 Sources/JavaKit/JavaRuntime+Reexport.swift diff --git a/Sources/Java2Swift/JavaToSwift.swift b/Sources/Java2Swift/JavaToSwift.swift index 87fcc7e7..fb24e091 100644 --- a/Sources/Java2Swift/JavaToSwift.swift +++ b/Sources/Java2Swift/JavaToSwift.swift @@ -19,7 +19,6 @@ import JavaKitJar import JavaKitNetwork import JavaKitReflection import JavaKitVM -import JavaRuntime import SwiftSyntax import SwiftSyntaxBuilder diff --git a/Sources/JavaKit/BridgedValues/JavaValue+Array.swift b/Sources/JavaKit/BridgedValues/JavaValue+Array.swift index dce723d1..26996578 100644 --- a/Sources/JavaKit/BridgedValues/JavaValue+Array.swift +++ b/Sources/JavaKit/BridgedValues/JavaValue+Array.swift @@ -12,7 +12,6 @@ // //===----------------------------------------------------------------------===// -import JavaRuntime import JavaTypes extension Array: JavaValue where Element: JavaValue { diff --git a/Sources/JavaKit/BridgedValues/JavaValue+Bool.swift b/Sources/JavaKit/BridgedValues/JavaValue+Bool.swift index c1599076..3e64f38e 100644 --- a/Sources/JavaKit/BridgedValues/JavaValue+Bool.swift +++ b/Sources/JavaKit/BridgedValues/JavaValue+Bool.swift @@ -12,7 +12,6 @@ // //===----------------------------------------------------------------------===// -import JavaRuntime import JavaTypes extension Bool: JavaValue { diff --git a/Sources/JavaKit/BridgedValues/JavaValue+FloatingPoint.swift b/Sources/JavaKit/BridgedValues/JavaValue+FloatingPoint.swift index f90c5019..32f4bd0a 100644 --- a/Sources/JavaKit/BridgedValues/JavaValue+FloatingPoint.swift +++ b/Sources/JavaKit/BridgedValues/JavaValue+FloatingPoint.swift @@ -12,7 +12,6 @@ // //===----------------------------------------------------------------------===// -import JavaRuntime import JavaTypes extension Float: JavaValue { diff --git a/Sources/JavaKit/BridgedValues/JavaValue+Integers.swift b/Sources/JavaKit/BridgedValues/JavaValue+Integers.swift index 39dca985..01a7bdba 100644 --- a/Sources/JavaKit/BridgedValues/JavaValue+Integers.swift +++ b/Sources/JavaKit/BridgedValues/JavaValue+Integers.swift @@ -12,7 +12,6 @@ // //===----------------------------------------------------------------------===// -import JavaRuntime import JavaTypes extension Int8: JavaValue { diff --git a/Sources/JavaKit/BridgedValues/JavaValue+String.swift b/Sources/JavaKit/BridgedValues/JavaValue+String.swift index 028cf390..5c9ca117 100644 --- a/Sources/JavaKit/BridgedValues/JavaValue+String.swift +++ b/Sources/JavaKit/BridgedValues/JavaValue+String.swift @@ -12,7 +12,6 @@ // //===----------------------------------------------------------------------===// -import JavaRuntime import JavaTypes extension String: JavaValue { diff --git a/Sources/JavaKit/JavaRuntime+Reexport.swift b/Sources/JavaKit/JavaRuntime+Reexport.swift new file mode 100644 index 00000000..e65d4e18 --- /dev/null +++ b/Sources/JavaKit/JavaRuntime+Reexport.swift @@ -0,0 +1,15 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +@_exported import JavaRuntime diff --git a/Sources/JavaKitVM/JavaVirtualMachine.swift b/Sources/JavaKitVM/JavaVirtualMachine.swift index 1d144157..d1cc97ec 100644 --- a/Sources/JavaKitVM/JavaVirtualMachine.swift +++ b/Sources/JavaKitVM/JavaVirtualMachine.swift @@ -13,7 +13,6 @@ //===----------------------------------------------------------------------===// import JavaKit -import JavaRuntime typealias JavaVMPointer = UnsafeMutablePointer diff --git a/Tests/JavaKitTests/BasicRuntimeTests.swift b/Tests/JavaKitTests/BasicRuntimeTests.swift index 4dd5d196..b05579ae 100644 --- a/Tests/JavaKitTests/BasicRuntimeTests.swift +++ b/Tests/JavaKitTests/BasicRuntimeTests.swift @@ -15,7 +15,6 @@ import JavaKit import JavaKitNetwork import JavaKitVM -import JavaRuntime import Testing @MainActor diff --git a/USER_GUIDE.md b/USER_GUIDE.md index 6420ec4e..fba674c2 100644 --- a/USER_GUIDE.md +++ b/USER_GUIDE.md @@ -57,7 +57,6 @@ Now, in the `HelloSwift` Swift library, define a `struct` that provides the `mai ```swift import JavaKit -import JavaRuntime @JavaClass("org.swift.javakit.HelloSwiftMain") struct HelloSwiftMain { @@ -87,7 +86,6 @@ The easiest way to build a command-line program in Swift is with the [Swift argu ```swift import ArgumentParser import JavaKit -import JavaRuntime @JavaClass("org.swift.javakit.HelloSwiftMain") struct HelloSwiftMain: ParsableCommand { From 39d76f81b1611a346e104d910ca1570e23a97d76 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Mon, 7 Oct 2024 10:53:44 -0700 Subject: [PATCH 031/426] Only build the JavaKitExample shared library itself as a dynamic library Everything else can be static --- Package.swift | 7 ------- 1 file changed, 7 deletions(-) diff --git a/Package.swift b/Package.swift index dea2b000..84efccda 100644 --- a/Package.swift +++ b/Package.swift @@ -52,25 +52,21 @@ let package = Package( products: [ .library( name: "JavaKit", - type: .dynamic, targets: ["JavaKit"] ), .library( name: "JavaKitJar", - type: .dynamic, targets: ["JavaKitReflection"] ), .library( name: "JavaKitNetwork", - type: .dynamic, targets: ["JavaKitReflection"] ), .library( name: "JavaKitReflection", - type: .dynamic, targets: ["JavaKitReflection"] ), @@ -82,19 +78,16 @@ let package = Package( .library( name: "JavaKitVM", - type: .dynamic, targets: ["JavaKitVM"] ), .library( name: "JavaTypes", - type: .dynamic, targets: ["JavaTypes"] ), .library( name: "JExtractSwift", - type: .dynamic, targets: ["JExtractSwift"] ), From c85371f2a3bda26cb649f68ba16c7cb91d682d72 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Mon, 7 Oct 2024 11:16:17 -0700 Subject: [PATCH 032/426] Improve lookup of JavaClass instances in an environment Teach the low-level getJNIClass API to properly check for Java exceptions and turn them into Swift errors. Then add a higher-level API `JavaClass.init(in:)` to look up a specific imported Java class within the given environment. --- Sources/JavaKit/AnyJavaObject.swift | 12 ++++++----- .../Exceptions/ExceptionHandling.swift | 2 +- Sources/JavaKit/JavaClass.swift | 10 +++++++++- Sources/JavaKit/JavaObject+Inheritance.swift | 2 +- Sources/JavaKit/JavaObject+MethodCalls.swift | 2 +- Sources/JavaKit/Optional+JavaObject.swift | 2 +- Tests/JavaKitTests/BasicRuntimeTests.swift | 20 +++++++++++++------ 7 files changed, 34 insertions(+), 16 deletions(-) diff --git a/Sources/JavaKit/AnyJavaObject.swift b/Sources/JavaKit/AnyJavaObject.swift index aaddaa9a..8f28c098 100644 --- a/Sources/JavaKit/AnyJavaObject.swift +++ b/Sources/JavaKit/AnyJavaObject.swift @@ -81,10 +81,12 @@ extension AnyJavaObject { } /// Retrieve the Java class for this type. - public static func getJNIClass(in environment: JNIEnvironment) -> jclass? { - return environment.interface.FindClass( - environment, - fullJavaClassNameWithSlashes - ) + public static func getJNIClass(in environment: JNIEnvironment) throws -> jclass { + try environment.translatingJNIExceptions { + environment.interface.FindClass( + environment, + fullJavaClassNameWithSlashes + ) + }! } } diff --git a/Sources/JavaKit/Exceptions/ExceptionHandling.swift b/Sources/JavaKit/Exceptions/ExceptionHandling.swift index 44f1897c..efd98e94 100644 --- a/Sources/JavaKit/Exceptions/ExceptionHandling.swift +++ b/Sources/JavaKit/Exceptions/ExceptionHandling.swift @@ -42,7 +42,7 @@ extension JNIEnvironment { // Otherwise, create a exception with a message. _ = interface.ThrowNew( self, - JavaClass.getJNIClass(in: self), + try! JavaClass.getJNIClass(in: self), String(describing: error) ) } diff --git a/Sources/JavaKit/JavaClass.swift b/Sources/JavaKit/JavaClass.swift index 8cb2e3c2..c9f0fdd2 100644 --- a/Sources/JavaKit/JavaClass.swift +++ b/Sources/JavaKit/JavaClass.swift @@ -17,4 +17,12 @@ import JavaRuntime /// Wrapper around a Java class that provides access to the static members of /// the class. @JavaClass("java.lang.Class") -public struct JavaClass { } +public struct JavaClass { + /// Lookup this Java class within the given environment. + public init(in environment: JNIEnvironment) throws { + self.init( + javaThis: try ObjectType.getJNIClass(in: environment), + environment: environment + ) + } +} diff --git a/Sources/JavaKit/JavaObject+Inheritance.swift b/Sources/JavaKit/JavaObject+Inheritance.swift index 8d6b68fa..cbd27c91 100644 --- a/Sources/JavaKit/JavaObject+Inheritance.swift +++ b/Sources/JavaKit/JavaObject+Inheritance.swift @@ -27,7 +27,7 @@ extension AnyJavaObject { private func isInstanceOf( _ otherClass: OtherClass.Type ) -> jclass? { - guard let otherJavaClass = otherClass.getJNIClass(in: javaEnvironment) else { + guard let otherJavaClass = try? otherClass.getJNIClass(in: javaEnvironment) else { return nil } diff --git a/Sources/JavaKit/JavaObject+MethodCalls.swift b/Sources/JavaKit/JavaObject+MethodCalls.swift index ad091943..e9b97bc2 100644 --- a/Sources/JavaKit/JavaObject+MethodCalls.swift +++ b/Sources/JavaKit/JavaObject+MethodCalls.swift @@ -247,7 +247,7 @@ extension AnyJavaObject { in environment: JNIEnvironment, arguments: repeat each Param ) throws -> Self { - let thisClass = Self.getJNIClass(in: environment)! + let thisClass = try Self.getJNIClass(in: environment) // Compute the method signature so we can find the right method, then look up the // method within the class. diff --git a/Sources/JavaKit/Optional+JavaObject.swift b/Sources/JavaKit/Optional+JavaObject.swift index 0444b4f1..55ad366e 100644 --- a/Sources/JavaKit/Optional+JavaObject.swift +++ b/Sources/JavaKit/Optional+JavaObject.swift @@ -70,7 +70,7 @@ extension Optional: JavaValue where Wrapped: AnyJavaObject { public static func jniNewArray(in environment: JNIEnvironment) -> JNINewArray { return { environment, size in - let jniClass = Wrapped.getJNIClass(in: environment) + let jniClass = try! Wrapped.getJNIClass(in: environment) return environment.interface.NewObjectArray(environment, size, jniClass, nil) } } diff --git a/Tests/JavaKitTests/BasicRuntimeTests.swift b/Tests/JavaKitTests/BasicRuntimeTests.swift index b05579ae..085c907c 100644 --- a/Tests/JavaKitTests/BasicRuntimeTests.swift +++ b/Tests/JavaKitTests/BasicRuntimeTests.swift @@ -59,16 +59,24 @@ struct BasicRuntimeTests { } @Test("Static methods") - func staticMethods() { - let urlConnectionClass = JavaClass( - javaThis: URLConnection.getJNIClass(in: jvm.environment)!, - environment: jvm.environment - ) - + func staticMethods() throws { + let urlConnectionClass = try JavaClass(in: jvm.environment) #expect(urlConnectionClass.getDefaultAllowUserInteraction() == false) } + + @Test("Class instance lookup") + func classInstanceLookup() throws { + do { + _ = try JavaClass(in: jvm.environment) + } catch { + #expect(String(describing: error) == "org/swift/javakit/Nonexistent") + } + } } +@JavaClass("org.swift.javakit.Nonexistent") +struct Nonexistent { } + /// Whether we're running on Linux. var isLinux: Bool { #if os(Linux) From 091d49fc75336df88e34b95cb0cbad9b4a1a0f55 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Mon, 7 Oct 2024 12:02:10 -0700 Subject: [PATCH 033/426] Improve and document the JavaVirtualMachine initializer Add options for the class path (so clients don't need to re-learn how to spell it) and for telling the JVM whether to ignore unrecognized arguments. --- Sources/JavaKitVM/JavaVirtualMachine.swift | 30 +++++++++++++++++++--- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/Sources/JavaKitVM/JavaVirtualMachine.swift b/Sources/JavaKitVM/JavaVirtualMachine.swift index d1cc97ec..117cca2b 100644 --- a/Sources/JavaKitVM/JavaVirtualMachine.swift +++ b/Sources/JavaKitVM/JavaVirtualMachine.swift @@ -23,19 +23,41 @@ public final class JavaVirtualMachine: @unchecked Sendable { /// The JNI environment for the JVM. public let environment: JNIEnvironment - public init(vmOptions: [String] = []) throws { + /// Initialize a new Java virtual machine instance. + /// + /// - Parameters: + /// - classPath: The directories, JAR files, and ZIP files in which the JVM + /// should look to find classes. This maps to the VM option + /// `-Djava.class.path=`. + /// - vmOptions: Options that should be passed along to the JVM, which will + /// be prefixed by the class-path argument described above. + /// - ignoreUnrecognized: Whether the JVM should ignore any VM options it + /// does not recognize. + public init( + classPath: [String] = [], + vmOptions: [String] = [], + ignoreUnrecognized: Bool = true + ) throws { var jvm: JavaVMPointer? = nil var environment: UnsafeMutableRawPointer? = nil var vmArgs = JavaVMInitArgs() vmArgs.version = JNI_VERSION_21 - vmArgs.ignoreUnrecognized = jboolean(JNI_TRUE) + vmArgs.ignoreUnrecognized = jboolean(ignoreUnrecognized ? JNI_TRUE : JNI_FALSE) + + // Construct the complete list of VM options. + var allVMOptions: [String] = [] + if !classPath.isEmpty { + let colonSeparatedClassPath = classPath.joined(separator: ":") + allVMOptions.append("-Djava.class.path=\(colonSeparatedClassPath)") + } + allVMOptions.append(contentsOf: vmOptions) // Convert the options - let optionsBuffer = UnsafeMutableBufferPointer.allocate(capacity: vmOptions.count) + let optionsBuffer = UnsafeMutableBufferPointer.allocate(capacity: allVMOptions.count) defer { optionsBuffer.deallocate() } - for (index, vmOption) in vmOptions.enumerated() { + for (index, vmOption) in allVMOptions.enumerated() { let optionString = vmOption.utf8CString.withUnsafeBufferPointer { buffer in let cString = UnsafeMutableBufferPointer.allocate(capacity: buffer.count + 1) _ = cString.initialize(from: buffer) From 7e7ad2a15b35e9ba1d74d88d3309e74519220b8d Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Mon, 7 Oct 2024 12:03:55 -0700 Subject: [PATCH 034/426] Require only JNI version 1.6 Based on our uses of the JNI APIs, the JavaKit path (Swift wrapping Java classes) only requires JNI as of Java 1.6, far earlier than the JDK 21 we had previously required. --- Sources/JavaKitVM/JavaVirtualMachine.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/JavaKitVM/JavaVirtualMachine.swift b/Sources/JavaKitVM/JavaVirtualMachine.swift index 117cca2b..5fc26940 100644 --- a/Sources/JavaKitVM/JavaVirtualMachine.swift +++ b/Sources/JavaKitVM/JavaVirtualMachine.swift @@ -41,7 +41,7 @@ public final class JavaVirtualMachine: @unchecked Sendable { var jvm: JavaVMPointer? = nil var environment: UnsafeMutableRawPointer? = nil var vmArgs = JavaVMInitArgs() - vmArgs.version = JNI_VERSION_21 + vmArgs.version = JNI_VERSION_1_6 vmArgs.ignoreUnrecognized = jboolean(ignoreUnrecognized ? JNI_TRUE : JNI_FALSE) // Construct the complete list of VM options. From 7f93a622b9ee98e201f67903b837fe0c0d5a3a36 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Mon, 7 Oct 2024 18:38:48 +0900 Subject: [PATCH 035/426] Reorganize build: SwiftKit has "swift kit" core, and SwiftKitExample Further progress on cleaning up the build. We're still having issues with various runtime issues but this gets us to a more understandable separation of "what is a sample" and "what is the library". There's more to be done before we can kill off `make` but this does quite some progress. - Sample apps "anything with a main()" have their own place; it used to be very mixed up in the same target; together with the example lib - `JavaKitSampleApp` there's a sample for javakit which uses the `JavaKitExample` defined swift type - `SwiftKitSampleApp` the jextract demo app, uses the `ExampleSwiftLibrary` - those JavaKitExample and ExampleSwiftLibrary could use further moving out of `Sources/...` as they're example stuff, not "the library" but I leave at this for now... Running samples: ./gradlew Samples:SwiftKitSampleApp:run (Samples:Name:run) - `./gradlew test` does the jextract and whatever the sample apps need - make is still around; didn't hook up any of the javakit generation - generated sources no longer in wrong directory; `src/generated/`... as the usual convention in Java land (and not committed) --- .github/workflows/pull_request.yml | 5 +- .gitignore | 7 +- ...d-logic.java-common-conventions.gradle.kts | 54 +++++--- Makefile | 32 ++--- Package.resolved | 32 ----- Package.swift | 60 +++++++-- .../JavaKitSampleApp/build.gradle | 25 ++-- .../java/com/example/swift/HelloSubclass.java | 2 - .../java/com/example/swift/HelloSwift.java | 7 -- .../com/example/swift/JavaKitSampleMain.java | 16 ++- Samples/SwiftKitSampleApp/build.gradle | 107 ++++++++++++++++ .../main/java/com/example/swift}/CallMe.java | 2 +- .../com/example/swift}/HelloJava2Swift.java | 27 ++-- .../example/swift/ManualJavaKitExample.java | 4 +- .../example/swift/ManualMySwiftClass.java | 4 +- .../example/swift/Manual_MySwiftClass.java | 2 +- .../GeneratedJavaKitExampleModuleTest.java | 36 +++--- .../swift/generated/MySwiftClassTest.java | 22 ++-- .../org/swift/swiftkit/MySwiftClassTest.java | 32 ++--- .../MySwiftLibrary.swift | 6 +- Sources/JExtractSwift/Swift2Java.swift | 2 +- .../Swift2JavaTranslator+Printing.swift | 13 +- .../JExtractSwift/Swift2JavaTranslator.swift | 8 +- Sources/JExtractSwift/Swift2JavaVisitor.swift | 4 +- Sources/JavaKitExample/JavaKitExample.swift | 2 +- Sources/JavaKitJar/generated/JarFile.swift | 6 +- .../JavaKitJar/generated/JarInputStream.swift | 4 +- .../SwiftKit.swift | 0 SwiftJavaKitExample/README.md | 2 - SwiftKit/{build.gradle.kts => build.gradle} | 20 ++- .../org/swift/swiftkit}/ManagedSwiftType.java | 2 +- .../java/org/swift/swiftkit/SwiftArena.java | 2 - .../org/swift/swiftkit/SwiftHeapObject.java | 0 .../java/org/swift/swiftkit}/SwiftKit.java | 119 ++++++++++-------- .../JExtractSwiftTests/FuncImportTests.swift | 43 ++++--- .../FunctionDescriptorImportTests.swift | 2 +- .../JExtractSwiftTests/SwiftDylibTests.swift | 8 +- Tests/JavaKitTests/BasicRuntimeTests.swift | 2 +- buildSrc/build.gradle | 3 + .../swift/swiftkit/gradle/BuildUtils.groovy | 36 ++++++ settings.gradle.kts => settings.gradle | 16 ++- 41 files changed, 480 insertions(+), 296 deletions(-) delete mode 100644 Package.resolved rename JavaSwiftKitDemo/build.gradle.kts => Samples/JavaKitSampleApp/build.gradle (75%) rename {JavaSwiftKitDemo => Samples/JavaKitSampleApp}/src/main/java/com/example/swift/HelloSubclass.java (95%) rename {JavaSwiftKitDemo => Samples/JavaKitSampleApp}/src/main/java/com/example/swift/HelloSwift.java (87%) rename SwiftJavaKitExample/build.gradle.kts => Samples/JavaKitSampleApp/src/main/java/com/example/swift/JavaKitSampleMain.java (56%) create mode 100644 Samples/SwiftKitSampleApp/build.gradle rename {JavaSwiftKitDemo/src/main/java/org/example => Samples/SwiftKitSampleApp/src/main/java/com/example/swift}/CallMe.java (96%) rename {JavaSwiftKitDemo/src/main/java/org/example => Samples/SwiftKitSampleApp/src/main/java/com/example/swift}/HelloJava2Swift.java (79%) rename {JavaSwiftKitDemo/src/main/java/org => Samples/SwiftKitSampleApp/src/main/java/com}/example/swift/ManualJavaKitExample.java (99%) rename {JavaSwiftKitDemo/src/main/java/org => Samples/SwiftKitSampleApp/src/main/java/com}/example/swift/ManualMySwiftClass.java (99%) rename {JavaSwiftKitDemo/src/main/java/org => Samples/SwiftKitSampleApp/src/main/java/com}/example/swift/Manual_MySwiftClass.java (99%) rename JavaSwiftKitDemo/src/test/java/org/example/swift/GlobalFunctionsTest.java => Samples/SwiftKitSampleApp/src/test/java/com/example/swift/generated/GeneratedJavaKitExampleModuleTest.java (52%) rename JavaSwiftKitDemo/src/test/java/org/example/swift/JavaKitTest.java => Samples/SwiftKitSampleApp/src/test/java/com/example/swift/generated/MySwiftClassTest.java (61%) rename JavaSwiftKitDemo/src/test/java/org/example/swift/SwiftKitTest.java => Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/MySwiftClassTest.java (65%) rename Sources/{JavaKitExample => ExampleSwiftLibrary}/MySwiftLibrary.swift (95%) rename Sources/{JavaKitExample => SwiftKitSwift}/SwiftKit.swift (100%) delete mode 100644 SwiftJavaKitExample/README.md rename SwiftKit/{build.gradle.kts => build.gradle} (57%) rename {JavaSwiftKitDemo/src/main/java/org/swift/javakit => SwiftKit/src/main/java/org/swift/swiftkit}/ManagedSwiftType.java (96%) rename {JavaSwiftKitDemo => SwiftKit}/src/main/java/org/swift/swiftkit/SwiftArena.java (97%) rename {JavaSwiftKitDemo => SwiftKit}/src/main/java/org/swift/swiftkit/SwiftHeapObject.java (100%) rename {JavaSwiftKitDemo/src/main/java/org/swift/javakit => SwiftKit/src/main/java/org/swift/swiftkit}/SwiftKit.java (81%) create mode 100644 buildSrc/build.gradle create mode 100644 buildSrc/src/main/groovy/org/swift/swiftkit/gradle/BuildUtils.groovy rename settings.gradle.kts => settings.gradle (66%) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 0114da27..8aad2c67 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -41,11 +41,8 @@ jobs: # distribution: 'zulu' # java-version: '22' # cache: 'gradle' - - name: Generate sources (make) (Temporary) - # TODO: this should be triggered by the respective builds - run: make jextract-run - name: Gradle build - run: ./gradlew build --no-daemon + run: ./gradlew build --info --no-daemon test-swift: name: Swift tests (swift:${{ matrix.swift_version }} jdk:${{matrix.jdk_vendor}} os:${{ matrix.os_version }}) diff --git a/.gitignore b/.gitignore index 416f253f..381bd778 100644 --- a/.gitignore +++ b/.gitignore @@ -9,10 +9,15 @@ DerivedData/ .netrc *.class bin/ +BuildLogic/out/ # Ignore gradle build artifacts .gradle **/build/ +lib/ + +# Ignore package resolved +Package.resolved # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) !gradle-wrapper.jar @@ -24,4 +29,4 @@ bin/ .gradletasknamecache # Ignore generated sources -JavaSwiftKitDemo/src/main/java/com/example/swift/generated/* +**/generated/ diff --git a/BuildLogic/src/main/kotlin/build-logic.java-common-conventions.gradle.kts b/BuildLogic/src/main/kotlin/build-logic.java-common-conventions.gradle.kts index 85142bd9..8789ebfe 100644 --- a/BuildLogic/src/main/kotlin/build-logic.java-common-conventions.gradle.kts +++ b/BuildLogic/src/main/kotlin/build-logic.java-common-conventions.gradle.kts @@ -12,6 +12,8 @@ // //===----------------------------------------------------------------------===// +import java.util.* + plugins { java } @@ -40,16 +42,39 @@ tasks.withType(JavaCompile::class).forEach { it.options.compilerArgs.add("-Xlint:preview") } + +fun javaLibraryPaths(): List { + val osName = System.getProperty("os.name") + val osArch = System.getProperty("os.arch") + val isLinux = osName.lowercase(Locale.getDefault()).contains("linux") + + return listOf( + if (osName.lowercase(Locale.getDefault()).contains("linux")) { + """$rootDir/.build/$osArch-unknown-linux-gnu/debug/""" + } else { + if (osArch.equals("aarch64")) { + """$rootDir/.build/arm64-apple-macosx/debug/""" + } else { + """$rootDir/.build/$osArch-apple-macosx/debug/""" + } + }, + if (isLinux) { + "/usr/lib/swift/linux" + } else { + // assume macOS + "/usr/lib/swift/" + } + ) +} + + // Configure paths for native (Swift) libraries tasks.test { jvmArgs( "--enable-native-access=ALL-UNNAMED", // Include the library paths where our dylibs are that we want to load and call - "-Djava.library.path=" + listOf( - """$rootDir/.build/arm64-apple-macosx/debug/""", - "/usr/lib/swift/" - ).joinToString(File.pathSeparator) + "-Djava.library.path=" + javaLibraryPaths().joinToString(File.pathSeparator) ) } @@ -60,14 +85,15 @@ tasks.withType { } -val buildSwiftJExtract = tasks.register("buildSwiftJExtract") { - description = "Builds Swift targets, including jextract-swift" - - workingDir("..") - commandLine("make") -} - -tasks.build { - dependsOn(buildSwiftJExtract) -} +// TODO: This is a crude workaround, we'll remove 'make' soon and properly track build dependencies +// val buildSwiftJExtract = tasks.register("buildMake") { +// description = "Triggers 'make' build" +// +// workingDir(rootDir) +// commandLine("make") +// } +// +// tasks.build { +// dependsOn(buildSwiftJExtract) +// } diff --git a/Makefile b/Makefile index a0baff12..3528d1a6 100644 --- a/Makefile +++ b/Makefile @@ -37,17 +37,15 @@ BUILD_DIR := .build/$(ARCH_SUBDIR)-apple-macosx LIB_SUFFIX := dylib endif +SAMPLES_DIR := "Samples" all: generate-all -$(BUILD_DIR)/debug/libJavaKit.$(LIB_SUFFIX) $(BUILD_DIR)/debug/libJavaKitExample.$(LIB_SUFFIX) $(BUILD_DIR)/debug/Java2Swift: +$(BUILD_DIR)/debug/libJavaKit.$(LIB_SUFFIX) $(BUILD_DIR)/debug/Java2Swift: swift build -./JavaSwiftKitDemo/build/classes/java/main/com/example/swift/HelloSubclass.class: JavaSwiftKitDemo/src/main/java/com/example/swift - ./gradlew build - -run: $(BUILD_DIR)/debug/libJavaKit.$(LIB_SUFFIX) $(BUILD_DIR)/debug/libJavaKitExample.$(LIB_SUFFIX) JavaSwiftKitDemo/src/main/java/com/example/swift - java -cp JavaSwiftKitDemo/build/classes/java/main -Djava.library.path=$(BUILD_DIR)/debug/ com.example.swift.HelloSwift +run: $(BUILD_DIR)/debug/libJavaKit.$(LIB_SUFFIX) $(BUILD_DIR)/debug/libExampleSwiftLibrary.$(LIB_SUFFIX) + ./gradlew Samples:JavaKitSampleApp:run Java2Swift: $(BUILD_DIR)/debug/Java2Swift @@ -70,7 +68,8 @@ generate-JavaKitNetwork: Java2Swift generate-JavaKit generate-all: generate-JavaKit generate-JavaKitReflection generate-JavaKitJar generate-JavaKitNetwork \ jextract-swift clean: - rm -rf .build + rm -rf .build; \ + rm -rf Samples/SwiftKitExampleApp/src/generated/java/* format: swift format --recursive . -i @@ -81,7 +80,6 @@ format: JEXTRACT_BUILD_DIR="$(BUILD_DIR)/jextract" -# Parameter: Swift source file define make_swiftinterface $(eval $@_MODULE = $(1)) $(eval $@_FILENAME = $(2)) @@ -99,17 +97,21 @@ jextract-swift: generate-JExtract-interface-files generate-JExtract-interface-files: $(BUILD_DIR)/debug/libJavaKit.$(LIB_SUFFIX) echo "Generate .swiftinterface files..." - @$(call make_swiftinterface, "JavaKitExample", "MySwiftLibrary") - @$(call make_swiftinterface, "JavaKitExample", "SwiftKit") + @$(call make_swiftinterface, "ExampleSwiftLibrary", "MySwiftLibrary") + @$(call make_swiftinterface, "SwiftKitSwift", "SwiftKit") jextract-run: jextract-swift generate-JExtract-interface-files swift run jextract-swift \ --package-name com.example.swift.generated \ - --swift-module JavaKitExample \ - --output-directory JavaSwiftKitDemo/src/main/java \ - $(BUILD_DIR)/jextract/JavaKitExample/MySwiftLibrary.swiftinterface \ - $(BUILD_DIR)/jextract/JavaKitExample/SwiftKit.swiftinterface + --swift-module ExampleSwiftLibrary \ + --output-directory ${SAMPLES_DIR}/SwiftKitSampleApp/src/generated/java \ + $(BUILD_DIR)/jextract/ExampleSwiftLibrary/MySwiftLibrary.swiftinterface; \ + swift run jextract-swift \ + --package-name org.swift.swiftkit.generated \ + --swift-module SwiftKitSwift \ + --output-directory ${SAMPLES_DIR}/SwiftKitSampleApp/src/generated/java \ + $(BUILD_DIR)/jextract/SwiftKitSwift/SwiftKit.swiftinterface jextract-run-java: jextract-swift generate-JExtract-interface-files - ./gradlew run + ./gradlew Samples:SwiftKitSampleApp:run diff --git a/Package.resolved b/Package.resolved deleted file mode 100644 index 60931987..00000000 --- a/Package.resolved +++ /dev/null @@ -1,32 +0,0 @@ -{ - "pins" : [ - { - "identity" : "swift-argument-parser", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-argument-parser", - "state" : { - "revision" : "41982a3656a71c768319979febd796c6fd111d5c", - "version" : "1.5.0" - } - }, - { - "identity" : "swift-syntax", - "kind" : "remoteSourceControl", - "location" : "https://github.com/swiftlang/swift-syntax.git", - "state" : { - "branch" : "main", - "revision" : "16dc4f87937fa8a639f064d4b2369c4d3e0fc672" - } - }, - { - "identity" : "swift-system", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-system", - "state" : { - "revision" : "d2ba781702a1d8285419c15ee62fd734a9437ff5", - "version" : "1.3.2" - } - } - ], - "version" : 2 -} diff --git a/Package.swift b/Package.swift index 84efccda..df96b8f4 100644 --- a/Package.swift +++ b/Package.swift @@ -18,7 +18,7 @@ func findJavaHome() -> String { // This is a workaround for envs (some IDEs) which have trouble with // picking up env variables during the build process let path = "\(FileManager.default.homeDirectoryForCurrentUser.path()).java_home" - if let home = try? String(contentsOfFile: path) { + if let home = try? String(contentsOfFile: path, encoding: .utf8) { if let lastChar = home.last, lastChar.isNewline { return String(home.dropLast()) } @@ -36,8 +36,8 @@ let javaIncludePath = "\(javaHome)/include" #elseif os(macOS) let javaPlatformIncludePath = "\(javaIncludePath)/darwin" #else + // TODO: Handle windows as well #error("Currently only macOS and Linux platforms are supported, this may change in the future.") -// TODO: Handle windows as well #endif let package = Package( @@ -50,6 +50,7 @@ let package = Package( .macCatalyst(.v13), ], products: [ + // ==== JavaKit (i.e. calling Java directly Swift utilities) .library( name: "JavaKit", targets: ["JavaKit"] @@ -70,12 +71,6 @@ let package = Package( targets: ["JavaKitReflection"] ), - .library( - name: "JavaKitExample", - type: .dynamic, - targets: ["JavaKitExample"] - ), - .library( name: "JavaKitVM", targets: ["JavaKitVM"] @@ -86,20 +81,43 @@ let package = Package( targets: ["JavaTypes"] ), - .library( - name: "JExtractSwift", - targets: ["JExtractSwift"] - ), - .executable( name: "Java2Swift", targets: ["Java2Swift"] ), + // ==== jextract-swift (extract Java accessors from Swift interface files) + .executable( name: "jextract-swift", targets: ["JExtractSwiftTool"] ), + + // Support library written in Swift for SwiftKit "Java" + .library( + name: "SwiftKitSwift", + type: .dynamic, + targets: ["SwiftKitSwift"] + ), + + .library( + name: "JExtractSwift", + targets: ["JExtractSwift"] + ), + + // ==== Examples + + .library( + name: "JavaKitExample", + type: .dynamic, + targets: ["JavaKitExample"] + ), + .library( + name: "ExampleSwiftLibrary", + type: .dynamic, + targets: ["ExampleSwiftLibrary"] + ), + ], dependencies: [ .package(url: "https://github.com/swiftlang/swift-syntax.git", branch: "main"), @@ -187,6 +205,22 @@ let package = Package( .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) ] ), + .target( + name: "ExampleSwiftLibrary", + dependencies: [], + swiftSettings: [ + .swiftLanguageMode(.v5), + .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) + ] + ), + .target( + name: "SwiftKitSwift", + dependencies: [], + swiftSettings: [ + .swiftLanguageMode(.v5), + .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) + ] + ), .target( name: "JavaRuntime", diff --git a/JavaSwiftKitDemo/build.gradle.kts b/Samples/JavaKitSampleApp/build.gradle similarity index 75% rename from JavaSwiftKitDemo/build.gradle.kts rename to Samples/JavaKitSampleApp/build.gradle index 84c0b924..67295994 100644 --- a/JavaSwiftKitDemo/build.gradle.kts +++ b/Samples/JavaKitSampleApp/build.gradle @@ -12,6 +12,8 @@ // //===----------------------------------------------------------------------===// +import org.swift.swiftkit.gradle.BuildUtils + plugins { id("build-logic.java-application-conventions") } @@ -30,6 +32,8 @@ java { } dependencies { + implementation(project(':SwiftKit')) + testImplementation(platform("org.junit:junit-bom:5.10.0")) testImplementation("org.junit.jupiter:junit-jupiter") } @@ -39,7 +43,7 @@ tasks.test { } application { - mainClass = "org.example.HelloJava2Swift" + mainClass = "com.example.swift.JavaKitSampleMain" // In order to silence: // WARNING: A restricted method in java.lang.foreign.SymbolLookup has been called @@ -47,17 +51,10 @@ application { // WARNING: Use --enable-native-access=ALL-UNNAMED to avoid a warning for callers in this module // WARNING: Restricted methods will be blocked in a future release unless native access is enabled // FIXME: Find out the proper solution to this - applicationDefaultJvmArgs = listOf( - "--enable-native-access=ALL-UNNAMED", - - // Include the library paths where our dylibs are that we want to load and call - "-Djava.library.path=" + listOf( - """$rootDir/.build/arm64-apple-macosx/debug/""", - "/usr/lib/swift/" - ).joinToString(":"), - - // Enable tracing downcalls (to Swift) - "-Djextract.trace.downcalls=true" - ) -} + applicationDefaultJvmArgs = [ + "--enable-native-access=ALL-UNNAMED", + // Include the library paths where our dylibs are that we want to load and call + "-Djava.library.path=" + BuildUtils.javaLibraryPaths(rootDir).join(":") + ] +} diff --git a/JavaSwiftKitDemo/src/main/java/com/example/swift/HelloSubclass.java b/Samples/JavaKitSampleApp/src/main/java/com/example/swift/HelloSubclass.java similarity index 95% rename from JavaSwiftKitDemo/src/main/java/com/example/swift/HelloSubclass.java rename to Samples/JavaKitSampleApp/src/main/java/com/example/swift/HelloSubclass.java index 25cc9245..eb3cba32 100644 --- a/JavaSwiftKitDemo/src/main/java/com/example/swift/HelloSubclass.java +++ b/Samples/JavaKitSampleApp/src/main/java/com/example/swift/HelloSubclass.java @@ -14,8 +14,6 @@ package com.example.swift; -import com.example.swift.HelloSwift; - public class HelloSubclass extends HelloSwift { private String greeting; diff --git a/JavaSwiftKitDemo/src/main/java/com/example/swift/HelloSwift.java b/Samples/JavaKitSampleApp/src/main/java/com/example/swift/HelloSwift.java similarity index 87% rename from JavaSwiftKitDemo/src/main/java/com/example/swift/HelloSwift.java rename to Samples/JavaKitSampleApp/src/main/java/com/example/swift/HelloSwift.java index 652d230b..b4c87f71 100644 --- a/JavaSwiftKitDemo/src/main/java/com/example/swift/HelloSwift.java +++ b/Samples/JavaKitSampleApp/src/main/java/com/example/swift/HelloSwift.java @@ -14,8 +14,6 @@ package com.example.swift; -import com.example.swift.HelloSubclass; - public class HelloSwift { private double value; private static double initialValue = 3.14159; @@ -29,11 +27,6 @@ public HelloSwift() { this.value = initialValue; } - public static void main(String[] args) { - int result = new HelloSubclass("Swift").sayHello(17, 25); - System.out.println("sayHello(17, 25) = " + result); - } - public native int sayHello(int x, int y); public native String throwMessageFromSwift(String message) throws Exception; diff --git a/SwiftJavaKitExample/build.gradle.kts b/Samples/JavaKitSampleApp/src/main/java/com/example/swift/JavaKitSampleMain.java similarity index 56% rename from SwiftJavaKitExample/build.gradle.kts rename to Samples/JavaKitSampleApp/src/main/java/com/example/swift/JavaKitSampleMain.java index 4c77db83..2b565608 100644 --- a/SwiftJavaKitExample/build.gradle.kts +++ b/Samples/JavaKitSampleApp/src/main/java/com/example/swift/JavaKitSampleMain.java @@ -12,10 +12,16 @@ // //===----------------------------------------------------------------------===// -plugins { - `swift-library` -} +package com.example.swift; + +/** + * This sample shows off a {@link HelloSwift} type which is partially implemented in Swift. + * For the Swift implementation refer to + */ +public class JavaKitSampleMain { -extensions.configure { - source.from(file("../Sources/JavaKitExample")) + public static void main(String[] args) { + int result = new HelloSubclass("Swift").sayHello(17, 25); + System.out.println("sayHello(17, 25) = " + result); + } } diff --git a/Samples/SwiftKitSampleApp/build.gradle b/Samples/SwiftKitSampleApp/build.gradle new file mode 100644 index 00000000..158fdfcf --- /dev/null +++ b/Samples/SwiftKitSampleApp/build.gradle @@ -0,0 +1,107 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +plugins { + id("build-logic.java-application-conventions") +} + +group = "org.swift.swiftkit" +version = "1.0-SNAPSHOT" + +repositories { + mavenCentral() +} + +java { + toolchain { + languageVersion.set(JavaLanguageVersion.of(22)) + } +} + +sourceSets { + generated { + java.srcDir "${buildDir}/generated/src/java/" + } + + // Make the 'main' and 'test' source sets depend on the generated sources + main { + compileClasspath += sourceSets.generated.output + runtimeClasspath += sourceSets.generated.output + } + test { + compileClasspath += sourceSets.main.output + runtimeClasspath += sourceSets.main.output + + compileClasspath += sourceSets.generated.output + runtimeClasspath += sourceSets.generated.output + } +} + +dependencies { + implementation(project(':SwiftKit')) + generatedImplementation(project(':SwiftKit')) + + testImplementation(platform("org.junit:junit-bom:5.10.0")) + testImplementation("org.junit.jupiter:junit-jupiter") +} + +configurations { + generatedImplementation.extendsFrom(mainImplementation) + generatedRuntimeOnly.extendsFrom(mainRuntimeOnly) +} + +tasks.named("compileJava").configure { + dependsOn("jextract") +} + +tasks.test { + useJUnitPlatform() +} + +application { + mainClass = "com.example.swift.HelloJava2Swift" + + // In order to silence: + // WARNING: A restricted method in java.lang.foreign.SymbolLookup has been called + // WARNING: java.lang.foreign.SymbolLookup::libraryLookup has been called by org.example.swift.JavaKitExample in an unnamed module + // WARNING: Use --enable-native-access=ALL-UNNAMED to avoid a warning for callers in this module + // WARNING: Restricted methods will be blocked in a future release unless native access is enabled + // FIXME: Find out the proper solution to this + applicationDefaultJvmArgs = [ + "--enable-native-access=ALL-UNNAMED", + + // Include the library paths where our dylibs are that we want to load and call + "-Djava.library.path=" + [ + "$rootDir/.build/arm64-apple-macosx/debug/", + "/usr/lib/swift/" + ].join(":"), + + // Enable tracing downcalls (to Swift) + "-Djextract.trace.downcalls=true" + ] +} + +task jextract(type: Exec) { + description = "Extracts Java accessor sources using jextract" + outputs.dir(layout.buildDirectory.dir("generated")) + inputs.dir("$rootDir/Sources/ExampleSwiftLibrary") + + workingDir = rootDir + commandLine "make" + args "jextract-run" +} + +tasks.named("compileGeneratedJava").configure { + dependsOn jextract +} diff --git a/JavaSwiftKitDemo/src/main/java/org/example/CallMe.java b/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/CallMe.java similarity index 96% rename from JavaSwiftKitDemo/src/main/java/org/example/CallMe.java rename to Samples/SwiftKitSampleApp/src/main/java/com/example/swift/CallMe.java index 4af50f91..e3e10815 100644 --- a/JavaSwiftKitDemo/src/main/java/org/example/CallMe.java +++ b/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/CallMe.java @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -package org.example; +package com.example.swift; public class CallMe { public static String callMeStatic() { diff --git a/JavaSwiftKitDemo/src/main/java/org/example/HelloJava2Swift.java b/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java similarity index 79% rename from JavaSwiftKitDemo/src/main/java/org/example/HelloJava2Swift.java rename to Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java index 95870989..28054047 100644 --- a/JavaSwiftKitDemo/src/main/java/org/example/HelloJava2Swift.java +++ b/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java @@ -12,24 +12,17 @@ // //===----------------------------------------------------------------------===// -package org.example; +package com.example.swift; -// Import javakit/swiftkit support libraries - -import com.example.swift.generated.JavaKitExample; +// Import swift-extract generated sources +import com.example.swift.generated.ExampleSwiftLibrary; import com.example.swift.generated.MySwiftClass; -import org.example.swift.ManualJavaKitExample; -import org.example.swift.ManualMySwiftClass; -import org.swift.javakit.*; -// Import swift-extract generated sources -import static com.example.swift.generated.JavaKitExample.*; -import static com.example.swift.generated.MySwiftClass.*; +// Import javakit/swiftkit support libraries +import org.swift.swiftkit.SwiftKit; + import java.lang.foreign.*; -import java.nio.file.FileSystems; -import java.nio.file.Paths; -import java.util.Arrays; import java.util.List; @@ -53,13 +46,13 @@ public static void main(String[] args) { System.out.println("ok."); } - tests(); + examples(); } - static void tests() { - JavaKitExample.helloWorld(); + static void examples() { + ExampleSwiftLibrary.helloWorld(); - JavaKitExample.globalTakeInt(1337); + ExampleSwiftLibrary.globalTakeInt(1337); MySwiftClass obj = new MySwiftClass(2222, 7777); diff --git a/JavaSwiftKitDemo/src/main/java/org/example/swift/ManualJavaKitExample.java b/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/ManualJavaKitExample.java similarity index 99% rename from JavaSwiftKitDemo/src/main/java/org/example/swift/ManualJavaKitExample.java rename to Samples/SwiftKitSampleApp/src/main/java/com/example/swift/ManualJavaKitExample.java index f11c5637..1d9cfa77 100644 --- a/JavaSwiftKitDemo/src/main/java/org/example/swift/ManualJavaKitExample.java +++ b/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/ManualJavaKitExample.java @@ -12,9 +12,7 @@ // //===----------------------------------------------------------------------===// -package org.example.swift; - -import com.example.swift.generated.JavaKitExample; +package com.example.swift; import java.lang.invoke.*; import java.lang.foreign.*; diff --git a/JavaSwiftKitDemo/src/main/java/org/example/swift/ManualMySwiftClass.java b/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/ManualMySwiftClass.java similarity index 99% rename from JavaSwiftKitDemo/src/main/java/org/example/swift/ManualMySwiftClass.java rename to Samples/SwiftKitSampleApp/src/main/java/com/example/swift/ManualMySwiftClass.java index 53b21e8a..0a40f293 100644 --- a/JavaSwiftKitDemo/src/main/java/org/example/swift/ManualMySwiftClass.java +++ b/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/ManualMySwiftClass.java @@ -12,12 +12,12 @@ // //===----------------------------------------------------------------------===// -package org.example.swift; +package com.example.swift; // ==== Extra convenience APIs ------------------------------------------------------------------------------------- // TODO: Think about offering these or not, perhaps only as an option? -import org.swift.javakit.ManagedSwiftType; +import org.swift.swiftkit.ManagedSwiftType; import java.lang.foreign.*; import java.lang.invoke.MethodHandle; diff --git a/JavaSwiftKitDemo/src/main/java/org/example/swift/Manual_MySwiftClass.java b/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/Manual_MySwiftClass.java similarity index 99% rename from JavaSwiftKitDemo/src/main/java/org/example/swift/Manual_MySwiftClass.java rename to Samples/SwiftKitSampleApp/src/main/java/com/example/swift/Manual_MySwiftClass.java index 9ef51038..f57ac9d8 100644 --- a/JavaSwiftKitDemo/src/main/java/org/example/swift/Manual_MySwiftClass.java +++ b/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/Manual_MySwiftClass.java @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -package org.example.swift; +package com.example.swift; import java.lang.foreign.*; import java.lang.invoke.MethodHandle; diff --git a/JavaSwiftKitDemo/src/test/java/org/example/swift/GlobalFunctionsTest.java b/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/generated/GeneratedJavaKitExampleModuleTest.java similarity index 52% rename from JavaSwiftKitDemo/src/test/java/org/example/swift/GlobalFunctionsTest.java rename to Samples/SwiftKitSampleApp/src/test/java/com/example/swift/generated/GeneratedJavaKitExampleModuleTest.java index 7faff6b0..7bad75f2 100644 --- a/JavaSwiftKitDemo/src/test/java/org/example/swift/GlobalFunctionsTest.java +++ b/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/generated/GeneratedJavaKitExampleModuleTest.java @@ -12,49 +12,41 @@ // //===----------------------------------------------------------------------===// -package org.example.swift; +package com.example.swift.generated; -import com.example.swift.generated.JavaKitExample; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.DisabledOnOs; +import org.junit.jupiter.api.condition.OS; -import static com.example.swift.generated.JavaKitExample.*; import static org.junit.jupiter.api.Assertions.*; -public class GlobalFunctionsTest { +public class GeneratedJavaKitExampleModuleTest { + @BeforeAll static void beforeAll() { + System.out.println("java.library.path = " + System.getProperty("java.library.path")); + System.loadLibrary("swiftCore"); - System.loadLibrary("JavaKitExample"); + System.loadLibrary("ExampleSwiftLibrary"); System.setProperty("jextract.trace.downcalls", "true"); } @Test + @DisabledOnOs(OS.LINUX) // FIXME: enable on Linux when we get new compiler with mangled names in swift interfaces void call_helloWorld() { - helloWorld(); + ExampleSwiftLibrary.helloWorld(); - assertNotNull(helloWorld$address()); + assertNotNull(ExampleSwiftLibrary.helloWorld$address()); } @Test + @DisabledOnOs(OS.LINUX) // FIXME: enable on Linux when we get new compiler with mangled names in swift interfaces void call_globalTakeInt() { - JavaKitExample.globalTakeInt(12); + ExampleSwiftLibrary.globalTakeInt(12); - assertNotNull(globalTakeInt$address()); + assertNotNull(ExampleSwiftLibrary.globalTakeInt$address()); } -// @Test -// void call_globalCallJavaCallback() { -// var num = 0; -// -// JavaKitExample.globalCallJavaCallback(new Runnable() { -// @Override -// public void run() { -// num += 1; -// } -// }); -// -// assertEquals(1, num); -// } } diff --git a/JavaSwiftKitDemo/src/test/java/org/example/swift/JavaKitTest.java b/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/generated/MySwiftClassTest.java similarity index 61% rename from JavaSwiftKitDemo/src/test/java/org/example/swift/JavaKitTest.java rename to Samples/SwiftKitSampleApp/src/test/java/com/example/swift/generated/MySwiftClassTest.java index 404dca42..1a5f0d5a 100644 --- a/JavaSwiftKitDemo/src/test/java/org/example/swift/JavaKitTest.java +++ b/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/generated/MySwiftClassTest.java @@ -12,33 +12,25 @@ // //===----------------------------------------------------------------------===// -package org.example.swift; +package com.example.swift.generated; -import com.example.swift.generated.MySwiftClass; -import org.junit.jupiter.api.*; +import org.junit.jupiter.api.BeforeAll; -import static org.junit.jupiter.api.Assertions.*; -import static org.example.swift.ManualJavaKitExample.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; -import java.lang.foreign.Arena; -import java.lang.foreign.MemorySegment; +public class MySwiftClassTest { -public class JavaKitTest { @BeforeAll static void beforeAll() { System.out.printf("java.library.path = %s\n", System.getProperty("java.library.path")); System.loadLibrary("swiftCore"); - System.loadLibrary("JavaKitExample"); + System.loadLibrary("ExampleSwiftLibrary"); System.setProperty("jextract.trace.downcalls", "true"); } - @Test - void call_helloWorld() { - helloWorld(); + // TODO: test member methods on MySwiftClass - assertNotNull(helloWorld$address()); - } - } diff --git a/JavaSwiftKitDemo/src/test/java/org/example/swift/SwiftKitTest.java b/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/MySwiftClassTest.java similarity index 65% rename from JavaSwiftKitDemo/src/test/java/org/example/swift/SwiftKitTest.java rename to Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/MySwiftClassTest.java index acc1f372..7968cfae 100644 --- a/JavaSwiftKitDemo/src/test/java/org/example/swift/SwiftKitTest.java +++ b/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/MySwiftClassTest.java @@ -12,35 +12,31 @@ // //===----------------------------------------------------------------------===// -package org.example.swift; +package org.swift.swiftkit; import com.example.swift.generated.MySwiftClass; import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; -import org.swift.javakit.SwiftKit; -import org.swift.swiftkit.SwiftArena; +import org.junit.jupiter.api.condition.DisabledOnOs; +import org.junit.jupiter.api.condition.OS; -import java.lang.foreign.Arena; -import java.lang.foreign.MemorySegment; - -import static org.example.swift.ManualJavaKitExample.helloWorld; -import static org.example.swift.ManualJavaKitExample.helloWorld$address; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; -public class SwiftKitTest { +public class MySwiftClassTest { + @BeforeAll static void beforeAll() { System.out.printf("java.library.path = %s\n", System.getProperty("java.library.path")); System.loadLibrary("swiftCore"); - System.loadLibrary("JavaKitExample"); + System.loadLibrary("ExampleSwiftLibrary"); System.setProperty("jextract.trace.downcalls", "true"); } @Test + @DisabledOnOs(OS.LINUX) // FIXME: enable on Linux when we get new compiler with mangled names in swift interfaces void call_retain_retainCount_release() { var obj = new MySwiftClass(1, 2); @@ -53,18 +49,4 @@ void call_retain_retainCount_release() { SwiftKit.release(obj.$memorySegment()); assertEquals(1, SwiftKit.retainCount(obj.$memorySegment())); } - - @Test - void use_MySwiftClass_repr_init_arena() { - int lenValue = 1111; - int capValue = 2222; - - try (Arena arena = Arena.ofConfined()) { - ManualMySwiftClass obj = ManualMySwiftClass.init(arena, lenValue, capValue); - - -// assertEquals(lenValue, obj.len()); -// assertEquals(capValue, obj.cap()); - } - } } diff --git a/Sources/JavaKitExample/MySwiftLibrary.swift b/Sources/ExampleSwiftLibrary/MySwiftLibrary.swift similarity index 95% rename from Sources/JavaKitExample/MySwiftLibrary.swift rename to Sources/ExampleSwiftLibrary/MySwiftLibrary.swift index bd76fcf1..e5faaad7 100644 --- a/Sources/JavaKitExample/MySwiftLibrary.swift +++ b/Sources/ExampleSwiftLibrary/MySwiftLibrary.swift @@ -28,7 +28,11 @@ public func helloWorld() { } public func globalTakeInt(i: Int) { - p("int:\(i)") + p("i:\(i)") +} + +public func globalTakeIntInt(i: Int, j: Int) { + p("i:\(i), j:\(j)") } public class MySwiftClass { diff --git a/Sources/JExtractSwift/Swift2Java.swift b/Sources/JExtractSwift/Swift2Java.swift index 5c6d8a69..73a4d22b 100644 --- a/Sources/JExtractSwift/Swift2Java.swift +++ b/Sources/JExtractSwift/Swift2Java.swift @@ -36,7 +36,7 @@ public struct SwiftToJava: AsyncParsableCommand { // TODO: Once we ship this, make this `.warning` by default @Option(name: .shortAndLong, help: "Configure the level of lots that should be printed") - var logLevel: Logger.Level = .trace + var logLevel: Logger.Level = .notice @Argument(help: "The Swift interface files to export to Java.") var swiftInterfaceFiles: [String] diff --git a/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift b/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift index 7f238c75..35ed6133 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift @@ -239,12 +239,21 @@ extension Swift2JavaTranslator { """ ) + // SymbolLookup.libraryLookup is platform dependent and does not take into account java.library.path + // https://bugs.openjdk.org/browse/JDK-8311090 printer.print( """ - static final SymbolLookup SYMBOL_LOOKUP = - SymbolLookup.libraryLookup(System.mapLibraryName(DYLIB_NAME), LIBRARY_ARENA) + static final SymbolLookup SYMBOL_LOOKUP = getSymbolLookup(); + private static SymbolLookup getSymbolLookup() { + if (SwiftKit.isMacOS()) { + return SymbolLookup.libraryLookup(System.mapLibraryName(DYLIB_NAME), LIBRARY_ARENA) .or(SymbolLookup.loaderLookup()) .or(Linker.nativeLinker().defaultLookup()); + } else { + return SymbolLookup.loaderLookup() + .or(Linker.nativeLinker().defaultLookup()); + } + } """ ) diff --git a/Sources/JExtractSwift/Swift2JavaTranslator.swift b/Sources/JExtractSwift/Swift2JavaTranslator.swift index e942ff9b..27f55a4d 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator.swift @@ -22,7 +22,7 @@ import SwiftSyntax public final class Swift2JavaTranslator { static let SWIFT_INTERFACE_SUFFIX = ".swiftinterface" - public var log = Logger(label: "translator", logLevel: .info) + package var log = Logger(label: "translator", logLevel: .info) // ==== Input configuration let swiftModuleName: String @@ -110,7 +110,7 @@ extension Swift2JavaTranslator { } public func postProcessImportedDecls() async throws { - log.info( + log.debug( "Post process imported decls...", metadata: [ "types": "\(importedTypes.count)", @@ -143,7 +143,7 @@ extension Swift2JavaTranslator { log.info("Mapping members of: \(tyDecl.swiftTypeName)") tyDecl.initializers = try await tyDecl.initializers._mapAsync { initDecl in - dylib.log.logLevel = .trace + dylib.log.logLevel = .info let initDecl = try await dylib.fillInAllocatingInitMangledName(initDecl) log.info("Mapped initializer '\(initDecl.identifier)' -> '\(initDecl.swiftMangledName)'") @@ -171,7 +171,7 @@ extension Swift2JavaTranslator { /// Default set Java imports for every generated file static let defaultJavaImports: Array = [ // Support library in Java - "org.swift.javakit.SwiftKit", + "org.swift.swiftkit.SwiftKit", // Necessary for native calls and type mapping "java.lang.foreign.*", diff --git a/Sources/JExtractSwift/Swift2JavaVisitor.swift b/Sources/JExtractSwift/Swift2JavaVisitor.swift index c6c9bb56..3c8c252d 100644 --- a/Sources/JExtractSwift/Swift2JavaVisitor.swift +++ b/Sources/JExtractSwift/Swift2JavaVisitor.swift @@ -78,7 +78,7 @@ final class Swift2JavaVisitor: SyntaxVisitor { return .skipChildren } - self.log.info("Import function: \(node.kind) \(node.name)") + self.log.debug("Import function: \(node.kind) \(node.name)") // TODO: this must handle inout and other stuff, strip it off etc let returnTy: TypeSyntax @@ -129,7 +129,7 @@ final class Swift2JavaVisitor: SyntaxVisitor { } if let currentTypeName { - log.info("Record method in \(currentTypeName)") + log.debug("Record method in \(currentTypeName)") translator.importedTypes[currentTypeName]?.methods.append(funcDecl) } else { translator.importedGlobalFuncs.append(funcDecl) diff --git a/Sources/JavaKitExample/JavaKitExample.swift b/Sources/JavaKitExample/JavaKitExample.swift index 7252d648..bcc58114 100644 --- a/Sources/JavaKitExample/JavaKitExample.swift +++ b/Sources/JavaKitExample/JavaKitExample.swift @@ -117,4 +117,4 @@ struct HelloSubclass { @JavaMethod init(greeting: String, environment: JNIEnvironment) -} +} \ No newline at end of file diff --git a/Sources/JavaKitJar/generated/JarFile.swift b/Sources/JavaKitJar/generated/JarFile.swift index bbad9585..aa04c098 100644 --- a/Sources/JavaKitJar/generated/JarFile.swift +++ b/Sources/JavaKitJar/generated/JarFile.swift @@ -28,6 +28,9 @@ public struct JarFile { @JavaMethod public func size() -> Int32 + @JavaMethod + public func toString() -> String + @JavaMethod public func close() throws @@ -37,9 +40,6 @@ public struct JarFile { @JavaMethod public func equals(_ arg0: JavaObject?) -> Bool - @JavaMethod - public func toString() -> String - @JavaMethod public func hashCode() -> Int32 diff --git a/Sources/JavaKitJar/generated/JarInputStream.swift b/Sources/JavaKitJar/generated/JarInputStream.swift index e0987f25..9793a431 100644 --- a/Sources/JavaKitJar/generated/JarInputStream.swift +++ b/Sources/JavaKitJar/generated/JarInputStream.swift @@ -26,10 +26,10 @@ public struct JarInputStream { public func readAllBytes() throws -> [Int8] @JavaMethod - public func readNBytes(_ arg0: [Int8], _ arg1: Int32, _ arg2: Int32) throws -> Int32 + public func readNBytes(_ arg0: Int32) throws -> [Int8] @JavaMethod - public func readNBytes(_ arg0: Int32) throws -> [Int8] + public func readNBytes(_ arg0: [Int8], _ arg1: Int32, _ arg2: Int32) throws -> Int32 @JavaMethod public func skip(_ arg0: Int64) throws -> Int64 diff --git a/Sources/JavaKitExample/SwiftKit.swift b/Sources/SwiftKitSwift/SwiftKit.swift similarity index 100% rename from Sources/JavaKitExample/SwiftKit.swift rename to Sources/SwiftKitSwift/SwiftKit.swift diff --git a/SwiftJavaKitExample/README.md b/SwiftJavaKitExample/README.md deleted file mode 100644 index 97e41df7..00000000 --- a/SwiftJavaKitExample/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# Gradle build for Sources/JavaKitExample - diff --git a/SwiftKit/build.gradle.kts b/SwiftKit/build.gradle similarity index 57% rename from SwiftKit/build.gradle.kts rename to SwiftKit/build.gradle index 3842620b..5a6d15c0 100644 --- a/SwiftKit/build.gradle.kts +++ b/SwiftKit/build.gradle @@ -13,9 +13,27 @@ //===----------------------------------------------------------------------===// plugins { - id("java") + id("build-logic.java-application-conventions") +} + +group = "org.swift.swiftkit" +version = "1.0-SNAPSHOT" + +repositories { + mavenCentral() +} + +java { + toolchain { + languageVersion.set(JavaLanguageVersion.of(22)) + } } dependencies { + testImplementation(platform("org.junit:junit-bom:5.10.0")) + testImplementation("org.junit.jupiter:junit-jupiter") +} +tasks.test { + useJUnitPlatform() } diff --git a/JavaSwiftKitDemo/src/main/java/org/swift/javakit/ManagedSwiftType.java b/SwiftKit/src/main/java/org/swift/swiftkit/ManagedSwiftType.java similarity index 96% rename from JavaSwiftKitDemo/src/main/java/org/swift/javakit/ManagedSwiftType.java rename to SwiftKit/src/main/java/org/swift/swiftkit/ManagedSwiftType.java index 117a0a09..2abaf85a 100644 --- a/JavaSwiftKitDemo/src/main/java/org/swift/javakit/ManagedSwiftType.java +++ b/SwiftKit/src/main/java/org/swift/swiftkit/ManagedSwiftType.java @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -package org.swift.javakit; +package org.swift.swiftkit; import java.lang.foreign.MemorySegment; diff --git a/JavaSwiftKitDemo/src/main/java/org/swift/swiftkit/SwiftArena.java b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftArena.java similarity index 97% rename from JavaSwiftKitDemo/src/main/java/org/swift/swiftkit/SwiftArena.java rename to SwiftKit/src/main/java/org/swift/swiftkit/SwiftArena.java index 2c60dc3f..54c801b4 100644 --- a/JavaSwiftKitDemo/src/main/java/org/swift/swiftkit/SwiftArena.java +++ b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftArena.java @@ -14,8 +14,6 @@ package org.swift.swiftkit; -import org.swift.javakit.SwiftKit; - import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; import java.util.concurrent.ConcurrentSkipListSet; diff --git a/JavaSwiftKitDemo/src/main/java/org/swift/swiftkit/SwiftHeapObject.java b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftHeapObject.java similarity index 100% rename from JavaSwiftKitDemo/src/main/java/org/swift/swiftkit/SwiftHeapObject.java rename to SwiftKit/src/main/java/org/swift/swiftkit/SwiftHeapObject.java diff --git a/JavaSwiftKitDemo/src/main/java/org/swift/javakit/SwiftKit.java b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftKit.java similarity index 81% rename from JavaSwiftKitDemo/src/main/java/org/swift/javakit/SwiftKit.java rename to SwiftKit/src/main/java/org/swift/swiftkit/SwiftKit.java index ba76232b..821169b9 100644 --- a/JavaSwiftKitDemo/src/main/java/org/swift/javakit/SwiftKit.java +++ b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftKit.java @@ -12,9 +12,7 @@ // //===----------------------------------------------------------------------===// -package org.swift.javakit; - -import org.swift.swiftkit.SwiftHeapObject; +package org.swift.swiftkit; import java.lang.foreign.*; import java.lang.foreign.MemoryLayout.PathElement; @@ -22,14 +20,12 @@ import java.util.Arrays; import java.util.stream.Collectors; -import static java.lang.foreign.ValueLayout.ADDRESS; import static java.lang.foreign.ValueLayout.JAVA_BYTE; public class SwiftKit { - // FIXME: why do we need to hardcore the path, seems it can't find by name - private static final String STDLIB_DYLIB_NAME = "swiftCore"; - private static final String STDLIB_DYLIB_PATH = "/usr/lib/swift/libswiftCore.dylib"; + private static final String STDLIB_DYLIB_NAME = "swiftCore"; + private static final String STDLIB_MACOS_DYLIB_PATH = "/usr/lib/swift/libswiftCore.dylib"; private static final Arena LIBRARY_ARENA = Arena.ofAuto(); static final boolean TRACE_DOWNCALLS = Boolean.getBoolean("jextract.trace.downcalls"); @@ -41,16 +37,35 @@ public class SwiftKit { public static final AddressLayout SWIFT_POINTER = ValueLayout.ADDRESS .withTargetLayout(MemoryLayout.sequenceLayout(java.lang.Long.MAX_VALUE, JAVA_BYTE)); - static final SymbolLookup SYMBOL_LOOKUP = - // FIXME: why does this not find just by name? + static final SymbolLookup SYMBOL_LOOKUP = getSymbolLookup(); + + private static SymbolLookup getSymbolLookup() { + if (isMacOS()) { + // FIXME: why does this not find just by name on macOS? // SymbolLookup.libraryLookup(System.mapLibraryName(STDLIB_DYLIB_NAME), LIBRARY_ARENA) - SymbolLookup.libraryLookup(STDLIB_DYLIB_PATH, LIBRARY_ARENA) + return SymbolLookup.libraryLookup(STDLIB_MACOS_DYLIB_PATH, LIBRARY_ARENA) .or(SymbolLookup.loaderLookup()) .or(Linker.nativeLinker().defaultLookup()); - + } else { + return SymbolLookup.loaderLookup() + .or(Linker.nativeLinker().defaultLookup()); + } + } public SwiftKit() { } + public static boolean isLinux() { + return System.getProperty("os.name").toLowerCase().contains("linux"); + } + + public static boolean isMacOS() { + return System.getProperty("os.name").toLowerCase().contains("mac"); + } + + public static boolean isWindows() { + return System.getProperty("os.name").toLowerCase().contains("windows"); + } + static void traceDowncall(String name, Object... args) { String traceArgs = Arrays.stream(args) .map(Object::toString) @@ -69,7 +84,7 @@ static MemorySegment findOrThrow(String symbol) { * Descriptor for the free C runtime function. */ public static final FunctionDescriptor free$descriptor = FunctionDescriptor.ofVoid( - ValueLayout.ADDRESS + ValueLayout.ADDRESS ); /** @@ -187,9 +202,9 @@ public static long release(SwiftHeapObject object) { // ==== ------------------------------------------------------------------------------------------------------------ /** - * {@snippet lang=swift : + * {@snippet lang = swift: * func _typeByName(_: Swift.String) -> Any.Type? - * } + *} */ private static class swift_getTypeByName { public static final FunctionDescriptor DESC = FunctionDescriptor.of( @@ -221,14 +236,14 @@ public static MemorySegment getTypeByName(String string) { } /** - * {@snippet lang=swift : + * {@snippet lang = swift: * func _swift_getTypeByMangledNameInEnvironment( * _ name: UnsafePointer, * _ nameLength: UInt, * genericEnvironment: UnsafeRawPointer?, * genericArguments: UnsafeRawPointer? * ) -> Any.Type? - * } + *} */ private static class swift_getTypeByMangledNameInEnvironment { public static final FunctionDescriptor DESC = FunctionDescriptor.of( @@ -268,7 +283,7 @@ public static MemorySegment getTypeByMangledNameInEnvironment(String string) { * the size of a pointer (aka C's ptrdiff_t). */ public static ValueLayout SWIFT_INT = (ValueLayout.ADDRESS.byteSize() == 4) ? - ValueLayout.JAVA_INT : ValueLayout.JAVA_LONG; + ValueLayout.JAVA_INT : ValueLayout.JAVA_LONG; /** * The value layout for Swift's UInt type, which is an unsigned type that follows @@ -279,7 +294,7 @@ public static MemorySegment getTypeByMangledNameInEnvironment(String string) { /** * Read a Swift.Int value from memory at the given offset and translate it into a Java long. - * + *

* This function copes with the fact that a Swift.Int might be 32 or 64 bits. */ public static final long getSwiftInt(MemorySegment memorySegment, long offset) { @@ -294,50 +309,50 @@ public static final long getSwiftInt(MemorySegment memorySegment, long offset) { * Value witness table layout. */ public static final MemoryLayout valueWitnessTableLayout = MemoryLayout.structLayout( - ValueLayout.ADDRESS.withName("initializeBufferWithCopyOfBuffer"), - ValueLayout.ADDRESS.withName("destroy"), - ValueLayout.ADDRESS.withName("initializeWithCopy"), - ValueLayout.ADDRESS.withName("assignWithCopy"), - ValueLayout.ADDRESS.withName("initializeWithTake"), - ValueLayout.ADDRESS.withName("assignWithTake"), - ValueLayout.ADDRESS.withName("getEnumTagSinglePayload"), - ValueLayout.ADDRESS.withName("storeEnumTagSinglePayload"), - SwiftKit.SWIFT_INT.withName("size"), - SwiftKit.SWIFT_INT.withName("stride"), - SwiftKit.SWIFT_UINT.withName("flags"), - SwiftKit.SWIFT_UINT.withName("extraInhabitantCount") + ValueLayout.ADDRESS.withName("initializeBufferWithCopyOfBuffer"), + ValueLayout.ADDRESS.withName("destroy"), + ValueLayout.ADDRESS.withName("initializeWithCopy"), + ValueLayout.ADDRESS.withName("assignWithCopy"), + ValueLayout.ADDRESS.withName("initializeWithTake"), + ValueLayout.ADDRESS.withName("assignWithTake"), + ValueLayout.ADDRESS.withName("getEnumTagSinglePayload"), + ValueLayout.ADDRESS.withName("storeEnumTagSinglePayload"), + SwiftKit.SWIFT_INT.withName("size"), + SwiftKit.SWIFT_INT.withName("stride"), + SwiftKit.SWIFT_UINT.withName("flags"), + SwiftKit.SWIFT_UINT.withName("extraInhabitantCount") ).withName("SwiftValueWitnessTable"); /** * Offset for the "size" field within the value witness table. */ static final long valueWitnessTable$size$offset = - valueWitnessTableLayout.byteOffset(PathElement.groupElement("size")); + valueWitnessTableLayout.byteOffset(PathElement.groupElement("size")); /** * Offset for the "stride" field within the value witness table. */ static final long valueWitnessTable$stride$offset = - valueWitnessTableLayout.byteOffset(PathElement.groupElement("stride")); + valueWitnessTableLayout.byteOffset(PathElement.groupElement("stride")); /** * Offset for the "flags" field within the value witness table. */ static final long valueWitnessTable$flags$offset = - valueWitnessTableLayout.byteOffset(PathElement.groupElement("flags")); + valueWitnessTableLayout.byteOffset(PathElement.groupElement("flags")); /** * Type metadata pointer. */ public static final StructLayout fullTypeMetadataLayout = MemoryLayout.structLayout( - SWIFT_POINTER.withName("vwt") + SWIFT_POINTER.withName("vwt") ).withName("SwiftFullTypeMetadata"); /** * Offset for the "vwt" field within the full type metadata. */ static final long fullTypeMetadata$vwt$offset = - fullTypeMetadataLayout.byteOffset(PathElement.groupElement("vwt")); + fullTypeMetadataLayout.byteOffset(PathElement.groupElement("vwt")); /** * Given the address of Swift type metadata for a type, return the addres @@ -345,7 +360,7 @@ public static final long getSwiftInt(MemorySegment memorySegment, long offset) { */ public static MemorySegment fullTypeMetadata(MemorySegment typeMetadata) { return MemorySegment.ofAddress(typeMetadata.address() - SWIFT_POINTER.byteSize()) - .reinterpret(fullTypeMetadataLayout.byteSize()); + .reinterpret(fullTypeMetadataLayout.byteSize()); } /** @@ -384,12 +399,12 @@ public static long alignmentOfSwiftType(MemorySegment typeMetadata) { * Descriptor for the swift_getTypeName runtime function. */ public static final FunctionDescriptor swift_getTypeName$descriptor = FunctionDescriptor.of( - /*returns=*/MemoryLayout.structLayout( - SWIFT_POINTER.withName("utf8Chars"), - SWIFT_INT.withName("length") - ), - ValueLayout.ADDRESS, - ValueLayout.JAVA_BOOLEAN + /*returns=*/MemoryLayout.structLayout( + SWIFT_POINTER.withName("utf8Chars"), + SWIFT_INT.withName("length") + ), + ValueLayout.ADDRESS, + ValueLayout.JAVA_BOOLEAN ); /** @@ -404,18 +419,18 @@ public static long alignmentOfSwiftType(MemorySegment typeMetadata) { /** * Produce the name of the Swift type given its Swift type metadata. - * + *

* If 'qualified' is true, leave all of the qualification in place to * disambiguate the type, producing a more complete (but longer) type name. */ public static String nameOfSwiftType(MemorySegment typeMetadata, boolean qualified) { try { try (Arena arena = Arena.ofConfined()) { - MemorySegment charsAndLength = (MemorySegment)swift_getTypeName$handle.invokeExact((SegmentAllocator)arena, typeMetadata, qualified); - MemorySegment utf8Chars = charsAndLength.get(SWIFT_POINTER, 0); - String typeName = utf8Chars.getString(0); - cFree(utf8Chars); - return typeName; + MemorySegment charsAndLength = (MemorySegment) swift_getTypeName$handle.invokeExact((SegmentAllocator) arena, typeMetadata, qualified); + MemorySegment utf8Chars = charsAndLength.get(SWIFT_POINTER, 0); + String typeName = utf8Chars.getString(0); + cFree(utf8Chars); + return typeName; } } catch (Throwable ex$) { throw new AssertionError("should not reach here", ex$); @@ -427,7 +442,7 @@ public static String nameOfSwiftType(MemorySegment typeMetadata, boolean qualifi * type metadata. The resulting layout is completely opaque to Java, but * has appropriate size/alignment to model the memory associated with a * Swift type. - * + *

* In the future, this layout could be extended to provide more detail, * such as the fields of a Swift struct. */ @@ -435,9 +450,9 @@ public static MemoryLayout layoutOfSwiftType(MemorySegment typeMetadata) { long size = sizeOfSwiftType(typeMetadata); long stride = strideOfSwiftType(typeMetadata); return MemoryLayout.structLayout( - MemoryLayout.sequenceLayout(size, JAVA_BYTE) - .withByteAlignment(alignmentOfSwiftType(typeMetadata)), - MemoryLayout.paddingLayout(stride - size) + MemoryLayout.sequenceLayout(size, JAVA_BYTE) + .withByteAlignment(alignmentOfSwiftType(typeMetadata)), + MemoryLayout.paddingLayout(stride - size) ).withName(nameOfSwiftType(typeMetadata, true)); } } diff --git a/Tests/JExtractSwiftTests/FuncImportTests.swift b/Tests/JExtractSwiftTests/FuncImportTests.swift index ed71c14d..c2eb5c27 100644 --- a/Tests/JExtractSwiftTests/FuncImportTests.swift +++ b/Tests/JExtractSwiftTests/FuncImportTests.swift @@ -62,12 +62,13 @@ final class MethodImportTests { } """ - @Test func method_helloWorld() async throws { + @Test + func method_helloWorld() async throws { let st = Swift2JavaTranslator( javaPackage: "com.example.swift", swiftModuleName: "__FakeModule" ) - st.log.logLevel = .trace + st.log.logLevel = .error try await st.analyze(swiftInterfacePath: "/fake/Fake.swiftinterface", text: class_interfaceFile) @@ -101,12 +102,13 @@ final class MethodImportTests { ) } - @Test func method_globalTakeInt() async throws { + @Test + func method_globalTakeInt() async throws { let st = Swift2JavaTranslator( javaPackage: "com.example.swift", swiftModuleName: "__FakeModule" ) - st.log.logLevel = .trace + st.log.logLevel = .error try await st.analyze(swiftInterfacePath: "/fake/__FakeModule/SwiftFile.swiftinterface", text: class_interfaceFile) @@ -142,12 +144,13 @@ final class MethodImportTests { ) } - @Test func method_globalTakeIntLongString() async throws { + @Test + func method_globalTakeIntLongString() async throws { let st = Swift2JavaTranslator( javaPackage: "com.example.swift", swiftModuleName: "__FakeModule" ) - st.log.logLevel = .trace + st.log.logLevel = .error try await st.analyze(swiftInterfacePath: "/fake/__FakeModule/SwiftFile.swiftinterface", text: class_interfaceFile) @@ -183,12 +186,13 @@ final class MethodImportTests { ) } - @Test func method_class_helloMemberFunction_self_memorySegment() async throws { + @Test + func method_class_helloMemberFunction_self_memorySegment() async throws { let st = Swift2JavaTranslator( javaPackage: "com.example.swift", swiftModuleName: "__FakeModule" ) - st.log.logLevel = .trace + st.log.logLevel = .error try await st.analyze(swiftInterfacePath: "/fake/__FakeModule/SwiftFile.swiftinterface", text: class_interfaceFile) @@ -224,12 +228,13 @@ final class MethodImportTests { ) } - @Test func method_class_helloMemberFunction_self_wrapper() async throws { + @Test + func method_class_helloMemberFunction_self_wrapper() async throws { let st = Swift2JavaTranslator( javaPackage: "com.example.swift", swiftModuleName: "__FakeModule" ) - st.log.logLevel = .trace + st.log.logLevel = .error try await st.analyze(swiftInterfacePath: "/fake/__FakeModule/SwiftFile.swiftinterface", text: class_interfaceFile) @@ -265,12 +270,13 @@ final class MethodImportTests { ) } + @Test func test_method_class_helloMemberFunction_self_wrapper() async throws { let st = Swift2JavaTranslator( javaPackage: "com.example.swift", swiftModuleName: "__FakeModule" ) - st.log.logLevel = .trace + st.log.logLevel = .info try await st.analyze(swiftInterfacePath: "/fake/__FakeModule/SwiftFile.swiftinterface", text: class_interfaceFile) @@ -306,12 +312,13 @@ final class MethodImportTests { ) } - @Test func method_class_helloMemberFunction_wrapper() async throws { + @Test + func method_class_helloMemberFunction_wrapper() async throws { let st = Swift2JavaTranslator( javaPackage: "com.example.swift", swiftModuleName: "__FakeModule" ) - st.log.logLevel = .trace + st.log.logLevel = .info try await st.analyze(swiftInterfacePath: "/fake/__FakeModule/SwiftFile.swiftinterface", text: class_interfaceFile) @@ -339,12 +346,13 @@ final class MethodImportTests { ) } - @Test func method_class_makeInt_wrapper() async throws { + @Test + func method_class_makeInt_wrapper() async throws { let st = Swift2JavaTranslator( javaPackage: "com.example.swift", swiftModuleName: "__FakeModule" ) - st.log.logLevel = .trace + st.log.logLevel = .info try await st.analyze(swiftInterfacePath: "/fake/__FakeModule/SwiftFile.swiftinterface", text: class_interfaceFile) @@ -372,12 +380,13 @@ final class MethodImportTests { ) } - @Test func class_constructor() async throws { + @Test + func class_constructor() async throws { let st = Swift2JavaTranslator( javaPackage: "com.example.swift", swiftModuleName: "__FakeModule" ) - st.log.logLevel = .trace + st.log.logLevel = .info try await st.analyze(swiftInterfacePath: "/fake/__FakeModule/SwiftFile.swiftinterface", text: class_interfaceFile) diff --git a/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift b/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift index b6f93eb2..cf175197 100644 --- a/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift +++ b/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift @@ -52,7 +52,7 @@ final class FunctionDescriptorTests { _ methodIdentifier: String, javaPackage: String = "com.example.swift", swiftModuleName: String = "SwiftModule", - logLevel: Logger.Level = .trace, + logLevel: Logger.Level = .warning, body: (String) async throws -> () ) async throws { let st = Swift2JavaTranslator( diff --git a/Tests/JExtractSwiftTests/SwiftDylibTests.swift b/Tests/JExtractSwiftTests/SwiftDylibTests.swift index 2cf8894b..c3a67a07 100644 --- a/Tests/JExtractSwiftTests/SwiftDylibTests.swift +++ b/Tests/JExtractSwiftTests/SwiftDylibTests.swift @@ -23,18 +23,18 @@ final class SwiftDylibTests { @Test #endif func test_nm() async throws { - let dylib = SwiftDylib(path: ".build/arm64-apple-macosx/debug/libJavaKitExample.dylib")! + let dylib = SwiftDylib(path: ".build/arm64-apple-macosx/debug/libExampleSwiftLibrary.dylib")! let names = try await dylib.nmSymbolNames(grepDemangled: ["MySwiftClass", "len"]) #expect( names.contains { - $0.descriptiveName.contains("JavaKitExample.MySwiftClass.len.getter") + $0.descriptiveName.contains("ExampleSwiftLibrary.MySwiftClass.len.getter") } ) let getter = names.findPropertyGetter() - #expect(getter?.mangledName == "$s14JavaKitExample12MySwiftClassC3lenSivg") - #expect(getter?.descriptiveName == "JavaKitExample.MySwiftClass.len.getter : Swift.Int") + #expect(getter?.mangledName == "$s19ExampleSwiftLibrary02MyB5ClassC3lenSivg") + #expect(getter?.descriptiveName == "ExampleSwiftLibrary.MySwiftClass.len.getter : Swift.Int") } } diff --git a/Tests/JavaKitTests/BasicRuntimeTests.swift b/Tests/JavaKitTests/BasicRuntimeTests.swift index 085c907c..6293f271 100644 --- a/Tests/JavaKitTests/BasicRuntimeTests.swift +++ b/Tests/JavaKitTests/BasicRuntimeTests.swift @@ -58,7 +58,7 @@ struct BasicRuntimeTests { } } - @Test("Static methods") + @Test("Static methods", .disabled(if: isMacOS, "Fails on macOS command line")) func staticMethods() throws { let urlConnectionClass = try JavaClass(in: jvm.environment) #expect(urlConnectionClass.getDefaultAllowUserInteraction() == false) diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle new file mode 100644 index 00000000..b965e9bb --- /dev/null +++ b/buildSrc/build.gradle @@ -0,0 +1,3 @@ +repositories { + mavenCentral() +} diff --git a/buildSrc/src/main/groovy/org/swift/swiftkit/gradle/BuildUtils.groovy b/buildSrc/src/main/groovy/org/swift/swiftkit/gradle/BuildUtils.groovy new file mode 100644 index 00000000..ca95a71c --- /dev/null +++ b/buildSrc/src/main/groovy/org/swift/swiftkit/gradle/BuildUtils.groovy @@ -0,0 +1,36 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package org.swift.swiftkit.gradle + +final class BuildUtils { + static def javaLibraryPaths(File rootDir) { + def osName = System.getProperty("os.name") + def osArch = System.getProperty("os.arch") + def isLinux = osName.toLowerCase(Locale.getDefault()).contains("linux") + + return [ + osName.toLowerCase(Locale.getDefault()).contains("linux") ? + "${rootDir}/.build/${osArch}-unknown-linux-gnu/debug/" : + osArch == "aarch64" ? + "${rootDir}/.build/arm64-apple-macosx/debug/" : + "${rootDir}/.build/${osArch}-apple-macosx/debug/", + isLinux ? + "/usr/lib/swift/linux" : + // assume macOS + "/usr/lib/swift/" + ] + } + +} diff --git a/settings.gradle.kts b/settings.gradle similarity index 66% rename from settings.gradle.kts rename to settings.gradle index 04c6b6ed..7ec81ed0 100644 --- a/settings.gradle.kts +++ b/settings.gradle @@ -16,10 +16,14 @@ pluginManagement{ includeBuild("BuildLogic") } -rootProject.name = "SwiftKit" -include( - // The Swift sources we use in our Demo apps, a "Swift library" - // "SwiftJavaKitExample", // TODO: Gradle doesn't seem to understand Swift 6.0 yet, so we can't do this yet +rootProject.name = "swift-java" + +include "SwiftKit" + +// Include sample apps -- you can run them via `gradle Name:run` +new File(rootDir, "Samples").listFiles().each { + if (it.directory && new File(it, 'build.gradle').exists()) { + include ":Samples:${it.name}" + } +} - "JavaSwiftKitDemo", -) From 53b811a0a0464041fa15c9065c802cbbb82e79c8 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Tue, 8 Oct 2024 14:52:17 +0900 Subject: [PATCH 036/426] fix isMacOS detection in BasicRuntimeTests --- Tests/JavaKitTests/BasicRuntimeTests.swift | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Tests/JavaKitTests/BasicRuntimeTests.swift b/Tests/JavaKitTests/BasicRuntimeTests.swift index 6293f271..2e47b84f 100644 --- a/Tests/JavaKitTests/BasicRuntimeTests.swift +++ b/Tests/JavaKitTests/BasicRuntimeTests.swift @@ -85,3 +85,12 @@ var isLinux: Bool { return false #endif } + +/// Whether we're running on MacOS. +var isMacOS: Bool { + #if os(macOS) + return true + #else + return false + #endif +} From 0b1ca0aa777b3f14418f93cfeb2afad54ad1289c Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Tue, 8 Oct 2024 15:58:35 +0900 Subject: [PATCH 037/426] build: fix how we handle x86_64 library paths --- .../build-logic.java-common-conventions.gradle.kts | 13 +++++++++---- buildSrc/README.md | 1 + buildSrc/build.gradle | 14 ++++++++++++++ .../org/swift/swiftkit/gradle/BuildUtils.groovy | 12 ++++++++---- 4 files changed, 32 insertions(+), 8 deletions(-) create mode 100644 buildSrc/README.md diff --git a/BuildLogic/src/main/kotlin/build-logic.java-common-conventions.gradle.kts b/BuildLogic/src/main/kotlin/build-logic.java-common-conventions.gradle.kts index 8789ebfe..e3fc499f 100644 --- a/BuildLogic/src/main/kotlin/build-logic.java-common-conventions.gradle.kts +++ b/BuildLogic/src/main/kotlin/build-logic.java-common-conventions.gradle.kts @@ -43,19 +43,24 @@ tasks.withType(JavaCompile::class).forEach { } +// FIXME: cannot share definition with 'buildSrc' so we duplicated the impl here fun javaLibraryPaths(): List { val osName = System.getProperty("os.name") val osArch = System.getProperty("os.arch") val isLinux = osName.lowercase(Locale.getDefault()).contains("linux") return listOf( - if (osName.lowercase(Locale.getDefault()).contains("linux")) { - """$rootDir/.build/$osArch-unknown-linux-gnu/debug/""" + if (isLinux) { + if (osArch.equals("x86_64") || osArch.equals("amd64")) { + "$rootDir/.build/x86_64-unknown-linux-gnu/debug/" + } else { + "$rootDir/.build/$osArch-unknown-linux-gnu/debug/" + } } else { if (osArch.equals("aarch64")) { - """$rootDir/.build/arm64-apple-macosx/debug/""" + "$rootDir/.build/arm64-apple-macosx/debug/" } else { - """$rootDir/.build/$osArch-apple-macosx/debug/""" + "$rootDir/.build/$osArch-apple-macosx/debug/" } }, if (isLinux) { diff --git a/buildSrc/README.md b/buildSrc/README.md new file mode 100644 index 00000000..f3559b80 --- /dev/null +++ b/buildSrc/README.md @@ -0,0 +1 @@ +buildSrc are shared "build library code" that is available to all sub-projects of the primary build. diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle index b965e9bb..a61e5793 100644 --- a/buildSrc/build.gradle +++ b/buildSrc/build.gradle @@ -1,3 +1,17 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + repositories { mavenCentral() } diff --git a/buildSrc/src/main/groovy/org/swift/swiftkit/gradle/BuildUtils.groovy b/buildSrc/src/main/groovy/org/swift/swiftkit/gradle/BuildUtils.groovy index ca95a71c..3f50890d 100644 --- a/buildSrc/src/main/groovy/org/swift/swiftkit/gradle/BuildUtils.groovy +++ b/buildSrc/src/main/groovy/org/swift/swiftkit/gradle/BuildUtils.groovy @@ -15,17 +15,21 @@ package org.swift.swiftkit.gradle final class BuildUtils { + + /// Find library paths for 'java.library.path' when running or testing projects inside this build. static def javaLibraryPaths(File rootDir) { def osName = System.getProperty("os.name") def osArch = System.getProperty("os.arch") def isLinux = osName.toLowerCase(Locale.getDefault()).contains("linux") return [ - osName.toLowerCase(Locale.getDefault()).contains("linux") ? - "${rootDir}/.build/${osArch}-unknown-linux-gnu/debug/" : - osArch == "aarch64" ? + isLinux ? + /* Linux */(osArch == "amd64" || osArch == "amd64" ? + "${rootDir}/.build/x86_64-unknown-linux-gnu/debug/" : + "${rootDir}/.build/${osArch}-unknown-linux-gnu/debug/") : + /* macOS */(osArch == "aarch64" ? "${rootDir}/.build/arm64-apple-macosx/debug/" : - "${rootDir}/.build/${osArch}-apple-macosx/debug/", + "${rootDir}/.build/${osArch}-apple-macosx/debug/"), isLinux ? "/usr/lib/swift/linux" : // assume macOS From 4a43d27e7d9cf6b42ae4a959a28d8a324872c7ae Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Tue, 8 Oct 2024 16:15:59 +0900 Subject: [PATCH 038/426] Updated sample app instructions Update info how to run the sample apps --- README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index a2facd6a..3161a23b 100644 --- a/README.md +++ b/README.md @@ -56,28 +56,28 @@ docker-compose -f docker/docker-compose.yaml -f docker/docker-compose.2204.main. docker-compose -f docker/docker-compose.yaml -f docker/docker-compose.2204.main.yaml run test ``` -### Examples +### Sample Apps + +Sample apps are located in the `Samples/` directory, and they showcase full "roundtrip" usage of the library and/or tools. #### JavaKit (Swift -> Java) To run a simple app showcasing a Swift process calling into a Java library you can run: ```bash -make run +./gradlew Samples:JavaKitSampleApp:run ``` -Which executes a small Java app (`com.example.swift.HelloSwift`). - #### jextract (Java -> Swift) To run a simple example app showcasing the jextract (Java calling Swift) approach you can: ```bash -make jextract-run -./gradlew run +./gradlew Samples:SwiftKitSampleApp:run ``` -which will run `JavaSwiftKitDemo` sample app. +This will also generate the necessary sources (by invoking jextract, extracting the `Sources/ExampleSwiftLibrary`) +and generating Java sources in `src/generated/java`. ## User Guide From 258ccfff6971b872941ed1510c36fc40682880a8 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Tue, 8 Oct 2024 16:17:54 +0900 Subject: [PATCH 039/426] Prepare accessor function descriptors for properties: get set --- .../ExampleSwiftLibrary/MySwiftLibrary.swift | 2 + Sources/JExtractSwift/ImportedDecls.swift | 159 +++++++++++++++++- .../Swift2JavaTranslator+Printing.swift | 83 ++++++++- Sources/JExtractSwift/Swift2JavaVisitor.swift | 64 +++++-- Sources/JExtractSwift/TranslatedType.swift | 11 ++ .../FunctionDescriptorImportTests.swift | 125 +++++++++++--- 6 files changed, 397 insertions(+), 47 deletions(-) diff --git a/Sources/ExampleSwiftLibrary/MySwiftLibrary.swift b/Sources/ExampleSwiftLibrary/MySwiftLibrary.swift index e5faaad7..4928233e 100644 --- a/Sources/ExampleSwiftLibrary/MySwiftLibrary.swift +++ b/Sources/ExampleSwiftLibrary/MySwiftLibrary.swift @@ -55,6 +55,8 @@ public class MySwiftClass { p("Deinit, self = 0x\(String(addr, radix: 16, uppercase: true))") } + public var counter: Int32 = 0 + public func voidMethod() { p("") } diff --git a/Sources/JExtractSwift/ImportedDecls.swift b/Sources/JExtractSwift/ImportedDecls.swift index c8cdd8fa..84314bc5 100644 --- a/Sources/JExtractSwift/ImportedDecls.swift +++ b/Sources/JExtractSwift/ImportedDecls.swift @@ -16,6 +16,7 @@ import Foundation import JavaTypes import SwiftSyntax +/// Any imported (Swift) declaration protocol ImportedDecl { } @@ -32,6 +33,7 @@ public struct ImportedNominalType: ImportedDecl { public var initializers: [ImportedFunc] = [] public var methods: [ImportedFunc] = [] + public var variables: [ImportedVariable] = [] public init(swiftTypeName: String, javaType: JavaType, swiftMangledName: String? = nil, kind: NominalTypeKind) { self.swiftTypeName = swiftTypeName @@ -195,7 +197,7 @@ public struct ImportedFunc: ImportedDecl, CustomStringConvertible { public var swiftMangledName: String = "" - public var swiftDeclRaw: String? = nil + public var syntax: String? = nil public var isInit: Bool = false @@ -221,7 +223,160 @@ public struct ImportedFunc: ImportedDecl, CustomStringConvertible { Swift mangled name: Imported from: - \(swiftDeclRaw ?? "") + \(syntax?.description ?? "") + } + """ + } +} + +public enum VariableAccessorKind { + case get + case set + + public var renderDescFieldName: String { + switch self { + case .get: "DESC_GET" + case .set: "DESC_SET" + } + } +} + +public struct ImportedVariable: ImportedDecl, CustomStringConvertible { + /// If this function/method is member of a class/struct/protocol, + /// this will contain that declaration's imported name. + /// + /// This is necessary when rendering accessor Java code we need the type that "self" is expecting to have. + public var parentName: TranslatedType? + public var hasParent: Bool { parentName != nil } + + /// This is a full name such as "counter". + public var identifier: String + + /// Which accessors are we able to expose. + /// + /// Usually this will be all the accessors the variable declares, + /// however if the getter is async or throwing we may not be able to import it + /// (yet), and therefore would skip it from the supported set. + public var supportedAccessorKinds: Set = [.get, .set] + + /// This is the base identifier for the function, e.g., "init" for an + /// initializer or "f" for "f(a:b:)". + public var baseIdentifier: String { + guard let idx = identifier.firstIndex(of: "(") else { + return identifier + } + return String(identifier[.. ImportedFunc? { + guard self.supportedAccessorKinds.contains(kind) else { + return nil + } + + switch kind { + case .set: + let newValueParam: FunctionParameterSyntax = "_ newValue: \(self.returnType.cCompatibleSwiftType)" + var funcDecl = ImportedFunc( + parentName: self.parentName, + identifier: self.identifier, + returnType: TranslatedType.void, + parameters: [.init(param: newValueParam, type: self.returnType)]) + funcDecl.swiftMangledName = self.swiftMangledName + "s" // form mangled name of the getter by adding the suffix + return funcDecl + + case .get: + var funcDecl = ImportedFunc( + parentName: self.parentName, + identifier: self.identifier, + returnType: self.returnType, + parameters: []) + funcDecl.swiftMangledName = self.swiftMangledName + "g" // form mangled name of the getter by adding the suffix + return funcDecl + } + } + + public func effectiveAccessorParameters(_ kind: VariableAccessorKind, selfVariant: SelfParameterVariant?) -> [ImportedParam] { + var params: [ImportedParam] = [] + + if kind == .set { + let newValueParam: FunctionParameterSyntax = "_ newValue: \(raw: self.returnType.swiftTypeName)" + params.append( + ImportedParam( + param: newValueParam, + type: self.returnType) + ) + } + + if let parentName { + // Add `self: Self` for method calls on a member + // + // allocating initializer takes a Self.Type instead, but it's also a pointer + switch selfVariant { + case nil, .wrapper: + break + + case .pointer: + let selfParam: FunctionParameterSyntax = "self$: $swift_pointer" + params.append( + ImportedParam( + param: selfParam, + type: parentName + ) + ) + + case .memorySegment: + let selfParam: FunctionParameterSyntax = "self$: $java_lang_foreign_MemorySegment" + var parentForSelf = parentName + parentForSelf.javaType = .javaForeignMemorySegment + params.append( + ImportedParam( + param: selfParam, + type: parentForSelf + ) + ) + } + } + + return params + } + + public var swiftMangledName: String = "" + + public var syntax: VariableDeclSyntax? = nil + + public init( + parentName: TranslatedType?, + identifier: String, + returnType: TranslatedType + ) { + self.parentName = parentName + self.identifier = identifier + self.returnType = returnType + } + + public var description: String { + """ + ImportedFunc { + mangledName: \(swiftMangledName) + identifier: \(identifier) + returnType: \(returnType) + + Swift mangled name: + Imported from: + \(syntax?.description ?? "") } """ } diff --git a/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift b/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift index 35ed6133..14b44e03 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift @@ -437,7 +437,7 @@ extension Swift2JavaTranslator { * Create an instance of {@code \(parentName.unqualifiedJavaTypeName)}. * * {@snippet lang=swift : - * \(decl.swiftDeclRaw ?? "") + * \(decl.syntax ?? "") * } */ public \(parentName.unqualifiedJavaTypeName)(\(renderJavaParamDecls(decl, selfVariant: .wrapper))) { @@ -470,7 +470,7 @@ extension Swift2JavaTranslator { /** * Function descriptor for: * {@snippet lang=swift : - * \(/*TODO: make a printSnippet func*/decl.swiftDeclRaw ?? "") + * \(/*TODO: make a printSnippet func*/decl.syntax ?? "") * } */ public static FunctionDescriptor \(decl.baseIdentifier)$descriptor() { @@ -484,7 +484,7 @@ extension Swift2JavaTranslator { /** * Downcall method handle for: * {@snippet lang=swift : - * \(/*TODO: make a printSnippet func*/decl.swiftDeclRaw ?? "") + * \(/*TODO: make a printSnippet func*/decl.syntax ?? "") * } */ public static MethodHandle \(decl.baseIdentifier)$handle() { @@ -498,7 +498,7 @@ extension Swift2JavaTranslator { /** * Address for: * {@snippet lang=swift : - * \(/*TODO: make a printSnippet func*/decl.swiftDeclRaw ?? "") + * \(/*TODO: make a printSnippet func*/decl.syntax ?? "") * } */ public static MemorySegment \(decl.baseIdentifier)$address() { @@ -557,7 +557,7 @@ extension Swift2JavaTranslator { """ /** * {@snippet lang=swift : - * \(/*TODO: make a printSnippet func*/decl.swiftDeclRaw ?? "") + * \(/*TODO: make a printSnippet func*/decl.syntax ?? "") * } */ public \(returnTy) \(decl.baseIdentifier)(\(renderJavaParamDecls(decl, selfVariant: .wrapper))) { @@ -572,7 +572,60 @@ extension Swift2JavaTranslator { """ /** * {@snippet lang=swift : - * \(/*TODO: make a printSnippet func*/decl.swiftDeclRaw ?? "") + * \(/*TODO: make a printSnippet func*/decl.syntax ?? "") + * } + */ + public static \(returnTy) \(decl.baseIdentifier)(\(renderJavaParamDecls(decl, selfVariant: selfVariant))) { + var mh$ = \(decl.baseIdentifier).HANDLE; + try { + if (TRACE_DOWNCALLS) { + traceDowncall(\(renderForwardParams(decl, selfVariant: .memorySegment))); + } + \(maybeReturnCast) mh$.invokeExact(\(renderForwardParams(decl, selfVariant: selfVariant))); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + """ + ) + } + + public func printPropertyAccessorDowncallMethod( + _ printer: inout CodePrinter, + decl: ImportedFunc, + selfVariant: SelfParameterVariant? + ) { + let returnTy = decl.returnType.javaType + + let maybeReturnCast: String + if decl.returnType.javaType == .void { + maybeReturnCast = "" // nothing to return or cast to + } else { + maybeReturnCast = "return (\(returnTy))" + } + + if selfVariant == SelfParameterVariant.wrapper { + // delegate to the MemorySegment "self" accepting overload + printer.print( + """ + /** + * {@snippet lang=swift : + * \(/*TODO: make a printSnippet func*/decl.syntax ?? "") + * } + */ + public \(returnTy) \(decl.baseIdentifier)(\(renderJavaParamDecls(decl, selfVariant: .wrapper))) { + \(maybeReturnCast) \(decl.baseIdentifier)(\(renderForwardParams(decl, selfVariant: .wrapper))); + } + """ + ) + return + } + + printer.print( + """ + /** + * {@snippet lang=swift : + * \(/*TODO: make a printSnippet func*/decl.syntax ?? "") * } */ public static \(returnTy) \(decl.baseIdentifier)(\(renderJavaParamDecls(decl, selfVariant: selfVariant))) { @@ -656,8 +709,11 @@ extension Swift2JavaTranslator { return ps.joined(separator: ", ") } - public func printFunctionDescriptorValue(_ printer: inout CodePrinter, _ decl: ImportedFunc) { - printer.start("public static final FunctionDescriptor DESC = ") + public func printFunctionDescriptorValue( + _ printer: inout CodePrinter, + _ decl: ImportedFunc, + fieldName: String = "DESC") { + printer.start("public static final FunctionDescriptor \(fieldName) = ") let parameterLayoutDescriptors = javaMemoryLayoutDescriptors( forParametersOf: decl, @@ -692,4 +748,15 @@ extension Swift2JavaTranslator { printer.outdent(); printer.print(");"); } + + public func printPropertyAccessorDescriptorValue( + _ printer: inout CodePrinter, + _ decl: ImportedVariable, + _ kind: VariableAccessorKind) { + guard let funcDecl = decl.accessorFunc(kind: kind) else { + return + } + + printFunctionDescriptorValue(&printer, funcDecl, fieldName: kind.renderDescFieldName) + } } diff --git a/Sources/JExtractSwift/Swift2JavaVisitor.swift b/Sources/JExtractSwift/Swift2JavaVisitor.swift index 3c8c252d..db42c02b 100644 --- a/Sources/JExtractSwift/Swift2JavaVisitor.swift +++ b/Sources/JExtractSwift/Swift2JavaVisitor.swift @@ -80,7 +80,6 @@ final class Swift2JavaVisitor: SyntaxVisitor { self.log.debug("Import function: \(node.kind) \(node.name)") - // TODO: this must handle inout and other stuff, strip it off etc let returnTy: TypeSyntax if let returnClause = node.signature.returnClause { returnTy = returnClause.type @@ -106,14 +105,7 @@ final class Swift2JavaVisitor: SyntaxVisitor { return .skipChildren } - let argumentLabels = node.signature.parameterClause.parameters.map { param in - param.firstName.identifier?.name ?? "_" - } - let argumentLabelsStr = String(argumentLabels.flatMap { label in - label + ":" - }) - - let fullName = "\(node.name.text)(\(argumentLabelsStr))" + let fullName = "\(node.name.text)" var funcDecl = ImportedFunc( parentName: currentTypeName.map { translator.importedTypes[$0] }??.translatedType, @@ -121,7 +113,7 @@ final class Swift2JavaVisitor: SyntaxVisitor { returnType: javaResultType, parameters: params ) - funcDecl.swiftDeclRaw = "\(node.trimmed)" // TODO: rethink this, it's useful for comments in Java + funcDecl.syntax = "\(node.trimmed)" // TODO: rethink this, it's useful for comments in Java // Retrieve the mangled name, if available. if let mangledName = node.mangledNameFromComment { @@ -138,6 +130,56 @@ final class Swift2JavaVisitor: SyntaxVisitor { return .skipChildren } + override func visit(_ node: VariableDeclSyntax) -> SyntaxVisitorContinueKind { + self.log.warning("NODE: \(node.debugDescription)") + + guard let binding = node.bindings.first else { + return .skipChildren + } + + let fullName = "\(binding.pattern.trimmed)" + + // TODO filter out kinds of variables we cannot import + + self.log.info("Import variable: \(node.kind) \(fullName)") + + let returnTy: TypeSyntax + if let typeAnnotation = binding.typeAnnotation{ + returnTy = typeAnnotation.type + } else { + returnTy = "Swift.Void" + } + + let javaResultType: TranslatedType + do { + javaResultType = try cCompatibleType(for: returnTy) + } catch { + self.log.info("Unable to import variable \(node.debugDescription) - \(error)") + return .skipChildren + } + + var varDecl = ImportedVariable( + parentName: currentTypeName.map { translator.importedTypes[$0] }??.translatedType, + identifier: fullName, + returnType: javaResultType + ) + varDecl.syntax = node.trimmed + + // Retrieve the mangled name, if available. + if let mangledName = node.mangledNameFromComment { + varDecl.swiftMangledName = mangledName + } + + if let currentTypeName { + log.info("Record variable in \(currentTypeName)") + translator.importedTypes[currentTypeName]!.variables.append(varDecl) + } else { + fatalError("Global variables are not supported yet: \(node.debugDescription)") + } + + return .skipChildren + } + override func visit(_ node: InitializerDeclSyntax) -> SyntaxVisitorContinueKind { guard let currentTypeName, let currentType = translator.importedTypes[currentTypeName] else { @@ -173,7 +215,7 @@ final class Swift2JavaVisitor: SyntaxVisitor { parameters: params ) funcDecl.isInit = true - funcDecl.swiftDeclRaw = "\(node.trimmed)" // TODO: rethink this, it's useful for comments in Java + funcDecl.syntax = "\(node.trimmed)" // TODO: rethink this, it's useful for comments in Java // Retrieve the mangled name, if available. if let mangledName = node.mangledNameFromComment { diff --git a/Sources/JExtractSwift/TranslatedType.swift b/Sources/JExtractSwift/TranslatedType.swift index c759b3af..367c92cc 100644 --- a/Sources/JExtractSwift/TranslatedType.swift +++ b/Sources/JExtractSwift/TranslatedType.swift @@ -234,6 +234,17 @@ public struct TranslatedType { } } +extension TranslatedType { + public static var void: Self { + TranslatedType( + cCompatibleConvention: .direct, + originalSwiftType: "Void", + cCompatibleSwiftType: "Swift.Void", + cCompatibleJavaMemoryLayout: .primitive(.void), + javaType: JavaType.void) + } +} + /// Describes the C-compatible layout as it should be referenced from Java. enum CCompatibleJavaMemoryLayout { /// A primitive Java type that has a direct counterpart in C. diff --git a/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift b/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift index cf175197..25152c76 100644 --- a/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift +++ b/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift @@ -45,34 +45,13 @@ final class FunctionDescriptorTests { // MANGLED NAME: $s14MySwiftLibrary0aB5ClassC3len3capACSi_SitcfC public init(len: Swift.Int, cap: Swift.Int) @objc deinit - } - """ - - func functionDescriptorTest( - _ methodIdentifier: String, - javaPackage: String = "com.example.swift", - swiftModuleName: String = "SwiftModule", - logLevel: Logger.Level = .warning, - body: (String) async throws -> () - ) async throws { - let st = Swift2JavaTranslator( - javaPackage: javaPackage, - swiftModuleName: swiftModuleName - ) - st.log.logLevel = logLevel - - try await st.analyze(swiftInterfacePath: "/fake/Sample.swiftinterface", text: interfaceFile) - - let funcDecl = st.importedGlobalFuncs.first { - $0.baseIdentifier == methodIdentifier - }! - let output = CodePrinter.toString { printer in - st.printFunctionDescriptorValue(&printer, funcDecl) + // #MySwiftClass.counter!getter: (MySwiftClass) -> () -> Int32 : @$s14MySwiftLibrary0aB5ClassC7counters5Int32Vvg\t// MySwiftClass.counter.getter + // #MySwiftClass.counter!setter: (MySwiftClass) -> (Int32) -> () : @$s14MySwiftLibrary0aB5ClassC7counters5Int32Vvs\t// MySwiftClass.counter.setter + // #MySwiftClass.counter!modify: (MySwiftClass) -> () -> () : @$s14MySwiftLibrary0aB5ClassC7counters5Int32VvM\t// MySwiftClass.counter.modify + var counter: Int32 } - - try await body(output) - } + """ @Test func FunctionDescriptor_globalTakeInt() async throws { @@ -121,4 +100,98 @@ final class FunctionDescriptorTests { } } + @Test + func FunctionDescriptor_class_counter_get() async throws { + try await variableAccessorDescriptorTest("counter", .get) { output in + assertOutput( + output, + expected: + """ + public static final FunctionDescriptor DESC_GET = FunctionDescriptor.of( + /* -> */SWIFT_INT32, + SWIFT_POINTER + ); + """ + ) + } + } + @Test + func FunctionDescriptor_class_counter_set() async throws { + try await variableAccessorDescriptorTest("counter", .set) { output in + assertOutput( + output, + expected: + """ + public static final FunctionDescriptor DESC_SET = FunctionDescriptor.ofVoid( + SWIFT_INT32, + SWIFT_POINTER + ); + """ + ) + } + } + } + +extension FunctionDescriptorTests { + + func functionDescriptorTest( + _ methodIdentifier: String, + javaPackage: String = "com.example.swift", + swiftModuleName: String = "SwiftModule", + logLevel: Logger.Level = .trace, + body: (String) async throws -> () + ) async throws { + let st = Swift2JavaTranslator( + javaPackage: javaPackage, + swiftModuleName: swiftModuleName + ) + st.log.logLevel = logLevel + + try await st.analyze(swiftInterfacePath: "/fake/Sample.swiftinterface", text: interfaceFile) + + let funcDecl = st.importedGlobalFuncs.first { + $0.baseIdentifier == methodIdentifier + }! + + let output = CodePrinter.toString { printer in + st.printFunctionDescriptorValue(&printer, funcDecl) + } + + try await body(output) + } + + func variableAccessorDescriptorTest( + _ methodIdentifier: String, + _ kind: VariableAccessorKind, + javaPackage: String = "com.example.swift", + swiftModuleName: String = "SwiftModule", + logLevel: Logger.Level = .trace, + body: (String) async throws -> () + ) async throws { + let st = Swift2JavaTranslator( + javaPackage: javaPackage, + swiftModuleName: swiftModuleName + ) + st.log.logLevel = logLevel + + try await st.analyze(swiftInterfacePath: "/fake/Sample.swiftinterface", text: interfaceFile) + + let varDecl: ImportedVariable? = + st.importedTypes.values.compactMap { + $0.variables.first { + $0.identifier == methodIdentifier + } + }.first + guard let varDecl else { + fatalError("Cannot find descriptor of: \(methodIdentifier)") as! ImportedVariable + } + + let getOutput = CodePrinter.toString { printer in + st.printPropertyAccessorDescriptorValue(&printer, varDecl, kind) + } + + try await body(getOutput) + } + +} \ No newline at end of file From a8f1cc996f713f941a2e6e58e1784bc1f617ace3 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Tue, 8 Oct 2024 17:48:00 +0900 Subject: [PATCH 040/426] Printing for handles, descriptors and address methods for props --- Package.swift | 4 +- .../ImportedDecls+Printing.swift | 65 +++++++++ Sources/JExtractSwift/ImportedDecls.swift | 10 +- .../Swift2JavaTranslator+Printing.swift | 94 ++++++++++--- .../Asserts/TextAssertions.swift | 19 ++- .../FunctionDescriptorImportTests.swift | 2 +- .../VariableImportTests.swift | 123 ++++++++++++++++++ 7 files changed, 280 insertions(+), 37 deletions(-) create mode 100644 Sources/JExtractSwift/ImportedDecls+Printing.swift create mode 100644 Tests/JExtractSwiftTests/VariableImportTests.swift diff --git a/Package.swift b/Package.swift index df96b8f4..4ec487b7 100644 --- a/Package.swift +++ b/Package.swift @@ -122,7 +122,8 @@ let package = Package( dependencies: [ .package(url: "https://github.com/swiftlang/swift-syntax.git", branch: "main"), .package(url: "https://github.com/apple/swift-argument-parser", from: "1.5.0"), - .package(url: "https://github.com/apple/swift-system", from: "1.0.0"), + .package(url: "https://github.com/apple/swift-system", from: "1.0.0"), // TODO: remove, we should not need 'nm' or process callouts + .package(url: "https://github.com/apple/swift-collections.git", .upToNextMinor(from: "1.1.0")), ], targets: [ .macro( @@ -282,6 +283,7 @@ let package = Package( .product(name: "SwiftSyntax", package: "swift-syntax"), .product(name: "SwiftSyntaxBuilder", package: "swift-syntax"), .product(name: "ArgumentParser", package: "swift-argument-parser"), + .product(name: "Collections", package: "swift-collections"), "_Subprocess", "JavaTypes", ], diff --git a/Sources/JExtractSwift/ImportedDecls+Printing.swift b/Sources/JExtractSwift/ImportedDecls+Printing.swift new file mode 100644 index 00000000..8eaa4f66 --- /dev/null +++ b/Sources/JExtractSwift/ImportedDecls+Printing.swift @@ -0,0 +1,65 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import Foundation +import JavaTypes +import SwiftSyntax +import OrderedCollections + +extension ImportedFunc { + /// Render a `@{@snippet ... }` comment section that can be put inside a JavaDoc comment + /// when referring to the original declaration a printed method refers to. + var renderCommentSnippet: String? { + if let syntax { + """ + * {@snippet lang=swift : + * \(syntax) + * } + """ + } else { + nil + } + } +} + +extension VariableAccessorKind { + public var renderDescFieldName: String { + switch self { + case .get: "DESC_GET" + case .set: "DESC_SET" + } + } + + public var renderAddrFieldName: String { + switch self { + case .get: "ADDR_GET" + case .set: "ADDR_SET" + } + } + + public var renderHandleFieldName: String { + switch self { + case .get: "HANDLE_GET" + case .set: "HANDLE_SET" + } + } + + /// Renders a "$get" part that can be used in a method signature representing this accessor. + public var renderMethodNameSegment: String { + switch self { + case .get: "$get" + case .set: "$set" + } + } +} \ No newline at end of file diff --git a/Sources/JExtractSwift/ImportedDecls.swift b/Sources/JExtractSwift/ImportedDecls.swift index 84314bc5..d89ed77d 100644 --- a/Sources/JExtractSwift/ImportedDecls.swift +++ b/Sources/JExtractSwift/ImportedDecls.swift @@ -15,6 +15,7 @@ import Foundation import JavaTypes import SwiftSyntax +import OrderedCollections /// Any imported (Swift) declaration protocol ImportedDecl { @@ -232,13 +233,6 @@ public struct ImportedFunc: ImportedDecl, CustomStringConvertible { public enum VariableAccessorKind { case get case set - - public var renderDescFieldName: String { - switch self { - case .get: "DESC_GET" - case .set: "DESC_SET" - } - } } public struct ImportedVariable: ImportedDecl, CustomStringConvertible { @@ -257,7 +251,7 @@ public struct ImportedVariable: ImportedDecl, CustomStringConvertible { /// Usually this will be all the accessors the variable declares, /// however if the getter is async or throwing we may not be able to import it /// (yet), and therefore would skip it from the supported set. - public var supportedAccessorKinds: Set = [.get, .set] + public var supportedAccessorKinds: OrderedSet = [.get, .set] /// This is the base identifier for the function, e.g., "init" for an /// initializer or "f" for "f(a:b:)". diff --git a/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift b/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift index 14b44e03..54897e5a 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift @@ -465,54 +465,108 @@ extension Swift2JavaTranslator { printMethodDowncallHandleForAddrDesc(&printer) } + printFunctionDescriptorMethod(&printer, decl: decl) + printFunctionMethodHandleMethod(&printer, decl: decl) + printFunctionAddressMethod(&printer, decl: decl) + + // Render the basic "make the downcall" function + if decl.hasParent { + printFuncDowncallMethod(&printer, decl: decl, selfVariant: .memorySegment) + printFuncDowncallMethod(&printer, decl: decl, selfVariant: .wrapper) + } else { + printFuncDowncallMethod(&printer, decl: decl, selfVariant: nil) + } + } + + private func printFunctionAddressMethod(_ printer: inout CodePrinter, + decl: ImportedFunc, + accessorKind: VariableAccessorKind? = nil) { + + let addrName = accessorKind?.renderAddrFieldName ?? "ADDR" + let methodNameSegment = accessorKind?.renderMethodNameSegment ?? "" + let snippet = decl.renderCommentSnippet ?? "* " + printer.print( """ /** - * Function descriptor for: - * {@snippet lang=swift : - * \(/*TODO: make a printSnippet func*/decl.syntax ?? "") - * } + * Address for: + \(snippet) */ - public static FunctionDescriptor \(decl.baseIdentifier)$descriptor() { - return \(decl.baseIdentifier).DESC; + public static MemorySegment \(decl.baseIdentifier)\(methodNameSegment)$address() { + return \(decl.baseIdentifier).\(addrName); } """ ) + } + + private func printFunctionMethodHandleMethod(_ printer: inout CodePrinter, + decl: ImportedFunc, + accessorKind: VariableAccessorKind? = nil) { + let handleName = accessorKind?.renderHandleFieldName ?? "HANDLE" + let methodNameSegment = accessorKind?.renderMethodNameSegment ?? "" + let snippet = decl.renderCommentSnippet ?? "* " printer.print( """ /** * Downcall method handle for: - * {@snippet lang=swift : - * \(/*TODO: make a printSnippet func*/decl.syntax ?? "") - * } + \(snippet) */ - public static MethodHandle \(decl.baseIdentifier)$handle() { - return \(decl.baseIdentifier).HANDLE; + public static MethodHandle \(decl.baseIdentifier)\(methodNameSegment)$handle() { + return \(decl.baseIdentifier).\(handleName); } """ ) + } + + private func printFunctionDescriptorMethod(_ printer: inout CodePrinter, + decl: ImportedFunc, + accessorKind: VariableAccessorKind? = nil) { + let descName = accessorKind?.renderDescFieldName ?? "DESC" + let methodNameSegment = accessorKind?.renderMethodNameSegment ?? "" + let snippet = decl.renderCommentSnippet ?? "* " printer.print( """ /** - * Address for: - * {@snippet lang=swift : - * \(/*TODO: make a printSnippet func*/decl.syntax ?? "") - * } + * Function descriptor for: + \(snippet) */ - public static MemorySegment \(decl.baseIdentifier)$address() { - return \(decl.baseIdentifier).ADDR; + public static FunctionDescriptor \(decl.baseIdentifier)\(methodNameSegment)$descriptor() { + return \(decl.baseIdentifier).\(descName); } """ ) + } + + public func printVariableDowncallMethods(_ printer: inout CodePrinter, _ decl: ImportedVariable) { + printer.printSeparator(decl.identifier) + + printer.printTypeDecl("private static class \(decl.baseIdentifier)") { printer in + for accessorKind in decl.supportedAccessorKinds { + printPropertyAccessorDescriptorValue(&printer, decl, accessorKind) +// printFunctionDescriptorValue(&printer, decl); +// printFindMemorySegmentAddrByMangledName(&printer, decl) +// printMethodDowncallHandleForAddrDesc(&printer) + } + } + + for accessorKind in decl.supportedAccessorKinds { + guard let accessor = decl.accessorFunc(kind: accessorKind) else { + log.warning("Skip print for \(accessorKind) of \(decl.identifier)!") + continue + } + printFunctionDescriptorMethod(&printer, decl: accessor, accessorKind: accessorKind) + printFunctionMethodHandleMethod(&printer, decl: accessor, accessorKind: accessorKind) + printFunctionAddressMethod(&printer, decl: accessor, accessorKind: accessorKind) + } // Render the basic "make the downcall" function if decl.hasParent { - printFuncDowncallMethod(&printer, decl: decl, selfVariant: .memorySegment) - printFuncDowncallMethod(&printer, decl: decl, selfVariant: .wrapper) +// printFuncDowncallMethod(&printer, decl: decl, selfVariant: .memorySegment) +// printFuncDowncallMethod(&printer, decl: decl, selfVariant: .wrapper) } else { - printFuncDowncallMethod(&printer, decl: decl, selfVariant: nil) +// printFuncDowncallMethod(&printer, decl: decl, selfVariant: nil) } } diff --git a/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift b/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift index 8017822f..84c4b2ec 100644 --- a/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift +++ b/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift @@ -17,6 +17,7 @@ import Testing import struct Foundation.CharacterSet func assertOutput( + dump: Bool = false, _ got: String, expected: String, fileID: String = #fileID, @@ -38,7 +39,7 @@ func assertOutput( let ge = g.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines) let ee = e.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines) - if ge != ee { + if ge.commonPrefix(with: ee) != ee { // print("") // print("[\(file):\(line)] " + "Difference found on line: \(no + 1)!".red) // print("Expected @ \(file):\(Int(line) + no + 3 /*formatting*/ + 1):") @@ -55,15 +56,19 @@ func assertOutput( } - if diffLineNumbers.count > 0 { + let hasDiff = diffLineNumbers.count > 0 + if hasDiff || dump{ print("") - print("error: Number of not matching lines: \(diffLineNumbers.count)!".red) + if hasDiff { + print("error: Number of not matching lines: \(diffLineNumbers.count)!".red) - print("==== ---------------------------------------------------------------") - print("Expected output:") - for (n, e) in expectedLines.enumerated() { - print("\(e)".yellow(if: diffLineNumbers.contains(n))) + print("==== ---------------------------------------------------------------") + print("Expected output:") + for (n, e) in expectedLines.enumerated() { + print("\(e)".yellow(if: diffLineNumbers.contains(n))) + } } + print("==== ---------------------------------------------------------------") print("Got output:") for (n, g) in gotLines.enumerated() { diff --git a/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift b/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift index 25152c76..f52757a4 100644 --- a/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift +++ b/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift @@ -184,7 +184,7 @@ extension FunctionDescriptorTests { } }.first guard let varDecl else { - fatalError("Cannot find descriptor of: \(methodIdentifier)") as! ImportedVariable + fatalError("Cannot find descriptor of: \(methodIdentifier)") } let getOutput = CodePrinter.toString { printer in diff --git a/Tests/JExtractSwiftTests/VariableImportTests.swift b/Tests/JExtractSwiftTests/VariableImportTests.swift new file mode 100644 index 00000000..5674780e --- /dev/null +++ b/Tests/JExtractSwiftTests/VariableImportTests.swift @@ -0,0 +1,123 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import JExtractSwift +import Testing + +final class VariableImportTests { + let class_interfaceFile = + """ + // swift-interface-format-version: 1.0 + // swift-compiler-version: Apple Swift version 6.0 effective-5.10 (swiftlang-6.0.0.7.6 clang-1600.0.24.1) + // swift-module-flags: -target arm64-apple-macosx15.0 -enable-objc-interop -enable-library-evolution -module-name MySwiftLibrary + import Darwin.C + import Darwin + import Swift + import _Concurrency + import _StringProcessing + import _SwiftConcurrencyShims + + public class MySwiftClass { + public var counterInt: Int + } + """ + + @Test("Import: var counter: Int") + func variable_() async throws { + let st = Swift2JavaTranslator( + javaPackage: "com.example.swift", + swiftModuleName: "__FakeModule" + ) + st.log.logLevel = .error + + try await st.analyze(swiftInterfacePath: "/fake/Fake.swiftinterface", text: class_interfaceFile) + + let identifier = "counterInt" + let varDecl: ImportedVariable? = + st.importedTypes.values.compactMap { + $0.variables.first { + $0.identifier == identifier + } + }.first + guard let varDecl else { + fatalError("Cannot find: \(identifier)") + } + + let output = CodePrinter.toString { printer in + st.printVariableDowncallMethods(&printer, varDecl) + } + + assertOutput( + dump: true, + output, + expected: + """ + // ==== -------------------------------------------------- + // counterInt + private static class counterInt { + public static final FunctionDescriptor DESC_GET = FunctionDescriptor.of( + /* -> */SWIFT_INT, + SWIFT_POINTER + ); + public static final FunctionDescriptor DESC_SET = FunctionDescriptor.ofVoid( + SWIFT_INT, + SWIFT_POINTER + ); + } + /** + * Function descriptor for: + * + */ + public static FunctionDescriptor counterInt$get$descriptor() { + return counterInt.DESC_GET; + } + /** + * Downcall method handle for: + * + */ + public static MethodHandle counterInt$get$handle() { + return counterInt.HANDLE_GET; + } + /** + * Address for: + * + */ + public static MemorySegment counterInt$get$address() { + return counterInt.ADDR_GET; + } + /** + * Function descriptor for: + * + */ + public static FunctionDescriptor counterInt$set$descriptor() { + return counterInt.DESC_SET; + } + /** + * Downcall method handle for: + * + */ + public static MethodHandle counterInt$set$handle() { + return counterInt.HANDLE_SET; + } + /** + * Address for: + * + */ + public static MemorySegment counterInt$set$address() { + return counterInt.ADDR_SET; + } + """ + ) + } +} \ No newline at end of file From aa2d0179cf27fe305bc04a3d093c7c8f3dde9d82 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Tue, 8 Oct 2024 19:02:20 +0900 Subject: [PATCH 041/426] getter and setter generated for stored property --- .../Convenience/String+Extensions.swift | 25 ++++++++ .../ImportedDecls+Printing.swift | 29 +++++++++ .../Swift2JavaTranslator+Printing.swift | 63 ++++++++++++------- .../JExtractSwiftTests/FuncImportTests.swift | 10 +-- .../VariableImportTests.swift | 44 +++++++++++++ 5 files changed, 142 insertions(+), 29 deletions(-) create mode 100644 Sources/JExtractSwift/Convenience/String+Extensions.swift diff --git a/Sources/JExtractSwift/Convenience/String+Extensions.swift b/Sources/JExtractSwift/Convenience/String+Extensions.swift new file mode 100644 index 00000000..53781cef --- /dev/null +++ b/Sources/JExtractSwift/Convenience/String+Extensions.swift @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +extension String { + + // TODO: naive implementation good enough for our simple case `methodMethodSomething` -> `MethodSomething` + var toCamelCase: String { + guard let f = first else { + return self + } + + return "\(f.uppercased())\(String(dropFirst()))" + } +} \ No newline at end of file diff --git a/Sources/JExtractSwift/ImportedDecls+Printing.swift b/Sources/JExtractSwift/ImportedDecls+Printing.swift index 8eaa4f66..84f718e0 100644 --- a/Sources/JExtractSwift/ImportedDecls+Printing.swift +++ b/Sources/JExtractSwift/ImportedDecls+Printing.swift @@ -62,4 +62,33 @@ extension VariableAccessorKind { case .set: "$set" } } + + func renderMethodName(_ decl: ImportedFunc) -> String? { + switch self { + case .get: "get\(decl.identifier.toCamelCase)" + case .set: "set\(decl.identifier.toCamelCase)" + } + } +} + +extension Optional where Wrapped == VariableAccessorKind { + public var renderDescFieldName: String { + self?.renderDescFieldName ?? "DESC" + } + + public var renderAddrFieldName: String { + self?.renderAddrFieldName ?? "ADDR" + } + + public var renderHandleFieldName: String { + self?.renderHandleFieldName ?? "HANDLE" + } + + public var renderMethodNameSegment: String { + self?.renderMethodNameSegment ?? "" + } + + func renderMethodName(_ decl: ImportedFunc) -> String { + self?.renderMethodName(decl) ?? decl.baseIdentifier + } } \ No newline at end of file diff --git a/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift b/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift index 54897e5a..3f021d07 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift @@ -102,7 +102,7 @@ extension Swift2JavaTranslator { printModuleClass(&printer) { printer in // TODO: print all "static" methods for decl in importedGlobalFuncs { - printDowncallMethods(&printer, decl) + printFunctionDowncallMethods(&printer, decl) } } } @@ -133,7 +133,7 @@ extension Swift2JavaTranslator { // Methods for funcDecl in decl.methods { - printDowncallMethods(&printer, funcDecl) + printFunctionDowncallMethods(&printer, funcDecl) } } } @@ -456,7 +456,7 @@ extension Swift2JavaTranslator { ) } - public func printDowncallMethods(_ printer: inout CodePrinter, _ decl: ImportedFunc) { + public func printFunctionDowncallMethods(_ printer: inout CodePrinter, _ decl: ImportedFunc) { printer.printSeparator(decl.identifier) printer.printTypeDecl("private static class \(decl.baseIdentifier)") { printer in @@ -551,6 +551,7 @@ extension Swift2JavaTranslator { } } + // First print all the supporting infra for accessorKind in decl.supportedAccessorKinds { guard let accessor = decl.accessorFunc(kind: accessorKind) else { log.warning("Skip print for \(accessorKind) of \(decl.identifier)!") @@ -561,12 +562,20 @@ extension Swift2JavaTranslator { printFunctionAddressMethod(&printer, decl: accessor, accessorKind: accessorKind) } - // Render the basic "make the downcall" function - if decl.hasParent { -// printFuncDowncallMethod(&printer, decl: decl, selfVariant: .memorySegment) -// printFuncDowncallMethod(&printer, decl: decl, selfVariant: .wrapper) - } else { -// printFuncDowncallMethod(&printer, decl: decl, selfVariant: nil) + // Then print the actual downcall methods + for accessorKind in decl.supportedAccessorKinds { + guard let accessor = decl.accessorFunc(kind: accessorKind) else { + log.warning("Skip print for \(accessorKind) of \(decl.identifier)!") + continue + } + + // Render the basic "make the downcall" function + if decl.hasParent { + printFuncDowncallMethod(&printer, decl: accessor, selfVariant: .memorySegment, accessorKind: accessorKind) + printFuncDowncallMethod(&printer, decl: accessor, selfVariant: .wrapper, accessorKind: accessorKind) + } else { + printFuncDowncallMethod(&printer, decl: accessor, selfVariant: nil, accessorKind: accessorKind) + } } } @@ -594,7 +603,8 @@ extension Swift2JavaTranslator { public func printFuncDowncallMethod( _ printer: inout CodePrinter, decl: ImportedFunc, - selfVariant: SelfParameterVariant? + selfVariant: SelfParameterVariant?, + accessorKind: VariableAccessorKind? = nil ) { let returnTy = decl.returnType.javaType @@ -605,32 +615,37 @@ extension Swift2JavaTranslator { maybeReturnCast = "return (\(returnTy))" } + // TODO: we could copy the Swift method's documentation over here, that'd be great UX + let javaDocComment: String = + """ + /** + * Downcall to Swift: + \(decl.renderCommentSnippet ?? "* ") + */ + """ + + // An identifier may be "getX", "setX" or just the plain method name + let identifier = accessorKind.renderMethodName(decl) + if selfVariant == SelfParameterVariant.wrapper { // delegate to the MemorySegment "self" accepting overload printer.print( """ - /** - * {@snippet lang=swift : - * \(/*TODO: make a printSnippet func*/decl.syntax ?? "") - * } - */ - public \(returnTy) \(decl.baseIdentifier)(\(renderJavaParamDecls(decl, selfVariant: .wrapper))) { - \(maybeReturnCast) \(decl.baseIdentifier)(\(renderForwardParams(decl, selfVariant: .wrapper))); + \(javaDocComment) + public \(returnTy) \(identifier)(\(renderJavaParamDecls(decl, selfVariant: .wrapper))) { + \(maybeReturnCast) \(identifier)(\(renderForwardParams(decl, selfVariant: .wrapper))); } """ ) return } + let handleName = accessorKind.renderHandleFieldName printer.print( """ - /** - * {@snippet lang=swift : - * \(/*TODO: make a printSnippet func*/decl.syntax ?? "") - * } - */ - public static \(returnTy) \(decl.baseIdentifier)(\(renderJavaParamDecls(decl, selfVariant: selfVariant))) { - var mh$ = \(decl.baseIdentifier).HANDLE; + \(javaDocComment) + public static \(returnTy) \(identifier)(\(renderJavaParamDecls(decl, selfVariant: selfVariant))) { + var mh$ = \(decl.baseIdentifier).\(handleName); try { if (TRACE_DOWNCALLS) { traceDowncall(\(renderForwardParams(decl, selfVariant: .memorySegment))); diff --git a/Tests/JExtractSwiftTests/FuncImportTests.swift b/Tests/JExtractSwiftTests/FuncImportTests.swift index c2eb5c27..0a2cd1b6 100644 --- a/Tests/JExtractSwiftTests/FuncImportTests.swift +++ b/Tests/JExtractSwiftTests/FuncImportTests.swift @@ -62,7 +62,7 @@ final class MethodImportTests { } """ - @Test + @Test("Import: public func helloWorld()") func method_helloWorld() async throws { let st = Swift2JavaTranslator( javaPackage: "com.example.swift", @@ -102,8 +102,8 @@ final class MethodImportTests { ) } - @Test - func method_globalTakeInt() async throws { + @Test("Import: public func globalTakeInt(i: Int)") + func func_globalTakeInt() async throws { let st = Swift2JavaTranslator( javaPackage: "com.example.swift", swiftModuleName: "__FakeModule" @@ -144,8 +144,8 @@ final class MethodImportTests { ) } - @Test - func method_globalTakeIntLongString() async throws { + @Test("Import: public func globalTakeIntLongString(i32: Int32, l: Int64, s: String)") + func func_globalTakeIntLongString() async throws { let st = Swift2JavaTranslator( javaPackage: "com.example.swift", swiftModuleName: "__FakeModule" diff --git a/Tests/JExtractSwiftTests/VariableImportTests.swift b/Tests/JExtractSwiftTests/VariableImportTests.swift index 5674780e..2305d4ec 100644 --- a/Tests/JExtractSwiftTests/VariableImportTests.swift +++ b/Tests/JExtractSwiftTests/VariableImportTests.swift @@ -117,6 +117,50 @@ final class VariableImportTests { public static MemorySegment counterInt$set$address() { return counterInt.ADDR_SET; } + /** + * Downcall to Swift: + * + */ + public static long getCounterInt(java.lang.foreign.MemorySegment self$) { + var mh$ = counterInt.HANDLE_GET; + try { + if (TRACE_DOWNCALLS) { + traceDowncall(self$); + } + return (long) mh$.invokeExact(self$); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + /** + * Downcall to Swift: + * + */ + public long getCounterInt() { + return (long) getCounterInt($memorySegment()); + } + /** + * Downcall to Swift: + * + */ + public static void setCounterInt(long newValue, java.lang.foreign.MemorySegment self$) { + var mh$ = counterInt.HANDLE_SET; + try { + if (TRACE_DOWNCALLS) { + traceDowncall(newValue, self$); + } + mh$.invokeExact(newValue, self$); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + /** + * Downcall to Swift: + * + */ + public void setCounterInt(long newValue) { + setCounterInt(newValue, $memorySegment()); + } """ ) } From 5986b3005ae877f6af26b6b08f8b9245cefd4185 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Tue, 8 Oct 2024 22:48:14 +0900 Subject: [PATCH 042/426] jextract: end to end run for a property import --- Samples/SwiftKitSampleApp/build.gradle | 6 +- .../swift/generated/MySwiftClassTest.java | 21 ++++++- .../ImportedDecls+Printing.swift | 8 +++ .../Swift2JavaTranslator+Printing.swift | 55 ++++++++----------- Sources/JExtractSwift/Swift2JavaVisitor.swift | 4 +- .../JExtractSwiftTests/FuncImportTests.swift | 8 +++ .../FunctionDescriptorImportTests.swift | 10 ++-- .../VariableImportTests.swift | 10 +++- 8 files changed, 78 insertions(+), 44 deletions(-) diff --git a/Samples/SwiftKitSampleApp/build.gradle b/Samples/SwiftKitSampleApp/build.gradle index 158fdfcf..28304626 100644 --- a/Samples/SwiftKitSampleApp/build.gradle +++ b/Samples/SwiftKitSampleApp/build.gradle @@ -95,7 +95,11 @@ application { task jextract(type: Exec) { description = "Extracts Java accessor sources using jextract" outputs.dir(layout.buildDirectory.dir("generated")) - inputs.dir("$rootDir/Sources/ExampleSwiftLibrary") + inputs.dir("$rootDir/Sources/ExampleSwiftLibrary") // monitored library + + // any changes in the source generator sources also mean the resulting output might change + inputs.dir("$rootDir/Sources/JExtractSwift") + inputs.dir("$rootDir/Sources/JExtractSwiftTool") workingDir = rootDir commandLine "make" diff --git a/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/generated/MySwiftClassTest.java b/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/generated/MySwiftClassTest.java index 1a5f0d5a..740e711b 100644 --- a/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/generated/MySwiftClassTest.java +++ b/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/generated/MySwiftClassTest.java @@ -15,6 +15,7 @@ package com.example.swift.generated; import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -31,6 +32,24 @@ static void beforeAll() { System.setProperty("jextract.trace.downcalls", "true"); } - // TODO: test member methods on MySwiftClass + @Test + void test_MySwiftClass_voidMethod() { + MySwiftClass o = new MySwiftClass(12, 42); + o.voidMethod(); + } + + @Test + void test_MySwiftClass_makeIntMethod() { + MySwiftClass o = new MySwiftClass(12, 42); + var got = o.makeIntMethod(); + assertEquals(12, got); + } + + @Test + void test_MySwiftClass_property_len() { + MySwiftClass o = new MySwiftClass(12, 42); + var got = o.makeIntMethod(); + assertEquals(12, got); + } } diff --git a/Sources/JExtractSwift/ImportedDecls+Printing.swift b/Sources/JExtractSwift/ImportedDecls+Printing.swift index 84f718e0..76422d09 100644 --- a/Sources/JExtractSwift/ImportedDecls+Printing.swift +++ b/Sources/JExtractSwift/ImportedDecls+Printing.swift @@ -34,6 +34,14 @@ extension ImportedFunc { } extension VariableAccessorKind { + + public var fieldSuffix: String { + switch self { + case .get: "_GET" + case .set: "_SET" + } + } + public var renderDescFieldName: String { switch self { case .get: "DESC_GET" diff --git a/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift b/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift index 3f021d07..db35a1c4 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift @@ -129,7 +129,9 @@ extension Swift2JavaTranslator { } // Properties - // TODO: property accessors + for varDecl in decl.variables { + printVariableDowncallMethods(&printer, varDecl) + } // Methods for funcDecl in decl.methods { @@ -482,8 +484,8 @@ extension Swift2JavaTranslator { decl: ImportedFunc, accessorKind: VariableAccessorKind? = nil) { - let addrName = accessorKind?.renderAddrFieldName ?? "ADDR" - let methodNameSegment = accessorKind?.renderMethodNameSegment ?? "" + let addrName = accessorKind.renderAddrFieldName + let methodNameSegment = accessorKind.renderMethodNameSegment let snippet = decl.renderCommentSnippet ?? "* " printer.print( @@ -502,8 +504,8 @@ extension Swift2JavaTranslator { private func printFunctionMethodHandleMethod(_ printer: inout CodePrinter, decl: ImportedFunc, accessorKind: VariableAccessorKind? = nil) { - let handleName = accessorKind?.renderHandleFieldName ?? "HANDLE" - let methodNameSegment = accessorKind?.renderMethodNameSegment ?? "" + let handleName = accessorKind.renderHandleFieldName + let methodNameSegment = accessorKind.renderMethodNameSegment let snippet = decl.renderCommentSnippet ?? "* " printer.print( @@ -522,8 +524,8 @@ extension Swift2JavaTranslator { private func printFunctionDescriptorMethod(_ printer: inout CodePrinter, decl: ImportedFunc, accessorKind: VariableAccessorKind? = nil) { - let descName = accessorKind?.renderDescFieldName ?? "DESC" - let methodNameSegment = accessorKind?.renderMethodNameSegment ?? "" + let descName = accessorKind.renderDescFieldName + let methodNameSegment = accessorKind.renderMethodNameSegment let snippet = decl.renderCommentSnippet ?? "* " printer.print( @@ -544,10 +546,14 @@ extension Swift2JavaTranslator { printer.printTypeDecl("private static class \(decl.baseIdentifier)") { printer in for accessorKind in decl.supportedAccessorKinds { - printPropertyAccessorDescriptorValue(&printer, decl, accessorKind) -// printFunctionDescriptorValue(&printer, decl); -// printFindMemorySegmentAddrByMangledName(&printer, decl) -// printMethodDowncallHandleForAddrDesc(&printer) + guard let accessor = decl.accessorFunc(kind: accessorKind) else { + log.warning("Skip print for \(accessorKind) of \(decl.identifier)!") + continue + } + + printFunctionDescriptorValue(&printer, accessor, accessorKind: accessorKind); + printFindMemorySegmentAddrByMangledName(&printer, accessor, accessorKind: accessorKind) + printMethodDowncallHandleForAddrDesc(&printer, accessorKind: accessorKind) } } @@ -579,23 +585,19 @@ extension Swift2JavaTranslator { } } - func printFindMemorySegmentAddrByMangledName(_ printer: inout CodePrinter, _ decl: ImportedFunc) { + func printFindMemorySegmentAddrByMangledName(_ printer: inout CodePrinter, _ decl: ImportedFunc, + accessorKind: VariableAccessorKind? = nil) { printer.print( """ - /** - * {@snippet lang = Swift: - * \(decl.displayName) - * } - */ - public static final MemorySegment ADDR = \(swiftModuleName).findOrThrow("\(decl.swiftMangledName)"); + public static final MemorySegment \(accessorKind.renderAddrFieldName) = \(swiftModuleName).findOrThrow("\(decl.swiftMangledName)"); """ ); } - func printMethodDowncallHandleForAddrDesc(_ printer: inout CodePrinter) { + func printMethodDowncallHandleForAddrDesc(_ printer: inout CodePrinter, accessorKind: VariableAccessorKind? = nil) { printer.print( """ - public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + public static final MethodHandle \(accessorKind.renderHandleFieldName) = Linker.nativeLinker().downcallHandle(\(accessorKind.renderAddrFieldName), \(accessorKind.renderDescFieldName)); """ ) } @@ -781,7 +783,8 @@ extension Swift2JavaTranslator { public func printFunctionDescriptorValue( _ printer: inout CodePrinter, _ decl: ImportedFunc, - fieldName: String = "DESC") { + accessorKind: VariableAccessorKind? = nil) { + let fieldName = accessorKind.renderDescFieldName printer.start("public static final FunctionDescriptor \(fieldName) = ") let parameterLayoutDescriptors = javaMemoryLayoutDescriptors( @@ -818,14 +821,4 @@ extension Swift2JavaTranslator { printer.print(");"); } - public func printPropertyAccessorDescriptorValue( - _ printer: inout CodePrinter, - _ decl: ImportedVariable, - _ kind: VariableAccessorKind) { - guard let funcDecl = decl.accessorFunc(kind: kind) else { - return - } - - printFunctionDescriptorValue(&printer, funcDecl, fieldName: kind.renderDescFieldName) - } } diff --git a/Sources/JExtractSwift/Swift2JavaVisitor.swift b/Sources/JExtractSwift/Swift2JavaVisitor.swift index db42c02b..8cf39eab 100644 --- a/Sources/JExtractSwift/Swift2JavaVisitor.swift +++ b/Sources/JExtractSwift/Swift2JavaVisitor.swift @@ -131,15 +131,13 @@ final class Swift2JavaVisitor: SyntaxVisitor { } override func visit(_ node: VariableDeclSyntax) -> SyntaxVisitorContinueKind { - self.log.warning("NODE: \(node.debugDescription)") - guard let binding = node.bindings.first else { return .skipChildren } let fullName = "\(binding.pattern.trimmed)" - // TODO filter out kinds of variables we cannot import + // TODO: filter out kinds of variables we cannot import self.log.info("Import variable: \(node.kind) \(fullName)") diff --git a/Tests/JExtractSwiftTests/FuncImportTests.swift b/Tests/JExtractSwiftTests/FuncImportTests.swift index 0a2cd1b6..5a6c0f38 100644 --- a/Tests/JExtractSwiftTests/FuncImportTests.swift +++ b/Tests/JExtractSwiftTests/FuncImportTests.swift @@ -83,6 +83,7 @@ final class MethodImportTests { expected: """ /** + * Downcall to Swift: * {@snippet lang=swift : * public func helloWorld() * } @@ -125,6 +126,7 @@ final class MethodImportTests { expected: """ /** + * Downcall to Swift: * {@snippet lang=swift : * public func globalTakeInt(i: Int) * } @@ -167,6 +169,7 @@ final class MethodImportTests { expected: """ /** + * Downcall to Swift: * {@snippet lang=swift : * public func globalTakeIntLongString(i32: Int32, l: Int64, s: String) * } @@ -209,6 +212,7 @@ final class MethodImportTests { expected: """ /** + * Downcall to Swift: * {@snippet lang=swift : * public func helloMemberFunction() * } @@ -251,6 +255,7 @@ final class MethodImportTests { expected: """ /** + * Downcall to Swift: * {@snippet lang=swift : * public func helloMemberInExtension() * } @@ -293,6 +298,7 @@ final class MethodImportTests { expected: """ /** + * Downcall to Swift: * {@snippet lang=swift : * public func helloMemberFunction() * } @@ -335,6 +341,7 @@ final class MethodImportTests { expected: """ /** + * Downcall to Swift: * {@snippet lang=swift : * public func helloMemberFunction() * } @@ -369,6 +376,7 @@ final class MethodImportTests { expected: """ /** + * Downcall to Swift: * {@snippet lang=swift : * public func makeInt() -> Int * } diff --git a/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift b/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift index f52757a4..4199ca16 100644 --- a/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift +++ b/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift @@ -162,8 +162,8 @@ extension FunctionDescriptorTests { } func variableAccessorDescriptorTest( - _ methodIdentifier: String, - _ kind: VariableAccessorKind, + _ identifier: String, + _ accessorKind: VariableAccessorKind, javaPackage: String = "com.example.swift", swiftModuleName: String = "SwiftModule", logLevel: Logger.Level = .trace, @@ -180,15 +180,15 @@ extension FunctionDescriptorTests { let varDecl: ImportedVariable? = st.importedTypes.values.compactMap { $0.variables.first { - $0.identifier == methodIdentifier + $0.identifier == identifier } }.first guard let varDecl else { - fatalError("Cannot find descriptor of: \(methodIdentifier)") + fatalError("Cannot find descriptor of: \(identifier)") } let getOutput = CodePrinter.toString { printer in - st.printPropertyAccessorDescriptorValue(&printer, varDecl, kind) + st.printFunctionDescriptorValue(&printer, varDecl.accessorFunc(kind: accessorKind)!, accessorKind: accessorKind) } try await body(getOutput) diff --git a/Tests/JExtractSwiftTests/VariableImportTests.swift b/Tests/JExtractSwiftTests/VariableImportTests.swift index 2305d4ec..f59b8ff4 100644 --- a/Tests/JExtractSwiftTests/VariableImportTests.swift +++ b/Tests/JExtractSwiftTests/VariableImportTests.swift @@ -67,13 +67,17 @@ final class VariableImportTests { // counterInt private static class counterInt { public static final FunctionDescriptor DESC_GET = FunctionDescriptor.of( - /* -> */SWIFT_INT, + /* -> */SWIFT_INT, SWIFT_POINTER - ); + ); + public static final MemorySegment ADDR_GET = __FakeModule.findOrThrow("g"); + public static final MethodHandle HANDLE_GET = Linker.nativeLinker().downcallHandle(ADDR_GET, DESC_GET); public static final FunctionDescriptor DESC_SET = FunctionDescriptor.ofVoid( - SWIFT_INT, + SWIFT_INT, SWIFT_POINTER ); + public static final MemorySegment ADDR_SET = __FakeModule.findOrThrow("s"); + public static final MethodHandle HANDLE_SET = Linker.nativeLinker().downcallHandle(ADDR_SET, DESC_SET); } /** * Function descriptor for: From 9a561cf85f10ad0fb808c8259ad75a570c164a12 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Tue, 8 Oct 2024 23:07:50 +0900 Subject: [PATCH 043/426] disable runtime tests on linux until we have mangling --- .../java/com/example/swift/generated/MySwiftClassTest.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/generated/MySwiftClassTest.java b/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/generated/MySwiftClassTest.java index 740e711b..8ca3f96b 100644 --- a/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/generated/MySwiftClassTest.java +++ b/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/generated/MySwiftClassTest.java @@ -16,6 +16,8 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.DisabledOnOs; +import org.junit.jupiter.api.condition.OS; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -33,12 +35,14 @@ static void beforeAll() { } @Test + @DisabledOnOs(OS.LINUX) // FIXME: enable on Linux when we get new compiler with mangled names in swift interfaces void test_MySwiftClass_voidMethod() { MySwiftClass o = new MySwiftClass(12, 42); o.voidMethod(); } @Test + @DisabledOnOs(OS.LINUX) // FIXME: enable on Linux when we get new compiler with mangled names in swift interfaces void test_MySwiftClass_makeIntMethod() { MySwiftClass o = new MySwiftClass(12, 42); var got = o.makeIntMethod(); @@ -46,6 +50,7 @@ void test_MySwiftClass_makeIntMethod() { } @Test + @DisabledOnOs(OS.LINUX) // FIXME: enable on Linux when we get new compiler with mangled names in swift interfaces void test_MySwiftClass_property_len() { MySwiftClass o = new MySwiftClass(12, 42); var got = o.makeIntMethod(); From 70edd09318f255408903ab9216d8924b14d49f0b Mon Sep 17 00:00:00 2001 From: jrosen081 Date: Wed, 9 Oct 2024 09:16:24 -0400 Subject: [PATCH 044/426] Add Support for Field Accessors --- Makefile | 2 +- Sources/Java2Swift/JavaTranslator.swift | 30 +++++++++++++++++++ .../JavaKitReflection/Field+Utilities.swift | 20 +++++++++++++ .../JavaClass+Reflection.swift | 3 ++ 4 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 Sources/JavaKitReflection/Field+Utilities.swift diff --git a/Makefile b/Makefile index 3528d1a6..7e067cce 100644 --- a/Makefile +++ b/Makefile @@ -55,7 +55,7 @@ generate-JavaKit: Java2Swift generate-JavaKitReflection: Java2Swift generate-JavaKit mkdir -p Sources/JavaKitReflection/generated - $(BUILD_DIR)/debug/Java2Swift --module-name JavaKitReflection --manifests Sources/JavaKit/generated/JavaKit.swift2java -o Sources/JavaKitReflection/generated java.lang.reflect.Method java.lang.reflect.Type java.lang.reflect.Constructor java.lang.reflect.Parameter java.lang.reflect.ParameterizedType java.lang.reflect.Executable java.lang.reflect.AnnotatedType java.lang.reflect.TypeVariable java.lang.reflect.WildcardType java.lang.reflect.GenericArrayType java.lang.reflect.AccessibleObject java.lang.annotation.Annotation java.lang.reflect.GenericDeclaration + $(BUILD_DIR)/debug/Java2Swift --module-name JavaKitReflection --manifests Sources/JavaKit/generated/JavaKit.swift2java -o Sources/JavaKitReflection/generated java.lang.reflect.Method java.lang.reflect.Type java.lang.reflect.Constructor java.lang.reflect.Parameter java.lang.reflect.ParameterizedType java.lang.reflect.Executable java.lang.reflect.AnnotatedType java.lang.reflect.TypeVariable java.lang.reflect.WildcardType java.lang.reflect.GenericArrayType java.lang.reflect.AccessibleObject java.lang.annotation.Annotation java.lang.reflect.GenericDeclaration java.lang.reflect.Field generate-JavaKitJar: Java2Swift generate-JavaKit mkdir -p Sources/JavaKitJar/generated diff --git a/Sources/Java2Swift/JavaTranslator.swift b/Sources/Java2Swift/JavaTranslator.swift index bc2140a0..6ca0c978 100644 --- a/Sources/Java2Swift/JavaTranslator.swift +++ b/Sources/Java2Swift/JavaTranslator.swift @@ -280,6 +280,25 @@ extension JavaTranslator { } } ) + + var staticFields: [Field] = [] + members.append( + contentsOf: javaClass.getFields().compactMap { + $0.flatMap { field in + if field.isStatic { + staticFields.append(field) + return nil + } + + do { + return try translateField(field) + } catch { + logUntranslated("Unable to translate '\(fullName)' field '\(field.getName())': \(error)") + return nil + } + } + } + ) // Map the generic parameters. let genericParameterClause: String @@ -327,6 +346,8 @@ extension JavaTranslator { // Format the class declaration. classDecl = classDecl.formatted(using: format).cast(DeclSyntax.self) + + // TODO: Handle static fields in https://github.com/swiftlang/swift-java/issues/39 if staticMethods.isEmpty { return [classDecl] @@ -422,6 +443,15 @@ extension JavaTranslator { public func \(raw: javaMethod.getName())\(raw: genericParameterClause)(\(raw: parametersStr))\(raw: throwsStr)\(raw: resultTypeStr)\(raw: whereClause) """ } + + func translateField(_ javaField: Field) throws -> DeclSyntax { + let typeName = try getSwiftTypeNameAsString(javaField.getGenericType()!, outerOptional: true) + let fieldAttribute: AttributeSyntax = "@JavaField"; + return """ + \(fieldAttribute) + public func \(raw: javaField.getName()): \(raw: typeName) + """ + } // Translate a Java parameter list into Swift parameters. private func translateParameters(_ parameters: [Parameter?]) throws -> [FunctionParameterSyntax] { diff --git a/Sources/JavaKitReflection/Field+Utilities.swift b/Sources/JavaKitReflection/Field+Utilities.swift new file mode 100644 index 00000000..1f803bac --- /dev/null +++ b/Sources/JavaKitReflection/Field+Utilities.swift @@ -0,0 +1,20 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +extension Field { + /// Whether this is a 'static' field. + public var isStatic: Bool { + return (getModifiers() & 0x08) != 0 + } +} diff --git a/Sources/JavaKitReflection/JavaClass+Reflection.swift b/Sources/JavaKitReflection/JavaClass+Reflection.swift index 5191a7b7..fcaf80cc 100644 --- a/Sources/JavaKitReflection/JavaClass+Reflection.swift +++ b/Sources/JavaKitReflection/JavaClass+Reflection.swift @@ -28,6 +28,9 @@ extension JavaClass { @JavaMethod public func getMethods() -> [Method?] + + @JavaMethod + public func getFields() -> [Field?] @JavaMethod public func getConstructors() -> [Constructor?] From bbc4fc8ee2db63e0d0ef19e302d9c79103dedf9f Mon Sep 17 00:00:00 2001 From: jrosen081 Date: Wed, 9 Oct 2024 09:23:50 -0400 Subject: [PATCH 045/426] Add small updates --- Sources/Java2Swift/JavaTranslator.swift | 40 +++++++++---------- .../generated/JavaKitReflection.swift2java | 1 + 2 files changed, 21 insertions(+), 20 deletions(-) diff --git a/Sources/Java2Swift/JavaTranslator.swift b/Sources/Java2Swift/JavaTranslator.swift index 6ca0c978..3721513b 100644 --- a/Sources/Java2Swift/JavaTranslator.swift +++ b/Sources/Java2Swift/JavaTranslator.swift @@ -257,6 +257,25 @@ extension JavaTranslator { } } ) + + var staticFields: [Field] = [] + members.append( + contentsOf: javaClass.getFields().compactMap { + $0.flatMap { field in + if field.isStatic { + staticFields.append(field) + return nil + } + + do { + return try translateField(field) + } catch { + logUntranslated("Unable to translate '\(fullName)' field '\(field.getName())': \(error)") + return nil + } + } + } + ) // Methods var staticMethods: [Method] = [] @@ -280,25 +299,6 @@ extension JavaTranslator { } } ) - - var staticFields: [Field] = [] - members.append( - contentsOf: javaClass.getFields().compactMap { - $0.flatMap { field in - if field.isStatic { - staticFields.append(field) - return nil - } - - do { - return try translateField(field) - } catch { - logUntranslated("Unable to translate '\(fullName)' field '\(field.getName())': \(error)") - return nil - } - } - } - ) // Map the generic parameters. let genericParameterClause: String @@ -449,7 +449,7 @@ extension JavaTranslator { let fieldAttribute: AttributeSyntax = "@JavaField"; return """ \(fieldAttribute) - public func \(raw: javaField.getName()): \(raw: typeName) + public var \(raw: javaField.getName()): \(raw: typeName) """ } diff --git a/Sources/JavaKitReflection/generated/JavaKitReflection.swift2java b/Sources/JavaKitReflection/generated/JavaKitReflection.swift2java index 19725c6a..72e42f6f 100644 --- a/Sources/JavaKitReflection/generated/JavaKitReflection.swift2java +++ b/Sources/JavaKitReflection/generated/JavaKitReflection.swift2java @@ -6,6 +6,7 @@ "java.lang.reflect.AnnotatedType" : "AnnotatedType", "java.lang.reflect.Constructor" : "Constructor", "java.lang.reflect.Executable" : "Executable", + "java.lang.reflect.Field" : "Field", "java.lang.reflect.GenericArrayType" : "GenericArrayType", "java.lang.reflect.GenericDeclaration" : "GenericDeclaration", "java.lang.reflect.Method" : "Method", From 7a7fcc6caaf910a6c189e4fd02f13e63c11b91ea Mon Sep 17 00:00:00 2001 From: jrosen081 Date: Wed, 9 Oct 2024 17:32:38 -0400 Subject: [PATCH 046/426] Put fields first --- Sources/Java2Swift/JavaTranslator.swift | 29 +++++++++++++------------ 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/Sources/Java2Swift/JavaTranslator.swift b/Sources/Java2Swift/JavaTranslator.swift index 3721513b..97103c63 100644 --- a/Sources/Java2Swift/JavaTranslator.swift +++ b/Sources/Java2Swift/JavaTranslator.swift @@ -243,21 +243,8 @@ extension JavaTranslator { // Members var members: [DeclSyntax] = [] - - // Constructors - members.append( - contentsOf: javaClass.getConstructors().compactMap { - $0.flatMap { constructor in - do { - return try translateConstructor(constructor) - } catch { - logUntranslated("Unable to translate '\(fullName)' constructor: \(error)") - return nil - } - } - } - ) + // Fields var staticFields: [Field] = [] members.append( contentsOf: javaClass.getFields().compactMap { @@ -277,6 +264,20 @@ extension JavaTranslator { } ) + // Constructors + members.append( + contentsOf: javaClass.getConstructors().compactMap { + $0.flatMap { constructor in + do { + return try translateConstructor(constructor) + } catch { + logUntranslated("Unable to translate '\(fullName)' constructor: \(error)") + return nil + } + } + } + ) + // Methods var staticMethods: [Method] = [] members.append( From 235911c039a96cf9d44b9c0a9568124c9ecd41c6 Mon Sep 17 00:00:00 2001 From: jrosen081 Date: Wed, 9 Oct 2024 17:33:32 -0400 Subject: [PATCH 047/426] Add Field class --- .../JavaKitReflection/generated/Field.swift | 151 ++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 Sources/JavaKitReflection/generated/Field.swift diff --git a/Sources/JavaKitReflection/generated/Field.swift b/Sources/JavaKitReflection/generated/Field.swift new file mode 100644 index 00000000..f6823600 --- /dev/null +++ b/Sources/JavaKitReflection/generated/Field.swift @@ -0,0 +1,151 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaClass("java.lang.reflect.Field", extends: AccessibleObject.self) +public struct Field { + @JavaMethod + public func getName() -> String + + @JavaMethod + public func get(_ arg0: JavaObject?) throws -> JavaObject? + + @JavaMethod + public func equals(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func toString() -> String + + @JavaMethod + public func hashCode() -> Int32 + + @JavaMethod + public func getModifiers() -> Int32 + + @JavaMethod + public func getBoolean(_ arg0: JavaObject?) throws -> Bool + + @JavaMethod + public func getByte(_ arg0: JavaObject?) throws -> Int8 + + @JavaMethod + public func getShort(_ arg0: JavaObject?) throws -> Int16 + + @JavaMethod + public func getChar(_ arg0: JavaObject?) throws -> UInt16 + + @JavaMethod + public func getInt(_ arg0: JavaObject?) throws -> Int32 + + @JavaMethod + public func getLong(_ arg0: JavaObject?) throws -> Int64 + + @JavaMethod + public func getFloat(_ arg0: JavaObject?) throws -> Float + + @JavaMethod + public func getDouble(_ arg0: JavaObject?) throws -> Double + + @JavaMethod + public func toGenericString() -> String + + @JavaMethod + public func isSynthetic() -> Bool + + @JavaMethod + public func getDeclaringClass() -> JavaClass? + + @JavaMethod + public func getAnnotation(_ arg0: JavaClass?) -> Annotation? + + @JavaMethod + public func getAnnotationsByType(_ arg0: JavaClass?) -> [Annotation?] + + @JavaMethod + public func getDeclaredAnnotations() -> [Annotation?] + + @JavaMethod + public func set(_ arg0: JavaObject?, _ arg1: JavaObject?) throws + + @JavaMethod + public func setAccessible(_ arg0: Bool) + + @JavaMethod + public func getGenericType() -> Type? + + @JavaMethod + public func getType() -> JavaClass? + + @JavaMethod + public func setBoolean(_ arg0: JavaObject?, _ arg1: Bool) throws + + @JavaMethod + public func setByte(_ arg0: JavaObject?, _ arg1: Int8) throws + + @JavaMethod + public func setChar(_ arg0: JavaObject?, _ arg1: UInt16) throws + + @JavaMethod + public func setShort(_ arg0: JavaObject?, _ arg1: Int16) throws + + @JavaMethod + public func setInt(_ arg0: JavaObject?, _ arg1: Int32) throws + + @JavaMethod + public func setLong(_ arg0: JavaObject?, _ arg1: Int64) throws + + @JavaMethod + public func setFloat(_ arg0: JavaObject?, _ arg1: Float) throws + + @JavaMethod + public func setDouble(_ arg0: JavaObject?, _ arg1: Double) throws + + @JavaMethod + public func isEnumConstant() -> Bool + + @JavaMethod + public func getAnnotatedType() -> AnnotatedType? + + @JavaMethod + public func isAnnotationPresent(_ arg0: JavaClass?) -> Bool + + @JavaMethod + public func getAnnotations() -> [Annotation?] + + @JavaMethod + public func getDeclaredAnnotation(_ arg0: JavaClass?) -> Annotation? + + @JavaMethod + public func getDeclaredAnnotationsByType(_ arg0: JavaClass?) -> [Annotation?] + + @JavaMethod + public func trySetAccessible() -> Bool + + @JavaMethod + public func canAccess(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func isAccessible() -> Bool + + @JavaMethod + public func getClass() -> JavaClass? + + @JavaMethod + public func notify() + + @JavaMethod + public func notifyAll() + + @JavaMethod + public func wait(_ arg0: Int64) throws + + @JavaMethod + public func wait(_ arg0: Int64, _ arg1: Int32) throws + + @JavaMethod + public func wait() throws +} +extension JavaClass { + @JavaStaticMethod + public func setAccessible(_ arg0: [AccessibleObject?], _ arg1: Bool) +} From 202a5cd5c43ac2931fd78d4204b1cac82d854d50 Mon Sep 17 00:00:00 2001 From: jrosen081 Date: Wed, 9 Oct 2024 18:32:59 -0400 Subject: [PATCH 048/426] Formatting --- Sources/Java2Swift/JavaTranslator.swift | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Sources/Java2Swift/JavaTranslator.swift b/Sources/Java2Swift/JavaTranslator.swift index 97103c63..9c445df7 100644 --- a/Sources/Java2Swift/JavaTranslator.swift +++ b/Sources/Java2Swift/JavaTranslator.swift @@ -445,14 +445,14 @@ extension JavaTranslator { """ } - func translateField(_ javaField: Field) throws -> DeclSyntax { - let typeName = try getSwiftTypeNameAsString(javaField.getGenericType()!, outerOptional: true) - let fieldAttribute: AttributeSyntax = "@JavaField"; - return """ - \(fieldAttribute) - public var \(raw: javaField.getName()): \(raw: typeName) - """ - } + func translateField(_ javaField: Field) throws -> DeclSyntax { + let typeName = try getSwiftTypeNameAsString(javaField.getGenericType()!, outerOptional: true) + let fieldAttribute: AttributeSyntax = "@JavaField"; + return """ + \(fieldAttribute) + public var \(raw: javaField.getName()): \(raw: typeName) + """ + } // Translate a Java parameter list into Swift parameters. private func translateParameters(_ parameters: [Parameter?]) throws -> [FunctionParameterSyntax] { From 20db81ead81f6ea8b190f44c46540806e27f36ee Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Thu, 10 Oct 2024 08:47:26 +0900 Subject: [PATCH 049/426] ci: try out untested nightly swift to unblock nm removal --- .github/workflows/pull_request.yml | 10 ++++--- docker/Dockerfile | 6 +++- docker/install_untested_nightly_swift.sh | 38 ++++++++++++++++++++++++ 3 files changed, 49 insertions(+), 5 deletions(-) create mode 100644 docker/install_untested_nightly_swift.sh diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 8aad2c67..53fbf576 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -31,8 +31,8 @@ jobs: JAVA_HOME: "/usr/lib/jvm/default-jdk" steps: - uses: actions/checkout@v4 - - name: Install Make - run: apt-get -qq update && apt-get -qq install -y make + - name: Install System Dependencies + run: apt-get -qq update && apt-get -qq install -y make curl wget - name: Install JDK run: "bash -xc 'JDK_VENDOR=${{ matrix.jdk_vendor }} ./docker/install_jdk.sh'" # TODO: not using setup-java since incompatible with the swiftlang/swift base image @@ -41,6 +41,8 @@ jobs: # distribution: 'zulu' # java-version: '22' # cache: 'gradle' + - name: Install Nightly Swift + run: "bash -xc './docker/install_nightly_untested_swift.sh'" - name: Gradle build run: ./gradlew build --info --no-daemon @@ -59,8 +61,8 @@ jobs: JAVA_HOME: "/usr/lib/jvm/default-jdk" steps: - uses: actions/checkout@v4 - - name: Install Make - run: apt-get -qq update && apt-get -qq install -y make + - name: Install System Dependencies + run: apt-get -qq update && apt-get -qq install -y make curl wget - name: Install JDK run: "bash -xc 'JDK_VENDOR=${{ matrix.jdk_vendor }} ./docker/install_jdk.sh'" - name: Generate sources (make) (Temporary) diff --git a/docker/Dockerfile b/docker/Dockerfile index 170619e1..216e3108 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -19,4 +19,8 @@ ENV LANGUAGE=en_US.UTF-8 COPY install_jdk.sh . RUN bash -xc 'JDK_VENDOR=Corretto ./install_jdk.sh' ENV JAVA_HOME="/usr/lib/jvm/default-jdk" -ENV PATH="$PATH:/usr/lib/jvm/default-jdk/bin" \ No newline at end of file +ENV PATH="$PATH:/usr/lib/jvm/default-jdk/bin" + +# Install "untested" nightly 'main' Swift +# TODO: Only do this if the released Swift is older than what we require +RUN bash -xc './install_nightly_untested_swift.sh' diff --git a/docker/install_untested_nightly_swift.sh b/docker/install_untested_nightly_swift.sh new file mode 100644 index 00000000..9e542b41 --- /dev/null +++ b/docker/install_untested_nightly_swift.sh @@ -0,0 +1,38 @@ +#!/bin/bash +##===----------------------------------------------------------------------===## +## +## This source file is part of the Swift.org open source project +## +## Copyright (c) 2024 Apple Inc. and the Swift.org project authors +## Licensed under Apache License v2.0 +## +## See LICENSE.txt for license information +## See CONTRIBUTORS.txt for the list of Swift.org project authors +## +## SPDX-License-Identifier: Apache-2.0 +## +##===----------------------------------------------------------------------===## +set -euo pipefail + +echo "Download [nightly] [untested] Swift toolchain for: $(uname -m)" + +declare -r SWIFT_UNTESTED_TOOLCHAIN_JOB_URL="https://ci.swift.org/job/oss-swift-package-ubuntu-22_04/lastSuccessfulBuild/consoleText" + +if [[ "$(cat /etc/lsb-release | grep "22.04")" = "" ]]; then + echo "This script specifically only supports Ubuntu 20.04 due to nightly toolchain availability" + exit 1 +fi + +declare -r UNTESTED_TOOLCHAIN_URL=$(curl -s $SWIFT_UNTESTED_TOOLCHAIN_JOB_URL | grep 'Toolchain: ' | sed 's/Toolchain: //g') +declare -r UNTESTED_TOOLCHAIN_FILENAME=$(echo "$UNTESTED_TOOLCHAIN_URL" | awk ' + function basename(file) { + sub(".*/", "", file) + return file + } + {print FILENAME, basename(FILENAME)}') + +cd / +curl $UNTESTED_TOOLCHAIN_URL > $UNTESTED_TOOLCHAIN_FILENAME + +tar xzf $UNTESTED_TOOLCHAIN_FILENAME +swift -version \ No newline at end of file From ddc9642a395eca38068e2e186d19b61b39e23487 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Wed, 9 Oct 2024 17:01:36 -0700 Subject: [PATCH 050/426] Add a test for macro expansion of @JavaClass/@JavaMethod/@JavaField --- Package.swift | 11 +++ Sources/JavaKitMacros/JavaClassMacro.swift | 8 +- Sources/JavaKitMacros/JavaFieldMacro.swift | 4 +- Sources/JavaKitMacros/JavaMethodMacro.swift | 4 +- .../JavaClassMacroTests.swift | 87 +++++++++++++++++++ 5 files changed, 106 insertions(+), 8 deletions(-) create mode 100644 Tests/JavaKitMacroTests/JavaClassMacroTests.swift diff --git a/Package.swift b/Package.swift index 4ec487b7..5ccec379 100644 --- a/Package.swift +++ b/Package.swift @@ -318,6 +318,17 @@ let package = Package( ] ), + .testTarget( + name: "JavaKitMacroTests", + dependencies: [ + "JavaKitMacros", + .product(name: "SwiftSyntaxMacrosTestSupport", package: "swift-syntax"), + ], + swiftSettings: [ + .swiftLanguageMode(.v5) + ] + ), + .testTarget( name: "JExtractSwiftTests", dependencies: [ diff --git a/Sources/JavaKitMacros/JavaClassMacro.swift b/Sources/JavaKitMacros/JavaClassMacro.swift index b1da49dd..23d6d4fc 100644 --- a/Sources/JavaKitMacros/JavaClassMacro.swift +++ b/Sources/JavaKitMacros/JavaClassMacro.swift @@ -17,10 +17,10 @@ import SwiftSyntaxBuilder import SwiftSyntaxMacros import Foundation // for e.g. replacingOccurrences -enum JavaClassMacro {} +package enum JavaClassMacro {} extension JavaClassMacro: MemberMacro { - static func expansion( + package static func expansion( of node: AttributeSyntax, providingMembersOf declaration: some DeclGroupSyntax, conformingTo protocols: [TypeSyntax], @@ -99,7 +99,7 @@ extension JavaClassMacro: MemberMacro { } extension JavaClassMacro: ExtensionMacro { - static func expansion( + package static func expansion( of node: AttributeSyntax, attachedTo declaration: some DeclGroupSyntax, providingExtensionsOf type: some TypeSyntaxProtocol, @@ -120,7 +120,7 @@ extension JavaClassMacro: ExtensionMacro { } extension JavaClassMacro: PeerMacro { - static func expansion( + package static func expansion( of node: AttributeSyntax, providingPeersOf declaration: some DeclSyntaxProtocol, in context: some MacroExpansionContext diff --git a/Sources/JavaKitMacros/JavaFieldMacro.swift b/Sources/JavaKitMacros/JavaFieldMacro.swift index 10f06ad3..d9c7929f 100644 --- a/Sources/JavaKitMacros/JavaFieldMacro.swift +++ b/Sources/JavaKitMacros/JavaFieldMacro.swift @@ -16,10 +16,10 @@ import SwiftSyntax import SwiftSyntaxBuilder import SwiftSyntaxMacros -enum JavaFieldMacro {} +package enum JavaFieldMacro {} extension JavaFieldMacro: AccessorMacro { - static func expansion( + package static func expansion( of node: AttributeSyntax, providingAccessorsOf declaration: some DeclSyntaxProtocol, in context: some MacroExpansionContext diff --git a/Sources/JavaKitMacros/JavaMethodMacro.swift b/Sources/JavaKitMacros/JavaMethodMacro.swift index b16d8ab2..dc08374d 100644 --- a/Sources/JavaKitMacros/JavaMethodMacro.swift +++ b/Sources/JavaKitMacros/JavaMethodMacro.swift @@ -17,10 +17,10 @@ import SwiftSyntaxBuilder @_spi(Testing) import SwiftSyntaxMacroExpansion import SwiftSyntaxMacros -enum JavaMethodMacro {} +package enum JavaMethodMacro {} extension JavaMethodMacro: BodyMacro { - static func expansion( + package static func expansion( of node: AttributeSyntax, providingBodyFor declaration: some DeclSyntaxProtocol & WithOptionalCodeBlockSyntax, in context: some MacroExpansionContext diff --git a/Tests/JavaKitMacroTests/JavaClassMacroTests.swift b/Tests/JavaKitMacroTests/JavaClassMacroTests.swift new file mode 100644 index 00000000..72ff432d --- /dev/null +++ b/Tests/JavaKitMacroTests/JavaClassMacroTests.swift @@ -0,0 +1,87 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import JavaKitMacros +import SwiftSyntax +import SwiftSyntaxBuilder +import SwiftSyntaxMacros +import SwiftSyntaxMacrosTestSupport +import XCTest + +class JavaKitMacroTests: XCTestCase { + static let javaKitMacros: [String: any Macro.Type] = [ + "JavaClass": JavaClassMacro.self, + "JavaMethod": JavaMethodMacro.self, + "JavaField": JavaFieldMacro.self + ] + + func testJavaClass() throws { + assertMacroExpansion(""" + @JavaClass("org.swift.example.HelloWorld") + public struct HelloWorld { + @JavaMethod + public init(_ value: Int32, environment: JNIEnvironment) + + @JavaMethod + public func isBigEnough(_: Int32) -> Bool + + @JavaField + public var myField: Int64 + } + """, + expandedSource: """ + + public struct HelloWorld { + public init(_ value: Int32, environment: JNIEnvironment) { + self = try! Self.dynamicJavaNewObject(in: environment, arguments: value.self) + } + public func isBigEnough(_: Int32) -> Bool { + return try! dynamicJavaMethodCall(methodName: "isBigEnough", resultType: Bool.self) + } + public var myField: Int64 { + get { + self[javaFieldName: "myField", fieldType: Int64.self] + } + nonmutating set { + self[javaFieldName: "myField", fieldType: Int64.self] = newValue + } + } + + /// The full Java class name for this Swift type. + public static var fullJavaClassName: String { + "org.swift.example.HelloWorld" + } + + public typealias JavaSuperclass = JavaObject + + public var javaHolder: JavaObjectHolder + + public var javaThis: jobject { + javaHolder.object! + } + + public var javaEnvironment: JNIEnvironment { + javaHolder.environment + } + + public init(javaHolder: JavaObjectHolder) { + self.javaHolder = javaHolder + } + } + """, + macros: Self.javaKitMacros + ) + } +} + From 224e1f972cbf96034ce8705be92fd5420524e569 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Thu, 10 Oct 2024 09:10:50 +0900 Subject: [PATCH 051/426] cache gradle repository --- .github/workflows/pull_request.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 53fbf576..21b2e1fc 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -43,6 +43,16 @@ jobs: # cache: 'gradle' - name: Install Nightly Swift run: "bash -xc './docker/install_nightly_untested_swift.sh'" + # Cache .m2/repository + - name: Cache local Gradle repository + uses: actions/cache@v4 + continue-on-error: true + with: + path: ~/.gradle/caches + key: ${{ runner.os }}-gradle-cache-${{ hashFiles('**/build.gradle') }}-${{ ${{ hashFiles('**/build.gradle.kts') }} }} + restore-keys: | + ${{ runner.os }}-gradle-cache + ${{ runner.os }}-gradle- - name: Gradle build run: ./gradlew build --info --no-daemon From c909781852a726f076d39f9591810b36f8ac4917 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Thu, 10 Oct 2024 09:11:03 +0900 Subject: [PATCH 052/426] fix shell script warnings --- docker/install_untested_nightly_swift.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docker/install_untested_nightly_swift.sh b/docker/install_untested_nightly_swift.sh index 9e542b41..76d01895 100644 --- a/docker/install_untested_nightly_swift.sh +++ b/docker/install_untested_nightly_swift.sh @@ -18,13 +18,13 @@ echo "Download [nightly] [untested] Swift toolchain for: $(uname -m)" declare -r SWIFT_UNTESTED_TOOLCHAIN_JOB_URL="https://ci.swift.org/job/oss-swift-package-ubuntu-22_04/lastSuccessfulBuild/consoleText" -if [[ "$(cat /etc/lsb-release | grep "22.04")" = "" ]]; then +if [[ "$(grep "22.04" /etc/lsb-release)" = "" ]]; then echo "This script specifically only supports Ubuntu 20.04 due to nightly toolchain availability" exit 1 fi -declare -r UNTESTED_TOOLCHAIN_URL=$(curl -s $SWIFT_UNTESTED_TOOLCHAIN_JOB_URL | grep 'Toolchain: ' | sed 's/Toolchain: //g') -declare -r UNTESTED_TOOLCHAIN_FILENAME=$(echo "$UNTESTED_TOOLCHAIN_URL" | awk ' +UNTESTED_TOOLCHAIN_URL=$(curl -s $SWIFT_UNTESTED_TOOLCHAIN_JOB_URL | grep 'Toolchain: ' | sed 's/Toolchain: //g') +UNTESTED_TOOLCHAIN_FILENAME=$(echo "$UNTESTED_TOOLCHAIN_URL" | awk ' function basename(file) { sub(".*/", "", file) return file @@ -32,7 +32,7 @@ declare -r UNTESTED_TOOLCHAIN_FILENAME=$(echo "$UNTESTED_TOOLCHAIN_URL" | awk ' {print FILENAME, basename(FILENAME)}') cd / -curl $UNTESTED_TOOLCHAIN_URL > $UNTESTED_TOOLCHAIN_FILENAME +curl "$UNTESTED_TOOLCHAIN_URL" > "$UNTESTED_TOOLCHAIN_FILENAME" -tar xzf $UNTESTED_TOOLCHAIN_FILENAME +tar xzf "$UNTESTED_TOOLCHAIN_FILENAME" swift -version \ No newline at end of file From f7bd174ba3af463a3b7520eede65e25b02addf6c Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Thu, 10 Oct 2024 09:11:12 +0900 Subject: [PATCH 053/426] cleanup --- settings.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.gradle b/settings.gradle index 7ec81ed0..3a0bd106 100644 --- a/settings.gradle +++ b/settings.gradle @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -pluginManagement{ +pluginManagement { includeBuild("BuildLogic") } From 4907ec2defdab4c4e97b0623b503dfa0f0abc80b Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Thu, 10 Oct 2024 09:12:22 +0900 Subject: [PATCH 054/426] install nightly swift in both CI jobs --- .github/workflows/pull_request.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 21b2e1fc..1b8013f1 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -42,14 +42,14 @@ jobs: # java-version: '22' # cache: 'gradle' - name: Install Nightly Swift - run: "bash -xc './docker/install_nightly_untested_swift.sh'" + run: "bash -xc './docker/install_untested_nightly_swift.sh'" # Cache .m2/repository - name: Cache local Gradle repository uses: actions/cache@v4 continue-on-error: true with: path: ~/.gradle/caches - key: ${{ runner.os }}-gradle-cache-${{ hashFiles('**/build.gradle') }}-${{ ${{ hashFiles('**/build.gradle.kts') }} }} + key: ${{ runner.os }}-gradle-cache-${{ hashFiles('**/build.gradle') }}-${{ hashFiles('**/build.gradle.kts') }} restore-keys: | ${{ runner.os }}-gradle-cache ${{ runner.os }}-gradle- @@ -75,6 +75,8 @@ jobs: run: apt-get -qq update && apt-get -qq install -y make curl wget - name: Install JDK run: "bash -xc 'JDK_VENDOR=${{ matrix.jdk_vendor }} ./docker/install_jdk.sh'" + - name: Install Nightly Swift + run: "bash -xc './docker/install_untested_nightly_swift.sh'" - name: Generate sources (make) (Temporary) # TODO: this should be triggered by the respective builds run: "make jextract-run" From 7becdfbdb4ecf4c734305d2a4d23b80d58b98703 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Thu, 10 Oct 2024 09:15:02 +0900 Subject: [PATCH 055/426] fix permissions of script --- docker/install_untested_nightly_swift.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 docker/install_untested_nightly_swift.sh diff --git a/docker/install_untested_nightly_swift.sh b/docker/install_untested_nightly_swift.sh old mode 100644 new mode 100755 From 7a66a01e4ba363ddee266757c2d7c2218795cc8b Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Thu, 10 Oct 2024 09:27:06 +0900 Subject: [PATCH 056/426] cache downloaded swiftpm artifacts --- .github/workflows/pull_request.yml | 51 ++++++++++++++++++------ docker/install_untested_nightly_swift.sh | 16 ++++---- 2 files changed, 47 insertions(+), 20 deletions(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 1b8013f1..f27d5276 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -36,25 +36,31 @@ jobs: - name: Install JDK run: "bash -xc 'JDK_VENDOR=${{ matrix.jdk_vendor }} ./docker/install_jdk.sh'" # TODO: not using setup-java since incompatible with the swiftlang/swift base image - # - uses: actions/setup-java@v4 - # with: - # distribution: 'zulu' - # java-version: '22' - # cache: 'gradle' - - name: Install Nightly Swift + - name: Install Untested Nightly Swift run: "bash -xc './docker/install_untested_nightly_swift.sh'" - # Cache .m2/repository + # setup caches - name: Cache local Gradle repository uses: actions/cache@v4 continue-on-error: true with: - path: ~/.gradle/caches - key: ${{ runner.os }}-gradle-cache-${{ hashFiles('**/build.gradle') }}-${{ hashFiles('**/build.gradle.kts') }} + path: | + /root/.gradle/caches + /root/.gradle/wrapper + key: ${{ runner.os }}-gradle-${{ hashFiles('*/*.gradle*', 'settings.gradle') }} restore-keys: | - ${{ runner.os }}-gradle-cache ${{ runner.os }}-gradle- + - name: Cache local SwiftPM repository + uses: actions/cache@v4 + continue-on-error: true + with: + path: /__w/swift-java/swift-java/.build/checkouts + key: ${{ runner.os }}-swiftpm-cache-${{ hashFiles('Package.swift') }} + restore-keys: | + ${{ runner.os }}-swiftpm-cache + ${{ runner.os }}-swiftpm- + # run the actual build - name: Gradle build - run: ./gradlew build --info --no-daemon + run: ./gradlew update --info --no-daemon test-swift: name: Swift tests (swift:${{ matrix.swift_version }} jdk:${{matrix.jdk_vendor}} os:${{ matrix.os_version }}) @@ -75,8 +81,29 @@ jobs: run: apt-get -qq update && apt-get -qq install -y make curl wget - name: Install JDK run: "bash -xc 'JDK_VENDOR=${{ matrix.jdk_vendor }} ./docker/install_jdk.sh'" - - name: Install Nightly Swift + - name: Install Untested Nightly Swift run: "bash -xc './docker/install_untested_nightly_swift.sh'" + # setup caches + - name: Cache local Gradle repository + uses: actions/cache@v4 + continue-on-error: true + with: + path: | + /root/.gradle/caches + /root/.gradle/wrapper + key: ${{ runner.os }}-gradle-${{ hashFiles('*/*.gradle*', 'settings.gradle') }} + restore-keys: | + ${{ runner.os }}-gradle- + - name: Cache local SwiftPM repository + uses: actions/cache@v4 + continue-on-error: true + with: + path: /__w/swift-java/swift-java/.build/checkouts + key: ${{ runner.os }}-swiftpm-cache-${{ hashFiles('Package.swift') }} + restore-keys: | + ${{ runner.os }}-swiftpm-cache + ${{ runner.os }}-swiftpm- + # run the actual build - name: Generate sources (make) (Temporary) # TODO: this should be triggered by the respective builds run: "make jextract-run" diff --git a/docker/install_untested_nightly_swift.sh b/docker/install_untested_nightly_swift.sh index 76d01895..369a15cb 100755 --- a/docker/install_untested_nightly_swift.sh +++ b/docker/install_untested_nightly_swift.sh @@ -24,15 +24,15 @@ if [[ "$(grep "22.04" /etc/lsb-release)" = "" ]]; then fi UNTESTED_TOOLCHAIN_URL=$(curl -s $SWIFT_UNTESTED_TOOLCHAIN_JOB_URL | grep 'Toolchain: ' | sed 's/Toolchain: //g') -UNTESTED_TOOLCHAIN_FILENAME=$(echo "$UNTESTED_TOOLCHAIN_URL" | awk ' - function basename(file) { - sub(".*/", "", file) - return file - } - {print FILENAME, basename(FILENAME)}') +UNTESTED_TOOLCHAIN_FILENAME=$"toolchain.tar.gz" + +echo "Download toolchain: $UNTESTED_TOOLCHAIN_URL" cd / -curl "$UNTESTED_TOOLCHAIN_URL" > "$UNTESTED_TOOLCHAIN_FILENAME" +curl -s "$UNTESTED_TOOLCHAIN_URL" > "$UNTESTED_TOOLCHAIN_FILENAME" + +swift -version +echo "Extract toolchain: $UNTESTED_TOOLCHAIN_FILENAME" tar xzf "$UNTESTED_TOOLCHAIN_FILENAME" -swift -version \ No newline at end of file +swift -version From 11ab200a957d8c1a3f4d16da79b2cddb6e0532d9 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Thu, 10 Oct 2024 12:08:42 +0900 Subject: [PATCH 057/426] CI: Gradle build should "build" --- .github/workflows/pull_request.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index f27d5276..4d99bff5 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -60,7 +60,7 @@ jobs: ${{ runner.os }}-swiftpm- # run the actual build - name: Gradle build - run: ./gradlew update --info --no-daemon + run: ./gradlew build --info --no-daemon test-swift: name: Swift tests (swift:${{ matrix.swift_version }} jdk:${{matrix.jdk_vendor}} os:${{ matrix.os_version }}) From 2e42b28d3b67aed41b3148f11819f7b7b4062105 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Thu, 10 Oct 2024 12:24:59 +0900 Subject: [PATCH 058/426] undo explicit Darwin reference --- Sources/ExampleSwiftLibrary/MySwiftLibrary.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/ExampleSwiftLibrary/MySwiftLibrary.swift b/Sources/ExampleSwiftLibrary/MySwiftLibrary.swift index 333cd22a..4928233e 100644 --- a/Sources/ExampleSwiftLibrary/MySwiftLibrary.swift +++ b/Sources/ExampleSwiftLibrary/MySwiftLibrary.swift @@ -80,5 +80,5 @@ public class MySwiftClass { private func p(_ msg: String, file: String = #fileID, line: UInt = #line, function: String = #function) { print("[swift][\(file):\(line)](\(function)) \(msg)") - fflush(Darwin.stdout) + fflush(stdout) } From 655599077eed4a6dcd44a87af4b4799523679b7d Mon Sep 17 00:00:00 2001 From: AbdAlRahman Gad <89566409+AbdAlRahmanGad@users.noreply.github.com> Date: Thu, 10 Oct 2024 03:26:03 +0000 Subject: [PATCH 059/426] Fix build with docker issues - fix `install_untested_nightly_swift.sh` name in Dockerfile - add `curl` to the Dockerfile - fix `java` and `JAVA_HOME` path Signed-off-by: AbdAlRahman Gad --- docker/Dockerfile | 6 ++++-- docker/docker-compose.yaml | 8 ++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index 216e3108..0660f117 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -10,7 +10,8 @@ ARG ubuntu_version RUN apt-get update && apt-get install -y \ locales locales-all \ make \ - libc6-dev + libc6-dev \ + curl ENV LC_ALL=en_US.UTF-8 ENV LANG=en_US.UTF-8 ENV LANGUAGE=en_US.UTF-8 @@ -23,4 +24,5 @@ ENV PATH="$PATH:/usr/lib/jvm/default-jdk/bin" # Install "untested" nightly 'main' Swift # TODO: Only do this if the released Swift is older than what we require -RUN bash -xc './install_nightly_untested_swift.sh' +COPY install_untested_nightly_swift.sh . +RUN bash -xc './install_untested_nightly_swift.sh' diff --git a/docker/docker-compose.yaml b/docker/docker-compose.yaml index a2097226..6bfe52d0 100644 --- a/docker/docker-compose.yaml +++ b/docker/docker-compose.yaml @@ -17,7 +17,7 @@ services: - ..:/swift-java:z working_dir: /swift-java environment: - JAVA_HOME: /jdk + JAVA_HOME: /usr/lib/jvm/default-jdk soundness: <<: *common @@ -29,15 +29,15 @@ services: test-swift: <<: *common - command: /bin/bash -xcl "uname -a && swift -version && /jdk/bin/java -version && swift $${SWIFT_TEST_VERB-test} $${WARN_AS_ERROR_ARG-} $${SANITIZER_ARG-} $${IMPORT_CHECK_ARG-}" + command: /bin/bash -xcl "uname -a && swift -version && java -version && swift $${SWIFT_TEST_VERB-test} $${WARN_AS_ERROR_ARG-} $${SANITIZER_ARG-} $${IMPORT_CHECK_ARG-}" test-java: <<: *common - command: /bin/bash -xcl "uname -a && swift -version && /jdk/bin/java -version && make jextract-run && ./gradlew test --debug" + command: /bin/bash -xcl "uname -a && swift -version && java -version && make jextract-run && ./gradlew test --debug" test: <<: *common - command: /bin/bash -xcl "uname -a && swift -version && /jdk/bin/java -version && make jextract-run && swift $${SWIFT_TEST_VERB-test} $${WARN_AS_ERROR_ARG-} $${SANITIZER_ARG-} $${IMPORT_CHECK_ARG-} && ./gradlew test --debug" + command: /bin/bash -xcl "uname -a && swift -version && java -version && make jextract-run && swift $${SWIFT_TEST_VERB-test} $${WARN_AS_ERROR_ARG-} $${SANITIZER_ARG-} $${IMPORT_CHECK_ARG-} && ./gradlew test --debug" # util From 695f0259c83172053eaf09cc2d2fbdba84581659 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Thu, 10 Oct 2024 17:00:40 +0900 Subject: [PATCH 060/426] working with snapshot toolchains also on arm --- Makefile | 20 +++++-- README.md | 29 +++++++++++ .../JExtractSwift/Swift2JavaTranslator.swift | 52 ------------------- .../FunctionDescriptorImportTests.swift | 16 +++--- docker/install_untested_nightly_swift.sh | 9 +++- 5 files changed, 61 insertions(+), 65 deletions(-) diff --git a/Makefile b/Makefile index 82ec954d..a114a61f 100644 --- a/Makefile +++ b/Makefile @@ -37,6 +37,20 @@ BUILD_DIR := .build/$(ARCH_SUBDIR)-apple-macosx LIB_SUFFIX := dylib endif +ifeq ($(UNAME), Darwin) +ifeq ("${TOOLCHAINS}", "") + SWIFTC := "xcrun swiftc" +else + SWIFTC := "xcrun ${TOOLCHAINS}/usr/bin/swiftc" +endif +else +ifeq ("${TOOLCHAINS}", "") + SWIFTC := "swiftc" +else + SWIFTC := "${TOOLCHAINS}/usr/bin/swiftc" +endif +endif + SAMPLES_DIR := "Samples" all: generate-all @@ -83,13 +97,13 @@ JEXTRACT_BUILD_DIR="$(BUILD_DIR)/jextract" define make_swiftinterface $(eval $@_MODULE = $(1)) $(eval $@_FILENAME = $(2)) - eval swiftc \ + eval ${SWIFTC} \ -emit-module-interface-path ${JEXTRACT_BUILD_DIR}/${$@_MODULE}/${$@_FILENAME}.swiftinterface \ -emit-module-path ${JEXTRACT_BUILD_DIR}/${$@_MODULE}/${$@_FILENAME}.swiftmodule \ -enable-library-evolution \ - -Xfrontend -abi-comments-in-module-interface \ + -Xfrontend -abi-comments-in-module-interface \ -module-name ${$@_MODULE} \ - -Xfrontend -abi-comments-in-module-interface \ + -Xfrontend -abi-comments-in-module-interface \ Sources/${$@_MODULE}/${$@_FILENAME}.swift echo "Generated: ${JEXTRACT_BUILD_DIR}/${$@_MODULE}/${$@_FILENAME}.swiftinterface" endef diff --git a/README.md b/README.md index 3161a23b..db491fe7 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,35 @@ The primary purpose of this repository is to create an environment for collabora ## Dependencies +### Required Swift Development Toolchains + +To build and use this project, currently, you will need to download a custom toolchain which includes some improvements in Swift that this project relies on: + +**Required toolchain download:** + +- Go to https://www.swift.org/download/ +- Find the "latest" `Trunk Development (main)` toolchain for your OS + +If these are too old, you can resort to one of these fallback toolchains: + +Fallback development toolchain on **macOS**: + +- https://ci.swift.org/job/swift-PR-toolchain-macos/1539/artifact/branch-main/swift-PR-76905-1539-osx.tar.gz + +Fallback development toolchain on **Linux (Ubuntu 22.04)**: + +``` +URL=$(curl -s "https://ci.swift.org/job/oss-swift-package-ubuntu-22_04/lastSuccessfulBuild/consoleText" | grep 'Toolchain: ' | sed 's/Toolchain: //g') +wget ${URL} +``` + +or just use the provided docker image (explained below). + +https://www.swift.org/download/ + + +### Required JDK versions + This project consists of different modules which have different Swift and Java runtime requirements. **JavaKit** – the Swift macros allowing the invocation of Java libraries from Swift diff --git a/Sources/JExtractSwift/Swift2JavaTranslator.swift b/Sources/JExtractSwift/Swift2JavaTranslator.swift index 722a94f1..b57c19af 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator.swift @@ -105,60 +105,8 @@ extension Swift2JavaTranslator { translator: self ) visitor.walk(sourceFileSyntax) - - try await self.postProcessImportedDecls() } - public func postProcessImportedDecls() async throws { - log.debug( - "Post process imported decls...", - metadata: [ - "types": "\(importedTypes.count)", - "global/funcs": "\(importedGlobalFuncs.count)", - ] - ) - - // FIXME: the use of dylibs to get symbols is a hack we need to remove and replace with interfaces containing mangled names - let dylibPath = ".build/arm64-apple-macosx/debug/lib\(swiftModuleName).dylib" - guard var dylib = SwiftDylib(path: dylibPath) else { - log.warning( - """ - Unable to find mangled names for imported symbols. Dylib not found: \(dylibPath) This method of obtaining symbols is a workaround; it will be removed. - """ - ) - return - } - - importedGlobalFuncs = try await importedGlobalFuncs._mapAsync { funcDecl in - let funcDecl = try await dylib.fillInMethodMangledName(funcDecl) - log.info("Mapped method '\(funcDecl.identifier)' -> '\(funcDecl.swiftMangledName)'") - return funcDecl - } - - importedTypes = Dictionary(uniqueKeysWithValues: try await importedTypes._mapAsync { (tyName, tyDecl) in - var tyDecl = tyDecl - log.info("Mapping type: \(tyDecl.swiftTypeName)") - - tyDecl = try await dylib.fillInTypeMangledName(tyDecl) - - log.info("Mapping members of: \(tyDecl.swiftTypeName)") - tyDecl.initializers = try await tyDecl.initializers._mapAsync { initDecl in - dylib.log.logLevel = .info - - let initDecl = try await dylib.fillInAllocatingInitMangledName(initDecl) - log.info("Mapped initializer '\(initDecl.identifier)' -> '\(initDecl.swiftMangledName)'") - return initDecl - } - - tyDecl.methods = try await tyDecl.methods._mapAsync { funcDecl in - let funcDecl = try await dylib.fillInMethodMangledName(funcDecl) - log.info("Mapped method '\(funcDecl.identifier)' -> '\(funcDecl.swiftMangledName)'") - return funcDecl - } - - return (tyName, tyDecl) - }) - } } // ===== -------------------------------------------------------------------------------------------------------------- diff --git a/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift b/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift index dcff090f..1c1dceaa 100644 --- a/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift +++ b/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift @@ -141,15 +141,15 @@ extension FunctionDescriptorTests { javaPackage: String = "com.example.swift", swiftModuleName: String = "SwiftModule", logLevel: Logger.Level = .trace, - body: (String) async throws -> () - ) async throws { + body: (String) throws -> () + ) throws { let st = Swift2JavaTranslator( javaPackage: javaPackage, swiftModuleName: swiftModuleName ) st.log.logLevel = logLevel - try await st.analyze(swiftInterfacePath: "/fake/Sample.swiftinterface", text: interfaceFile) + try st.analyze(swiftInterfacePath: "/fake/Sample.swiftinterface", text: interfaceFile) let funcDecl = st.importedGlobalFuncs.first { $0.baseIdentifier == methodIdentifier @@ -159,7 +159,7 @@ extension FunctionDescriptorTests { st.printFunctionDescriptorValue(&printer, funcDecl) } - try await body(output) + try body(output) } func variableAccessorDescriptorTest( @@ -168,15 +168,15 @@ extension FunctionDescriptorTests { javaPackage: String = "com.example.swift", swiftModuleName: String = "SwiftModule", logLevel: Logger.Level = .trace, - body: (String) async throws -> () - ) async throws { + body: (String) throws -> () + ) throws { let st = Swift2JavaTranslator( javaPackage: javaPackage, swiftModuleName: swiftModuleName ) st.log.logLevel = logLevel - try await st.analyze(swiftInterfacePath: "/fake/Sample.swiftinterface", text: interfaceFile) + try st.analyze(swiftInterfacePath: "/fake/Sample.swiftinterface", text: interfaceFile) let varDecl: ImportedVariable? = st.importedTypes.values.compactMap { @@ -192,7 +192,7 @@ extension FunctionDescriptorTests { st.printFunctionDescriptorValue(&printer, varDecl.accessorFunc(kind: accessorKind)!, accessorKind: accessorKind) } - try await body(getOutput) + try body(getOutput) } } \ No newline at end of file diff --git a/docker/install_untested_nightly_swift.sh b/docker/install_untested_nightly_swift.sh index 369a15cb..e3f1f15a 100755 --- a/docker/install_untested_nightly_swift.sh +++ b/docker/install_untested_nightly_swift.sh @@ -16,10 +16,15 @@ set -euo pipefail echo "Download [nightly] [untested] Swift toolchain for: $(uname -m)" -declare -r SWIFT_UNTESTED_TOOLCHAIN_JOB_URL="https://ci.swift.org/job/oss-swift-package-ubuntu-22_04/lastSuccessfulBuild/consoleText" +ARCH="$(arch)" +if [[ "$ARCH" = "i386" ]]; then + SWIFT_UNTESTED_TOOLCHAIN_JOB_URL="https://ci.swift.org/job/oss-swift-package-ubuntu-22_04/lastSuccessfulBuild/consoleText" +else + SWIFT_UNTESTED_TOOLCHAIN_JOB_URL="https://ci.swift.org/job/oss-swift-package-ubuntu-22_04-aarch64/lastSuccessfulBuild/consoleText" +fi if [[ "$(grep "22.04" /etc/lsb-release)" = "" ]]; then - echo "This script specifically only supports Ubuntu 20.04 due to nightly toolchain availability" + echo "This script specifically only supports Ubuntu 22.04 due to nightly toolchain availability" exit 1 fi From f49e408b366b517a04fa5fbdbbf0de549bdbb0fa Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Thu, 10 Oct 2024 17:01:58 +0900 Subject: [PATCH 061/426] enable tests which should not work with swift interface mangled names --- .../swift/generated/GeneratedJavaKitExampleModuleTest.java | 2 -- .../java/com/example/swift/generated/MySwiftClassTest.java | 3 --- .../src/test/java/org/swift/swiftkit/MySwiftClassTest.java | 1 - 3 files changed, 6 deletions(-) diff --git a/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/generated/GeneratedJavaKitExampleModuleTest.java b/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/generated/GeneratedJavaKitExampleModuleTest.java index 7bad75f2..9ec18ba6 100644 --- a/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/generated/GeneratedJavaKitExampleModuleTest.java +++ b/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/generated/GeneratedJavaKitExampleModuleTest.java @@ -34,7 +34,6 @@ static void beforeAll() { } @Test - @DisabledOnOs(OS.LINUX) // FIXME: enable on Linux when we get new compiler with mangled names in swift interfaces void call_helloWorld() { ExampleSwiftLibrary.helloWorld(); @@ -42,7 +41,6 @@ void call_helloWorld() { } @Test - @DisabledOnOs(OS.LINUX) // FIXME: enable on Linux when we get new compiler with mangled names in swift interfaces void call_globalTakeInt() { ExampleSwiftLibrary.globalTakeInt(12); diff --git a/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/generated/MySwiftClassTest.java b/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/generated/MySwiftClassTest.java index 8ca3f96b..0f20c172 100644 --- a/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/generated/MySwiftClassTest.java +++ b/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/generated/MySwiftClassTest.java @@ -35,14 +35,12 @@ static void beforeAll() { } @Test - @DisabledOnOs(OS.LINUX) // FIXME: enable on Linux when we get new compiler with mangled names in swift interfaces void test_MySwiftClass_voidMethod() { MySwiftClass o = new MySwiftClass(12, 42); o.voidMethod(); } @Test - @DisabledOnOs(OS.LINUX) // FIXME: enable on Linux when we get new compiler with mangled names in swift interfaces void test_MySwiftClass_makeIntMethod() { MySwiftClass o = new MySwiftClass(12, 42); var got = o.makeIntMethod(); @@ -50,7 +48,6 @@ void test_MySwiftClass_makeIntMethod() { } @Test - @DisabledOnOs(OS.LINUX) // FIXME: enable on Linux when we get new compiler with mangled names in swift interfaces void test_MySwiftClass_property_len() { MySwiftClass o = new MySwiftClass(12, 42); var got = o.makeIntMethod(); diff --git a/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/MySwiftClassTest.java b/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/MySwiftClassTest.java index 7968cfae..b04da744 100644 --- a/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/MySwiftClassTest.java +++ b/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/MySwiftClassTest.java @@ -36,7 +36,6 @@ static void beforeAll() { } @Test - @DisabledOnOs(OS.LINUX) // FIXME: enable on Linux when we get new compiler with mangled names in swift interfaces void call_retain_retainCount_release() { var obj = new MySwiftClass(1, 2); From 482e70396632783826568d1fa2b51eba286ce349 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Thu, 10 Oct 2024 17:07:07 +0900 Subject: [PATCH 062/426] correct x86 handling in installer script --- docker/install_untested_nightly_swift.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/install_untested_nightly_swift.sh b/docker/install_untested_nightly_swift.sh index e3f1f15a..9cb920ab 100755 --- a/docker/install_untested_nightly_swift.sh +++ b/docker/install_untested_nightly_swift.sh @@ -17,7 +17,7 @@ set -euo pipefail echo "Download [nightly] [untested] Swift toolchain for: $(uname -m)" ARCH="$(arch)" -if [[ "$ARCH" = "i386" ]]; then +if [[ "$ARCH" = "i386" || "$ARCH" = "x86_64" ]]; then SWIFT_UNTESTED_TOOLCHAIN_JOB_URL="https://ci.swift.org/job/oss-swift-package-ubuntu-22_04/lastSuccessfulBuild/consoleText" else SWIFT_UNTESTED_TOOLCHAIN_JOB_URL="https://ci.swift.org/job/oss-swift-package-ubuntu-22_04-aarch64/lastSuccessfulBuild/consoleText" From 6f6c3500d995dc90d296a15230e66ffbb742f674 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Thu, 10 Oct 2024 18:24:42 +0900 Subject: [PATCH 063/426] Skipping the JVM tests on macOS terminal since unreliable (crashes in JVM create) --- .../VariableImportTests.swift | 3 +-- Tests/JavaKitTests/BasicRuntimeTests.swift | 19 +++++++++++++++---- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/Tests/JExtractSwiftTests/VariableImportTests.swift b/Tests/JExtractSwiftTests/VariableImportTests.swift index f59b8ff4..2f58c5c8 100644 --- a/Tests/JExtractSwiftTests/VariableImportTests.swift +++ b/Tests/JExtractSwiftTests/VariableImportTests.swift @@ -41,7 +41,7 @@ final class VariableImportTests { ) st.log.logLevel = .error - try await st.analyze(swiftInterfacePath: "/fake/Fake.swiftinterface", text: class_interfaceFile) + try st.analyze(swiftInterfacePath: "/fake/Fake.swiftinterface", text: class_interfaceFile) let identifier = "counterInt" let varDecl: ImportedVariable? = @@ -59,7 +59,6 @@ final class VariableImportTests { } assertOutput( - dump: true, output, expected: """ diff --git a/Tests/JavaKitTests/BasicRuntimeTests.swift b/Tests/JavaKitTests/BasicRuntimeTests.swift index 2e47b84f..ff368fbd 100644 --- a/Tests/JavaKitTests/BasicRuntimeTests.swift +++ b/Tests/JavaKitTests/BasicRuntimeTests.swift @@ -17,13 +17,19 @@ import JavaKitNetwork import JavaKitVM import Testing +#if os(Linux) +import Glibc +#else +import Darwin +#endif + @MainActor let jvm = try! JavaVirtualMachine(vmOptions: []) @Suite @MainActor struct BasicRuntimeTests { - @Test("Object management", .disabled(if: isLinux, "Attempts to refcount a null pointer on Linux")) + @Test("Object management", .disabled(if: isMacOSTerminal || isLinux, "JVM creation fails occasionally in terminal on macOS, and some issues on Linux")) func javaObjectManagement() throws { let sneakyJavaThis: jobject do { @@ -49,7 +55,7 @@ struct BasicRuntimeTests { #expect(url.javaHolder === urlAgain.javaHolder) } - @Test("Java exceptions", .disabled(if: isLinux, "Attempts to refcount a null pointer on Linux")) + @Test("Java exceptions", .disabled(if: isMacOSTerminal || isLinux, "JVM creation fails occasionally in terminal on macOS, and some issues on Linux")) func javaExceptionsInSwift() throws { do { _ = try URL("bad url", environment: jvm.environment) @@ -58,13 +64,13 @@ struct BasicRuntimeTests { } } - @Test("Static methods", .disabled(if: isMacOS, "Fails on macOS command line")) + @Test("Static methods", .disabled(if: isMacOSTerminal || isLinux, "JVM creation fails occasionally in terminal on macOS, and some issues on Linux")) func staticMethods() throws { let urlConnectionClass = try JavaClass(in: jvm.environment) #expect(urlConnectionClass.getDefaultAllowUserInteraction() == false) } - @Test("Class instance lookup") + @Test("Class instance lookup", .disabled(if: isMacOSTerminal || isLinux, "JVM creation fails occasionally in terminal on macOS, and some issues on Linux")) func classInstanceLookup() throws { do { _ = try JavaClass(in: jvm.environment) @@ -86,6 +92,11 @@ var isLinux: Bool { #endif } +/// Whether we're running on MacOS in an interactive terminal session. +var isMacOSTerminal: Bool { + isMacOS && isatty(STDOUT_FILENO) == 1 +} + /// Whether we're running on MacOS. var isMacOS: Bool { #if os(macOS) From c70f3d2b2468e48ff7386b92fd638214909f33f3 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Thu, 10 Oct 2024 18:39:23 +0900 Subject: [PATCH 064/426] additional env var to force saying we're in tty --- Tests/JavaKitTests/BasicRuntimeTests.swift | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Tests/JavaKitTests/BasicRuntimeTests.swift b/Tests/JavaKitTests/BasicRuntimeTests.swift index ff368fbd..e8e9ac82 100644 --- a/Tests/JavaKitTests/BasicRuntimeTests.swift +++ b/Tests/JavaKitTests/BasicRuntimeTests.swift @@ -16,6 +16,7 @@ import JavaKit import JavaKitNetwork import JavaKitVM import Testing +import Foundation #if os(Linux) import Glibc @@ -94,7 +95,10 @@ var isLinux: Bool { /// Whether we're running on MacOS in an interactive terminal session. var isMacOSTerminal: Bool { - isMacOS && isatty(STDOUT_FILENO) == 1 + isMacOS && ( + isatty(STDOUT_FILENO) == 1 || + ProcessInfo.processInfo.environment["IS_TTY"] != nil // since 'swift test' still sometimes hides the fact we're in tty + ) } /// Whether we're running on MacOS. From 5ed00636f4684d74d70dc48261df812478ffbf2c Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Thu, 10 Oct 2024 09:30:22 -0700 Subject: [PATCH 065/426] Revert "additional env var to force saying we're in tty" This reverts commit c70f3d2b2468e48ff7386b92fd638214909f33f3. --- Tests/JavaKitTests/BasicRuntimeTests.swift | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Tests/JavaKitTests/BasicRuntimeTests.swift b/Tests/JavaKitTests/BasicRuntimeTests.swift index e8e9ac82..ff368fbd 100644 --- a/Tests/JavaKitTests/BasicRuntimeTests.swift +++ b/Tests/JavaKitTests/BasicRuntimeTests.swift @@ -16,7 +16,6 @@ import JavaKit import JavaKitNetwork import JavaKitVM import Testing -import Foundation #if os(Linux) import Glibc @@ -95,10 +94,7 @@ var isLinux: Bool { /// Whether we're running on MacOS in an interactive terminal session. var isMacOSTerminal: Bool { - isMacOS && ( - isatty(STDOUT_FILENO) == 1 || - ProcessInfo.processInfo.environment["IS_TTY"] != nil // since 'swift test' still sometimes hides the fact we're in tty - ) + isMacOS && isatty(STDOUT_FILENO) == 1 } /// Whether we're running on MacOS. From e40db8b8af643649023147a3850fd585cf5b74e2 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Thu, 10 Oct 2024 09:30:57 -0700 Subject: [PATCH 066/426] Revert "Skipping the JVM tests on macOS terminal since unreliable (crashes in JVM create)" This reverts commit 6f6c3500d995dc90d296a15230e66ffbb742f674. --- .../VariableImportTests.swift | 3 ++- Tests/JavaKitTests/BasicRuntimeTests.swift | 19 ++++--------------- 2 files changed, 6 insertions(+), 16 deletions(-) diff --git a/Tests/JExtractSwiftTests/VariableImportTests.swift b/Tests/JExtractSwiftTests/VariableImportTests.swift index 2f58c5c8..f59b8ff4 100644 --- a/Tests/JExtractSwiftTests/VariableImportTests.swift +++ b/Tests/JExtractSwiftTests/VariableImportTests.swift @@ -41,7 +41,7 @@ final class VariableImportTests { ) st.log.logLevel = .error - try st.analyze(swiftInterfacePath: "/fake/Fake.swiftinterface", text: class_interfaceFile) + try await st.analyze(swiftInterfacePath: "/fake/Fake.swiftinterface", text: class_interfaceFile) let identifier = "counterInt" let varDecl: ImportedVariable? = @@ -59,6 +59,7 @@ final class VariableImportTests { } assertOutput( + dump: true, output, expected: """ diff --git a/Tests/JavaKitTests/BasicRuntimeTests.swift b/Tests/JavaKitTests/BasicRuntimeTests.swift index ff368fbd..2e47b84f 100644 --- a/Tests/JavaKitTests/BasicRuntimeTests.swift +++ b/Tests/JavaKitTests/BasicRuntimeTests.swift @@ -17,19 +17,13 @@ import JavaKitNetwork import JavaKitVM import Testing -#if os(Linux) -import Glibc -#else -import Darwin -#endif - @MainActor let jvm = try! JavaVirtualMachine(vmOptions: []) @Suite @MainActor struct BasicRuntimeTests { - @Test("Object management", .disabled(if: isMacOSTerminal || isLinux, "JVM creation fails occasionally in terminal on macOS, and some issues on Linux")) + @Test("Object management", .disabled(if: isLinux, "Attempts to refcount a null pointer on Linux")) func javaObjectManagement() throws { let sneakyJavaThis: jobject do { @@ -55,7 +49,7 @@ struct BasicRuntimeTests { #expect(url.javaHolder === urlAgain.javaHolder) } - @Test("Java exceptions", .disabled(if: isMacOSTerminal || isLinux, "JVM creation fails occasionally in terminal on macOS, and some issues on Linux")) + @Test("Java exceptions", .disabled(if: isLinux, "Attempts to refcount a null pointer on Linux")) func javaExceptionsInSwift() throws { do { _ = try URL("bad url", environment: jvm.environment) @@ -64,13 +58,13 @@ struct BasicRuntimeTests { } } - @Test("Static methods", .disabled(if: isMacOSTerminal || isLinux, "JVM creation fails occasionally in terminal on macOS, and some issues on Linux")) + @Test("Static methods", .disabled(if: isMacOS, "Fails on macOS command line")) func staticMethods() throws { let urlConnectionClass = try JavaClass(in: jvm.environment) #expect(urlConnectionClass.getDefaultAllowUserInteraction() == false) } - @Test("Class instance lookup", .disabled(if: isMacOSTerminal || isLinux, "JVM creation fails occasionally in terminal on macOS, and some issues on Linux")) + @Test("Class instance lookup") func classInstanceLookup() throws { do { _ = try JavaClass(in: jvm.environment) @@ -92,11 +86,6 @@ var isLinux: Bool { #endif } -/// Whether we're running on MacOS in an interactive terminal session. -var isMacOSTerminal: Bool { - isMacOS && isatty(STDOUT_FILENO) == 1 -} - /// Whether we're running on MacOS. var isMacOS: Bool { #if os(macOS) From 48396488cf3276b748593bc9c93788ce59b257ab Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Thu, 10 Oct 2024 09:40:07 -0700 Subject: [PATCH 067/426] Temporarily switch JavaKitTests target to XCTest Command-line testing on macOS is broken for the JavaKitTests due to an interaction between the Java Virtual Machine, a helper test process for swift-testing (`swiftpm-testing-helper`), and some macOS security features. Work around the issue by replacing our use of swift-testing with XCTest, whose helper process doesn't seem to have this problem. Only do so for test targets that need to spin up an instance of the JVM, and keep using swift-testing everywhere we can. This makes me very sad, but is better than the current solution of disabling these tests when running from the terminal. Once we've found a solution for the underlying issue, we'll revert this change as get back to swift-testing and its much nicer testing output. Fixes issue #43 without disabling tests. --- Tests/JavaKitTests/BasicRuntimeTests.swift | 54 +++++++++++----------- 1 file changed, 26 insertions(+), 28 deletions(-) diff --git a/Tests/JavaKitTests/BasicRuntimeTests.swift b/Tests/JavaKitTests/BasicRuntimeTests.swift index 2e47b84f..ea51a4e2 100644 --- a/Tests/JavaKitTests/BasicRuntimeTests.swift +++ b/Tests/JavaKitTests/BasicRuntimeTests.swift @@ -15,23 +15,25 @@ import JavaKit import JavaKitNetwork import JavaKitVM -import Testing +import XCTest // NOTE: Workaround for https://github.com/swiftlang/swift-java/issues/43 @MainActor let jvm = try! JavaVirtualMachine(vmOptions: []) -@Suite @MainActor -struct BasicRuntimeTests { - @Test("Object management", .disabled(if: isLinux, "Attempts to refcount a null pointer on Linux")) - func javaObjectManagement() throws { +class BasicRuntimeTests: XCTestCase { + func testJavaObjectManagement() throws { + if isLinux { + throw XCTSkip("Attempts to refcount a null pointer on Linux") + } + let sneakyJavaThis: jobject do { let object = JavaObject(environment: jvm.environment) - #expect(object.toString().starts(with: "java.lang.Object")) + XCTAssert(object.toString().starts(with: "java.lang.Object")) // Make sure this object was promoted to a global reference. - #expect(object.javaEnvironment.pointee?.pointee.GetObjectRefType(object.javaEnvironment, object.javaThis) == JNIGlobalRefType) + XCTAssertEqual(object.javaEnvironment.pointee?.pointee.GetObjectRefType(object.javaEnvironment, object.javaThis), JNIGlobalRefType) // Keep track of the Java object. sneakyJavaThis = object.javaThis @@ -39,37 +41,42 @@ struct BasicRuntimeTests { // The reference should now be invalid, because we've deleted the // global reference. - #expect(jvm.environment.pointee?.pointee.GetObjectRefType(jvm.environment, sneakyJavaThis) == JNIInvalidRefType) + XCTAssertEqual(jvm.environment.pointee?.pointee.GetObjectRefType(jvm.environment, sneakyJavaThis), JNIInvalidRefType) // 'super' and 'as' don't require allocating a new holder. let url = try URL("http://swift.org", environment: jvm.environment) let superURL = url.super - #expect(url.javaHolder === superURL.javaHolder) + XCTAssert(url.javaHolder === superURL.javaHolder) let urlAgain = superURL.as(URL.self)! - #expect(url.javaHolder === urlAgain.javaHolder) + XCTAssert(url.javaHolder === urlAgain.javaHolder) } - @Test("Java exceptions", .disabled(if: isLinux, "Attempts to refcount a null pointer on Linux")) - func javaExceptionsInSwift() throws { + func testJavaExceptionsInSwift() throws { + if isLinux { + throw XCTSkip("Attempts to refcount a null pointer on Linux") + } + do { _ = try URL("bad url", environment: jvm.environment) } catch { - #expect(String(describing: error) == "no protocol: bad url") + XCTAssert(String(describing: error) == "no protocol: bad url") } } - @Test("Static methods", .disabled(if: isMacOS, "Fails on macOS command line")) - func staticMethods() throws { + func testStaticMethods() throws { + if isLinux { + throw XCTSkip("Attempts to refcount a null pointer on Linux") + } + let urlConnectionClass = try JavaClass(in: jvm.environment) - #expect(urlConnectionClass.getDefaultAllowUserInteraction() == false) + XCTAssert(urlConnectionClass.getDefaultAllowUserInteraction() == false) } - @Test("Class instance lookup") - func classInstanceLookup() throws { + func testClassInstanceLookup() throws { do { _ = try JavaClass(in: jvm.environment) } catch { - #expect(String(describing: error) == "org/swift/javakit/Nonexistent") + XCTAssertEqual(String(describing: error), "org/swift/javakit/Nonexistent") } } } @@ -85,12 +92,3 @@ var isLinux: Bool { return false #endif } - -/// Whether we're running on MacOS. -var isMacOS: Bool { - #if os(macOS) - return true - #else - return false - #endif -} From 6d4c9f1871d39c72639c1373ab41e682f3b561bf Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Thu, 10 Oct 2024 09:56:45 -0700 Subject: [PATCH 068/426] async'ify the XCTest test cases so they can hop to the main actor --- Tests/JavaKitTests/BasicRuntimeTests.swift | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Tests/JavaKitTests/BasicRuntimeTests.swift b/Tests/JavaKitTests/BasicRuntimeTests.swift index ea51a4e2..33f795b9 100644 --- a/Tests/JavaKitTests/BasicRuntimeTests.swift +++ b/Tests/JavaKitTests/BasicRuntimeTests.swift @@ -22,7 +22,7 @@ let jvm = try! JavaVirtualMachine(vmOptions: []) @MainActor class BasicRuntimeTests: XCTestCase { - func testJavaObjectManagement() throws { + func testJavaObjectManagement() async throws { if isLinux { throw XCTSkip("Attempts to refcount a null pointer on Linux") } @@ -51,7 +51,7 @@ class BasicRuntimeTests: XCTestCase { XCTAssert(url.javaHolder === urlAgain.javaHolder) } - func testJavaExceptionsInSwift() throws { + func testJavaExceptionsInSwift() async throws { if isLinux { throw XCTSkip("Attempts to refcount a null pointer on Linux") } @@ -63,7 +63,7 @@ class BasicRuntimeTests: XCTestCase { } } - func testStaticMethods() throws { + func testStaticMethods() async throws { if isLinux { throw XCTSkip("Attempts to refcount a null pointer on Linux") } @@ -72,7 +72,7 @@ class BasicRuntimeTests: XCTestCase { XCTAssert(urlConnectionClass.getDefaultAllowUserInteraction() == false) } - func testClassInstanceLookup() throws { + func testClassInstanceLookup() async throws { do { _ = try JavaClass(in: jvm.environment) } catch { From b69f4d7341496e0ae5936d3cb413da7c76636606 Mon Sep 17 00:00:00 2001 From: Jack Rosen Date: Thu, 10 Oct 2024 22:58:36 +0200 Subject: [PATCH 069/426] Add Support for Static Fields to Java2Swift tool (#61) * Add JavaStaticField and Update Translator * Update name to be better * Update docs and usage * Add static to error --- Sources/Java2Swift/JavaTranslator.swift | 32 ++++++++++++--------- Sources/JavaKit/Macros.swift | 14 +++++++++ Sources/JavaKitExample/JavaKitExample.swift | 4 +-- 3 files changed, 34 insertions(+), 16 deletions(-) diff --git a/Sources/Java2Swift/JavaTranslator.swift b/Sources/Java2Swift/JavaTranslator.swift index 9c445df7..78f3cd87 100644 --- a/Sources/Java2Swift/JavaTranslator.swift +++ b/Sources/Java2Swift/JavaTranslator.swift @@ -257,7 +257,7 @@ extension JavaTranslator { do { return try translateField(field) } catch { - logUntranslated("Unable to translate '\(fullName)' field '\(field.getName())': \(error)") + logUntranslated("Unable to translate '\(fullName)' static field '\(field.getName())': \(error)") return nil } } @@ -347,23 +347,28 @@ extension JavaTranslator { // Format the class declaration. classDecl = classDecl.formatted(using: format).cast(DeclSyntax.self) - - // TODO: Handle static fields in https://github.com/swiftlang/swift-java/issues/39 - - if staticMethods.isEmpty { + + if staticMethods.isEmpty && staticFields.isEmpty { return [classDecl] } // Translate static members. var staticMembers: [DeclSyntax] = [] - staticMembers.append( - contentsOf: javaClass.getMethods().compactMap { - $0.flatMap { method in - // Skip the instance methods; they were handled above. - if !method.isStatic { - return nil - } + staticMembers.append( + contentsOf: staticFields.compactMap { field in + // Translate each static field. + do { + return try translateField(field) + } catch { + logUntranslated("Unable to translate '\(fullName)' field '\(field.getName())': \(error)") + return nil + } + } + ) + + staticMembers.append( + contentsOf: staticMethods.compactMap { method in // Translate each static method. do { return try translateMethod( @@ -376,7 +381,6 @@ extension JavaTranslator { return nil } } - } ) if staticMembers.isEmpty { @@ -447,7 +451,7 @@ extension JavaTranslator { func translateField(_ javaField: Field) throws -> DeclSyntax { let typeName = try getSwiftTypeNameAsString(javaField.getGenericType()!, outerOptional: true) - let fieldAttribute: AttributeSyntax = "@JavaField"; + let fieldAttribute: AttributeSyntax = javaField.isStatic ? "@JavaStaticField" : "@JavaField"; return """ \(fieldAttribute) public var \(raw: javaField.getName()): \(raw: typeName) diff --git a/Sources/JavaKit/Macros.swift b/Sources/JavaKit/Macros.swift index 772138f8..51d62739 100644 --- a/Sources/JavaKit/Macros.swift +++ b/Sources/JavaKit/Macros.swift @@ -93,6 +93,20 @@ public macro JavaInterface(_ fullClassName: String, extends: (any AnyJavaObject. @attached(accessor) public macro JavaField(_ javaFieldName: String? = nil) = #externalMacro(module: "JavaKitMacros", type: "JavaFieldMacro") + +/// Attached macro that turns a Swift property into one that accesses a Java static field on the underlying Java object. +/// +/// The macro must be used within a specific JavaClass instance. +/// +/// ```swift +/// extension JavaClass { +/// @JavaStaticField +/// var initialValue: Double +/// } +/// ``` +@attached(accessor) +public macro JavaStaticField(_ javaFieldName: String? = nil) = #externalMacro(module: "JavaKitMacros", type: "JavaFieldMacro") + /// Attached macro that turns a Swift method into one that wraps a Java method on the underlying Java object. /// /// The macro must be used in an AnyJavaObject-conforming type. diff --git a/Sources/JavaKitExample/JavaKitExample.swift b/Sources/JavaKitExample/JavaKitExample.swift index bcc58114..d6eba19d 100644 --- a/Sources/JavaKitExample/JavaKitExample.swift +++ b/Sources/JavaKitExample/JavaKitExample.swift @@ -103,7 +103,7 @@ struct HelloSwift { } extension JavaClass { - @JavaField + @JavaStaticField var initialValue: Double } @@ -117,4 +117,4 @@ struct HelloSubclass { @JavaMethod init(greeting: String, environment: JNIEnvironment) -} \ No newline at end of file +} From 98b7184143a9b719f11b165846ff06b20ac65650 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Fri, 11 Oct 2024 11:41:06 -0700 Subject: [PATCH 070/426] Lazily attach threads to the JVM when querying the JNI environment Instead of having the JavaVirtualMachine instance keep track of the JNI environment for the thread in which it was initialized, provide a JNI environment query function that attaches the current thread to the JVM if needed. This lets us query the JNI environment for multiple threads, should we want to. We no longer need to force all of the JavaKit runtime tests to the main actor. --- Sources/Java2Swift/JavaToSwift.swift | 2 +- Sources/JavaKitVM/JavaVirtualMachine.swift | 54 ++++++++++++++++++++-- Tests/JavaKitTests/BasicRuntimeTests.swift | 20 +++++--- 3 files changed, 63 insertions(+), 13 deletions(-) diff --git a/Sources/Java2Swift/JavaToSwift.swift b/Sources/Java2Swift/JavaToSwift.swift index fb24e091..b9df359c 100644 --- a/Sources/Java2Swift/JavaToSwift.swift +++ b/Sources/Java2Swift/JavaToSwift.swift @@ -71,7 +71,7 @@ struct JavaToSwift: ParsableCommand { let jvm = try JavaVirtualMachine(vmOptions: vmOptions) javaVirtualMachine = jvm - try run(environment: jvm.environment) + try run(environment: jvm.environment()) } mutating func run(environment: JNIEnvironment) throws { diff --git a/Sources/JavaKitVM/JavaVirtualMachine.swift b/Sources/JavaKitVM/JavaVirtualMachine.swift index 5fc26940..8985335c 100644 --- a/Sources/JavaKitVM/JavaVirtualMachine.swift +++ b/Sources/JavaKitVM/JavaVirtualMachine.swift @@ -17,12 +17,12 @@ import JavaKit typealias JavaVMPointer = UnsafeMutablePointer public final class JavaVirtualMachine: @unchecked Sendable { + /// The JNI version that we depend on. + static let jniVersion = JNI_VERSION_1_6 + /// The Java virtual machine instance. private let jvm: JavaVMPointer - /// The JNI environment for the JVM. - public let environment: JNIEnvironment - /// Initialize a new Java virtual machine instance. /// /// - Parameters: @@ -41,7 +41,7 @@ public final class JavaVirtualMachine: @unchecked Sendable { var jvm: JavaVMPointer? = nil var environment: UnsafeMutableRawPointer? = nil var vmArgs = JavaVMInitArgs() - vmArgs.version = JNI_VERSION_1_6 + vmArgs.version = JavaVirtualMachine.jniVersion vmArgs.ignoreUnrecognized = jboolean(ignoreUnrecognized ? JNI_TRUE : JNI_FALSE) // Construct the complete list of VM options. @@ -80,7 +80,6 @@ public final class JavaVirtualMachine: @unchecked Sendable { } self.jvm = jvm! - self.environment = environment!.assumingMemoryBound(to: JNIEnv?.self) } deinit { @@ -89,10 +88,55 @@ public final class JavaVirtualMachine: @unchecked Sendable { fatalError("Failed to destroy the JVM.") } } + + /// Produce the JNI environment for the active thread, attaching this + /// thread to the JVM if it isn't already. + /// + /// - Parameter + /// - asDaemon: Whether this thread should be treated as a daemon + /// thread in the Java Virtual Machine. + public func environment(asDaemon: Bool = false) throws -> JNIEnvironment { + // Check whether this thread is already attached. If so, return the + // corresponding environment. + var environment: UnsafeMutableRawPointer? = nil + let getEnvResult = jvm.pointee!.pointee.GetEnv( + jvm, + &environment, + JavaVirtualMachine.jniVersion + ) + if getEnvResult == JNI_OK, let environment { + return environment.assumingMemoryBound(to: JNIEnv?.self) + } + + // Attach the current thread to the JVM. + let attachResult: jint + if asDaemon { + attachResult = jvm.pointee!.pointee.AttachCurrentThreadAsDaemon(jvm, &environment, nil) + } else { + attachResult = jvm.pointee!.pointee.AttachCurrentThread(jvm, &environment, nil) + } + + if attachResult == JNI_OK, let environment { + return environment.assumingMemoryBound(to: JNIEnv?.self) + } + + throw VMError.failedToAttachThread + } + + /// Detach the current thread from the Java Virtual Machine. All Java + /// threads waiting for this thread to die are notified. + public func detachCurrentThread() throws { + let result = jvm.pointee!.pointee.DetachCurrentThread(jvm) + if result != JNI_OK { + throw VMError.failedToDetachThread + } + } } extension JavaVirtualMachine { enum VMError: Error { case failedToCreateVM + case failedToAttachThread + case failedToDetachThread } } diff --git a/Tests/JavaKitTests/BasicRuntimeTests.swift b/Tests/JavaKitTests/BasicRuntimeTests.swift index 33f795b9..55eee2d4 100644 --- a/Tests/JavaKitTests/BasicRuntimeTests.swift +++ b/Tests/JavaKitTests/BasicRuntimeTests.swift @@ -20,16 +20,16 @@ import XCTest // NOTE: Workaround for https://github.com/swiftlang/swift-java/is @MainActor let jvm = try! JavaVirtualMachine(vmOptions: []) -@MainActor class BasicRuntimeTests: XCTestCase { func testJavaObjectManagement() async throws { if isLinux { throw XCTSkip("Attempts to refcount a null pointer on Linux") } + let environment = try await jvm.environment() let sneakyJavaThis: jobject do { - let object = JavaObject(environment: jvm.environment) + let object = JavaObject(environment: environment) XCTAssert(object.toString().starts(with: "java.lang.Object")) // Make sure this object was promoted to a global reference. @@ -41,10 +41,10 @@ class BasicRuntimeTests: XCTestCase { // The reference should now be invalid, because we've deleted the // global reference. - XCTAssertEqual(jvm.environment.pointee?.pointee.GetObjectRefType(jvm.environment, sneakyJavaThis), JNIInvalidRefType) + XCTAssertEqual(environment.pointee?.pointee.GetObjectRefType(environment, sneakyJavaThis), JNIInvalidRefType) // 'super' and 'as' don't require allocating a new holder. - let url = try URL("http://swift.org", environment: jvm.environment) + let url = try URL("http://swift.org", environment: environment) let superURL = url.super XCTAssert(url.javaHolder === superURL.javaHolder) let urlAgain = superURL.as(URL.self)! @@ -56,8 +56,10 @@ class BasicRuntimeTests: XCTestCase { throw XCTSkip("Attempts to refcount a null pointer on Linux") } + let environment = try await jvm.environment() + do { - _ = try URL("bad url", environment: jvm.environment) + _ = try URL("bad url", environment: environment) } catch { XCTAssert(String(describing: error) == "no protocol: bad url") } @@ -68,13 +70,17 @@ class BasicRuntimeTests: XCTestCase { throw XCTSkip("Attempts to refcount a null pointer on Linux") } - let urlConnectionClass = try JavaClass(in: jvm.environment) + let environment = try await jvm.environment() + + let urlConnectionClass = try JavaClass(in: environment) XCTAssert(urlConnectionClass.getDefaultAllowUserInteraction() == false) } func testClassInstanceLookup() async throws { + let environment = try await jvm.environment() + do { - _ = try JavaClass(in: jvm.environment) + _ = try JavaClass(in: environment) } catch { XCTAssertEqual(String(describing: error), "org/swift/javakit/Nonexistent") } From adb1e0009f436963ed12e49c46447e9362f7135c Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Fri, 11 Oct 2024 12:20:16 -0700 Subject: [PATCH 071/426] Introduce support for a shared JavaVirtualMachine instance Java implementations have a longstanding limitation that there may only be one Java Virtual Machine instance per process. Take advantage of this to provide a shared JavaVirtualMachine instance, initialized on first use, that can be accessed from any thread. This eliminates the need to force JavaVirtualMachine creation to be on the main actor, since we can do it from any thread and get the same result. --- Sources/Java2Swift/JavaToSwift.swift | 7 +- Sources/JavaKitVM/JavaVirtualMachine.swift | 101 +++++++++++++++++- .../LockedState.swift | 0 Tests/JavaKitTests/BasicRuntimeTests.swift | 16 +-- 4 files changed, 109 insertions(+), 15 deletions(-) rename Sources/{_Subprocess => JavaKitVM}/LockedState.swift (100%) diff --git a/Sources/Java2Swift/JavaToSwift.swift b/Sources/Java2Swift/JavaToSwift.swift index b9df359c..ad9cf4f3 100644 --- a/Sources/Java2Swift/JavaToSwift.swift +++ b/Sources/Java2Swift/JavaToSwift.swift @@ -22,9 +22,6 @@ import JavaKitVM import SwiftSyntax import SwiftSyntaxBuilder -/// Global instance of the Java virtual machine that we keep alive forever. -var javaVirtualMachine: JavaVirtualMachine? = nil - /// Command-line utility to drive the export of Java classes into Swift types. @main struct JavaToSwift: ParsableCommand { @@ -68,9 +65,7 @@ struct JavaToSwift: ParsableCommand { vmOptions.append(contentsOf: classpath) } - let jvm = try JavaVirtualMachine(vmOptions: vmOptions) - javaVirtualMachine = jvm - + let jvm = try JavaVirtualMachine.shared(vmOptions: vmOptions) try run(environment: jvm.environment()) } diff --git a/Sources/JavaKitVM/JavaVirtualMachine.swift b/Sources/JavaKitVM/JavaVirtualMachine.swift index 8985335c..63c00ad9 100644 --- a/Sources/JavaKitVM/JavaVirtualMachine.swift +++ b/Sources/JavaKitVM/JavaVirtualMachine.swift @@ -23,6 +23,11 @@ public final class JavaVirtualMachine: @unchecked Sendable { /// The Java virtual machine instance. private let jvm: JavaVMPointer + /// Adopt an existing JVM pointer. + private init(adoptingJVM jvm: JavaVMPointer) { + self.jvm = jvm + } + /// Initialize a new Java virtual machine instance. /// /// - Parameters: @@ -33,7 +38,7 @@ public final class JavaVirtualMachine: @unchecked Sendable { /// be prefixed by the class-path argument described above. /// - ignoreUnrecognized: Whether the JVM should ignore any VM options it /// does not recognize. - public init( + private init( classPath: [String] = [], vmOptions: [String] = [], ignoreUnrecognized: Bool = true @@ -74,8 +79,13 @@ public final class JavaVirtualMachine: @unchecked Sendable { vmArgs.options = optionsBuffer.baseAddress vmArgs.nOptions = jint(optionsBuffer.count) - // Create the JVM. - if JNI_CreateJavaVM(&jvm, &environment, &vmArgs) != JNI_OK { + // Create the JVM instance. + let createResult = JNI_CreateJavaVM(&jvm, &environment, &vmArgs) + if createResult != JNI_OK { + if createResult == JNI_EEXIST { + throw VMError.existingVM + } + throw VMError.failedToCreateVM } @@ -88,7 +98,10 @@ public final class JavaVirtualMachine: @unchecked Sendable { fatalError("Failed to destroy the JVM.") } } +} +// MARK: Java thread management. +extension JavaVirtualMachine { /// Produce the JNI environment for the active thread, attaching this /// thread to the JVM if it isn't already. /// @@ -133,10 +146,92 @@ public final class JavaVirtualMachine: @unchecked Sendable { } } +// MARK: Shared Java Virtual Machine management. +extension JavaVirtualMachine { + /// The globally shared JavaVirtualMachine instance, behind a lock. + /// + /// TODO: If the use of the lock itself ends up being slow, we could + /// use an atomic here instead because our access pattern is fairly + /// simple. + private static let sharedJVM: LockedState = .init(initialState: nil) + + /// Access the shared Java Virtual Machine instance. + /// + /// If there is no shared Java Virtual Machine, create one with the given + /// arguments. Note that this function makes no attempt to try to augment + /// an existing virtual machine instance with the options given, so it is + /// up to clients to ensure that consistent arguments are provided to all + /// calls. + /// + /// - Parameters: + /// - classPath: The directories, JAR files, and ZIP files in which the JVM + /// should look to find classes. This maps to the VM option + /// `-Djava.class.path=`. + /// - vmOptions: Options that should be passed along to the JVM, which will + /// be prefixed by the class-path argument described above. + /// - ignoreUnrecognized: Whether the JVM should ignore any VM options it + /// does not recognize. + public static func shared( + classPath: [String] = [], + vmOptions: [String] = [], + ignoreUnrecognized: Bool = true + ) throws -> JavaVirtualMachine { + try sharedJVM.withLock { (sharedJVMPointer: inout JavaVirtualMachine?) in + // If we already have a JavaVirtualMachine instance, return it. + if let existingInstance = sharedJVMPointer { + return existingInstance + } + + while true { + var wasExistingVM: Bool = false + while true { + // Query the JVM itself to determine whether there is a JVM + // instance that we don't yet know about. + var jvm: UnsafeMutablePointer? = nil + var numJVMs: jsize = 0 + if JNI_GetCreatedJavaVMs(&jvm, 1, &numJVMs) == JNI_OK, numJVMs >= 1 { + // Adopt this JVM into a new instance of the JavaVirtualMachine + // wrapper. + let javaVirtualMachine = JavaVirtualMachine(adoptingJVM: jvm!) + sharedJVMPointer = javaVirtualMachine + return javaVirtualMachine + } + + precondition( + !wasExistingVM, + "JVM reports that an instance of the JVM was already created, but we didn't see it." + ) + + // Create a new instance of the JVM. + let javaVirtualMachine: JavaVirtualMachine + do { + javaVirtualMachine = try JavaVirtualMachine( + classPath: classPath, + vmOptions: vmOptions, + ignoreUnrecognized: ignoreUnrecognized + ) + } catch VMError.existingVM { + // We raced with code outside of this JavaVirtualMachine instance + // that created a VM while we were trying to do the same. Go + // through the loop again to pick up the underlying JVM pointer. + wasExistingVM = true + continue + } + + sharedJVMPointer = javaVirtualMachine + return javaVirtualMachine + } + } + } + } +} + extension JavaVirtualMachine { enum VMError: Error { case failedToCreateVM case failedToAttachThread case failedToDetachThread + case failedToQueryVM + case existingVM } } diff --git a/Sources/_Subprocess/LockedState.swift b/Sources/JavaKitVM/LockedState.swift similarity index 100% rename from Sources/_Subprocess/LockedState.swift rename to Sources/JavaKitVM/LockedState.swift diff --git a/Tests/JavaKitTests/BasicRuntimeTests.swift b/Tests/JavaKitTests/BasicRuntimeTests.swift index 55eee2d4..16669470 100644 --- a/Tests/JavaKitTests/BasicRuntimeTests.swift +++ b/Tests/JavaKitTests/BasicRuntimeTests.swift @@ -17,8 +17,12 @@ import JavaKitNetwork import JavaKitVM import XCTest // NOTE: Workaround for https://github.com/swiftlang/swift-java/issues/43 -@MainActor -let jvm = try! JavaVirtualMachine(vmOptions: []) +/// Handy reference to the JVM abstraction. +var jvm: JavaVirtualMachine { + get throws { + try .shared() + } +} class BasicRuntimeTests: XCTestCase { func testJavaObjectManagement() async throws { @@ -26,7 +30,7 @@ class BasicRuntimeTests: XCTestCase { throw XCTSkip("Attempts to refcount a null pointer on Linux") } - let environment = try await jvm.environment() + let environment = try jvm.environment() let sneakyJavaThis: jobject do { let object = JavaObject(environment: environment) @@ -56,7 +60,7 @@ class BasicRuntimeTests: XCTestCase { throw XCTSkip("Attempts to refcount a null pointer on Linux") } - let environment = try await jvm.environment() + let environment = try jvm.environment() do { _ = try URL("bad url", environment: environment) @@ -70,14 +74,14 @@ class BasicRuntimeTests: XCTestCase { throw XCTSkip("Attempts to refcount a null pointer on Linux") } - let environment = try await jvm.environment() + let environment = try jvm.environment() let urlConnectionClass = try JavaClass(in: environment) XCTAssert(urlConnectionClass.getDefaultAllowUserInteraction() == false) } func testClassInstanceLookup() async throws { - let environment = try await jvm.environment() + let environment = try jvm.environment() do { _ = try JavaClass(in: environment) From 7ec7f897b76bfca281fe65238363c8a44b4a22cc Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Fri, 11 Oct 2024 12:27:22 -0700 Subject: [PATCH 072/426] Don't destroy "adopted" JVM instances when JavaVirtualMachine is destroyed --- Sources/JavaKitVM/JavaVirtualMachine.swift | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/Sources/JavaKitVM/JavaVirtualMachine.swift b/Sources/JavaKitVM/JavaVirtualMachine.swift index 63c00ad9..cf1b63ac 100644 --- a/Sources/JavaKitVM/JavaVirtualMachine.swift +++ b/Sources/JavaKitVM/JavaVirtualMachine.swift @@ -23,9 +23,13 @@ public final class JavaVirtualMachine: @unchecked Sendable { /// The Java virtual machine instance. private let jvm: JavaVMPointer + /// Whether to destroy the JVM on deinit. + private let destroyOnDeinit: Bool + /// Adopt an existing JVM pointer. private init(adoptingJVM jvm: JavaVMPointer) { self.jvm = jvm + self.destroyOnDeinit = false } /// Initialize a new Java virtual machine instance. @@ -90,12 +94,15 @@ public final class JavaVirtualMachine: @unchecked Sendable { } self.jvm = jvm! + self.destroyOnDeinit = true } deinit { - // Destroy the JVM. - if jvm.pointee!.pointee.DestroyJavaVM(jvm) != JNI_OK { - fatalError("Failed to destroy the JVM.") + if destroyOnDeinit { + // Destroy the JVM. + if jvm.pointee!.pointee.DestroyJavaVM(jvm) != JNI_OK { + fatalError("Failed to destroy the JVM.") + } } } } From 2fe5c0393ebb21b061baa36c6cee306f25f8fd7f Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Fri, 11 Oct 2024 12:38:58 -0700 Subject: [PATCH 073/426] Map all of the documented JNI errors to cases in the Swift VMError This also cleans up various error-handling code paths that were doing narrow checks. --- Sources/JavaKitVM/JavaVirtualMachine.swift | 58 +++++++++++++++------- 1 file changed, 39 insertions(+), 19 deletions(-) diff --git a/Sources/JavaKitVM/JavaVirtualMachine.swift b/Sources/JavaKitVM/JavaVirtualMachine.swift index cf1b63ac..ad16b46e 100644 --- a/Sources/JavaKitVM/JavaVirtualMachine.swift +++ b/Sources/JavaKitVM/JavaVirtualMachine.swift @@ -84,13 +84,8 @@ public final class JavaVirtualMachine: @unchecked Sendable { vmArgs.nOptions = jint(optionsBuffer.count) // Create the JVM instance. - let createResult = JNI_CreateJavaVM(&jvm, &environment, &vmArgs) - if createResult != JNI_OK { - if createResult == JNI_EEXIST { - throw VMError.existingVM - } - - throw VMError.failedToCreateVM + if let createError = VMError(fromJNIError: JNI_CreateJavaVM(&jvm, &environment, &vmArgs)) { + throw createError } self.jvm = jvm! @@ -100,8 +95,8 @@ public final class JavaVirtualMachine: @unchecked Sendable { deinit { if destroyOnDeinit { // Destroy the JVM. - if jvm.pointee!.pointee.DestroyJavaVM(jvm) != JNI_OK { - fatalError("Failed to destroy the JVM.") + if let resultError = VMError(fromJNIError: jvm.pointee!.pointee.DestroyJavaVM(jvm)) { + fatalError("Failed to destroy the JVM: \(resultError)") } } } @@ -136,19 +131,19 @@ extension JavaVirtualMachine { attachResult = jvm.pointee!.pointee.AttachCurrentThread(jvm, &environment, nil) } - if attachResult == JNI_OK, let environment { - return environment.assumingMemoryBound(to: JNIEnv?.self) + // If we failed to attach, report that. + if let attachError = VMError(fromJNIError: attachResult) { + throw attachError } - throw VMError.failedToAttachThread + return environment!.assumingMemoryBound(to: JNIEnv?.self) } /// Detach the current thread from the Java Virtual Machine. All Java /// threads waiting for this thread to die are notified. public func detachCurrentThread() throws { - let result = jvm.pointee!.pointee.DetachCurrentThread(jvm) - if result != JNI_OK { - throw VMError.failedToDetachThread + if let resultError = VMError(fromJNIError: jvm.pointee!.pointee.DetachCurrentThread(jvm)) { + throw resultError } } } @@ -234,11 +229,36 @@ extension JavaVirtualMachine { } extension JavaVirtualMachine { + /// Describes the kinds of errors that can occur when interacting with JNI. enum VMError: Error { - case failedToCreateVM - case failedToAttachThread - case failedToDetachThread - case failedToQueryVM + /// There is already a Java Virtual Machine. case existingVM + + /// JNI version mismatch error. + case jniVersion + + /// Thread is detached from the VM. + case threadDetached + + /// Out of memory. + case outOfMemory + + /// Invalid arguments. + case invalidArguments + + /// Unknown JNI error. + case unknown(jint) + + init?(fromJNIError error: jint) { + switch error { + case JNI_OK: return nil + case JNI_EDETACHED: self = .threadDetached + case JNI_EVERSION: self = .jniVersion + case JNI_ENOMEM: self = .outOfMemory + case JNI_EEXIST: self = .existingVM + case JNI_EINVAL: self = .invalidArguments + default: self = .unknown(error) + } + } } } From 1adeb87bafd7418e40470119c27e30b8d6618af7 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Fri, 11 Oct 2024 12:43:10 -0700 Subject: [PATCH 074/426] Add an API to forget the shared JavaVirtualMachine instance --- Sources/JavaKitVM/JavaVirtualMachine.swift | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Sources/JavaKitVM/JavaVirtualMachine.swift b/Sources/JavaKitVM/JavaVirtualMachine.swift index ad16b46e..2e95795c 100644 --- a/Sources/JavaKitVM/JavaVirtualMachine.swift +++ b/Sources/JavaKitVM/JavaVirtualMachine.swift @@ -226,6 +226,15 @@ extension JavaVirtualMachine { } } } + + /// "Forget" the shared JavaVirtualMachine instance. + /// + /// This will allow the shared JavaVirtualMachine instance to be deallocated. + public static func forgetShared() { + sharedJVM.withLock { sharedJVMPointer in + sharedJVMPointer = nil + } + } } extension JavaVirtualMachine { From 3ddd2b730fc502a06cacaa68140e05116ccc33fb Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Fri, 11 Oct 2024 12:58:44 -0700 Subject: [PATCH 075/426] License fix --- Sources/JavaKitVM/LockedState.swift | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Sources/JavaKitVM/LockedState.swift b/Sources/JavaKitVM/LockedState.swift index 0cde3b94..e095668c 100644 --- a/Sources/JavaKitVM/LockedState.swift +++ b/Sources/JavaKitVM/LockedState.swift @@ -2,11 +2,13 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2022 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 // -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// From bd879185f95774889aca82f6b69e1c52bbcccaaa Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Fri, 11 Oct 2024 13:36:24 -0700 Subject: [PATCH 076/426] Rework makefile to split JavaKit targets from jextract-swift targets The JavaKit targets (Swift calling into Java via JNI) have fewer requirements (for JVM installations and development toolchains) and are a bit easier to get started with. Split those targets out, and turn `make` with no specified target into a little help target. Fixes issue #68. --- Makefile | 19 ++++++++++++------- README.md | 3 ++- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/Makefile b/Makefile index a114a61f..c120db6b 100644 --- a/Makefile +++ b/Makefile @@ -53,12 +53,17 @@ endif SAMPLES_DIR := "Samples" -all: generate-all +all: + @echo "Welcome to swift-java! There are several makefile targets to choose from:" + @echo " javakit-run: Run the JavaKit example program that uses Java libraries from Swift." + @echo " javakit-generate: Regenerate the Swift wrapper code for the various JavaKit libraries from Java. This only has to be done when changing the Java2Swift tool." + @echo " jextract-run: Run the Java example code that uses the wrapped Swift library. NOTE: this requires development toolchain described in the README." + @echo " jextract-generate: Generate Java wrapper code for the example Swift library allowing Swift to be called from Java. NOTE: this requires development toolchain described in the README." $(BUILD_DIR)/debug/libJavaKit.$(LIB_SUFFIX) $(BUILD_DIR)/debug/Java2Swift: swift build -run: $(BUILD_DIR)/debug/libJavaKit.$(LIB_SUFFIX) $(BUILD_DIR)/debug/libExampleSwiftLibrary.$(LIB_SUFFIX) +javakit-run: $(BUILD_DIR)/debug/libJavaKit.$(LIB_SUFFIX) $(BUILD_DIR)/debug/libExampleSwiftLibrary.$(LIB_SUFFIX) ./gradlew Samples:JavaKitSampleApp:run Java2Swift: $(BUILD_DIR)/debug/Java2Swift @@ -79,8 +84,8 @@ generate-JavaKitNetwork: Java2Swift generate-JavaKit mkdir -p Sources/JavaKitNetwork/generated $(BUILD_DIR)/debug/Java2Swift --module-name JavaKitNetwork --manifests Sources/JavaKit/generated/JavaKit.swift2java -o Sources/JavaKitNetwork/generated java.net.URI java.net.URL java.net.URLClassLoader -generate-all: generate-JavaKit generate-JavaKitReflection generate-JavaKitJar generate-JavaKitNetwork \ - jextract-swift +javakit-generate: generate-JavaKit generate-JavaKitReflection generate-JavaKitJar generate-JavaKitNetwork + clean: rm -rf .build; \ rm -rf Samples/SwiftKitExampleApp/src/generated/java/* @@ -112,11 +117,11 @@ jextract-swift: generate-JExtract-interface-files swift build generate-JExtract-interface-files: $(BUILD_DIR)/debug/libJavaKit.$(LIB_SUFFIX) - echo "Generate .swiftinterface files..." + @echo "Generate .swiftinterface files..." @$(call make_swiftinterface, "ExampleSwiftLibrary", "MySwiftLibrary") @$(call make_swiftinterface, "SwiftKitSwift", "SwiftKit") -jextract-run: jextract-swift generate-JExtract-interface-files +jextract-generate: jextract-swift generate-JExtract-interface-files swift run jextract-swift \ --package-name com.example.swift.generated \ --swift-module ExampleSwiftLibrary \ @@ -129,5 +134,5 @@ jextract-run: jextract-swift generate-JExtract-interface-files $(BUILD_DIR)/jextract/SwiftKitSwift/SwiftKit.swiftinterface -jextract-run-java: jextract-swift generate-JExtract-interface-files +jextract-run: jextract-generate generate-JExtract-interface-files ./gradlew Samples:SwiftKitSampleApp:run diff --git a/README.md b/README.md index db491fe7..b30d905e 100644 --- a/README.md +++ b/README.md @@ -67,7 +67,8 @@ This project contains quite a few builds, Swift, Java, and depends on some custo Easiest way to get going is to: ```bash -make +make javakit-run # Run the JavaKit example of Swift code using Java libraries +make jextract-run # Run the jextract-swift example of Java code using Swift libraries swift test # test all Swift code, e.g. jextract-swift ./gradlew test # test all Java code, including integration tests that actually use jextract-ed sources ``` From da409451eafedccc89510838adf808e140cecd99 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Fri, 11 Oct 2024 13:40:57 -0700 Subject: [PATCH 077/426] Update GitHub workflow to use jextract-generate --- .github/workflows/pull_request.yml | 2 +- Makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 4d99bff5..ab6b4cbc 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -106,6 +106,6 @@ jobs: # run the actual build - name: Generate sources (make) (Temporary) # TODO: this should be triggered by the respective builds - run: "make jextract-run" + run: "make jextract-generate" - name: Test Swift run: "swift test" diff --git a/Makefile b/Makefile index c120db6b..f7d075c4 100644 --- a/Makefile +++ b/Makefile @@ -134,5 +134,5 @@ jextract-generate: jextract-swift generate-JExtract-interface-files $(BUILD_DIR)/jextract/SwiftKitSwift/SwiftKit.swiftinterface -jextract-run: jextract-generate generate-JExtract-interface-files +jextract-run: jextract-generate ./gradlew Samples:SwiftKitSampleApp:run From bc33fc7e81243a98b7507aad0889912c1bd4ed35 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Fri, 11 Oct 2024 14:24:54 -0700 Subject: [PATCH 078/426] Switch docker build over to use the appropriate Makefile target --- docker/docker-compose.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docker/docker-compose.yaml b/docker/docker-compose.yaml index 6bfe52d0..2a22c484 100644 --- a/docker/docker-compose.yaml +++ b/docker/docker-compose.yaml @@ -33,11 +33,11 @@ services: test-java: <<: *common - command: /bin/bash -xcl "uname -a && swift -version && java -version && make jextract-run && ./gradlew test --debug" + command: /bin/bash -xcl "uname -a && swift -version && java -version && make jextract-generate && ./gradlew test --debug" test: <<: *common - command: /bin/bash -xcl "uname -a && swift -version && java -version && make jextract-run && swift $${SWIFT_TEST_VERB-test} $${WARN_AS_ERROR_ARG-} $${SANITIZER_ARG-} $${IMPORT_CHECK_ARG-} && ./gradlew test --debug" + command: /bin/bash -xcl "uname -a && swift -version && java -version && make jextract-generate && swift $${SWIFT_TEST_VERB-test} $${WARN_AS_ERROR_ARG-} $${SANITIZER_ARG-} $${IMPORT_CHECK_ARG-} && ./gradlew test --debug" # util From 03bfbe4da08a1b359201ac173104863f10bd029d Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Fri, 11 Oct 2024 14:33:30 -0700 Subject: [PATCH 079/426] Teach gradle build to use jextract-generate --- Samples/SwiftKitSampleApp/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Samples/SwiftKitSampleApp/build.gradle b/Samples/SwiftKitSampleApp/build.gradle index 28304626..1f2343b2 100644 --- a/Samples/SwiftKitSampleApp/build.gradle +++ b/Samples/SwiftKitSampleApp/build.gradle @@ -103,7 +103,7 @@ task jextract(type: Exec) { workingDir = rootDir commandLine "make" - args "jextract-run" + args "jextract-generate" } tasks.named("compileGeneratedJava").configure { From 206686719ed7b01d15e4803b5a6591b9ecb6c316 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Fri, 11 Oct 2024 14:13:18 -0700 Subject: [PATCH 080/426] Regenerate JavaKit Swift sources now that we have support for static fields --- Sources/JavaKitJar/generated/JarEntry.swift | 127 ++++++++++++++++ Sources/JavaKitJar/generated/JarFile.swift | 136 +++++++++++++++++- .../JavaKitJar/generated/JarInputStream.swift | 125 +++++++++++++++- .../generated/JarOutputStream.swift | 127 ++++++++++++++++ .../generated/Constructor.swift | 6 + .../generated/Executable.swift | 6 + .../JavaKitReflection/generated/Field.swift | 6 + .../JavaKitReflection/generated/Method.swift | 6 + 8 files changed, 534 insertions(+), 5 deletions(-) diff --git a/Sources/JavaKitJar/generated/JarEntry.swift b/Sources/JavaKitJar/generated/JarEntry.swift index 398422c9..75a34d4e 100644 --- a/Sources/JavaKitJar/generated/JarEntry.swift +++ b/Sources/JavaKitJar/generated/JarEntry.swift @@ -94,3 +94,130 @@ public struct JarEntry { @JavaMethod public func wait() throws } +extension JavaClass { + @JavaStaticField + public var STORED: Int32 + + @JavaStaticField + public var DEFLATED: Int32 + + @JavaStaticField + public var LOCSIG: Int64 + + @JavaStaticField + public var EXTSIG: Int64 + + @JavaStaticField + public var CENSIG: Int64 + + @JavaStaticField + public var ENDSIG: Int64 + + @JavaStaticField + public var LOCHDR: Int32 + + @JavaStaticField + public var EXTHDR: Int32 + + @JavaStaticField + public var CENHDR: Int32 + + @JavaStaticField + public var ENDHDR: Int32 + + @JavaStaticField + public var LOCVER: Int32 + + @JavaStaticField + public var LOCFLG: Int32 + + @JavaStaticField + public var LOCHOW: Int32 + + @JavaStaticField + public var LOCTIM: Int32 + + @JavaStaticField + public var LOCCRC: Int32 + + @JavaStaticField + public var LOCSIZ: Int32 + + @JavaStaticField + public var LOCLEN: Int32 + + @JavaStaticField + public var LOCNAM: Int32 + + @JavaStaticField + public var LOCEXT: Int32 + + @JavaStaticField + public var EXTCRC: Int32 + + @JavaStaticField + public var EXTSIZ: Int32 + + @JavaStaticField + public var EXTLEN: Int32 + + @JavaStaticField + public var CENVEM: Int32 + + @JavaStaticField + public var CENVER: Int32 + + @JavaStaticField + public var CENFLG: Int32 + + @JavaStaticField + public var CENHOW: Int32 + + @JavaStaticField + public var CENTIM: Int32 + + @JavaStaticField + public var CENCRC: Int32 + + @JavaStaticField + public var CENSIZ: Int32 + + @JavaStaticField + public var CENLEN: Int32 + + @JavaStaticField + public var CENNAM: Int32 + + @JavaStaticField + public var CENEXT: Int32 + + @JavaStaticField + public var CENCOM: Int32 + + @JavaStaticField + public var CENDSK: Int32 + + @JavaStaticField + public var CENATT: Int32 + + @JavaStaticField + public var CENATX: Int32 + + @JavaStaticField + public var CENOFF: Int32 + + @JavaStaticField + public var ENDSUB: Int32 + + @JavaStaticField + public var ENDTOT: Int32 + + @JavaStaticField + public var ENDSIZ: Int32 + + @JavaStaticField + public var ENDOFF: Int32 + + @JavaStaticField + public var ENDCOM: Int32 +} diff --git a/Sources/JavaKitJar/generated/JarFile.swift b/Sources/JavaKitJar/generated/JarFile.swift index aa04c098..dc7eb93b 100644 --- a/Sources/JavaKitJar/generated/JarFile.swift +++ b/Sources/JavaKitJar/generated/JarFile.swift @@ -28,9 +28,6 @@ public struct JarFile { @JavaMethod public func size() -> Int32 - @JavaMethod - public func toString() -> String - @JavaMethod public func close() throws @@ -40,6 +37,9 @@ public struct JarFile { @JavaMethod public func equals(_ arg0: JavaObject?) -> Bool + @JavaMethod + public func toString() -> String + @JavaMethod public func hashCode() -> Int32 @@ -61,3 +61,133 @@ public struct JarFile { @JavaMethod public func wait() throws } +extension JavaClass { + @JavaStaticField + public var MANIFEST_NAME: String + + @JavaStaticField + public var OPEN_READ: Int32 + + @JavaStaticField + public var OPEN_DELETE: Int32 + + @JavaStaticField + public var LOCSIG: Int64 + + @JavaStaticField + public var EXTSIG: Int64 + + @JavaStaticField + public var CENSIG: Int64 + + @JavaStaticField + public var ENDSIG: Int64 + + @JavaStaticField + public var LOCHDR: Int32 + + @JavaStaticField + public var EXTHDR: Int32 + + @JavaStaticField + public var CENHDR: Int32 + + @JavaStaticField + public var ENDHDR: Int32 + + @JavaStaticField + public var LOCVER: Int32 + + @JavaStaticField + public var LOCFLG: Int32 + + @JavaStaticField + public var LOCHOW: Int32 + + @JavaStaticField + public var LOCTIM: Int32 + + @JavaStaticField + public var LOCCRC: Int32 + + @JavaStaticField + public var LOCSIZ: Int32 + + @JavaStaticField + public var LOCLEN: Int32 + + @JavaStaticField + public var LOCNAM: Int32 + + @JavaStaticField + public var LOCEXT: Int32 + + @JavaStaticField + public var EXTCRC: Int32 + + @JavaStaticField + public var EXTSIZ: Int32 + + @JavaStaticField + public var EXTLEN: Int32 + + @JavaStaticField + public var CENVEM: Int32 + + @JavaStaticField + public var CENVER: Int32 + + @JavaStaticField + public var CENFLG: Int32 + + @JavaStaticField + public var CENHOW: Int32 + + @JavaStaticField + public var CENTIM: Int32 + + @JavaStaticField + public var CENCRC: Int32 + + @JavaStaticField + public var CENSIZ: Int32 + + @JavaStaticField + public var CENLEN: Int32 + + @JavaStaticField + public var CENNAM: Int32 + + @JavaStaticField + public var CENEXT: Int32 + + @JavaStaticField + public var CENCOM: Int32 + + @JavaStaticField + public var CENDSK: Int32 + + @JavaStaticField + public var CENATT: Int32 + + @JavaStaticField + public var CENATX: Int32 + + @JavaStaticField + public var CENOFF: Int32 + + @JavaStaticField + public var ENDSUB: Int32 + + @JavaStaticField + public var ENDTOT: Int32 + + @JavaStaticField + public var ENDSIZ: Int32 + + @JavaStaticField + public var ENDOFF: Int32 + + @JavaStaticField + public var ENDCOM: Int32 +} diff --git a/Sources/JavaKitJar/generated/JarInputStream.swift b/Sources/JavaKitJar/generated/JarInputStream.swift index 9793a431..467bb8f6 100644 --- a/Sources/JavaKitJar/generated/JarInputStream.swift +++ b/Sources/JavaKitJar/generated/JarInputStream.swift @@ -26,10 +26,10 @@ public struct JarInputStream { public func readAllBytes() throws -> [Int8] @JavaMethod - public func readNBytes(_ arg0: Int32) throws -> [Int8] + public func readNBytes(_ arg0: [Int8], _ arg1: Int32, _ arg2: Int32) throws -> Int32 @JavaMethod - public func readNBytes(_ arg0: [Int8], _ arg1: Int32, _ arg2: Int32) throws -> Int32 + public func readNBytes(_ arg0: Int32) throws -> [Int8] @JavaMethod public func skip(_ arg0: Int64) throws -> Int64 @@ -79,3 +79,124 @@ public struct JarInputStream { @JavaMethod public func wait() throws } +extension JavaClass { + @JavaStaticField + public var LOCSIG: Int64 + + @JavaStaticField + public var EXTSIG: Int64 + + @JavaStaticField + public var CENSIG: Int64 + + @JavaStaticField + public var ENDSIG: Int64 + + @JavaStaticField + public var LOCHDR: Int32 + + @JavaStaticField + public var EXTHDR: Int32 + + @JavaStaticField + public var CENHDR: Int32 + + @JavaStaticField + public var ENDHDR: Int32 + + @JavaStaticField + public var LOCVER: Int32 + + @JavaStaticField + public var LOCFLG: Int32 + + @JavaStaticField + public var LOCHOW: Int32 + + @JavaStaticField + public var LOCTIM: Int32 + + @JavaStaticField + public var LOCCRC: Int32 + + @JavaStaticField + public var LOCSIZ: Int32 + + @JavaStaticField + public var LOCLEN: Int32 + + @JavaStaticField + public var LOCNAM: Int32 + + @JavaStaticField + public var LOCEXT: Int32 + + @JavaStaticField + public var EXTCRC: Int32 + + @JavaStaticField + public var EXTSIZ: Int32 + + @JavaStaticField + public var EXTLEN: Int32 + + @JavaStaticField + public var CENVEM: Int32 + + @JavaStaticField + public var CENVER: Int32 + + @JavaStaticField + public var CENFLG: Int32 + + @JavaStaticField + public var CENHOW: Int32 + + @JavaStaticField + public var CENTIM: Int32 + + @JavaStaticField + public var CENCRC: Int32 + + @JavaStaticField + public var CENSIZ: Int32 + + @JavaStaticField + public var CENLEN: Int32 + + @JavaStaticField + public var CENNAM: Int32 + + @JavaStaticField + public var CENEXT: Int32 + + @JavaStaticField + public var CENCOM: Int32 + + @JavaStaticField + public var CENDSK: Int32 + + @JavaStaticField + public var CENATT: Int32 + + @JavaStaticField + public var CENATX: Int32 + + @JavaStaticField + public var CENOFF: Int32 + + @JavaStaticField + public var ENDSUB: Int32 + + @JavaStaticField + public var ENDTOT: Int32 + + @JavaStaticField + public var ENDSIZ: Int32 + + @JavaStaticField + public var ENDOFF: Int32 + + @JavaStaticField + public var ENDCOM: Int32 +} diff --git a/Sources/JavaKitJar/generated/JarOutputStream.swift b/Sources/JavaKitJar/generated/JarOutputStream.swift index f6b54f40..fdfbbbaa 100644 --- a/Sources/JavaKitJar/generated/JarOutputStream.swift +++ b/Sources/JavaKitJar/generated/JarOutputStream.swift @@ -61,3 +61,130 @@ public struct JarOutputStream { @JavaMethod public func wait() throws } +extension JavaClass { + @JavaStaticField + public var STORED: Int32 + + @JavaStaticField + public var DEFLATED: Int32 + + @JavaStaticField + public var LOCSIG: Int64 + + @JavaStaticField + public var EXTSIG: Int64 + + @JavaStaticField + public var CENSIG: Int64 + + @JavaStaticField + public var ENDSIG: Int64 + + @JavaStaticField + public var LOCHDR: Int32 + + @JavaStaticField + public var EXTHDR: Int32 + + @JavaStaticField + public var CENHDR: Int32 + + @JavaStaticField + public var ENDHDR: Int32 + + @JavaStaticField + public var LOCVER: Int32 + + @JavaStaticField + public var LOCFLG: Int32 + + @JavaStaticField + public var LOCHOW: Int32 + + @JavaStaticField + public var LOCTIM: Int32 + + @JavaStaticField + public var LOCCRC: Int32 + + @JavaStaticField + public var LOCSIZ: Int32 + + @JavaStaticField + public var LOCLEN: Int32 + + @JavaStaticField + public var LOCNAM: Int32 + + @JavaStaticField + public var LOCEXT: Int32 + + @JavaStaticField + public var EXTCRC: Int32 + + @JavaStaticField + public var EXTSIZ: Int32 + + @JavaStaticField + public var EXTLEN: Int32 + + @JavaStaticField + public var CENVEM: Int32 + + @JavaStaticField + public var CENVER: Int32 + + @JavaStaticField + public var CENFLG: Int32 + + @JavaStaticField + public var CENHOW: Int32 + + @JavaStaticField + public var CENTIM: Int32 + + @JavaStaticField + public var CENCRC: Int32 + + @JavaStaticField + public var CENSIZ: Int32 + + @JavaStaticField + public var CENLEN: Int32 + + @JavaStaticField + public var CENNAM: Int32 + + @JavaStaticField + public var CENEXT: Int32 + + @JavaStaticField + public var CENCOM: Int32 + + @JavaStaticField + public var CENDSK: Int32 + + @JavaStaticField + public var CENATT: Int32 + + @JavaStaticField + public var CENATX: Int32 + + @JavaStaticField + public var CENOFF: Int32 + + @JavaStaticField + public var ENDSUB: Int32 + + @JavaStaticField + public var ENDTOT: Int32 + + @JavaStaticField + public var ENDSIZ: Int32 + + @JavaStaticField + public var ENDOFF: Int32 + + @JavaStaticField + public var ENDCOM: Int32 +} diff --git a/Sources/JavaKitReflection/generated/Constructor.swift b/Sources/JavaKitReflection/generated/Constructor.swift index e7ea0476..b7900cd7 100644 --- a/Sources/JavaKitReflection/generated/Constructor.swift +++ b/Sources/JavaKitReflection/generated/Constructor.swift @@ -122,6 +122,12 @@ public struct Constructor { public func wait() throws } extension JavaClass { + @JavaStaticField + public var PUBLIC: Int32 + + @JavaStaticField + public var DECLARED: Int32 + @JavaStaticMethod public func setAccessible(_ arg0: [AccessibleObject?], _ arg1: Bool) where ObjectType == Constructor } diff --git a/Sources/JavaKitReflection/generated/Executable.swift b/Sources/JavaKitReflection/generated/Executable.swift index 76b34325..9084b84f 100644 --- a/Sources/JavaKitReflection/generated/Executable.swift +++ b/Sources/JavaKitReflection/generated/Executable.swift @@ -119,6 +119,12 @@ public struct Executable { public func wait() throws } extension JavaClass { + @JavaStaticField + public var PUBLIC: Int32 + + @JavaStaticField + public var DECLARED: Int32 + @JavaStaticMethod public func setAccessible(_ arg0: [AccessibleObject?], _ arg1: Bool) } diff --git a/Sources/JavaKitReflection/generated/Field.swift b/Sources/JavaKitReflection/generated/Field.swift index f6823600..fec0cb9a 100644 --- a/Sources/JavaKitReflection/generated/Field.swift +++ b/Sources/JavaKitReflection/generated/Field.swift @@ -146,6 +146,12 @@ public struct Field { public func wait() throws } extension JavaClass { + @JavaStaticField + public var PUBLIC: Int32 + + @JavaStaticField + public var DECLARED: Int32 + @JavaStaticMethod public func setAccessible(_ arg0: [AccessibleObject?], _ arg1: Bool) } diff --git a/Sources/JavaKitReflection/generated/Method.swift b/Sources/JavaKitReflection/generated/Method.swift index 84d0b90a..f438a327 100644 --- a/Sources/JavaKitReflection/generated/Method.swift +++ b/Sources/JavaKitReflection/generated/Method.swift @@ -137,6 +137,12 @@ public struct Method { public func wait() throws } extension JavaClass { + @JavaStaticField + public var PUBLIC: Int32 + + @JavaStaticField + public var DECLARED: Int32 + @JavaStaticMethod public func setAccessible(_ arg0: [AccessibleObject?], _ arg1: Bool) } From a04219ce8fa94655165b1554593f19943ceae71e Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Thu, 10 Oct 2024 14:56:04 -0700 Subject: [PATCH 081/426] Split the Java2Swift tool out into a library target and add a test harness Introduce a test harness so we can run the Java-to-Swift API translator against a Java class and then check the generated syntax. We could definitely do better with the diff'ing of lines to make it a little easier to use, but it's better than no testing. --- Package.swift | 37 +++++++- .../JavaTranslator+TranslationManifest.swift | 4 +- .../JavaTranslator.swift | 26 +++--- .../StringExtras.swift | 0 .../TranslationError.swift | 0 .../TranslationManifest.swift | 2 +- .../JavaToSwift.swift | 1 + Tests/Java2SwiftTests/Java2SwiftTests.swift | 93 +++++++++++++++++++ 8 files changed, 142 insertions(+), 21 deletions(-) rename Sources/{Java2Swift => Java2SwiftLib}/JavaTranslator+TranslationManifest.swift (91%) rename Sources/{Java2Swift => Java2SwiftLib}/JavaTranslator.swift (94%) rename Sources/{Java2Swift => Java2SwiftLib}/StringExtras.swift (100%) rename Sources/{Java2Swift => Java2SwiftLib}/TranslationError.swift (100%) rename Sources/{Java2Swift => Java2SwiftLib}/TranslationManifest.swift (94%) rename Sources/{Java2Swift => Java2SwiftTool}/JavaToSwift.swift (99%) create mode 100644 Tests/Java2SwiftTests/Java2SwiftTests.swift diff --git a/Package.swift b/Package.swift index a89997f0..2bd95713 100644 --- a/Package.swift +++ b/Package.swift @@ -83,7 +83,7 @@ let package = Package( .executable( name: "Java2Swift", - targets: ["Java2Swift"] + targets: ["Java2SwiftTool"] ), // ==== jextract-swift (extract Java accessors from Swift interface files) @@ -230,13 +230,12 @@ let package = Package( ] ), - .executableTarget( - name: "Java2Swift", + .target( + name: "Java2SwiftLib", dependencies: [ .product(name: "SwiftBasicFormat", package: "swift-syntax"), .product(name: "SwiftSyntax", package: "swift-syntax"), .product(name: "SwiftSyntaxBuilder", package: "swift-syntax"), - .product(name: "ArgumentParser", package: "swift-argument-parser"), "JavaKit", "JavaKitJar", "JavaKitReflection", @@ -250,6 +249,26 @@ let package = Package( ] ), + .executableTarget( + name: "Java2SwiftTool", + dependencies: [ + .product(name: "SwiftBasicFormat", package: "swift-syntax"), + .product(name: "SwiftSyntax", package: "swift-syntax"), + .product(name: "SwiftSyntaxBuilder", package: "swift-syntax"), + .product(name: "ArgumentParser", package: "swift-argument-parser"), + "JavaKit", + "JavaKitJar", + "JavaKitNetwork", + "JavaKitVM", + "Java2SwiftLib", + ], + + swiftSettings: [ + .swiftLanguageMode(.v5), + .enableUpcomingFeature("BareSlashRegexLiterals") + ] + ), + .target( name: "JExtractSwift", dependencies: [ @@ -301,7 +320,15 @@ let package = Package( .swiftLanguageMode(.v5) ] ), - + + .testTarget( + name: "Java2SwiftTests", + dependencies: ["Java2SwiftLib"], + swiftSettings: [ + .swiftLanguageMode(.v5) + ] + ), + .testTarget( name: "JExtractSwiftTests", dependencies: [ diff --git a/Sources/Java2Swift/JavaTranslator+TranslationManifest.swift b/Sources/Java2SwiftLib/JavaTranslator+TranslationManifest.swift similarity index 91% rename from Sources/Java2Swift/JavaTranslator+TranslationManifest.swift rename to Sources/Java2SwiftLib/JavaTranslator+TranslationManifest.swift index 244cefd4..896666d0 100644 --- a/Sources/Java2Swift/JavaTranslator+TranslationManifest.swift +++ b/Sources/Java2SwiftLib/JavaTranslator+TranslationManifest.swift @@ -17,7 +17,7 @@ import Foundation extension JavaTranslator { /// Load the manifest file with the given name to populate the known set of /// translated Java classes. - func loadTranslationManifest(from url: URL) throws { + package func loadTranslationManifest(from url: URL) throws { let contents = try Data(contentsOf: url) let manifest = try JSONDecoder().decode(TranslationManifest.self, from: contents) for (javaClassName, swiftName) in manifest.translatedClasses { @@ -30,7 +30,7 @@ extension JavaTranslator { } /// Emit the translation manifest for this source file - func encodeTranslationManifest() throws -> String { + package func encodeTranslationManifest() throws -> String { let encoder = JSONEncoder() encoder.outputFormatting = [.prettyPrinted, .sortedKeys] var contents = String(data: try encoder.encode(manifest), encoding: .utf8)! diff --git a/Sources/Java2Swift/JavaTranslator.swift b/Sources/Java2SwiftLib/JavaTranslator.swift similarity index 94% rename from Sources/Java2Swift/JavaTranslator.swift rename to Sources/Java2SwiftLib/JavaTranslator.swift index 78f3cd87..3a911d48 100644 --- a/Sources/Java2Swift/JavaTranslator.swift +++ b/Sources/Java2SwiftLib/JavaTranslator.swift @@ -21,7 +21,7 @@ import SwiftSyntaxBuilder /// Utility that translates Java classes into Swift source code to access /// those Java classes. -class JavaTranslator { +package class JavaTranslator { /// The name of the Swift module that we are translating into. let swiftModuleName: String @@ -36,18 +36,18 @@ class JavaTranslator { /// which is absolutely not scalable. We need a better way to be able to /// discover already-translated Java classes to get their corresponding /// Swift types and modules. - var translatedClasses: [String: (swiftType: String, swiftModule: String?, isOptional: Bool)] = + package var translatedClasses: [String: (swiftType: String, swiftModule: String?, isOptional: Bool)] = defaultTranslatedClasses /// The set of Swift modules that need to be imported to make the generated /// code compile. Use `getImportDecls()` to format this into a list of /// import declarations. - var importedSwiftModules: Set = JavaTranslator.defaultImportedSwiftModules + package var importedSwiftModules: Set = JavaTranslator.defaultImportedSwiftModules /// The manifest for the module being translated. - var manifest: TranslationManifest + package var manifest: TranslationManifest - init( + package init( swiftModuleName: String, environment: JNIEnvironment, format: BasicFormat = JavaTranslator.defaultFormat @@ -59,7 +59,7 @@ class JavaTranslator { } /// Clear out any per-file state when we want to start a new file. - func startNewFile() { + package func startNewFile() { importedSwiftModules = Self.defaultImportedSwiftModules } @@ -83,7 +83,7 @@ extension JavaTranslator { /// The default set of translated classes that do not come from JavaKit /// itself. This should only be used to refer to types that are built-in to /// JavaKit and therefore aren't captured in any manifest. - private static let defaultTranslatedClasses: [String: (swiftType: String, swiftModule: String?, isOptional: Bool)] = [ + package static let defaultTranslatedClasses: [String: (swiftType: String, swiftModule: String?, isOptional: Bool)] = [ "java.lang.Class": ("JavaClass", "JavaKit", true), "java.lang.String": ("String", "JavaKit", false), ] @@ -92,7 +92,7 @@ extension JavaTranslator { // MARK: Import translation extension JavaTranslator { /// Retrieve the import declarations. - func getImportDecls() -> [DeclSyntax] { + package func getImportDecls() -> [DeclSyntax] { importedSwiftModules.filter { $0 != swiftModuleName }.sorted().map { @@ -166,7 +166,7 @@ extension JavaTranslator { } /// Translate a Java class into its corresponding Swift type name. - func getSwiftTypeName(_ javaClass: JavaClass) throws -> (swiftName: String, isOptional: Bool) { + package func getSwiftTypeName(_ javaClass: JavaClass) throws -> (swiftName: String, isOptional: Bool) { let javaType = try JavaType(javaTypeName: javaClass.getName()) let isSwiftOptional = javaType.isSwiftOptional return ( @@ -195,7 +195,7 @@ extension JavaTranslator { /// Translates the given Java class into the corresponding Swift type. This /// can produce multiple declarations, such as a separate extension of /// JavaClass to house static methods. - func translateClass(_ javaClass: JavaClass) -> [DeclSyntax] { + package func translateClass(_ javaClass: JavaClass) -> [DeclSyntax] { let fullName = javaClass.getCanonicalName() let swiftTypeName = try! getSwiftTypeNameFromJavaClassName(fullName) @@ -409,7 +409,7 @@ extension JavaTranslator { // MARK: Method and constructor translation extension JavaTranslator { /// Translates the given Java constructor into a Swift declaration. - func translateConstructor(_ javaConstructor: Constructor) throws -> DeclSyntax { + package func translateConstructor(_ javaConstructor: Constructor) throws -> DeclSyntax { let parameters = try translateParameters(javaConstructor.getParameters()) + ["environment: JNIEnvironment"] let parametersStr = parameters.map { $0.description }.joined(separator: ", ") let throwsStr = javaConstructor.throwsCheckedException ? "throws" : "" @@ -421,7 +421,7 @@ extension JavaTranslator { } /// Translates the given Java method into a Swift declaration. - func translateMethod( + package func translateMethod( _ javaMethod: Method, genericParameterClause: String = "", whereClause: String = "" @@ -449,7 +449,7 @@ extension JavaTranslator { """ } - func translateField(_ javaField: Field) throws -> DeclSyntax { + package func translateField(_ javaField: Field) throws -> DeclSyntax { let typeName = try getSwiftTypeNameAsString(javaField.getGenericType()!, outerOptional: true) let fieldAttribute: AttributeSyntax = javaField.isStatic ? "@JavaStaticField" : "@JavaField"; return """ diff --git a/Sources/Java2Swift/StringExtras.swift b/Sources/Java2SwiftLib/StringExtras.swift similarity index 100% rename from Sources/Java2Swift/StringExtras.swift rename to Sources/Java2SwiftLib/StringExtras.swift diff --git a/Sources/Java2Swift/TranslationError.swift b/Sources/Java2SwiftLib/TranslationError.swift similarity index 100% rename from Sources/Java2Swift/TranslationError.swift rename to Sources/Java2SwiftLib/TranslationError.swift diff --git a/Sources/Java2Swift/TranslationManifest.swift b/Sources/Java2SwiftLib/TranslationManifest.swift similarity index 94% rename from Sources/Java2Swift/TranslationManifest.swift rename to Sources/Java2SwiftLib/TranslationManifest.swift index aa03eae6..564af422 100644 --- a/Sources/Java2Swift/TranslationManifest.swift +++ b/Sources/Java2SwiftLib/TranslationManifest.swift @@ -14,7 +14,7 @@ /// Manifest describing the a Swift module containing translations of /// Java classes into Swift types. -struct TranslationManifest: Codable { +package struct TranslationManifest: Codable { /// The Swift module name. var swiftModule: String diff --git a/Sources/Java2Swift/JavaToSwift.swift b/Sources/Java2SwiftTool/JavaToSwift.swift similarity index 99% rename from Sources/Java2Swift/JavaToSwift.swift rename to Sources/Java2SwiftTool/JavaToSwift.swift index ad9cf4f3..17fef0f7 100644 --- a/Sources/Java2Swift/JavaToSwift.swift +++ b/Sources/Java2SwiftTool/JavaToSwift.swift @@ -14,6 +14,7 @@ import ArgumentParser import Foundation +import Java2SwiftLib import JavaKit import JavaKitJar import JavaKitNetwork diff --git a/Tests/Java2SwiftTests/Java2SwiftTests.swift b/Tests/Java2SwiftTests/Java2SwiftTests.swift new file mode 100644 index 00000000..bac88d47 --- /dev/null +++ b/Tests/Java2SwiftTests/Java2SwiftTests.swift @@ -0,0 +1,93 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import JavaKit +import Java2SwiftLib +import JavaKitVM +import XCTest // NOTE: Workaround for https://github.com/swiftlang/swift-java/issues/43 + +/// Handy reference to the JVM abstraction. +var jvm: JavaVirtualMachine { + get throws { + try .shared() + } +} + +class Java2SwiftTests: XCTestCase { + func testJavaLangObjectMapping() async throws { + try assertTranslatedClass( + JavaObject.self, + swiftTypeName: "MyJavaObject", + expectedChunks: [ + "import JavaKit", + """ + @JavaClass("java.lang.Object") + public struct MyJavaObject { + """, + """ + @JavaMethod + public func toString() -> String + """, + """ + @JavaMethod + public func wait() throws + """ + ] + ) + } +} + +/// Translate a Java class and assert that the translated output contains +/// each of the expected "chunks" of text. +func assertTranslatedClass( + _ javaType: JavaClassType.Type, + swiftTypeName: String, + translatedClasses: [ + String: (swiftType: String, swiftModule: String?, isOptional: Bool) + ] = JavaTranslator.defaultTranslatedClasses, + expectedChunks: [String], + file: StaticString = #filePath, + line: UInt = #line +) throws { + let environment = try jvm.environment() + let translator = JavaTranslator( + swiftModuleName: "SwiftModule", + environment: environment + ) + + translator.translatedClasses = translatedClasses + translator.translatedClasses[javaType.fullJavaClassName] = (swiftTypeName, nil, true) + + translator.startNewFile() + let translatedDecls = translator.translateClass( + try JavaClass( + javaThis: javaType.getJNIClass(in: environment), + environment: environment) + ) + let importDecls = translator.getImportDecls() + + let swiftFileText = """ + // Auto-generated by Java-to-Swift wrapper generator. + \(importDecls.map { $0.description }.joined()) + \(translatedDecls.map { $0.description }.joined(separator: "\n")) + """ + + for expectedChunk in expectedChunks { + if swiftFileText.contains(expectedChunk) { + continue + } + + XCTFail("Expected chunk '\(expectedChunk)' not found in '\(swiftFileText)'", file: file, line: line) + } +} From 6967ab57043a0c6d048c9280b3bd3fb2705c15c7 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Mon, 14 Oct 2024 13:07:22 -0700 Subject: [PATCH 082/426] Introduce a SwiftPM plugin to compile Java sources Add a SwiftPM build tool plugin that compiles all of the Java source files that are part of a given SwiftPM target into class files. Use this within the JavaKit example so we can build everything through SwiftPM. --- Makefile | 4 +- Package.swift | 18 ++++ .../JavaCompilerPlugin.swift | 90 +++++++++++++++++++ .../com/example/swift/HelloSubclass.java | 27 ++++++ .../com/example/swift/HelloSwift.java | 57 ++++++++++++ .../com/example/swift/JavaKitSampleMain.java | 27 ++++++ 6 files changed, 221 insertions(+), 2 deletions(-) create mode 100644 Plugins/JavaCompilerPlugin/JavaCompilerPlugin.swift create mode 100644 Sources/JavaKitExample/com/example/swift/HelloSubclass.java create mode 100644 Sources/JavaKitExample/com/example/swift/HelloSwift.java create mode 100644 Sources/JavaKitExample/com/example/swift/JavaKitSampleMain.java diff --git a/Makefile b/Makefile index f7d075c4..191c7bb7 100644 --- a/Makefile +++ b/Makefile @@ -58,13 +58,13 @@ all: @echo " javakit-run: Run the JavaKit example program that uses Java libraries from Swift." @echo " javakit-generate: Regenerate the Swift wrapper code for the various JavaKit libraries from Java. This only has to be done when changing the Java2Swift tool." @echo " jextract-run: Run the Java example code that uses the wrapped Swift library. NOTE: this requires development toolchain described in the README." - @echo " jextract-generate: Generate Java wrapper code for the example Swift library allowing Swift to be called from Java. NOTE: this requires development toolchain described in the README." + @echo " jextract-generate: Generate Java wrapper code for the example Swift library allowing Swift to be called from Java. NOTE: this requires development toolchain described ein the README." $(BUILD_DIR)/debug/libJavaKit.$(LIB_SUFFIX) $(BUILD_DIR)/debug/Java2Swift: swift build javakit-run: $(BUILD_DIR)/debug/libJavaKit.$(LIB_SUFFIX) $(BUILD_DIR)/debug/libExampleSwiftLibrary.$(LIB_SUFFIX) - ./gradlew Samples:JavaKitSampleApp:run + java -cp .build/plugins/outputs/swift-java/JavaKitExample/destination/JavaCompilerPlugin/Java -Djava.library.path=.build/debug com.example.swift.JavaKitSampleMain Java2Swift: $(BUILD_DIR)/debug/Java2Swift diff --git a/Package.swift b/Package.swift index 2bd95713..50c02c12 100644 --- a/Package.swift +++ b/Package.swift @@ -86,6 +86,14 @@ let package = Package( targets: ["Java2SwiftTool"] ), + // ==== Plugin for building Java code + .plugin( + name: "JavaCompilerPlugin", + targets: [ + "JavaCompilerPlugin" + ] + ), + // ==== jextract-swift (extract Java accessors from Swift interface files) .executable( @@ -197,14 +205,24 @@ let package = Package( .linkedLibrary("jvm"), ] ), + + .plugin( + name: "JavaCompilerPlugin", + capability: .buildTool() + ), + .target( name: "JavaKitExample", dependencies: ["JavaKit"], swiftSettings: [ .swiftLanguageMode(.v5), .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) + ], + plugins: [ + .plugin(name: "JavaCompilerPlugin") ] ), + .target( name: "ExampleSwiftLibrary", dependencies: [], diff --git a/Plugins/JavaCompilerPlugin/JavaCompilerPlugin.swift b/Plugins/JavaCompilerPlugin/JavaCompilerPlugin.swift new file mode 100644 index 00000000..3a6c4286 --- /dev/null +++ b/Plugins/JavaCompilerPlugin/JavaCompilerPlugin.swift @@ -0,0 +1,90 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import Foundation +import PackagePlugin + +@main +struct JavaCompilerBuildToolPlugin: BuildToolPlugin { + func createBuildCommands(context: PluginContext, target: Target) throws -> [Command] { + guard let sourceModule = target.sourceModule else { return [] } + + // Collect all of the Java source files within this target's sources. + let javaFiles = sourceModule.sourceFiles.map { $0.url }.filter { + $0.pathExtension == "java" + } + if javaFiles.isEmpty { + return [] + } + + // Note: Target doesn't have a directoryURL counterpart to directory, + // so we cannot eliminate this deprecation warning. + let sourceDir = target.directory.string + + // The class files themselves will be generated into the build directory + // for this target. + let classFiles = javaFiles.map { sourceFileURL in + let sourceFilePath = sourceFileURL.path + guard sourceFilePath.starts(with: sourceDir) else { + fatalError("Could not get relative path for source file \(sourceFilePath)") + } + + return URL( + filePath: context.pluginWorkDirectoryURL.path + ).appending(path: "Java") + .appending(path: String(sourceFilePath.dropFirst(sourceDir.count))) + .deletingPathExtension() + .appendingPathExtension("class") + } + + let javaHome = URL(filePath: findJavaHome()) + let javaClassFileURL = context.pluginWorkDirectoryURL + .appending(path: "Java") + return [ + .buildCommand( + displayName: "Compiling \(javaFiles.count) Java files for target \(sourceModule.name) to \(javaClassFileURL)", + executable: javaHome + .appending(path: "bin") + .appending(path: "javac"), + arguments: javaFiles.map { $0.path(percentEncoded: false) } + [ + "-d", javaClassFileURL.path() + ], + inputFiles: javaFiles, + outputFiles: classFiles + ) + ] + } +} + +// Note: the JAVA_HOME environment variable must be set to point to where +// Java is installed, e.g., +// Library/Java/JavaVirtualMachines/openjdk-21.jdk/Contents/Home. +func findJavaHome() -> String { + if let home = ProcessInfo.processInfo.environment["JAVA_HOME"] { + return home + } + + // This is a workaround for envs (some IDEs) which have trouble with + // picking up env variables during the build process + let path = "\(FileManager.default.homeDirectoryForCurrentUser.path()).java_home" + if let home = try? String(contentsOfFile: path, encoding: .utf8) { + if let lastChar = home.last, lastChar.isNewline { + return String(home.dropLast()) + } + + return home + } + + fatalError("Please set the JAVA_HOME environment variable to point to where Java is installed.") +} diff --git a/Sources/JavaKitExample/com/example/swift/HelloSubclass.java b/Sources/JavaKitExample/com/example/swift/HelloSubclass.java new file mode 100644 index 00000000..eb3cba32 --- /dev/null +++ b/Sources/JavaKitExample/com/example/swift/HelloSubclass.java @@ -0,0 +1,27 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package com.example.swift; + +public class HelloSubclass extends HelloSwift { + private String greeting; + + public HelloSubclass(String greeting) { + this.greeting = greeting; + } + + private void greetMe() { + super.greet(greeting); + } +} diff --git a/Sources/JavaKitExample/com/example/swift/HelloSwift.java b/Sources/JavaKitExample/com/example/swift/HelloSwift.java new file mode 100644 index 00000000..b4c87f71 --- /dev/null +++ b/Sources/JavaKitExample/com/example/swift/HelloSwift.java @@ -0,0 +1,57 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package com.example.swift; + +public class HelloSwift { + private double value; + private static double initialValue = 3.14159; + private String name = "Java"; + + static { + System.loadLibrary("JavaKitExample"); + } + + public HelloSwift() { + this.value = initialValue; + } + + public native int sayHello(int x, int y); + public native String throwMessageFromSwift(String message) throws Exception; + + // To be called back by the native code + private double sayHelloBack(int i) { + System.out.println("And hello back from " + name + "! You passed me " + i); + return value; + } + + public void greet(String name) { + System.out.println("Salutations, " + name); + } + + String[] doublesToStrings(double[] doubles) { + int size = doubles.length; + String[] strings = new String[size]; + + for(int i = 0; i < size; i++) { + strings[i] = "" + doubles[i]; + } + + return strings; + } + + public void throwMessage(String message) throws Exception { + throw new Exception(message); + } +} diff --git a/Sources/JavaKitExample/com/example/swift/JavaKitSampleMain.java b/Sources/JavaKitExample/com/example/swift/JavaKitSampleMain.java new file mode 100644 index 00000000..2b565608 --- /dev/null +++ b/Sources/JavaKitExample/com/example/swift/JavaKitSampleMain.java @@ -0,0 +1,27 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package com.example.swift; + +/** + * This sample shows off a {@link HelloSwift} type which is partially implemented in Swift. + * For the Swift implementation refer to + */ +public class JavaKitSampleMain { + + public static void main(String[] args) { + int result = new HelloSubclass("Swift").sayHello(17, 25); + System.out.println("sayHello(17, 25) = " + result); + } +} From 27b96817996291ac8ce866689495c9bcb8740ba4 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Mon, 14 Oct 2024 13:30:03 -0700 Subject: [PATCH 083/426] Move the JavaKit sample app into its own sub-package Depend only on SwiftPM for this sample app --- Makefile | 4 +- Package.swift | 17 --- README.md | 4 +- Samples/JavaKitSampleApp/Package.swift | 43 +++++++ .../JavaKitExample/JavaKitExample.swift | 120 ++++++++++++++++++ .../com/example/swift/HelloSubclass.java | 0 .../com/example/swift/HelloSwift.java | 0 .../com/example/swift/JavaKitSampleMain.java | 0 Samples/JavaKitSampleApp/build.gradle | 60 --------- 9 files changed, 168 insertions(+), 80 deletions(-) create mode 100644 Samples/JavaKitSampleApp/Package.swift create mode 100644 Samples/JavaKitSampleApp/Sources/JavaKitExample/JavaKitExample.swift rename Samples/JavaKitSampleApp/{src/main/java => Sources/JavaKitExample}/com/example/swift/HelloSubclass.java (100%) rename Samples/JavaKitSampleApp/{src/main/java => Sources/JavaKitExample}/com/example/swift/HelloSwift.java (100%) rename Samples/JavaKitSampleApp/{src/main/java => Sources/JavaKitExample}/com/example/swift/JavaKitSampleMain.java (100%) delete mode 100644 Samples/JavaKitSampleApp/build.gradle diff --git a/Makefile b/Makefile index 191c7bb7..9833b086 100644 --- a/Makefile +++ b/Makefile @@ -63,8 +63,8 @@ all: $(BUILD_DIR)/debug/libJavaKit.$(LIB_SUFFIX) $(BUILD_DIR)/debug/Java2Swift: swift build -javakit-run: $(BUILD_DIR)/debug/libJavaKit.$(LIB_SUFFIX) $(BUILD_DIR)/debug/libExampleSwiftLibrary.$(LIB_SUFFIX) - java -cp .build/plugins/outputs/swift-java/JavaKitExample/destination/JavaCompilerPlugin/Java -Djava.library.path=.build/debug com.example.swift.JavaKitSampleMain +javakit-run: + cd Samples/JavaKitSampleApp && swift build && java -cp .build/plugins/outputs/javakitsampleapp/JavaKitExample/destination/JavaCompilerPlugin/Java -Djava.library.path=.build/debug com.example.swift.JavaKitSampleMain Java2Swift: $(BUILD_DIR)/debug/Java2Swift diff --git a/Package.swift b/Package.swift index 50c02c12..a581e842 100644 --- a/Package.swift +++ b/Package.swift @@ -115,11 +115,6 @@ let package = Package( // ==== Examples - .library( - name: "JavaKitExample", - type: .dynamic, - targets: ["JavaKitExample"] - ), .library( name: "ExampleSwiftLibrary", type: .dynamic, @@ -211,18 +206,6 @@ let package = Package( capability: .buildTool() ), - .target( - name: "JavaKitExample", - dependencies: ["JavaKit"], - swiftSettings: [ - .swiftLanguageMode(.v5), - .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) - ], - plugins: [ - .plugin(name: "JavaCompilerPlugin") - ] - ), - .target( name: "ExampleSwiftLibrary", dependencies: [], diff --git a/README.md b/README.md index b30d905e..6bf9df2f 100644 --- a/README.md +++ b/README.md @@ -95,7 +95,9 @@ Sample apps are located in the `Samples/` directory, and they showcase full "rou To run a simple app showcasing a Swift process calling into a Java library you can run: ```bash -./gradlew Samples:JavaKitSampleApp:run +cd Samples/JavaKitSampleApp +swift build +java -cp .build/plugins/outputs/javakitsampleapp/JavaKitExample/destination/JavaCompilerPlugin/Java -Djava.library.path=.build/debug com.example.swift.JavaKitSampleMain ``` #### jextract (Java -> Swift) diff --git a/Samples/JavaKitSampleApp/Package.swift b/Samples/JavaKitSampleApp/Package.swift new file mode 100644 index 00000000..92f41d14 --- /dev/null +++ b/Samples/JavaKitSampleApp/Package.swift @@ -0,0 +1,43 @@ +// swift-tools-version: 6.0 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import CompilerPluginSupport +import PackageDescription + +let package = Package( + name: "JavaKitSampleApp", + platforms: [ + .macOS(.v13), + .iOS(.v13), + .tvOS(.v13), + .watchOS(.v6), + .macCatalyst(.v13), + ], + + products: [ + .library( + name: "JavaKitExample", + type: .dynamic, + targets: ["JavaKitExample"] + ), + ], + + dependencies: [ + .package(name: "swift-java", path: "../../") + ], + + targets: [ + .target( + name: "JavaKitExample", + dependencies: [ + .product(name: "JavaKit", package: "swift-java") + ], + swiftSettings: [ + .swiftLanguageMode(.v5) + ], + plugins: [ + .plugin(name: "JavaCompilerPlugin", package: "swift-java") + ] + ), + ] +) \ No newline at end of file diff --git a/Samples/JavaKitSampleApp/Sources/JavaKitExample/JavaKitExample.swift b/Samples/JavaKitSampleApp/Sources/JavaKitExample/JavaKitExample.swift new file mode 100644 index 00000000..d6eba19d --- /dev/null +++ b/Samples/JavaKitSampleApp/Sources/JavaKitExample/JavaKitExample.swift @@ -0,0 +1,120 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import JavaKit +import JavaRuntime + +enum SwiftWrappedError: Error { + case message(String) +} + +@JavaClass("com.example.swift.HelloSwift") +struct HelloSwift { + @JavaMethod + init(environment: JNIEnvironment) + + @JavaMethod + func sayHelloBack(_ i: Int32) -> Double + + @JavaMethod + func greet(_ name: String) + + @JavaMethod + func doublesToStrings(doubles: [Double]) -> [String] + + @JavaMethod + func throwMessage(message: String) throws + + @JavaField + var value: Double + + @JavaField + var name: String + + @ImplementsJava + func sayHello(i: Int32, _ j: Int32) -> Int32 { + print("Hello from Swift!") + let answer = self.sayHelloBack(i + j) + print("Swift got back \(answer) from Java") + + print("We expect the above value to be the initial value, \(self.javaClass.initialValue)") + + print("Updating Java field value to something different") + self.value = 2.71828 + + let newAnswer = self.sayHelloBack(17) + print("Swift got back updated \(newAnswer) from Java") + + let newHello = HelloSwift(environment: javaEnvironment) + print("Swift created a new Java instance with the value \(newHello.value)") + + let name = newHello.name + print("Hello to \(name)") + newHello.greet("Swift 👋🏽 How's it going") + + self.name = "a 🗑️-collected language" + _ = self.sayHelloBack(42) + + let strings = doublesToStrings(doubles: [3.14159, 2.71828]) + print("Converting doubles to strings: \(strings)") + + // Try downcasting + if let helloSub = self.as(HelloSubclass.self) { + print("Hello from the subclass!") + helloSub.greetMe() + + assert(helloSub.super.value == 2.71828) + } else { + fatalError("Expected subclass here") + } + + // Check "is" behavior + assert(newHello.is(HelloSwift.self)) + assert(!newHello.is(HelloSubclass.self)) + + // Create a new instance. + let helloSubFromSwift = HelloSubclass(greeting: "Hello from Swift", environment: javaEnvironment) + helloSubFromSwift.greetMe() + + do { + try throwMessage(message: "I am an error") + } catch { + print("Caught Java error: \(error)") + } + + return i * j + } + + @ImplementsJava + func throwMessageFromSwift(message: String) throws -> String { + throw SwiftWrappedError.message(message) + } +} + +extension JavaClass { + @JavaStaticField + var initialValue: Double +} + +@JavaClass("com.example.swift.HelloSubclass", extends: HelloSwift.self) +struct HelloSubclass { + @JavaField + var greeting: String + + @JavaMethod + func greetMe() + + @JavaMethod + init(greeting: String, environment: JNIEnvironment) +} diff --git a/Samples/JavaKitSampleApp/src/main/java/com/example/swift/HelloSubclass.java b/Samples/JavaKitSampleApp/Sources/JavaKitExample/com/example/swift/HelloSubclass.java similarity index 100% rename from Samples/JavaKitSampleApp/src/main/java/com/example/swift/HelloSubclass.java rename to Samples/JavaKitSampleApp/Sources/JavaKitExample/com/example/swift/HelloSubclass.java diff --git a/Samples/JavaKitSampleApp/src/main/java/com/example/swift/HelloSwift.java b/Samples/JavaKitSampleApp/Sources/JavaKitExample/com/example/swift/HelloSwift.java similarity index 100% rename from Samples/JavaKitSampleApp/src/main/java/com/example/swift/HelloSwift.java rename to Samples/JavaKitSampleApp/Sources/JavaKitExample/com/example/swift/HelloSwift.java diff --git a/Samples/JavaKitSampleApp/src/main/java/com/example/swift/JavaKitSampleMain.java b/Samples/JavaKitSampleApp/Sources/JavaKitExample/com/example/swift/JavaKitSampleMain.java similarity index 100% rename from Samples/JavaKitSampleApp/src/main/java/com/example/swift/JavaKitSampleMain.java rename to Samples/JavaKitSampleApp/Sources/JavaKitExample/com/example/swift/JavaKitSampleMain.java diff --git a/Samples/JavaKitSampleApp/build.gradle b/Samples/JavaKitSampleApp/build.gradle deleted file mode 100644 index 67295994..00000000 --- a/Samples/JavaKitSampleApp/build.gradle +++ /dev/null @@ -1,60 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of Swift.org project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -import org.swift.swiftkit.gradle.BuildUtils - -plugins { - id("build-logic.java-application-conventions") -} - -group = "org.swift.javakit" -version = "1.0-SNAPSHOT" - -repositories { - mavenCentral() -} - -java { - toolchain { - languageVersion.set(JavaLanguageVersion.of(22)) - } -} - -dependencies { - implementation(project(':SwiftKit')) - - testImplementation(platform("org.junit:junit-bom:5.10.0")) - testImplementation("org.junit.jupiter:junit-jupiter") -} - -tasks.test { - useJUnitPlatform() -} - -application { - mainClass = "com.example.swift.JavaKitSampleMain" - - // In order to silence: - // WARNING: A restricted method in java.lang.foreign.SymbolLookup has been called - // WARNING: java.lang.foreign.SymbolLookup::libraryLookup has been called by org.example.swift.JavaKitExample in an unnamed module - // WARNING: Use --enable-native-access=ALL-UNNAMED to avoid a warning for callers in this module - // WARNING: Restricted methods will be blocked in a future release unless native access is enabled - // FIXME: Find out the proper solution to this - applicationDefaultJvmArgs = [ - "--enable-native-access=ALL-UNNAMED", - - // Include the library paths where our dylibs are that we want to load and call - "-Djava.library.path=" + BuildUtils.javaLibraryPaths(rootDir).join(":") - ] -} From 4eb6cc8efc23f1fb40f521e132f38d254765a30b Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Mon, 14 Oct 2024 17:08:47 -0700 Subject: [PATCH 084/426] Fix typo in makefile --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 9833b086..d804c41d 100644 --- a/Makefile +++ b/Makefile @@ -58,7 +58,7 @@ all: @echo " javakit-run: Run the JavaKit example program that uses Java libraries from Swift." @echo " javakit-generate: Regenerate the Swift wrapper code for the various JavaKit libraries from Java. This only has to be done when changing the Java2Swift tool." @echo " jextract-run: Run the Java example code that uses the wrapped Swift library. NOTE: this requires development toolchain described in the README." - @echo " jextract-generate: Generate Java wrapper code for the example Swift library allowing Swift to be called from Java. NOTE: this requires development toolchain described ein the README." + @echo " jextract-generate: Generate Java wrapper code for the example Swift library allowing Swift to be called from Java. NOTE: this requires development toolchain described in the README." $(BUILD_DIR)/debug/libJavaKit.$(LIB_SUFFIX) $(BUILD_DIR)/debug/Java2Swift: swift build From c575f00f4dd7e4aeb6293d82d6a60b6ccf6551a4 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Mon, 14 Oct 2024 17:00:40 -0700 Subject: [PATCH 085/426] Add a SwiftPM build plugin to generate Swift wrappers for Java classes Introduce the plugin `Java2SwiftPlugin`, which will invoke Java2Swift to generate Swift wrappers for the specified Java classes. Each SwiftPM target that uses this plugin must contain a file named `Java2Swift.config` that specifies options for the Java2Swift tool. This is a JSON file with a top-level dictionary that currently can contain keys for the Java class path (`classPath`) and a dictionary called `classes` whose keys are Java canonical class names (such as `java.util.Vector`) and whose values are the corresponding Swift names. For example: ```swift { "classes" : { "java.util.Vector" : "JavaVector" } } ``` will translate the class `java.util.Vector` into the Swift type `JavaVector`. The resulting Swift files will become part of the Swift module that uses this plugin. I've updated the JavaKitSampleApp to make use of this, albeit in a very narrow way that is not at all compelling. The user guide also needs updating. Fixes issue #16 --- Package.swift | 25 ++- Plugins/Java2SwiftPlugin/Configuration.swift | 26 +++ .../Java2SwiftPlugin/Java2SwiftPlugin.swift | 154 ++++++++++++++++++ Samples/JavaKitSampleApp/Package.swift | 6 +- .../Sources/JavaKitExample/Java2Swift.config | 5 + .../JavaKitExample/JavaKitExample.swift | 6 +- .../JavaToSwift.swift | 0 7 files changed, 217 insertions(+), 5 deletions(-) create mode 100644 Plugins/Java2SwiftPlugin/Configuration.swift create mode 100644 Plugins/Java2SwiftPlugin/Java2SwiftPlugin.swift create mode 100644 Samples/JavaKitSampleApp/Sources/JavaKitExample/Java2Swift.config rename Sources/{Java2SwiftTool => Java2Swift}/JavaToSwift.swift (100%) diff --git a/Package.swift b/Package.swift index a581e842..2b6e5e91 100644 --- a/Package.swift +++ b/Package.swift @@ -56,6 +56,11 @@ let package = Package( targets: ["JavaKit"] ), + .library( + name: "JavaRuntime", + targets: [ "JavaRuntime"] + ), + .library( name: "JavaKitJar", targets: ["JavaKitReflection"] @@ -83,7 +88,7 @@ let package = Package( .executable( name: "Java2Swift", - targets: ["Java2SwiftTool"] + targets: ["Java2Swift"] ), // ==== Plugin for building Java code @@ -94,6 +99,14 @@ let package = Package( ] ), + // ==== Plugin for wrapping Java classes in Swift + .plugin( + name: "Java2SwiftPlugin", + targets: [ + "Java2SwiftPlugin" + ] + ), + // ==== jextract-swift (extract Java accessors from Swift interface files) .executable( @@ -206,6 +219,14 @@ let package = Package( capability: .buildTool() ), + .plugin( + name: "Java2SwiftPlugin", + capability: .buildTool(), + dependencies: [ + "Java2Swift" + ] + ), + .target( name: "ExampleSwiftLibrary", dependencies: [], @@ -251,7 +272,7 @@ let package = Package( ), .executableTarget( - name: "Java2SwiftTool", + name: "Java2Swift", dependencies: [ .product(name: "SwiftBasicFormat", package: "swift-syntax"), .product(name: "SwiftSyntax", package: "swift-syntax"), diff --git a/Plugins/Java2SwiftPlugin/Configuration.swift b/Plugins/Java2SwiftPlugin/Configuration.swift new file mode 100644 index 00000000..e3e1b25a --- /dev/null +++ b/Plugins/Java2SwiftPlugin/Configuration.swift @@ -0,0 +1,26 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +/// Configuration for the Java2Swift translation tool, provided on a per-target +/// basis. +struct Configuration: Codable { + /// The Java class path that should be passed along to the Java2Swift tool. + var classPath: String? = nil + + /// The Java classes that should be translated to Swift. The keys are + /// canonical Java class names (e.g., java.util.Vector) and the values are + /// the corresponding Swift names (e.g., JavaVector). If the value is `nil`, + /// then the Java class name will be used for the Swift name, too. + var classes: [String: String?] = [:] +} diff --git a/Plugins/Java2SwiftPlugin/Java2SwiftPlugin.swift b/Plugins/Java2SwiftPlugin/Java2SwiftPlugin.swift new file mode 100644 index 00000000..e483b716 --- /dev/null +++ b/Plugins/Java2SwiftPlugin/Java2SwiftPlugin.swift @@ -0,0 +1,154 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import Foundation +import PackagePlugin + +@main +struct Java2SwiftBuildToolPlugin: BuildToolPlugin { + func createBuildCommands(context: PluginContext, target: Target) throws -> [Command] { + guard let sourceModule = target.sourceModule else { return [] } + + // Note: Target doesn't have a directoryURL counterpart to directory, + // so we cannot eliminate this deprecation warning. + let sourceDir = target.directory.string + + // Read a configuration file JavaKit.config from the target that provides + // information needed to call Java2Swift. + let configFile = URL(filePath: sourceDir) + .appending(path: "Java2Swift.config") + let configData = try Data(contentsOf: configFile) + let config = try JSONDecoder().decode(Configuration.self, from: configData) + + /// Find the manifest files from other Java2Swift executions in any targets + /// this target depends on. + var manifestFiles: [URL] = [] + func searchForManifestFiles(in target: any Target) { + let dependencyURL = URL(filePath: target.directory.string) + + // Look for a checked-in manifest file. + let generatedManifestURL = dependencyURL + .appending(path: "generated") + .appending(path: "\(target.name).swift2java") + let generatedManifestString = generatedManifestURL + .path(percentEncoded: false) + + if FileManager.default.fileExists(atPath: generatedManifestString) { + manifestFiles.append(generatedManifestURL) + } + + // TODO: Look for a manifest file that was built by the plugin itself. + } + + // Process direct dependencies of this target. + for dependency in target.dependencies { + switch dependency { + case .target(let target): + searchForManifestFiles(in: target) + + case .product(let product): + for target in product.targets { + searchForManifestFiles(in: target) + } + + @unknown default: + break + } + } + + // Process indirect target dependencies. + for dependency in target.recursiveTargetDependencies { + searchForManifestFiles(in: dependency) + } + + /// Determine the list of Java classes that will be translated into Swift, + /// along with the names of the corresponding Swift types. This will be + /// passed along to the Java2Swift tool. + let classes = config.classes.map { (javaClassName, swiftName) in + (javaClassName, swiftName ?? javaClassName.defaultSwiftNameForJavaClass) + }.sorted { (lhs, rhs) in + lhs.0 < rhs.0 + } + + let outputDirectory = context.pluginWorkDirectoryURL + .appending(path: "generated") + + var arguments: [String] = [ + "--module-name", sourceModule.name, + "--output-directory", outputDirectory.path(percentEncoded: false), + ] + if let classPath = config.classPath { + arguments += ["-cp", classPath] + } + arguments += manifestFiles.flatMap { manifestFile in + [ "--manifests", manifestFile.path(percentEncoded: false) ] + } + arguments += classes.map { (javaClassName, swiftName) in + "\(javaClassName)=\(swiftName)" + } + + /// Determine the set of Swift files that will be emitted by the Java2Swift + /// tool. + let outputSwiftFiles = classes.map { (javaClassName, swiftName) in + outputDirectory.appending(path: "\(swiftName).swift") + } + [ + outputDirectory.appending(path: "\(sourceModule.name).swift2java") + ] + + return [ + .buildCommand( + displayName: "Wrapping \(classes.count) Java classes target \(sourceModule.name) in Swift", + executable: try context.tool(named: "Java2Swift").url, + arguments: arguments, + inputFiles: [ configFile ], + outputFiles: outputSwiftFiles + ) + ] + } +} + +// Note: the JAVA_HOME environment variable must be set to point to where +// Java is installed, e.g., +// Library/Java/JavaVirtualMachines/openjdk-21.jdk/Contents/Home. +func findJavaHome() -> String { + if let home = ProcessInfo.processInfo.environment["JAVA_HOME"] { + return home + } + + // This is a workaround for envs (some IDEs) which have trouble with + // picking up env variables during the build process + let path = "\(FileManager.default.homeDirectoryForCurrentUser.path()).java_home" + if let home = try? String(contentsOfFile: path, encoding: .utf8) { + if let lastChar = home.last, lastChar.isNewline { + return String(home.dropLast()) + } + + return home + } + + fatalError("Please set the JAVA_HOME environment variable to point to where Java is installed.") +} + +extension String { + /// For a String that's of the form java.util.Vector, return the "Vector" + /// part. + fileprivate var defaultSwiftNameForJavaClass: String { + if let dotLoc = lastIndex(of: ".") { + let afterDot = index(after: dotLoc) + return String(self[afterDot...]) + } + + return self + } +} diff --git a/Samples/JavaKitSampleApp/Package.swift b/Samples/JavaKitSampleApp/Package.swift index 92f41d14..df2c65f1 100644 --- a/Samples/JavaKitSampleApp/Package.swift +++ b/Samples/JavaKitSampleApp/Package.swift @@ -30,14 +30,16 @@ let package = Package( .target( name: "JavaKitExample", dependencies: [ - .product(name: "JavaKit", package: "swift-java") + .product(name: "JavaKit", package: "swift-java"), + .product(name: "JavaKitJar", package: "swift-java"), ], swiftSettings: [ .swiftLanguageMode(.v5) ], plugins: [ + .plugin(name: "Java2SwiftPlugin", package: "swift-java"), .plugin(name: "JavaCompilerPlugin", package: "swift-java") ] ), ] -) \ No newline at end of file +) diff --git a/Samples/JavaKitSampleApp/Sources/JavaKitExample/Java2Swift.config b/Samples/JavaKitSampleApp/Sources/JavaKitExample/Java2Swift.config new file mode 100644 index 00000000..876f60bc --- /dev/null +++ b/Samples/JavaKitSampleApp/Sources/JavaKitExample/Java2Swift.config @@ -0,0 +1,5 @@ +{ + "classes" : { + "java.util.Vector" : null + } +} diff --git a/Samples/JavaKitSampleApp/Sources/JavaKitExample/JavaKitExample.swift b/Samples/JavaKitSampleApp/Sources/JavaKitExample/JavaKitExample.swift index d6eba19d..f5ac82d7 100644 --- a/Samples/JavaKitSampleApp/Sources/JavaKitExample/JavaKitExample.swift +++ b/Samples/JavaKitSampleApp/Sources/JavaKitExample/JavaKitExample.swift @@ -13,7 +13,6 @@ //===----------------------------------------------------------------------===// import JavaKit -import JavaRuntime enum SwiftWrappedError: Error { case message(String) @@ -118,3 +117,8 @@ struct HelloSubclass { @JavaMethod init(greeting: String, environment: JNIEnvironment) } + + +func returnNilVector() -> Vector>? { + nil +} diff --git a/Sources/Java2SwiftTool/JavaToSwift.swift b/Sources/Java2Swift/JavaToSwift.swift similarity index 100% rename from Sources/Java2SwiftTool/JavaToSwift.swift rename to Sources/Java2Swift/JavaToSwift.swift From a548b451dd7d7fabe7f665cb5cc7ef75b5c04109 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Tue, 15 Oct 2024 11:32:42 +0900 Subject: [PATCH 086/426] fix yamllint errors (#78) --- .github/workflows/pull_request.yml | 17 +++++++---------- docker/docker-compose.yaml | 1 - 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index ab6b4cbc..f37b0953 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -2,7 +2,7 @@ name: pull_request on: pull_request: - types: [ opened, reopened, synchronize ] + types: [opened, reopened, synchronize] jobs: soundness: @@ -12,9 +12,6 @@ jobs: # FIXME: Something is off with the format task and it gets "stuck", need to investigate format_check_enabled: false license_header_check_project_name: Swift.org - # FIXME: we're about to remove _Subprocess immediately anyway, so rather than fixing it one by one remove this adjusted list and use the default again ASAP - # swift-subprocess includes the word "kill" because SIGKILL signal handling so we allow it - unacceptable_language_check_word_list: "blacklist whitelist slave master sane sanity insane insanity killed killing hang hung hanged hanging" #ignore-unacceptable-language test-java: name: Java tests (swift:${{ matrix.swift_version }} jdk:${{matrix.jdk_vendor}} os:${{ matrix.os_version }}) @@ -22,9 +19,9 @@ jobs: strategy: fail-fast: true matrix: - swift_version: [ 'nightly-main' ] - os_version: [ 'jammy' ] - jdk_vendor: [ 'Corretto' ] + swift_version: ['nightly-main'] + os_version: ['jammy'] + jdk_vendor: ['Corretto'] container: image: ${{ (contains(matrix.swift_version, 'nightly') && 'swiftlang/swift') || 'swift' }}:${{ matrix.swift_version }}-${{ matrix.os_version }} env: @@ -68,9 +65,9 @@ jobs: strategy: fail-fast: false matrix: - swift_version: [ 'nightly-main' ] - os_version: [ 'jammy' ] - jdk_vendor: [ 'Corretto' ] + swift_version: ['nightly-main'] + os_version: ['jammy'] + jdk_vendor: ['Corretto'] container: image: ${{ (contains(matrix.swift_version, 'nightly') && 'swiftlang/swift') || 'swift' }}:${{ matrix.swift_version }}-${{ matrix.os_version }} env: diff --git a/docker/docker-compose.yaml b/docker/docker-compose.yaml index 2a22c484..af22ea4a 100644 --- a/docker/docker-compose.yaml +++ b/docker/docker-compose.yaml @@ -44,4 +44,3 @@ services: shell: <<: *common entrypoint: /bin/bash - From 8496f1a4cae01148ecca3862df7d9b794f42f742 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Mon, 14 Oct 2024 21:18:06 -0700 Subject: [PATCH 087/426] Address code review comments --- .licenseignore | 1 + Package.swift | 2 +- .../JavaKitSampleApp/Sources/JavaKitExample/Java2Swift.config | 2 +- .../Sources/JavaKitExample/JavaKitExample.swift | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.licenseignore b/.licenseignore index 86afc57b..cb3be0cf 100644 --- a/.licenseignore +++ b/.licenseignore @@ -5,6 +5,7 @@ .swift-format .github/* *.md +**/*.config CONTRIBUTORS.txt LICENSE.txt NOTICE.txt diff --git a/Package.swift b/Package.swift index 2b6e5e91..0d6aa048 100644 --- a/Package.swift +++ b/Package.swift @@ -58,7 +58,7 @@ let package = Package( .library( name: "JavaRuntime", - targets: [ "JavaRuntime"] + targets: ["JavaRuntime"] ), .library( diff --git a/Samples/JavaKitSampleApp/Sources/JavaKitExample/Java2Swift.config b/Samples/JavaKitSampleApp/Sources/JavaKitExample/Java2Swift.config index 876f60bc..ec19d82b 100644 --- a/Samples/JavaKitSampleApp/Sources/JavaKitExample/Java2Swift.config +++ b/Samples/JavaKitSampleApp/Sources/JavaKitExample/Java2Swift.config @@ -1,5 +1,5 @@ { "classes" : { - "java.util.Vector" : null + "java.util.ArrayList" : "ArrayList" } } diff --git a/Samples/JavaKitSampleApp/Sources/JavaKitExample/JavaKitExample.swift b/Samples/JavaKitSampleApp/Sources/JavaKitExample/JavaKitExample.swift index f5ac82d7..2f7554dd 100644 --- a/Samples/JavaKitSampleApp/Sources/JavaKitExample/JavaKitExample.swift +++ b/Samples/JavaKitSampleApp/Sources/JavaKitExample/JavaKitExample.swift @@ -119,6 +119,6 @@ struct HelloSubclass { } -func returnNilVector() -> Vector>? { +func returnNilVector() -> ArrayList>? { nil } From a9fdd61be9ad893c73e87d485ba03e33778425ff Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Mon, 14 Oct 2024 21:50:36 -0700 Subject: [PATCH 088/426] Make the example use of ArrayList a little bit more interesting --- .../Sources/JavaKitExample/JavaKitExample.swift | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Samples/JavaKitSampleApp/Sources/JavaKitExample/JavaKitExample.swift b/Samples/JavaKitSampleApp/Sources/JavaKitExample/JavaKitExample.swift index 2f7554dd..090c4356 100644 --- a/Samples/JavaKitSampleApp/Sources/JavaKitExample/JavaKitExample.swift +++ b/Samples/JavaKitSampleApp/Sources/JavaKitExample/JavaKitExample.swift @@ -119,6 +119,8 @@ struct HelloSubclass { } -func returnNilVector() -> ArrayList>? { - nil +func removeLast(arrayList: ArrayList>) { + if let lastObject = arrayList.getLast() { + _ = arrayList.remove(lastObject) + } } From 43a91c2396e149f2823bc45bbe58be868c7acf96 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Mon, 14 Oct 2024 23:49:22 -0700 Subject: [PATCH 089/426] Add a JavaKit sample that produces a Swift command-line app using Java APIs (#79) * Remove stale JavaKitExample sources * Add a JavaKit sample that produces a Swift command-line app using Java APIs This demonstrates how to pull in just one Java type (java.math.BigInteger) and use it from a Swift program (a command line app). --- Samples/JavaProbablyPrime/Package.swift | 45 +++++++ Samples/JavaProbablyPrime/README.md | 13 ++ .../JavaProbablyPrime/Java2Swift.config | 5 + .../Sources/JavaProbablyPrime/prime.swift | 38 ++++++ Sources/JavaKitExample/JavaKitExample.swift | 120 ------------------ .../com/example/swift/HelloSubclass.java | 27 ---- .../com/example/swift/HelloSwift.java | 57 --------- .../com/example/swift/JavaKitSampleMain.java | 27 ---- 8 files changed, 101 insertions(+), 231 deletions(-) create mode 100644 Samples/JavaProbablyPrime/Package.swift create mode 100644 Samples/JavaProbablyPrime/README.md create mode 100644 Samples/JavaProbablyPrime/Sources/JavaProbablyPrime/Java2Swift.config create mode 100644 Samples/JavaProbablyPrime/Sources/JavaProbablyPrime/prime.swift delete mode 100644 Sources/JavaKitExample/JavaKitExample.swift delete mode 100644 Sources/JavaKitExample/com/example/swift/HelloSubclass.java delete mode 100644 Sources/JavaKitExample/com/example/swift/HelloSwift.java delete mode 100644 Sources/JavaKitExample/com/example/swift/JavaKitSampleMain.java diff --git a/Samples/JavaProbablyPrime/Package.swift b/Samples/JavaProbablyPrime/Package.swift new file mode 100644 index 00000000..0420942b --- /dev/null +++ b/Samples/JavaProbablyPrime/Package.swift @@ -0,0 +1,45 @@ +// swift-tools-version: 6.0 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import CompilerPluginSupport +import PackageDescription + +let package = Package( + name: "JavaProbablyPrime", + platforms: [ + .macOS(.v13), + .iOS(.v13), + .tvOS(.v13), + .watchOS(.v6), + .macCatalyst(.v13), + ], + + products: [ + .executable( + name: "JavaProbablyPrime", + targets: ["JavaProbablyPrime"] + ), + ], + + dependencies: [ + .package(name: "swift-java", path: "../../"), + .package(url: "https://github.com/apple/swift-argument-parser", from: "1.5.0"), + ], + + targets: [ + .executableTarget( + name: "JavaProbablyPrime", + dependencies: [ + .product(name: "JavaKit", package: "swift-java"), + .product(name: "JavaKitVM", package: "swift-java"), + .product(name: "ArgumentParser", package: "swift-argument-parser"), + ], + swiftSettings: [ + .swiftLanguageMode(.v5) + ], + plugins: [ + .plugin(name: "Java2SwiftPlugin", package: "swift-java"), + ] + ), + ] +) diff --git a/Samples/JavaProbablyPrime/README.md b/Samples/JavaProbablyPrime/README.md new file mode 100644 index 00000000..f9fe318f --- /dev/null +++ b/Samples/JavaProbablyPrime/README.md @@ -0,0 +1,13 @@ +# JavaKit Example: Using Java APIs from Swift + +This package contains an example program that uses Java's [`java.math.BigInteger`](https://docs.oracle.com/javase/8/docs/api/?java/math/BigInteger.html) from Swift to determine whether a given number is probably prime. You can try it out with your own very big number: + +``` +swift run JavaProbablyPrime +``` + +The package itself demonstrates how to: + +* Use the Java2Swift build tool plugin to wrap the `java.math.BigInteger` type in Swift. +* Create a `JavaVirtualMachine` instance in a Swift command-line program. +* Create an instance of `BigInteger` in Swift and use its `isProbablyPrime`. diff --git a/Samples/JavaProbablyPrime/Sources/JavaProbablyPrime/Java2Swift.config b/Samples/JavaProbablyPrime/Sources/JavaProbablyPrime/Java2Swift.config new file mode 100644 index 00000000..f73d01df --- /dev/null +++ b/Samples/JavaProbablyPrime/Sources/JavaProbablyPrime/Java2Swift.config @@ -0,0 +1,5 @@ +{ + "classes" : { + "java.math.BigInteger" : "BigInteger" + } +} diff --git a/Samples/JavaProbablyPrime/Sources/JavaProbablyPrime/prime.swift b/Samples/JavaProbablyPrime/Sources/JavaProbablyPrime/prime.swift new file mode 100644 index 00000000..bd83c1ee --- /dev/null +++ b/Samples/JavaProbablyPrime/Sources/JavaProbablyPrime/prime.swift @@ -0,0 +1,38 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import ArgumentParser +import JavaKit +import JavaKitVM + +@main +struct ProbablyPrime: ParsableCommand { + @Argument(help: "The number to check for primality") + var number: String + + @Option(help: "The certainty to require in the prime check") + var certainty: Int32 = 10 + + func run() throws { + let javaVirtualMachine = try JavaVirtualMachine.shared() + let jniEnvironment = try javaVirtualMachine.environment() + + let bigInt = BigInteger(number, environment: jniEnvironment) + if bigInt.isProbablePrime(certainty) { + print("\(number) is probably prime") + } else { + print("\(number) is definitely not prime") + } + } +} diff --git a/Sources/JavaKitExample/JavaKitExample.swift b/Sources/JavaKitExample/JavaKitExample.swift deleted file mode 100644 index d6eba19d..00000000 --- a/Sources/JavaKitExample/JavaKitExample.swift +++ /dev/null @@ -1,120 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of Swift.org project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -import JavaKit -import JavaRuntime - -enum SwiftWrappedError: Error { - case message(String) -} - -@JavaClass("com.example.swift.HelloSwift") -struct HelloSwift { - @JavaMethod - init(environment: JNIEnvironment) - - @JavaMethod - func sayHelloBack(_ i: Int32) -> Double - - @JavaMethod - func greet(_ name: String) - - @JavaMethod - func doublesToStrings(doubles: [Double]) -> [String] - - @JavaMethod - func throwMessage(message: String) throws - - @JavaField - var value: Double - - @JavaField - var name: String - - @ImplementsJava - func sayHello(i: Int32, _ j: Int32) -> Int32 { - print("Hello from Swift!") - let answer = self.sayHelloBack(i + j) - print("Swift got back \(answer) from Java") - - print("We expect the above value to be the initial value, \(self.javaClass.initialValue)") - - print("Updating Java field value to something different") - self.value = 2.71828 - - let newAnswer = self.sayHelloBack(17) - print("Swift got back updated \(newAnswer) from Java") - - let newHello = HelloSwift(environment: javaEnvironment) - print("Swift created a new Java instance with the value \(newHello.value)") - - let name = newHello.name - print("Hello to \(name)") - newHello.greet("Swift 👋🏽 How's it going") - - self.name = "a 🗑️-collected language" - _ = self.sayHelloBack(42) - - let strings = doublesToStrings(doubles: [3.14159, 2.71828]) - print("Converting doubles to strings: \(strings)") - - // Try downcasting - if let helloSub = self.as(HelloSubclass.self) { - print("Hello from the subclass!") - helloSub.greetMe() - - assert(helloSub.super.value == 2.71828) - } else { - fatalError("Expected subclass here") - } - - // Check "is" behavior - assert(newHello.is(HelloSwift.self)) - assert(!newHello.is(HelloSubclass.self)) - - // Create a new instance. - let helloSubFromSwift = HelloSubclass(greeting: "Hello from Swift", environment: javaEnvironment) - helloSubFromSwift.greetMe() - - do { - try throwMessage(message: "I am an error") - } catch { - print("Caught Java error: \(error)") - } - - return i * j - } - - @ImplementsJava - func throwMessageFromSwift(message: String) throws -> String { - throw SwiftWrappedError.message(message) - } -} - -extension JavaClass { - @JavaStaticField - var initialValue: Double -} - -@JavaClass("com.example.swift.HelloSubclass", extends: HelloSwift.self) -struct HelloSubclass { - @JavaField - var greeting: String - - @JavaMethod - func greetMe() - - @JavaMethod - init(greeting: String, environment: JNIEnvironment) -} diff --git a/Sources/JavaKitExample/com/example/swift/HelloSubclass.java b/Sources/JavaKitExample/com/example/swift/HelloSubclass.java deleted file mode 100644 index eb3cba32..00000000 --- a/Sources/JavaKitExample/com/example/swift/HelloSubclass.java +++ /dev/null @@ -1,27 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of Swift.org project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -package com.example.swift; - -public class HelloSubclass extends HelloSwift { - private String greeting; - - public HelloSubclass(String greeting) { - this.greeting = greeting; - } - - private void greetMe() { - super.greet(greeting); - } -} diff --git a/Sources/JavaKitExample/com/example/swift/HelloSwift.java b/Sources/JavaKitExample/com/example/swift/HelloSwift.java deleted file mode 100644 index b4c87f71..00000000 --- a/Sources/JavaKitExample/com/example/swift/HelloSwift.java +++ /dev/null @@ -1,57 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of Swift.org project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -package com.example.swift; - -public class HelloSwift { - private double value; - private static double initialValue = 3.14159; - private String name = "Java"; - - static { - System.loadLibrary("JavaKitExample"); - } - - public HelloSwift() { - this.value = initialValue; - } - - public native int sayHello(int x, int y); - public native String throwMessageFromSwift(String message) throws Exception; - - // To be called back by the native code - private double sayHelloBack(int i) { - System.out.println("And hello back from " + name + "! You passed me " + i); - return value; - } - - public void greet(String name) { - System.out.println("Salutations, " + name); - } - - String[] doublesToStrings(double[] doubles) { - int size = doubles.length; - String[] strings = new String[size]; - - for(int i = 0; i < size; i++) { - strings[i] = "" + doubles[i]; - } - - return strings; - } - - public void throwMessage(String message) throws Exception { - throw new Exception(message); - } -} diff --git a/Sources/JavaKitExample/com/example/swift/JavaKitSampleMain.java b/Sources/JavaKitExample/com/example/swift/JavaKitSampleMain.java deleted file mode 100644 index 2b565608..00000000 --- a/Sources/JavaKitExample/com/example/swift/JavaKitSampleMain.java +++ /dev/null @@ -1,27 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of Swift.org project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -package com.example.swift; - -/** - * This sample shows off a {@link HelloSwift} type which is partially implemented in Swift. - * For the Swift implementation refer to - */ -public class JavaKitSampleMain { - - public static void main(String[] args) { - int result = new HelloSubclass("Swift").sayHello(17, 25); - System.out.println("sayHello(17, 25) = " + result); - } -} From 4b3387d85ef742feeaef14ff2614f0fce3354f29 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Tue, 15 Oct 2024 16:32:32 +0900 Subject: [PATCH 090/426] Include Swift samples/ in Ci verification (#80) * Include Swift samples in CI verification * maxdepth is more compatible in find command --- .github/workflows/pull_request.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index f37b0953..251ba1b3 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -106,3 +106,6 @@ jobs: run: "make jextract-generate" - name: Test Swift run: "swift test" + - name: Build (Swift) Sample Apps + run: | + find Samples/ -name Package.swift -maxdepth 2 -exec swift build --package-path $(dirname {}) \;; From 46a05cec452d11bef54ec7abb2e69d4811b1b6ab Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Tue, 15 Oct 2024 10:40:37 -0700 Subject: [PATCH 091/426] Java2SwiftPlugin: Drop the ability to infer Swift type names The configuration file should be explicit. If we want to infer Swift type names, we should do it when generating the configuration file. --- Plugins/Java2SwiftPlugin/Configuration.swift | 5 ++--- Plugins/Java2SwiftPlugin/Java2SwiftPlugin.swift | 17 +---------------- 2 files changed, 3 insertions(+), 19 deletions(-) diff --git a/Plugins/Java2SwiftPlugin/Configuration.swift b/Plugins/Java2SwiftPlugin/Configuration.swift index e3e1b25a..bf067f8d 100644 --- a/Plugins/Java2SwiftPlugin/Configuration.swift +++ b/Plugins/Java2SwiftPlugin/Configuration.swift @@ -20,7 +20,6 @@ struct Configuration: Codable { /// The Java classes that should be translated to Swift. The keys are /// canonical Java class names (e.g., java.util.Vector) and the values are - /// the corresponding Swift names (e.g., JavaVector). If the value is `nil`, - /// then the Java class name will be used for the Swift name, too. - var classes: [String: String?] = [:] + /// the corresponding Swift names (e.g., JavaVector). + var classes: [String: String] = [:] } diff --git a/Plugins/Java2SwiftPlugin/Java2SwiftPlugin.swift b/Plugins/Java2SwiftPlugin/Java2SwiftPlugin.swift index e483b716..b8ac32fe 100644 --- a/Plugins/Java2SwiftPlugin/Java2SwiftPlugin.swift +++ b/Plugins/Java2SwiftPlugin/Java2SwiftPlugin.swift @@ -75,9 +75,7 @@ struct Java2SwiftBuildToolPlugin: BuildToolPlugin { /// Determine the list of Java classes that will be translated into Swift, /// along with the names of the corresponding Swift types. This will be /// passed along to the Java2Swift tool. - let classes = config.classes.map { (javaClassName, swiftName) in - (javaClassName, swiftName ?? javaClassName.defaultSwiftNameForJavaClass) - }.sorted { (lhs, rhs) in + let classes = config.classes.sorted { (lhs, rhs) in lhs.0 < rhs.0 } @@ -139,16 +137,3 @@ func findJavaHome() -> String { fatalError("Please set the JAVA_HOME environment variable to point to where Java is installed.") } - -extension String { - /// For a String that's of the form java.util.Vector, return the "Vector" - /// part. - fileprivate var defaultSwiftNameForJavaClass: String { - if let dotLoc = lastIndex(of: ".") { - let afterDot = index(after: dotLoc) - return String(self[afterDot...]) - } - - return self - } -} From 18a105a8dd288d0be23b676b07fc858e42414118 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Tue, 15 Oct 2024 13:02:43 -0700 Subject: [PATCH 092/426] Rework Java2Swift to operate entirely on Java2Swift.config files Instead of having Java2Swift take in a list of classes on the command line, which the plugin synthesizes by reading a configuration file, and then emitting another almost-identical manifest file... rework the command-line interface to Java2Swift to operate entirely on the per-target Java2Swift.config files. This makes the plugin simpler, because it never has to look at build products for its dependencies. Change the `--jar-file` mode of Java2Swift to emit the configuration file but not translate any classes. This should be used as a tool, not a build step. Update the user guide to introduce JavaKit through the build tool. --- Makefile | 8 +- Plugins/Java2SwiftPlugin/Configuration.swift | 3 + .../Java2SwiftPlugin/Java2SwiftPlugin.swift | 57 +-- Sources/Java2Swift/JavaToSwift.swift | 164 ++++--- Sources/Java2SwiftLib/Configuration.swift | 33 ++ ...ift => JavaTranslator+Configuration.swift} | 29 +- Sources/Java2SwiftLib/JavaTranslator.swift | 14 +- .../Java2SwiftLib/TranslationManifest.swift | 24 - .../JavaKit.swift2java => Java2Swift.config} | 3 +- ...avaKitJar.swift2java => Java2Swift.config} | 3 +- .../generated/JavaKitNetwork.swift2java | 8 - .../generated/JavaKitReflection.swift2java | 19 - USER_GUIDE.md | 425 ++++++++++-------- 13 files changed, 406 insertions(+), 384 deletions(-) create mode 100644 Sources/Java2SwiftLib/Configuration.swift rename Sources/Java2SwiftLib/{JavaTranslator+TranslationManifest.swift => JavaTranslator+Configuration.swift} (52%) delete mode 100644 Sources/Java2SwiftLib/TranslationManifest.swift rename Sources/JavaKit/{generated/JavaKit.swift2java => Java2Swift.config} (82%) rename Sources/JavaKitJar/{generated/JavaKitJar.swift2java => Java2Swift.config} (83%) delete mode 100644 Sources/JavaKitNetwork/generated/JavaKitNetwork.swift2java delete mode 100644 Sources/JavaKitReflection/generated/JavaKitReflection.swift2java diff --git a/Makefile b/Makefile index d804c41d..00d33ca4 100644 --- a/Makefile +++ b/Makefile @@ -70,19 +70,19 @@ Java2Swift: $(BUILD_DIR)/debug/Java2Swift generate-JavaKit: Java2Swift mkdir -p Sources/JavaKit/generated - $(BUILD_DIR)/debug/Java2Swift --module-name JavaKit -o Sources/JavaKit/generated java.lang.Object=JavaObject java.util.Enumeration java.lang.Throwable java.lang.Exception java.lang.RuntimeException java.lang.Error=JavaError + $(BUILD_DIR)/debug/Java2Swift --module-name JavaKit -o Sources/JavaKit/generated Sources/JavaKit/Java2Swift.config generate-JavaKitReflection: Java2Swift generate-JavaKit mkdir -p Sources/JavaKitReflection/generated - $(BUILD_DIR)/debug/Java2Swift --module-name JavaKitReflection --manifests Sources/JavaKit/generated/JavaKit.swift2java -o Sources/JavaKitReflection/generated java.lang.reflect.Method java.lang.reflect.Type java.lang.reflect.Constructor java.lang.reflect.Parameter java.lang.reflect.ParameterizedType java.lang.reflect.Executable java.lang.reflect.AnnotatedType java.lang.reflect.TypeVariable java.lang.reflect.WildcardType java.lang.reflect.GenericArrayType java.lang.reflect.AccessibleObject java.lang.annotation.Annotation java.lang.reflect.GenericDeclaration java.lang.reflect.Field + $(BUILD_DIR)/debug/Java2Swift --module-name JavaKitReflection --depends-on JavaKit=Sources/JavaKit/Java2Swift.config -o Sources/JavaKitReflection/generated Sources/JavaKitReflection/Java2Swift.config generate-JavaKitJar: Java2Swift generate-JavaKit mkdir -p Sources/JavaKitJar/generated - $(BUILD_DIR)/debug/Java2Swift --module-name JavaKitJar --manifests Sources/JavaKit/generated/JavaKit.swift2java -o Sources/JavaKitJar/generated java.util.jar.Attributes java.util.jar.JarEntry java.util.jar.JarFile java.util.jar.JarInputStream java.util.jar.JarOutputStream java.util.jar.Manifest + $(BUILD_DIR)/debug/Java2Swift --module-name JavaKitJar --depends-on JavaKit=Sources/JavaKit/Java2Swift.config -o Sources/JavaKitJar/generated Sources/JavaKitJar/Java2Swift.config generate-JavaKitNetwork: Java2Swift generate-JavaKit mkdir -p Sources/JavaKitNetwork/generated - $(BUILD_DIR)/debug/Java2Swift --module-name JavaKitNetwork --manifests Sources/JavaKit/generated/JavaKit.swift2java -o Sources/JavaKitNetwork/generated java.net.URI java.net.URL java.net.URLClassLoader + $(BUILD_DIR)/debug/Java2Swift --module-name JavaKitNetwork --depends-on JavaKit=Sources/JavaKit/Java2Swift.config -o Sources/JavaKitNetwork/generated Sources/JavaKitNetwork/Java2Swift.config javakit-generate: generate-JavaKit generate-JavaKitReflection generate-JavaKitJar generate-JavaKitNetwork diff --git a/Plugins/Java2SwiftPlugin/Configuration.swift b/Plugins/Java2SwiftPlugin/Configuration.swift index bf067f8d..6b9b4076 100644 --- a/Plugins/Java2SwiftPlugin/Configuration.swift +++ b/Plugins/Java2SwiftPlugin/Configuration.swift @@ -14,6 +14,9 @@ /// Configuration for the Java2Swift translation tool, provided on a per-target /// basis. +/// +/// Note: there is a copy of this struct in the Java2Swift library. They +/// must be kept in sync. struct Configuration: Codable { /// The Java class path that should be passed along to the Java2Swift tool. var classPath: String? = nil diff --git a/Plugins/Java2SwiftPlugin/Java2SwiftPlugin.swift b/Plugins/Java2SwiftPlugin/Java2SwiftPlugin.swift index b8ac32fe..10b32729 100644 --- a/Plugins/Java2SwiftPlugin/Java2SwiftPlugin.swift +++ b/Plugins/Java2SwiftPlugin/Java2SwiftPlugin.swift @@ -15,6 +15,8 @@ import Foundation import PackagePlugin +fileprivate let Java2SwiftConfigFileName = "Java2Swift.config" + @main struct Java2SwiftBuildToolPlugin: BuildToolPlugin { func createBuildCommands(context: PluginContext, target: Target) throws -> [Command] { @@ -24,8 +26,8 @@ struct Java2SwiftBuildToolPlugin: BuildToolPlugin { // so we cannot eliminate this deprecation warning. let sourceDir = target.directory.string - // Read a configuration file JavaKit.config from the target that provides - // information needed to call Java2Swift. + // The name of the configuration file JavaKit.config from the target for + // which we are generating Swift wrappers for Java classes. let configFile = URL(filePath: sourceDir) .appending(path: "Java2Swift.config") let configData = try Data(contentsOf: configFile) @@ -33,33 +35,30 @@ struct Java2SwiftBuildToolPlugin: BuildToolPlugin { /// Find the manifest files from other Java2Swift executions in any targets /// this target depends on. - var manifestFiles: [URL] = [] - func searchForManifestFiles(in target: any Target) { + var dependentConfigFiles: [(String, URL)] = [] + func searchForConfigFiles(in target: any Target) { let dependencyURL = URL(filePath: target.directory.string) - // Look for a checked-in manifest file. - let generatedManifestURL = dependencyURL - .appending(path: "generated") - .appending(path: "\(target.name).swift2java") - let generatedManifestString = generatedManifestURL + // Look for a config file within this target. + let dependencyConfigURL = dependencyURL + .appending(path: Java2SwiftConfigFileName) + let dependencyConfigString = dependencyConfigURL .path(percentEncoded: false) - if FileManager.default.fileExists(atPath: generatedManifestString) { - manifestFiles.append(generatedManifestURL) + if FileManager.default.fileExists(atPath: dependencyConfigString) { + dependentConfigFiles.append((target.name, dependencyConfigURL)) } - - // TODO: Look for a manifest file that was built by the plugin itself. } // Process direct dependencies of this target. for dependency in target.dependencies { switch dependency { case .target(let target): - searchForManifestFiles(in: target) + searchForConfigFiles(in: target) case .product(let product): for target in product.targets { - searchForManifestFiles(in: target) + searchForConfigFiles(in: target) } @unknown default: @@ -69,14 +68,7 @@ struct Java2SwiftBuildToolPlugin: BuildToolPlugin { // Process indirect target dependencies. for dependency in target.recursiveTargetDependencies { - searchForManifestFiles(in: dependency) - } - - /// Determine the list of Java classes that will be translated into Swift, - /// along with the names of the corresponding Swift types. This will be - /// passed along to the Java2Swift tool. - let classes = config.classes.sorted { (lhs, rhs) in - lhs.0 < rhs.0 + searchForConfigFiles(in: dependency) } let outputDirectory = context.pluginWorkDirectoryURL @@ -86,19 +78,18 @@ struct Java2SwiftBuildToolPlugin: BuildToolPlugin { "--module-name", sourceModule.name, "--output-directory", outputDirectory.path(percentEncoded: false), ] - if let classPath = config.classPath { - arguments += ["-cp", classPath] - } - arguments += manifestFiles.flatMap { manifestFile in - [ "--manifests", manifestFile.path(percentEncoded: false) ] - } - arguments += classes.map { (javaClassName, swiftName) in - "\(javaClassName)=\(swiftName)" + arguments += dependentConfigFiles.flatMap { moduleAndConfigFile in + let (moduleName, configFile) = moduleAndConfigFile + return [ + "--depends-on", + "\(moduleName)=\(configFile.path(percentEncoded: false))" + ] } + arguments.append(configFile.path(percentEncoded: false)) /// Determine the set of Swift files that will be emitted by the Java2Swift /// tool. - let outputSwiftFiles = classes.map { (javaClassName, swiftName) in + let outputSwiftFiles = config.classes.map { (javaClassName, swiftName) in outputDirectory.appending(path: "\(swiftName).swift") } + [ outputDirectory.appending(path: "\(sourceModule.name).swift2java") @@ -106,7 +97,7 @@ struct Java2SwiftBuildToolPlugin: BuildToolPlugin { return [ .buildCommand( - displayName: "Wrapping \(classes.count) Java classes target \(sourceModule.name) in Swift", + displayName: "Wrapping \(config.classes.count) Java classes target \(sourceModule.name) in Swift", executable: try context.tool(named: "Java2Swift").url, arguments: arguments, inputFiles: [ configFile ], diff --git a/Sources/Java2Swift/JavaToSwift.swift b/Sources/Java2Swift/JavaToSwift.swift index 17fef0f7..4d7d582c 100644 --- a/Sources/Java2Swift/JavaToSwift.swift +++ b/Sources/Java2Swift/JavaToSwift.swift @@ -31,23 +31,17 @@ struct JavaToSwift: ParsableCommand { @Option(help: "The name of the Swift module into which the resulting Swift types will be generated.") var moduleName: String - @Argument( - help: - "The Java classes to translate into Swift written with their canonical names (e.g., java.lang.Object). If the Swift name of the type should be different from simple name of the type, it can appended to the class name with '='." - ) - var classes: [String] = [] - @Option( help: - "The Java-to-Swift module manifest files for any Swift module containing Swift types created to wrap Java classes." + "A Java2Swift configuration file for a given Swift module name on which this module depends, e.g., JavaKitJar=Sources/JavaKitJar/Java2Swift.config. There should be one of these options for each Swift module that this module depends on (transitively) that contains wrapped Java sources." ) - var manifests: [String] = [] + var dependsOn: [String] = [] - @Option( + @Flag( help: - "The Jar file from which the set of class names should be loaded, if the classes weren't explicitly listed." + "Specifies that the input is a Jar file whose public classes will be loaded. The output of Java2Swift will be a configuration file (Java2Swift.config) that can be used as input to a subsequent Java2Swift invocation to generate wrappers for those public classes." ) - var jarFile: String? = nil + var jarFile: Bool = false @Option( name: [.customLong("cp"), .customLong("classpath")], @@ -55,9 +49,15 @@ struct JavaToSwift: ParsableCommand { ) var classpath: [String] = [] - @Option(name: .shortAndLong, help: "The directory in which to output the generated Swift files and manifest.") + @Option(name: .shortAndLong, help: "The directory in which to output the generated Swift files or the Java2Swift configuration file.") var outputDirectory: String = "." + @Argument( + help: + "The input file, which is either a Java2Swift configuration file or (if '-jar-file' was specified) a Jar file." + ) + var input: String + mutating func run() throws { var vmOptions: [String] = [] let classpath = classPathWithJarFile @@ -76,62 +76,39 @@ struct JavaToSwift: ParsableCommand { environment: environment ) - // Load all of the translation manifests this depends on. - for manifest in manifests { - try translator.loadTranslationManifest(from: URL(filePath: manifest)) - } - - if jarFile == nil && classes.isEmpty { - throw JavaToSwiftError.noClasses - } + // Load all of the configurations this depends on. + for config in dependsOn { + guard let equalLoc = config.firstIndex(of: "=") else { + throw JavaToSwiftError.badConfigOption(config) + } - // If we have a Jar file but no classes were listed, find all of the - // classes in the Jar file. - if let jarFileName = jarFile, classes.isEmpty { - let jarFile = try JarFile(jarFileName, false, environment: environment) - classes = jarFile.entries()!.compactMap { (entry) -> String? in - guard entry.getName().hasSuffix(".class") else { - return nil - } + let afterEqual = config.index(after: equalLoc) + let swiftModuleName = String(config[..] = [] - for javaClassNameOpt in self.classes { - // Determine the Java class name and its resulting Swift name. - let javaClassName: String - let swiftName: String - if let equalLoc = javaClassNameOpt.firstIndex(of: "=") { - let afterEqual = javaClassNameOpt.index(after: equalLoc) - javaClassName = String(javaClassNameOpt[..=" } } } + +extension String { + /// For a String that's of the form java.util.Vector, return the "Vector" + /// part. + fileprivate var defaultSwiftNameForJavaClass: String { + if let dotLoc = lastIndex(of: ".") { + let afterDot = index(after: dotLoc) + return String(self[afterDot...]) + } + + return self + } +} diff --git a/Sources/Java2SwiftLib/Configuration.swift b/Sources/Java2SwiftLib/Configuration.swift new file mode 100644 index 00000000..6617b4d0 --- /dev/null +++ b/Sources/Java2SwiftLib/Configuration.swift @@ -0,0 +1,33 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +/// Configuration for the Java2Swift translation tool, provided on a per-target +/// basis. +/// +/// Note: there is a copy of this struct in the Java2Swift plugin. They +/// must be kept in sync. +package struct Configuration: Codable { + /// The Java class path that should be passed along to the Java2Swift tool. + package var classPath: String? = nil + + /// The Java classes that should be translated to Swift. The keys are + /// canonical Java class names (e.g., java.util.Vector) and the values are + /// the corresponding Swift names (e.g., JavaVector). + package var classes: [String: String] = [:] + + package init(classPath: String? = nil, classes: [String : String] = [:]) { + self.classPath = classPath + self.classes = classes + } +} diff --git a/Sources/Java2SwiftLib/JavaTranslator+TranslationManifest.swift b/Sources/Java2SwiftLib/JavaTranslator+Configuration.swift similarity index 52% rename from Sources/Java2SwiftLib/JavaTranslator+TranslationManifest.swift rename to Sources/Java2SwiftLib/JavaTranslator+Configuration.swift index 896666d0..6025731b 100644 --- a/Sources/Java2SwiftLib/JavaTranslator+TranslationManifest.swift +++ b/Sources/Java2SwiftLib/JavaTranslator+Configuration.swift @@ -15,26 +15,25 @@ import Foundation extension JavaTranslator { - /// Load the manifest file with the given name to populate the known set of - /// translated Java classes. - package func loadTranslationManifest(from url: URL) throws { + /// Read a configuration file from the given URL. + package func readConfiguration(from url: URL) throws -> Configuration { let contents = try Data(contentsOf: url) - let manifest = try JSONDecoder().decode(TranslationManifest.self, from: contents) - for (javaClassName, swiftName) in manifest.translatedClasses { + return try JSONDecoder().decode(Configuration.self, from: contents) + } + + /// Load the configuration file with the given name to populate the known set of + /// translated Java classes. + package func loadDependentConfiguration(forSwiftModule swiftModule: String, from url: URL) throws { + let config = try readConfiguration(from: url) + + // TODO: Should we merge the class path from our dependencies? + + for (javaClassName, swiftName) in config.classes { translatedClasses[javaClassName] = ( swiftType: swiftName, - swiftModule: manifest.swiftModule, + swiftModule: swiftModule, isOptional: true ) } } - - /// Emit the translation manifest for this source file - package func encodeTranslationManifest() throws -> String { - let encoder = JSONEncoder() - encoder.outputFormatting = [.prettyPrinted, .sortedKeys] - var contents = String(data: try encoder.encode(manifest), encoding: .utf8)! - contents.append("\n") - return contents - } } diff --git a/Sources/Java2SwiftLib/JavaTranslator.swift b/Sources/Java2SwiftLib/JavaTranslator.swift index 3a911d48..7d2d2e77 100644 --- a/Sources/Java2SwiftLib/JavaTranslator.swift +++ b/Sources/Java2SwiftLib/JavaTranslator.swift @@ -31,11 +31,6 @@ package class JavaTranslator { /// A mapping from the canonical name of Java classes to the corresponding /// Swift type name, its Swift module, and whether we need to be working /// with optionals. - /// - /// FIXME: This is currently prepopulated with known translated classes, - /// which is absolutely not scalable. We need a better way to be able to - /// discover already-translated Java classes to get their corresponding - /// Swift types and modules. package var translatedClasses: [String: (swiftType: String, swiftModule: String?, isOptional: Bool)] = defaultTranslatedClasses @@ -44,9 +39,6 @@ package class JavaTranslator { /// import declarations. package var importedSwiftModules: Set = JavaTranslator.defaultImportedSwiftModules - /// The manifest for the module being translated. - package var manifest: TranslationManifest - package init( swiftModuleName: String, environment: JNIEnvironment, @@ -55,7 +47,6 @@ package class JavaTranslator { self.swiftModuleName = swiftModuleName self.environment = environment self.format = format - self.manifest = TranslationManifest(swiftModule: swiftModuleName) } /// Clear out any per-file state when we want to start a new file. @@ -82,7 +73,7 @@ extension JavaTranslator { /// The default set of translated classes that do not come from JavaKit /// itself. This should only be used to refer to types that are built-in to - /// JavaKit and therefore aren't captured in any manifest. + /// JavaKit and therefore aren't captured in any configuration file. package static let defaultTranslatedClasses: [String: (swiftType: String, swiftModule: String?, isOptional: Bool)] = [ "java.lang.Class": ("JavaClass", "JavaKit", true), "java.lang.String": ("String", "JavaKit", false), @@ -199,9 +190,6 @@ extension JavaTranslator { let fullName = javaClass.getCanonicalName() let swiftTypeName = try! getSwiftTypeNameFromJavaClassName(fullName) - // Record this translated class into the manifest. - manifest.translatedClasses[fullName] = swiftTypeName - // Superclass. let extends: String if !javaClass.isInterface(), diff --git a/Sources/Java2SwiftLib/TranslationManifest.swift b/Sources/Java2SwiftLib/TranslationManifest.swift deleted file mode 100644 index 564af422..00000000 --- a/Sources/Java2SwiftLib/TranslationManifest.swift +++ /dev/null @@ -1,24 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of Swift.org project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -/// Manifest describing the a Swift module containing translations of -/// Java classes into Swift types. -package struct TranslationManifest: Codable { - /// The Swift module name. - var swiftModule: String - - /// The mapping from canonical Java class names (e.g., `java.lang.Object`) to - /// the Swift type name (e.g., `JavaObject`) within `swiftModule`. - var translatedClasses: [String: String] = [:] -} diff --git a/Sources/JavaKit/generated/JavaKit.swift2java b/Sources/JavaKit/Java2Swift.config similarity index 82% rename from Sources/JavaKit/generated/JavaKit.swift2java rename to Sources/JavaKit/Java2Swift.config index 6c90c6a7..b8c36594 100644 --- a/Sources/JavaKit/generated/JavaKit.swift2java +++ b/Sources/JavaKit/Java2Swift.config @@ -1,6 +1,5 @@ { - "swiftModule" : "JavaKit", - "translatedClasses" : { + "classes" : { "java.lang.Error" : "JavaError", "java.lang.Exception" : "Exception", "java.lang.Object" : "JavaObject", diff --git a/Sources/JavaKitJar/generated/JavaKitJar.swift2java b/Sources/JavaKitJar/Java2Swift.config similarity index 83% rename from Sources/JavaKitJar/generated/JavaKitJar.swift2java rename to Sources/JavaKitJar/Java2Swift.config index 8e2f5485..011b169f 100644 --- a/Sources/JavaKitJar/generated/JavaKitJar.swift2java +++ b/Sources/JavaKitJar/Java2Swift.config @@ -1,6 +1,5 @@ { - "swiftModule" : "JavaKitJar", - "translatedClasses" : { + "classes" : { "java.util.jar.Attributes" : "Attributes", "java.util.jar.JarEntry" : "JarEntry", "java.util.jar.JarFile" : "JarFile", diff --git a/Sources/JavaKitNetwork/generated/JavaKitNetwork.swift2java b/Sources/JavaKitNetwork/generated/JavaKitNetwork.swift2java deleted file mode 100644 index 6da0ac47..00000000 --- a/Sources/JavaKitNetwork/generated/JavaKitNetwork.swift2java +++ /dev/null @@ -1,8 +0,0 @@ -{ - "swiftModule" : "JavaKitNetwork", - "translatedClasses" : { - "java.net.URI" : "URI", - "java.net.URL" : "URL", - "java.net.URLClassLoader" : "URLClassLoader" - } -} diff --git a/Sources/JavaKitReflection/generated/JavaKitReflection.swift2java b/Sources/JavaKitReflection/generated/JavaKitReflection.swift2java deleted file mode 100644 index 72e42f6f..00000000 --- a/Sources/JavaKitReflection/generated/JavaKitReflection.swift2java +++ /dev/null @@ -1,19 +0,0 @@ -{ - "swiftModule" : "JavaKitReflection", - "translatedClasses" : { - "java.lang.annotation.Annotation" : "Annotation", - "java.lang.reflect.AccessibleObject" : "AccessibleObject", - "java.lang.reflect.AnnotatedType" : "AnnotatedType", - "java.lang.reflect.Constructor" : "Constructor", - "java.lang.reflect.Executable" : "Executable", - "java.lang.reflect.Field" : "Field", - "java.lang.reflect.GenericArrayType" : "GenericArrayType", - "java.lang.reflect.GenericDeclaration" : "GenericDeclaration", - "java.lang.reflect.Method" : "Method", - "java.lang.reflect.Parameter" : "Parameter", - "java.lang.reflect.ParameterizedType" : "ParameterizedType", - "java.lang.reflect.Type" : "Type", - "java.lang.reflect.TypeVariable" : "TypeVariable", - "java.lang.reflect.WildcardType" : "WildcardType" - } -} diff --git a/USER_GUIDE.md b/USER_GUIDE.md index fba674c2..92de4a23 100644 --- a/USER_GUIDE.md +++ b/USER_GUIDE.md @@ -1,115 +1,99 @@ # JavaKit -The support library and macros allowing Swift code to easily call into Java libraries. +Library and tools to make it easy to use Java libraries from Swift using the Java Native Interface (JNI). ## Getting started -Before using this package, set the `JAVA_HOME` environment variable to point at your Java installation. Failing to do so will produce errors when processing the package manifest. +Before using this package, set the `JAVA_HOME` environment variable to point at your Java installation. Failing to do so will produce errors when processing the package manifest. Alternatively, you can put the path to your Java installation in the file `~/.java_home`. -### Create a Java class to wrap the Swift library -All JavaKit-based applications start execution within the Java Virtual Machine. First, define your own Java class that loads your native Swift library and provides a `native` entry point to get into the Swift code. Here is a minimal Java class that has all of the program's logic written in Swift, including `main`: - -```java -package org.swift.javakit; +### Using Java libraries from Swift -public class HelloSwiftMain { - static { - System.loadLibrary("HelloSwift"); - } - - public native static void main(String[] args); +Existing Java libraries can be wrapped for use in Swift with the `Java2Swift` +tool. In a Swift program, the most direct way to access a Java API is to use the SwiftPM plugin to provide Swift wrappers for the Java classes. To do so, add a configuration file `Java2Swift.config` into the source directory for the Swift target. This is a JSON file that specifies Java classes and the Swift type name that should be generated to wrap them. For example, the following file maps `java.math.BigInteger` to a Swift type named `BigInteger`: + +``` +{ + "classes" : { + "java.math.BigInteger" : "BigInteger" + } } ``` -Compile this into a `.class` file with `javac` before we build the Swift half, e.g.,: +Once that is done, make sure your package depends on swift-java, either by running this command: ``` -javac Java/src/org/swift/javakit/JavaClassTranslator.java +swift package add-dependency https://github.com/swiftlang/swift-java --branch main ``` -### Create a Swift library - -The Java class created above loads a native library `HelloSwift` that needs to contain a definition of the `main` method in the class `org.swift.javakit.HelloSwiftMain`. `HelloSwift` should be defined as a SwiftPM dynamic library product, e.g., +or, equivalently, adding the following to the package dependencies: ```swift - products: [ - .library( - name: "HelloSwift", - type: .dynamic, - targets: ["HelloSwift"] - ), - ] +.package(url: "https://github.com/swiftlang/swift-java", branch: "main"), ``` -with an associated target that depends on `JavaKit`: +Finally, update `Package.swift` so that the `Java2SwiftPlugin` plugin runs on the target in which you want to generate Swift wrappers. The plugin looks like this: ```swift - .target( - name: "HelloSwift", - dependencies: [ - .product(name: "ArgumentParser", package: "swift-argument-parser"), - .product(name: "JavaKit", package: "JavaKit") - ]) + plugins: [ + .plugin(name: "Java2SwiftPlugin", package: "swift-java"), + ] ``` -### Implement the `native` Java method in Swift -Now, in the `HelloSwift` Swift library, define a `struct` that provides the `main` method for the Java class we already defined: +We will follow along with the `JavaProbablyPrime` sample project available in `swift-java/Samples/JavaProbablyPrime`. + +If you build the project, there will be a generated file `BigInteger.swift` that looks a bit like this: ```swift -import JavaKit +@JavaClass("java.math.BigInteger") +public struct BigInteger { + @JavaMethod + public init(_ arg0: String, environment: JNIEnvironment) + + @JavaMethod + public func toString() -> String + + @JavaMethod + public func isProbablePrime(_ arg0: Int32) -> Bool -@JavaClass("org.swift.javakit.HelloSwiftMain") -struct HelloSwiftMain { - @ImplementsJava - static func main(arguments: [String], environment: JNIEnvironment) { - print("Command line arguments are: \(arguments)") - } + // many more methods } ``` -Go ahead and build this library with `swift build`, and find the path to the directory containing the resulting shared library (e.g., `HelloSwift.dylib`, `HelloSwift.so`, or `HelloSwift.dll`, depending on platform). It is often in `.build/debug/` if you ran `swift build` on the command line. +This Swift type wraps `java.math.BigInteger`, exposing its constructors, methods, and fields for use directly to Swift. Let's try using it! -### Putting it all together! +### Creating a Java Virtual Machine instance from Swift -Finally, run this program on the command line like this: +The `JavaVirtualMachine` class, which is part of the `JavaKitVM` module, provides the ability to create and query the Java Virtual Machine. One can create a shared instance of `JavaVirtualMachine` by calling `JavaVirtualMachine.shared()`, optionally passing along extra options to the JVM (such as the class path): -``` -java -cp Java/src -Djava.library.path=$(PATH_CONTAINING_HELLO_SWIFT)/ org.swift.javakit.HelloSwiftMain -v argument +```swift +let javaVirtualMachine = try JavaVirtualMachine.shared() ``` -This will prints the command-line arguments `-v` and `argument` as seen by Swift. +If the JVM is already running, a `JavaVirtualMachine` instance will be created to reference that existing JVM. Given a `JavaVirtualMachine` instance, one can query the JNI environment for the currently-active thread by calling `environment()`, e.g., -### Bonus: Swift argument parser +```swift +let jniEnvironment = try javaVirtualMachine.environment() +``` -The easiest way to build a command-line program in Swift is with the [Swift argument parser library](https://github.com/apple/swift-argument-parser). We can extend our `HelloSwiftMain` type to conform to `ParsableCommand` and using the Swift argument parser to process the arguments provided by Java: +This JNI environment can be used to create instances of Java objects. For example, we can create a `BigInteger` instance from a Swift string like this: ```swift -import ArgumentParser -import JavaKit +let bigInt = BigInteger(veryBigNumber, environment: jniEnvironment) +``` -@JavaClass("org.swift.javakit.HelloSwiftMain") -struct HelloSwiftMain: ParsableCommand { - @Option(name: .shortAndLong, help: "Enable verbose output") - var verbose: Bool = false +And then call methods on it. For example, check whether the big integer is a probable prime with some certainty: - @ImplementsJava - static func main(arguments: [String], environment: JNIEnvironment) { - let command = Self.parseOrExit(arguments) - command.run(environment: environment) - } - - func run(environment: JNIEnvironment) { - print("Verbose = \(verbose)") - } +```swift +if bigInt.isProbablePrime(10) { + print("\(bigInt.toString()) is probably prime") } ``` -## JavaKit: Expose select Swift types to Java +Swift ensures that the Java garbage collector will keep the object alive until `bigInt` (and any copies of it) are been destroyed. -Each Java class that can be used from Swift is translated to a Swift `struct` that -provides information about the Java class itself and is populated with the Swift -projection of each of its constructors, methods, and fields. For example, -here is an excerpt of the Swift projection of [`java.util.jar.JarFile`](https://docs.oracle.com/javase/8/docs/api/java/util/jar/JarFile.html): +### Translation from Java classes into Swift + +Each Java class that can be used from Swift is translated to a Swift `struct` that provides information about the Java class itself and is populated with the Swift projection of each of its constructors, methods, and fields. For example, here is an excerpt of the Swift projection of [`java.util.jar.JarFile`](https://docs.oracle.com/javase/8/docs/api/java/util/jar/JarFile.html): ```swift @JavaClass("java.util.jar.JarFile", extends: ZipFile.self, implements: AutoCloseable.self) @@ -145,9 +129,7 @@ package java.util.jar public class JarFile extends java.util.zip.ZipFile implements java.lang.AutoClosable { ... } ``` -Each of the public Java constructors, methods, and fields in the Java class -will have a corresponding Swift declaration. Java constructors are written as -Swift initializers, e.g., +Each of the public Java constructors, methods, and fields in the Java class will have a corresponding Swift declaration. Java constructors are written as Swift initializers, e.g., ```swift @JavaMethod @@ -160,18 +142,14 @@ corresponds to the Java constructor: public JarFile(String arg0, bool arg1) ``` -The `environment` parameter is the pointer to the JNI environment (`JNIEnv*` in C) in which the underlying Java object lives. It is available to all methods -that are written in or exposed to Java, either directly as a parameter (as in -constructors) or on an instance of any type that's projected from Java through -the `javaEnvironment` property of the `AnyJavaObject` conformance. Given a +The `environment` parameter is the pointer to the JNI environment (`JNIEnv*` in C) in which the underlying Java object lives. It is available to all methods that are written in or exposed to Java, either directly as a parameter (as in constructors) or on an instance of any type that's projected from Java through the `javaEnvironment` property of the `AnyJavaObject` conformance. Given a Java environment, one can create a `JarFile` instance in Swift with, e.g., ```swift let jarFile = JarFile("MyJavaLibrary.jar", true) ``` -At this point, `jarFile` is a Swift instance backed by a Java object. One can directly call any of the Java methods that were reflected into Swift, each -of which is annotated with `@JavaMethod`. For example, we can iterate over all +At this point, `jarFile` is a Swift instance backed by a Java object. One can directly call any of the Java methods that were reflected into Swift, each of which is annotated with `@JavaMethod`. For example, we can iterate over all of the entries in the Jar file like this: ```swift @@ -182,10 +160,7 @@ for entry in jarFile.entries()! { `JavaMethod` is a [function body macro](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0415-function-body-macros.md) that translates the argument and result types to/from Java and performs a call to the named method via JNI. -A Java method or constructor that throws a checked exception should be marked -as `throws` in Swift. Swift's projection of Java throwable types -(as `JavaKit.Throwable`) conforms to the Swift `Error` protocol, so Java -exceptions will be rethrown as Swift errors. +A Java method or constructor that throws a checked exception should be marked as `throws` in Swift. Swift's projection of Java throwable types (as `JavaKit.Throwable`) conforms to the Swift `Error` protocol, so Java exceptions will be rethrown as Swift errors. ### Java <-> Swift Type mapping @@ -193,50 +168,39 @@ Each Java type has a mapping to a corresponding Swift type. This is expressed in Swift as a conformance to the `JavaValue` protocol. Here are the mappings between Java types and their Swift counterparts that conform to `JavaValue`: -| Java type | Swift type | -| ----------- | ------------- | -| `boolean` | `Bool` | -| `byte` | `Int8` | -| `char` | `UInt16` | -| `short` | `Int16` | -| `int` | `Int32` | -| `long` | `Int64` | -| `float` | `Float` | -| `double` | `Double` | -| `void` | `Void` (rare) | -| `T[]` | `[T]` | -| `String` | `String` | - -For Swift projections of Java classes, the Swift type itself conforms to the -`AnyJavaObject` protocol. This conformance is added automatically by the -`JavaClass` macro. Swift projects of Java classes can be generic. In such cases, each generic -parameter should itself conform to the `AnyJavaObject` protocol. - -Because Java has implicitly nullability of references, `AnyJavaObject` types do not - directly conform to `JavaValue`: rather, optionals of `AnyJavaObject`-conforming -type conform to `JavaValue`. This requires Swift code to deal with the optionality +| Java type | Swift type | +| --------- | ------------- | +| `boolean` | `Bool` | +| `byte` | `Int8` | +| `char` | `UInt16` | +| `short` | `Int16` | +| `int` | `Int32` | +| `long` | `Int64` | +| `float` | `Float` | +| `double` | `Double` | +| `void` | `Void` (rare) | +| `T[]` | `[T]` | +| `String` | `String` | + +For Swift projections of Java classes, the Swift type itself conforms to the `AnyJavaObject` protocol. This conformance is added automatically by the `JavaClass` macro. Swift projects of Java classes can be generic. In such cases, each generic parameter should itself conform to the `AnyJavaObject` protocol. + +Because Java has implicitly nullability of references, `AnyJavaObject` types do not directly conform to `JavaValue`: rather, optionals of `AnyJavaObject`-conforming type conform to `JavaValue`. This requires Swift code to deal with the optionality at interface boundaries rather than invite implicit NULL pointer dereferences. -A number of JavaKit modules provide Swift projections of Java classes and -interfaces. Here are a few: +A number of JavaKit modules provide Swift projections of Java classes and interfaces. Here are a few: -| Java class | Swift class | Swift module | -| -------------------------- | ---------------- | ---------------- | -| `java.lang.Object` | `JavaObject` | `JavaKit` | -| `java.lang.Class` | `JavaClass` | `JavaKit` | -| `java.lang.Throwable` | `Throwable` | `JavaKit` | -| `java.net.URL` | `URL` | `JavaKitNetwork` | +| Java class | Swift class | Swift module | +| --------------------- | -------------- | ---------------- | +| `java.lang.Object` | `JavaObject` | `JavaKit` | +| `java.lang.Class` | `JavaClass` | `JavaKit` | +| `java.lang.Throwable` | `Throwable` | `JavaKit` | +| `java.net.URL` | `URL` | `JavaKitNetwork` | -The `Java2Swift` tool can translate any other Java classes into -Swift projections. Instructions on using this tool are provided later in this -document. +The `Java2Swift` tool can translate any other Java classes into Swift projections. The easiest way to use `Java2Swift` is with the SwiftPM plugin described above. More information about using this tool directly are provided later in this document. ### Up and downcasting -All `AnyJavaObject` instances provide `is` and `as` methods to check whether -an object dynamically matches another type. The `is` operation is the -equivalent of Java's `instanceof` and Swift's `is` operator, and will checkin -whether a given object is of the specified type, e.g., +All `AnyJavaObject` instances provide `is` and `as` methods to check whether an object dynamically matches another type. The `is` operation is the equivalent of Java's `instanceof` and Swift's `is` operator, and will checkin whether a given object is of the specified type, e.g., ```swift if myObject.is(URL.self) { @@ -244,8 +208,7 @@ if myObject.is(URL.self) { } ``` -Often, one also wants to cast to that type. The `as` method returns an optional -of the specified type, so it works well with `if let`: +Often, one also wants to cast to that type. The `as` method returns an optional of the specified type, so it works well with `if let`: ```swift if let url = myObject.as(URL.self) { @@ -257,17 +220,8 @@ if let url = myObject.as(URL.self) { ### Class objects and static methods -Every `AnyJavaObject` has a property `javaClass` that provides an instance of -`JavaClass` specialized to the type. For example, `url.javaClass` will -produce an instance of `JavaClass`. The `JavaClass` instance is a wrapper -around a Java class object (`java.lang.Class`) that has two roles in Swift. First, -it provides access to all of the APIs on the Java class object. The `JavaKitReflection` -library, for example, exposes these APIs and the types they depend on (`Method`, - `Constructor`, etc.) for dynamic reflection. Second, the `JavaClass` provides -access to the `static` methods on the Java class. For example, -[`java.net.URLConnection`](https://docs.oracle.com/javase/8/docs/api/java/net/URLConnection.html) has static methods -to access default settings, such as the default for the `allowUserInteraction` -field. These are exposed as instance methods on `JavaClass`, e.g., +Every `AnyJavaObject` has a property `javaClass` that provides an instance of `JavaClass` specialized to the type. For example, `url.javaClass` will produce an instance of `JavaClass`. The `JavaClass` instance is a wrapper around a Java class object (`java.lang.Class`) that has two roles in Swift. First, it provides access to all of the APIs on the Java class object. The `JavaKitReflection` library, for example, exposes these APIs and the types they depend on (`Method`, + `Constructor`, etc.) for dynamic reflection. Second, the `JavaClass` provides access to the `static` methods on the Java class. For example, [`java.net.URLConnection`](https://docs.oracle.com/javase/8/docs/api/java/net/URLConnection.html) has static methods to access default settings, such as the default for the `allowUserInteraction` field. These are exposed as instance methods on `JavaClass`, e.g., ```swift extension JavaClass { @@ -278,11 +232,7 @@ extension JavaClass { ### Interfaces -Java interfaces are similar to classes, and are projected into Swift in -much the same way, but with the macro `JavaInterface`. The `JavaInterface` -macro takes the Java interface name as well as any Java interfaces that this -interface extends. As an example, here is the Swift projection of the -[`java.util.Enumeration`](https://docs.oracle.com/javase/8/docs/api/java/util/Enumeration.html) generic interface: +Java interfaces are similar to classes, and are projected into Swift in much the same way, but with the macro `JavaInterface`. The `JavaInterface` macro takes the Java interface name as well as any Java interfaces that this interface extends. As an example, here is the Swift projection of the [`java.util.Enumeration`](https://docs.oracle.com/javase/8/docs/api/java/util/Enumeration.html) generic interface: ```swift @JavaInterface("java.util.Enumeration") @@ -297,8 +247,7 @@ public struct Enumeration { ## Implementing Java `native` methods in Swift -JavaKit supports implementing Java `native` methods in Swift using JNI. In Java, -the method must be declared as `native`, e.g., +JavaKit supports implementing Java `native` methods in Swift using JNI. In Java, the method must be declared as `native`, e.g., ```java package org.swift.javakit; @@ -319,8 +268,7 @@ On the Swift side, the Java class needs to have been exposed to Swift: struct HelloSwift { ... } ``` -Implementations of `native` methods can be written within the Swift type or an -extension thereof, and should be marked with `@ImplementsJava`. For example: +Implementations of `native` methods can be written within the Swift type or an extension thereof, and should be marked with `@ImplementsJava`. For example: ```swift @JavaClass("org.swift.javakit.HelloSwift") @@ -333,23 +281,14 @@ extension HelloSwift { } ``` -Java native methods that throw any checked exception should be marked as -`throws` in Swift. Swift will translate any thrown error into a Java exception. - -The Swift implementations of Java `native` constructors and static methods -require an additional Swift parameter `environment: JNIEnvironment`, which will -receive the JNI environment in which the function is being executed. +Java native methods that throw any checked exception should be marked as `throws` in Swift. Swift will translate any thrown error into a Java exception. -> *Note*: The new [Java Foreign Function & Memory API](https://bugs.openjdk.org/browse/JDK-8312523) (aka Project Panama) provides a radically different and more efficient way to work with native libraries than the JNI approach implemented here. It should be possible to build a [`jextract`-like](https://github.com/openjdk/jextract) tool to produce Java wrappers for Swift APIs. +The Swift implementations of Java `native` constructors and static methods require an additional Swift parameter `environment: JNIEnvironment`, which will receive the JNI environment in which the function is being executed. ## Translating Java classes with `Java2Swift` -The `Java2Swift` is a Swift program that uses Java's runtime reflection -facilities to translate the requested Java classes into their Swift projections. -The output is a number of Swift source files, each of which corresponds to a -single Java class, along with a manifest file that provides the mapping from -canonical Java class names to the Swift projections. The `Java2Swift` -can be executed like this: +The `Java2Swift` is a Swift program that uses Java's runtime reflection facilities to translate the requested Java classes into their Swift projections. The output is a number of Swift source files, each of which corresponds to a +single Java class. The `Java2Swift` can be executed like this: ``` swift run Java2Swift @@ -358,59 +297,53 @@ swift run Java2Swift to produce help output like the following: ``` -USAGE: Java2Swift --module-name ... [--manifests ...] [--cp ...] [--output-directory ] +USAGE: Java2Swift --module-name [--depends-on ...] [--jar-file] [--cp ...] [--output-directory ] ARGUMENTS: - The Java classes to translate into Swift written with - their canonical names (e.g., java.lang.Object). If - the Swift name of the type should be different from - simple name of the type, it can appended to the class - name with '=' + The input file, which is either a Java2Swift + configuration file or (if '-jar-file' was specified) + a Jar file. OPTIONS: --module-name The name of the Swift module into which the resulting - Swift types will be generated - --manifests The Java-to-Swift module manifest files for any Swift - module containing Swift types created to wrap Java - classes. + Swift types will be generated. + --depends-on + A Java2Swift configuration file for a given Swift + module name on which this module depends, e.g., + JavaKitJar=Sources/JavaKitJar/Java2Swift.config. + There should be one of these options for each Swift + module that this module depends on (transitively) + that contains wrapped Java sources. + --jar-file Specifies that the input is a Jar file whose public + classes will be loaded. The output of Java2Swift will + be a configuration file (Java2Swift.config) that can + be used as input to a subsequent Java2Swift + invocation to generate wrappers for those public + classes. --cp, --classpath Class search path of directories and zip/jar files from which Java classes can be loaded. -o, --output-directory The directory in which to output the generated Swift - files and manifest. (default: .) + files or the Java2Swift configuration file. (default: + .) -h, --help Show help information. - ``` For example, the `JavaKitJar` library is generated with this command line: ```swift -swift run Java2Swift --module-name JavaKitJar --manifests Sources/JavaKit/generated/JavaKit.swift2java -o Sources/JavaKitJar/generated java.util.jar.Attributes java.util.jar.JarEntry java.util.jar.JarFile java.util.jar.JarInputStream java.util.jar.JarOutputStream java.util.jar.Manifest -``` - -The `--module-name JavaKitJar` parameter describes the name of the Swift module -in which the code will be generated. The `--manifests` option is followed by the -manifest files produced by this tool (`.swift2java`) for any Swift library on which -this new Swift library will depend. This should always contain at least the `JavaKit.swift2java`, but could also contain any other Swift modules -containing Swift projections of Java classes that this module will use. For -example, if your Java class uses `java.net.URL`, then you should include -`JavaKitNetwork.swift2java` as well. - -The `-o` option specifies the output directory. Typically, this will be -`Sources//generated` or similar to keep the generated Swift -files separate from any hand-written ones. To see the output on the terminal -rather than writing files to disk, pass `-` for this option. In addition to -writing the `.swift` source files, the tool will write a manifest file -named `.swift2java` that can be used as an input manifest for -translating to Swift modules that build on this one. - -Finally, the command line should contain the list of classes that should be -translated into Swift. The tool will output a single `.swift` file for -each class, along with warnings for any public API that cannot be -translated into Swift. The most common warnings are due to missing Swift -projections for Java classes. For example, here we have not translated -(or provided the translation manifests for) the Java classes +swift run Java2Swift --module-name JavaKitJar --depends-on JavaKit=Sources/JavaKit/Java2Swift.config -o Sources/JavaKitJar/generated Sources/JavaKitJar/Java2Swift.config +``` + +The `--module-name JavaKitJar` parameter describes the name of the Swift module in which the code will be generated. + +The `--depends-on` option is followed by the Java2Swift configuration files for any library on which this Swift library depends. Each `--depends-on` option is of the form `=`, and tells Java2Swift which other Java classes have already been translated to Swift. For example, if your Java class uses `java.net.URL`, then you should include +`JavaKitNetwork`'s configuration file as a dependency here. + +The `-o` option specifies the output directory. Typically, this will be `Sources//generated` or similar to keep the generated Swift files separate from any hand-written ones. To see the output on the terminal rather than writing files to disk, pass `-` for this option. + +Finally, the command line should contain the `Java2Swift.config` file containing the list of classes that should be translated into Swift and their corresponding Swift type names. The tool will output a single `.swift` file for each class, along with warnings for any public API that cannot be translated into Swift. The most common warnings are due to missing Swift projections for Java classes. For example, here we have not translated (or provided the translation manifests for) the Java classes `java.util.zip.ZipOutputStream` and `java.io.OutputStream`: ``` @@ -419,11 +352,111 @@ warning: Unable to translate 'java.util.jar.JarOutputStream' constructor: Java c warning: Unable to translate 'java.util.jar.JarInputStream' method 'transferTo': Java class 'java.io.OutputStream' has not been translated into Swift ``` -The result of such warnings is that certain information won't be statically -available in Swift, e.g., the superclass won't be known (so we will assume it -is `JavaObject`), or the specified constructors or methods won't be -translated. If you don't need these APIs, the warnings can be safely ignored. -The APIs can still be called dynamically via JNI. +The result of such warnings is that certain information won't be statically available in Swift, e.g., the superclass won't be known (so we will assume it is `JavaObject`), or the specified constructors or methods won't be translated. If you don't need these APIs, the warnings can be safely ignored. The APIs can still be called dynamically via JNI. + +The `--jar-file` option changes the operation of `Java2Swift`. Instead of wrapping Java classes in Swift, it scans the given input Jar file to find all public classes and outputs a configuration file `Java2Swift.config` mapping all of the Java classes in the Jar file to Swift types. The `--jar-file` mode is expected to be used to help import a Java library into Swift wholesale, after which Java2Swift should invoked again given the generated configuration file. + +### Under construction: Create a Java class to wrap the Swift library + +**NOTE**: the instructions here work, but we are still smoothing out the interoperability story. + +All JavaKit-based applications start execution within the Java Virtual Machine. First, define your own Java class that loads your native Swift library and provides a `native` entry point to get into the Swift code. Here is a minimal Java class that has all of the program's logic written in Swift, including `main`: + + +```java +package org.swift.javakit; + +public class HelloSwiftMain { + static { + System.loadLibrary("HelloSwift"); + } + + public native static void main(String[] args); +} +``` + +Compile this into a `.class` file with `javac` before we build the Swift half, e.g.,: + +``` +javac Java/src/org/swift/javakit/JavaClassTranslator.java +``` + +### Create a Swift library + +The Java class created above loads a native library `HelloSwift` that needs to contain a definition of the `main` method in the class `org.swift.javakit.HelloSwiftMain`. `HelloSwift` should be defined as a SwiftPM dynamic library product, e.g., + +```swift + products: [ + .library( + name: "HelloSwift", + type: .dynamic, + targets: ["HelloSwift"] + ), + ] +``` + +with an associated target that depends on `JavaKit`: + +```swift + .target( + name: "HelloSwift", + dependencies: [ + .product(name: "ArgumentParser", package: "swift-argument-parser"), + .product(name: "JavaKit", package: "JavaKit") + ]) +``` + +### Implement the `native` Java method in Swift +Now, in the `HelloSwift` Swift library, define a `struct` that provides the `main` method for the Java class we already defined: + +```swift +import JavaKit + +@JavaClass("org.swift.javakit.HelloSwiftMain") +struct HelloSwiftMain { + @ImplementsJava + static func main(arguments: [String], environment: JNIEnvironment) { + print("Command line arguments are: \(arguments)") + } +} +``` + +Go ahead and build this library with `swift build`, and find the path to the directory containing the resulting shared library (e.g., `HelloSwift.dylib`, `HelloSwift.so`, or `HelloSwift.dll`, depending on platform). It is often in `.build/debug/` if you ran `swift build` on the command line. + +### Putting it all together! + +Finally, run this program on the command line like this: + +``` +java -cp Java/src -Djava.library.path=$(PATH_CONTAINING_HELLO_SWIFT)/ org.swift.javakit.HelloSwiftMain -v argument +``` + +This will prints the command-line arguments `-v` and `argument` as seen by Swift. + +### Bonus: Swift argument parser + +The easiest way to build a command-line program in Swift is with the [Swift argument parser library](https://github.com/apple/swift-argument-parser). We can extend our `HelloSwiftMain` type to conform to `ParsableCommand` and using the Swift argument parser to process the arguments provided by Java: + +```swift +import ArgumentParser +import JavaKit + +@JavaClass("org.swift.javakit.HelloSwiftMain") +struct HelloSwiftMain: ParsableCommand { + @Option(name: .shortAndLong, help: "Enable verbose output") + var verbose: Bool = false + + @ImplementsJava + static func main(arguments: [String], environment: JNIEnvironment) { + let command = Self.parseOrExit(arguments) + command.run(environment: environment) + } + + func run(environment: JNIEnvironment) { + print("Verbose = \(verbose)") + } +} +``` # `jextract-swift` From f01800e359013e031a29d8386a0d1f9280423dea Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Tue, 15 Oct 2024 21:34:18 -0700 Subject: [PATCH 093/426] Remove remaining vestigates of the ".swift2java" manifest files We no longer need them --- Package.swift | 4 ---- Plugins/Java2SwiftPlugin/Java2SwiftPlugin.swift | 4 +--- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/Package.swift b/Package.swift index 0d6aa048..7f65648a 100644 --- a/Package.swift +++ b/Package.swift @@ -160,7 +160,6 @@ let package = Package( .target( name: "JavaKit", dependencies: ["JavaRuntime", "JavaKitMacros", "JavaTypes"], - exclude: ["generated/JavaKit.swift2java"], swiftSettings: [ .swiftLanguageMode(.v5), .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) @@ -169,7 +168,6 @@ let package = Package( .target( name: "JavaKitJar", dependencies: ["JavaKit"], - exclude: ["generated/JavaKitJar.swift2java"], swiftSettings: [ .swiftLanguageMode(.v5), .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) @@ -178,7 +176,6 @@ let package = Package( .target( name: "JavaKitNetwork", dependencies: ["JavaKit"], - exclude: ["generated/JavaKitNetwork.swift2java"], swiftSettings: [ .swiftLanguageMode(.v5), .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) @@ -187,7 +184,6 @@ let package = Package( .target( name: "JavaKitReflection", dependencies: ["JavaKit"], - exclude: ["generated/JavaKitReflection.swift2java"], swiftSettings: [ .swiftLanguageMode(.v5), .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) diff --git a/Plugins/Java2SwiftPlugin/Java2SwiftPlugin.swift b/Plugins/Java2SwiftPlugin/Java2SwiftPlugin.swift index 10b32729..30be39a9 100644 --- a/Plugins/Java2SwiftPlugin/Java2SwiftPlugin.swift +++ b/Plugins/Java2SwiftPlugin/Java2SwiftPlugin.swift @@ -91,9 +91,7 @@ struct Java2SwiftBuildToolPlugin: BuildToolPlugin { /// tool. let outputSwiftFiles = config.classes.map { (javaClassName, swiftName) in outputDirectory.appending(path: "\(swiftName).swift") - } + [ - outputDirectory.appending(path: "\(sourceModule.name).swift2java") - ] + } return [ .buildCommand( From e4535058b9aef32d99d5acc65e866bf269f2587c Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Thu, 17 Oct 2024 09:19:37 -0700 Subject: [PATCH 094/426] Java2Swift: Handle class paths provided in config files Read the `classPath` field from each config file and feed the concatenated class path into the Java virtual machine instance we create. As part of this, clean up the code path that emits a configuration file with all of the classes within a Jar file. --- Sources/Java2Swift/JavaToSwift.swift | 160 +++++++++++++----- .../JavaTranslator+Configuration.swift | 8 +- 2 files changed, 115 insertions(+), 53 deletions(-) diff --git a/Sources/Java2Swift/JavaToSwift.swift b/Sources/Java2Swift/JavaToSwift.swift index 4d7d582c..4008e84c 100644 --- a/Sources/Java2Swift/JavaToSwift.swift +++ b/Sources/Java2Swift/JavaToSwift.swift @@ -58,55 +58,118 @@ struct JavaToSwift: ParsableCommand { ) var input: String + /// Describes what kind of generation action is being performed by + /// Java2Swift. + enum GenerationMode { + /// Generate a configuration file given a Jar file. + case configuration(jarFile: String) + + /// Generate Swift wrappers for Java classes based on the given + /// configuration. + case classWrappers(Configuration) + } + mutating func run() throws { - var vmOptions: [String] = [] - let classpath = classPathWithJarFile - if !classpath.isEmpty { - vmOptions.append("-cp") - vmOptions.append(contentsOf: classpath) + // Determine the mode in which we'll execute. + let generationMode: GenerationMode + if jarFile { + generationMode = .configuration(jarFile: input) + } else { + let config = try JavaTranslator.readConfiguration(from: URL(filePath: input)) + generationMode = .classWrappers(config) + } + + // Load all of the dependent configurations and associate them with Swift + // modules. + let dependentConfigs = try dependsOn.map { dependentConfig in + guard let equalLoc = dependentConfig.firstIndex(of: "=") else { + throw JavaToSwiftError.badConfigOption(dependentConfig) + } + + let afterEqual = dependentConfig.index(after: equalLoc) + let swiftModuleName = String(dependentConfig[..(in: environment) + .getSystemClassLoader()! + #endif var javaClasses: [JavaClass] = [] for (javaClassName, swiftName) in config.classes { guard let javaClass = try classLoader.loadClass(javaClassName) else { @@ -146,15 +209,6 @@ struct JavaToSwift: ParsableCommand { } } - /// Return the class path augmented with the Jar file, if there is one. - var classPathWithJarFile: [String] { - if jarFile { - return [input] + classpath - } - - return classpath - } - func writeContents(_ contents: String, to filename: String, description: String) throws { if outputDirectory == "-" { print("// \(filename) - \(description)") @@ -171,10 +225,13 @@ struct JavaToSwift: ParsableCommand { print(" done.") } - func emitConfiguration(forJarFile jarFileName: String, environment: JNIEnvironment) throws { - var configuration = Configuration( - classPath: classPathWithJarFile.joined(separator: ":") - ) + func emitConfiguration( + forJarFile jarFileName: String, + classPath: String, + environment: JNIEnvironment + ) throws { + var configuration = Configuration(classPath: classPath) + let jarFile = try JarFile(jarFileName, false, environment: environment) for entry in jarFile.entries()! { // We only look at class files in the Jar file. @@ -205,9 +262,7 @@ struct JavaToSwift: ParsableCommand { // Write the file. try writeContents( contents, - to: URL(filePath: outputDirectory) - .appending(path: "Java2Swift.config") - .path(percentEncoded: false), + to: "Java2Swift.config", description: "Java2Swift configuration file" ) } @@ -238,3 +293,14 @@ extension String { return self } } + +@JavaClass("java.lang.ClassLoader") +public struct ClassLoader { + @JavaMethod + public func loadClass(_ arg0: String) throws -> JavaClass? +} + +extension JavaClass { + @JavaStaticMethod + public func getSystemClassLoader() -> ClassLoader? +} diff --git a/Sources/Java2SwiftLib/JavaTranslator+Configuration.swift b/Sources/Java2SwiftLib/JavaTranslator+Configuration.swift index 6025731b..f13a8cce 100644 --- a/Sources/Java2SwiftLib/JavaTranslator+Configuration.swift +++ b/Sources/Java2SwiftLib/JavaTranslator+Configuration.swift @@ -16,18 +16,14 @@ import Foundation extension JavaTranslator { /// Read a configuration file from the given URL. - package func readConfiguration(from url: URL) throws -> Configuration { + package static func readConfiguration(from url: URL) throws -> Configuration { let contents = try Data(contentsOf: url) return try JSONDecoder().decode(Configuration.self, from: contents) } /// Load the configuration file with the given name to populate the known set of /// translated Java classes. - package func loadDependentConfiguration(forSwiftModule swiftModule: String, from url: URL) throws { - let config = try readConfiguration(from: url) - - // TODO: Should we merge the class path from our dependencies? - + package func addConfiguration(_ config: Configuration, forSwiftModule swiftModule: String) { for (javaClassName, swiftName) in config.classes { translatedClasses[javaClassName] = ( swiftType: swiftName, From cd20135da893c57dae2e8be3e1d76b752e6df4b1 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Thu, 17 Oct 2024 09:27:50 -0700 Subject: [PATCH 095/426] [JavaVirtualMachine] Change the default for ignoreUnrecognized parameter The `ignoreUnrecognized` parameter to `JavaVirtualMachine.shared()` tells the JVM not to complain about options it doesn't recognize, which tends to mask usage errors. Change the default from `true` to `false`. --- Sources/JavaKitVM/JavaVirtualMachine.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/JavaKitVM/JavaVirtualMachine.swift b/Sources/JavaKitVM/JavaVirtualMachine.swift index 2e95795c..d01580d7 100644 --- a/Sources/JavaKitVM/JavaVirtualMachine.swift +++ b/Sources/JavaKitVM/JavaVirtualMachine.swift @@ -45,7 +45,7 @@ public final class JavaVirtualMachine: @unchecked Sendable { private init( classPath: [String] = [], vmOptions: [String] = [], - ignoreUnrecognized: Bool = true + ignoreUnrecognized: Bool = false ) throws { var jvm: JavaVMPointer? = nil var environment: UnsafeMutableRawPointer? = nil @@ -176,7 +176,7 @@ extension JavaVirtualMachine { public static func shared( classPath: [String] = [], vmOptions: [String] = [], - ignoreUnrecognized: Bool = true + ignoreUnrecognized: Bool = false ) throws -> JavaVirtualMachine { try sharedJVM.withLock { (sharedJVMPointer: inout JavaVirtualMachine?) in // If we already have a JavaVirtualMachine instance, return it. From 364a3f35c9c4fb94b4ac7b3573511c5ebf27a883 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Thu, 17 Oct 2024 09:31:04 -0700 Subject: [PATCH 096/426] Add missing Java2Swift configuration files --- Sources/JavaKitNetwork/Java2Swift.config | 7 +++++++ Sources/JavaKitReflection/Java2Swift.config | 18 ++++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 Sources/JavaKitNetwork/Java2Swift.config create mode 100644 Sources/JavaKitReflection/Java2Swift.config diff --git a/Sources/JavaKitNetwork/Java2Swift.config b/Sources/JavaKitNetwork/Java2Swift.config new file mode 100644 index 00000000..f44e2440 --- /dev/null +++ b/Sources/JavaKitNetwork/Java2Swift.config @@ -0,0 +1,7 @@ +{ + "classes" : { + "java.net.URI" : "URI", + "java.net.URL" : "URL", + "java.net.URLClassLoader" : "URLClassLoader" + } +} diff --git a/Sources/JavaKitReflection/Java2Swift.config b/Sources/JavaKitReflection/Java2Swift.config new file mode 100644 index 00000000..98eb4cd8 --- /dev/null +++ b/Sources/JavaKitReflection/Java2Swift.config @@ -0,0 +1,18 @@ +{ + "classes" : { + "java.lang.annotation.Annotation" : "Annotation", + "java.lang.reflect.AccessibleObject" : "AccessibleObject", + "java.lang.reflect.AnnotatedType" : "AnnotatedType", + "java.lang.reflect.Constructor" : "Constructor", + "java.lang.reflect.Executable" : "Executable", + "java.lang.reflect.Field" : "Field", + "java.lang.reflect.GenericArrayType" : "GenericArrayType", + "java.lang.reflect.GenericDeclaration" : "GenericDeclaration", + "java.lang.reflect.Method" : "Method", + "java.lang.reflect.Parameter" : "Parameter", + "java.lang.reflect.ParameterizedType" : "ParameterizedType", + "java.lang.reflect.Type" : "Type", + "java.lang.reflect.TypeVariable" : "TypeVariable", + "java.lang.reflect.WildcardType" : "WildcardType" + } +} From 1ef3a87d77141d0458f50840d42287234e93d579 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Thu, 17 Oct 2024 09:35:46 -0700 Subject: [PATCH 097/426] Java2Swift: In Jar file mode, don't emit nested classes into Java2Swift.config We aren't ready to handle nested classes just yet. --- Sources/Java2Swift/JavaToSwift.swift | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Sources/Java2Swift/JavaToSwift.swift b/Sources/Java2Swift/JavaToSwift.swift index 4008e84c..5799e678 100644 --- a/Sources/Java2Swift/JavaToSwift.swift +++ b/Sources/Java2Swift/JavaToSwift.swift @@ -247,6 +247,11 @@ struct JavaToSwift: ParsableCommand { } } + // TODO: For now, skip all nested classes. + if entry.getName().contains("$") { + continue + } + let javaCanonicalName = String(entry.getName().replacing("/", with: ".") .dropLast(".class".count)) configuration.classes[javaCanonicalName] = From 892e27e1a0f92fc9c8ec89e2f4019fd5be42f02f Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Thu, 17 Oct 2024 09:59:56 -0700 Subject: [PATCH 098/426] Java2Swift: Back-tick escaping for Java method/field names that are Swift keywords --- Sources/Java2SwiftLib/JavaTranslator.swift | 7 ++++--- Sources/Java2SwiftLib/StringExtras.swift | 10 ++++++++++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/Sources/Java2SwiftLib/JavaTranslator.swift b/Sources/Java2SwiftLib/JavaTranslator.swift index 7d2d2e77..2b482b13 100644 --- a/Sources/Java2SwiftLib/JavaTranslator.swift +++ b/Sources/Java2SwiftLib/JavaTranslator.swift @@ -429,20 +429,21 @@ extension JavaTranslator { } let throwsStr = javaMethod.throwsCheckedException ? "throws" : "" - + let swiftMethodName = javaMethod.getName().escapedSwiftName let methodAttribute: AttributeSyntax = javaMethod.isStatic ? "@JavaStaticMethod" : "@JavaMethod"; return """ \(methodAttribute) - public func \(raw: javaMethod.getName())\(raw: genericParameterClause)(\(raw: parametersStr))\(raw: throwsStr)\(raw: resultTypeStr)\(raw: whereClause) + public func \(raw: swiftMethodName)\(raw: genericParameterClause)(\(raw: parametersStr))\(raw: throwsStr)\(raw: resultTypeStr)\(raw: whereClause) """ } package func translateField(_ javaField: Field) throws -> DeclSyntax { let typeName = try getSwiftTypeNameAsString(javaField.getGenericType()!, outerOptional: true) let fieldAttribute: AttributeSyntax = javaField.isStatic ? "@JavaStaticField" : "@JavaField"; + let swiftFieldName = javaField.getName().escapedSwiftName return """ \(fieldAttribute) - public var \(raw: javaField.getName()): \(raw: typeName) + public var \(raw: swiftFieldName): \(raw: typeName) """ } diff --git a/Sources/Java2SwiftLib/StringExtras.swift b/Sources/Java2SwiftLib/StringExtras.swift index 34729883..3e6d7748 100644 --- a/Sources/Java2SwiftLib/StringExtras.swift +++ b/Sources/Java2SwiftLib/StringExtras.swift @@ -11,6 +11,7 @@ // SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// +import SwiftParser extension String { /// Split the Swift type name into parent type + innermost type name. @@ -24,4 +25,13 @@ extension String { name: String(suffix(from: index(after: lastDot))) ) } + + /// Escape a name with backticks if it's a Swift keyword. + var escapedSwiftName: String { + if isValidSwiftIdentifier(for: .variableName) { + return self + } + + return "`\(self)`" + } } From e8f2fdd1ff0b60f7ad5490f6e7f2d9b0f8ee413d Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Thu, 17 Oct 2024 11:42:14 -0700 Subject: [PATCH 099/426] Manually exclude Java2Swift.config files from targets that don't use the plugin This eliminates warnings about the Java2Swift.config files being "unhandled". SwiftPM is correct to warn here, because the files aren't used from SwiftPM themselves (we're not using the build plugin to generate them). --- Package.swift | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Package.swift b/Package.swift index 7f65648a..9198865a 100644 --- a/Package.swift +++ b/Package.swift @@ -160,6 +160,7 @@ let package = Package( .target( name: "JavaKit", dependencies: ["JavaRuntime", "JavaKitMacros", "JavaTypes"], + exclude: ["Java2Swift.config"], swiftSettings: [ .swiftLanguageMode(.v5), .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) @@ -168,6 +169,7 @@ let package = Package( .target( name: "JavaKitJar", dependencies: ["JavaKit"], + exclude: ["Java2Swift.config"], swiftSettings: [ .swiftLanguageMode(.v5), .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) @@ -176,6 +178,7 @@ let package = Package( .target( name: "JavaKitNetwork", dependencies: ["JavaKit"], + exclude: ["Java2Swift.config"], swiftSettings: [ .swiftLanguageMode(.v5), .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) @@ -184,6 +187,7 @@ let package = Package( .target( name: "JavaKitReflection", dependencies: ["JavaKit"], + exclude: ["Java2Swift.config"], swiftSettings: [ .swiftLanguageMode(.v5), .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) From 9e72ab6e42e2ba25cea654a2f456c760f4f0f2ba Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Thu, 17 Oct 2024 12:58:37 -0700 Subject: [PATCH 100/426] Reduce package requirements down to macOS 10.15 We were only using a handful of APIs introduced in macOS 13. Switch away from (or reimplement) those, and drop the package requirements down to macOS 10.15. --- Package.swift | 6 +----- Samples/JavaProbablyPrime/Package.swift | 6 +----- Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift | 2 +- Sources/Java2Swift/JavaToSwift.swift | 8 ++++---- Sources/Java2SwiftLib/StringExtras.swift | 5 +++++ 5 files changed, 12 insertions(+), 15 deletions(-) diff --git a/Package.swift b/Package.swift index 9198865a..87922d5b 100644 --- a/Package.swift +++ b/Package.swift @@ -43,11 +43,7 @@ let javaIncludePath = "\(javaHome)/include" let package = Package( name: "JavaKit", platforms: [ - .macOS(.v13), - .iOS(.v13), - .tvOS(.v13), - .watchOS(.v6), - .macCatalyst(.v13), + .macOS(.v10_15) ], products: [ // ==== JavaKit (i.e. calling Java directly Swift utilities) diff --git a/Samples/JavaProbablyPrime/Package.swift b/Samples/JavaProbablyPrime/Package.swift index 0420942b..8cd2be18 100644 --- a/Samples/JavaProbablyPrime/Package.swift +++ b/Samples/JavaProbablyPrime/Package.swift @@ -7,11 +7,7 @@ import PackageDescription let package = Package( name: "JavaProbablyPrime", platforms: [ - .macOS(.v13), - .iOS(.v13), - .tvOS(.v13), - .watchOS(.v6), - .macCatalyst(.v13), + .macOS(.v10_15), ], products: [ diff --git a/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift b/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift index db35a1c4..46d89dae 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift @@ -78,7 +78,7 @@ extension Swift2JavaTranslator { let targetFilePath = [javaPackagePath, filename].joined(separator: PATH_SEPARATOR) print("Writing '\(targetFilePath)'...", terminator: "") try contents.write( - to: Foundation.URL(filePath: targetDirectory).appending(path: filename), + to: Foundation.URL(fileURLWithPath: targetDirectory).appendingPathComponent(filename), atomically: true, encoding: .utf8 ) diff --git a/Sources/Java2Swift/JavaToSwift.swift b/Sources/Java2Swift/JavaToSwift.swift index 5799e678..1fd25ca9 100644 --- a/Sources/Java2Swift/JavaToSwift.swift +++ b/Sources/Java2Swift/JavaToSwift.swift @@ -75,7 +75,7 @@ struct JavaToSwift: ParsableCommand { if jarFile { generationMode = .configuration(jarFile: input) } else { - let config = try JavaTranslator.readConfiguration(from: URL(filePath: input)) + let config = try JavaTranslator.readConfiguration(from: URL(fileURLWithPath: input)) generationMode = .classWrappers(config) } @@ -90,7 +90,7 @@ struct JavaToSwift: ParsableCommand { let swiftModuleName = String(dependentConfig[.. String { + return replacingOccurrences(of: String(character), with: String(replacement)) + } } From f3487f24a5717b3f18a41a1bfc8d3bdfbef15917 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Thu, 17 Oct 2024 14:38:49 -0700 Subject: [PATCH 101/426] Move java.util.Enumeration wrapper into a new module JavaKitCollection --- Makefile | 16 ++++++++++------ Package.swift | 18 ++++++++++++++++-- Sources/JavaKitCollection/Java2Swift.config | 5 +++++ .../JavaEnumeration+Sequence.swift | 0 .../generated/Enumeration.swift | 1 + Sources/JavaKitJar/generated/JarFile.swift | 1 + .../generated/URLClassLoader.swift | 1 + 7 files changed, 34 insertions(+), 8 deletions(-) create mode 100644 Sources/JavaKitCollection/Java2Swift.config rename Sources/{JavaKit => JavaKitCollection}/JavaEnumeration+Sequence.swift (100%) rename Sources/{JavaKit => JavaKitCollection}/generated/Enumeration.swift (94%) diff --git a/Makefile b/Makefile index 00d33ca4..ab0a89b6 100644 --- a/Makefile +++ b/Makefile @@ -72,17 +72,21 @@ generate-JavaKit: Java2Swift mkdir -p Sources/JavaKit/generated $(BUILD_DIR)/debug/Java2Swift --module-name JavaKit -o Sources/JavaKit/generated Sources/JavaKit/Java2Swift.config -generate-JavaKitReflection: Java2Swift generate-JavaKit +generate-JavaKitCollection: Java2Swift + mkdir -p Sources/JavaKitCollection/generated + $(BUILD_DIR)/debug/Java2Swift --module-name JavaKitCollection --depends-on JavaKit=Sources/JavaKit/Java2Swift.config -o Sources/JavaKitCollection/generated Sources/JavaKitCollection/Java2Swift.config + +generate-JavaKitReflection: Java2Swift generate-JavaKit generate-JavaKitCollection mkdir -p Sources/JavaKitReflection/generated - $(BUILD_DIR)/debug/Java2Swift --module-name JavaKitReflection --depends-on JavaKit=Sources/JavaKit/Java2Swift.config -o Sources/JavaKitReflection/generated Sources/JavaKitReflection/Java2Swift.config + $(BUILD_DIR)/debug/Java2Swift --module-name JavaKitReflection --depends-on JavaKit=Sources/JavaKit/Java2Swift.config --depends-on JavaKitCollection=Sources/JavaKitCollection/Java2Swift.config -o Sources/JavaKitReflection/generated Sources/JavaKitReflection/Java2Swift.config -generate-JavaKitJar: Java2Swift generate-JavaKit +generate-JavaKitJar: Java2Swift generate-JavaKit generate-JavaKitCollection mkdir -p Sources/JavaKitJar/generated - $(BUILD_DIR)/debug/Java2Swift --module-name JavaKitJar --depends-on JavaKit=Sources/JavaKit/Java2Swift.config -o Sources/JavaKitJar/generated Sources/JavaKitJar/Java2Swift.config + $(BUILD_DIR)/debug/Java2Swift --module-name JavaKitJar --depends-on JavaKit=Sources/JavaKit/Java2Swift.config --depends-on JavaKitCollection=Sources/JavaKitCollection/Java2Swift.config -o Sources/JavaKitJar/generated Sources/JavaKitJar/Java2Swift.config -generate-JavaKitNetwork: Java2Swift generate-JavaKit +generate-JavaKitNetwork: Java2Swift generate-JavaKit generate-JavaKitCollection mkdir -p Sources/JavaKitNetwork/generated - $(BUILD_DIR)/debug/Java2Swift --module-name JavaKitNetwork --depends-on JavaKit=Sources/JavaKit/Java2Swift.config -o Sources/JavaKitNetwork/generated Sources/JavaKitNetwork/Java2Swift.config + $(BUILD_DIR)/debug/Java2Swift --module-name JavaKitNetwork --depends-on JavaKit=Sources/JavaKit/Java2Swift.config --depends-on JavaKitCollection=Sources/JavaKitCollection/Java2Swift.config -o Sources/JavaKitNetwork/generated Sources/JavaKitNetwork/Java2Swift.config javakit-generate: generate-JavaKit generate-JavaKitReflection generate-JavaKitJar generate-JavaKitNetwork diff --git a/Package.swift b/Package.swift index 87922d5b..a6ca8cf8 100644 --- a/Package.swift +++ b/Package.swift @@ -57,6 +57,11 @@ let package = Package( targets: ["JavaRuntime"] ), + .library( + name: "JavaKitCollection", + targets: ["JavaKitCollection"] + ), + .library( name: "JavaKitJar", targets: ["JavaKitReflection"] @@ -163,7 +168,7 @@ let package = Package( ] ), .target( - name: "JavaKitJar", + name: "JavaKitCollection", dependencies: ["JavaKit"], exclude: ["Java2Swift.config"], swiftSettings: [ @@ -171,9 +176,18 @@ let package = Package( .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) ] ), + .target( + name: "JavaKitJar", + dependencies: ["JavaKit", "JavaKitCollection"], + exclude: ["Java2Swift.config"], + swiftSettings: [ + .swiftLanguageMode(.v5), + .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) + ] + ), .target( name: "JavaKitNetwork", - dependencies: ["JavaKit"], + dependencies: ["JavaKit", "JavaKitCollection"], exclude: ["Java2Swift.config"], swiftSettings: [ .swiftLanguageMode(.v5), diff --git a/Sources/JavaKitCollection/Java2Swift.config b/Sources/JavaKitCollection/Java2Swift.config new file mode 100644 index 00000000..50c23be8 --- /dev/null +++ b/Sources/JavaKitCollection/Java2Swift.config @@ -0,0 +1,5 @@ +{ + "classes" : { + "java.util.Enumeration" : "Enumeration" + } +} diff --git a/Sources/JavaKit/JavaEnumeration+Sequence.swift b/Sources/JavaKitCollection/JavaEnumeration+Sequence.swift similarity index 100% rename from Sources/JavaKit/JavaEnumeration+Sequence.swift rename to Sources/JavaKitCollection/JavaEnumeration+Sequence.swift diff --git a/Sources/JavaKit/generated/Enumeration.swift b/Sources/JavaKitCollection/generated/Enumeration.swift similarity index 94% rename from Sources/JavaKit/generated/Enumeration.swift rename to Sources/JavaKitCollection/generated/Enumeration.swift index 703fb441..0ccf117b 100644 --- a/Sources/JavaKit/generated/Enumeration.swift +++ b/Sources/JavaKitCollection/generated/Enumeration.swift @@ -1,4 +1,5 @@ // Auto-generated by Java-to-Swift wrapper generator. +import JavaKit import JavaRuntime @JavaInterface("java.util.Enumeration") diff --git a/Sources/JavaKitJar/generated/JarFile.swift b/Sources/JavaKitJar/generated/JarFile.swift index dc7eb93b..e5d8eb6d 100644 --- a/Sources/JavaKitJar/generated/JarFile.swift +++ b/Sources/JavaKitJar/generated/JarFile.swift @@ -1,5 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import JavaKit +import JavaKitCollection import JavaRuntime @JavaClass("java.util.jar.JarFile") diff --git a/Sources/JavaKitNetwork/generated/URLClassLoader.swift b/Sources/JavaKitNetwork/generated/URLClassLoader.swift index 849d5715..6dd407f4 100644 --- a/Sources/JavaKitNetwork/generated/URLClassLoader.swift +++ b/Sources/JavaKitNetwork/generated/URLClassLoader.swift @@ -1,5 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import JavaKit +import JavaKitCollection import JavaRuntime @JavaClass("java.net.URLClassLoader") From 7b40a2a5abe68b2d4ca537850c57026368e2014a Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Thu, 17 Oct 2024 14:58:35 -0700 Subject: [PATCH 102/426] Expand JavaKitCollection module to encompass many more Java collections --- .gitignore | 3 - Sources/JavaKitCollection/Java2Swift.config | 19 +- .../generated/ArrayDeque.swift | 153 ++++++++++++++ .../generated/ArrayList.swift | 135 +++++++++++++ .../JavaKitCollection/generated/BitSet.swift | 127 ++++++++++++ .../generated/Enumeration.swift | 3 + .../JavaKitCollection/generated/HashMap.swift | 94 +++++++++ .../JavaKitCollection/generated/HashSet.swift | 91 +++++++++ .../generated/JavaCollection.swift | 51 +++++ .../generated/JavaDictionary.swift | 57 ++++++ .../generated/JavaIterator.swift | 15 ++ .../JavaKitCollection/generated/JavaSet.swift | 91 +++++++++ .../generated/LinkedList.swift | 177 ++++++++++++++++ .../generated/ListIterator.swift | 33 +++ .../generated/PriorityQueue.swift | 99 +++++++++ .../JavaKitCollection/generated/Queue.swift | 66 ++++++ .../generated/RandomAccess.swift | 8 + .../JavaKitCollection/generated/Stack.swift | 189 ++++++++++++++++++ .../JavaKitCollection/generated/TreeMap.swift | 108 ++++++++++ .../JavaKitCollection/generated/TreeSet.swift | 126 ++++++++++++ Sources/JavaKitJar/generated/Attributes.swift | 7 + .../generated/Constructor.swift | 1 + .../generated/Executable.swift | 1 + .../JavaKitReflection/generated/Field.swift | 1 + .../JavaKitReflection/generated/Method.swift | 1 + .../generated/Parameter.swift | 1 + 26 files changed, 1653 insertions(+), 4 deletions(-) create mode 100644 Sources/JavaKitCollection/generated/ArrayDeque.swift create mode 100644 Sources/JavaKitCollection/generated/ArrayList.swift create mode 100644 Sources/JavaKitCollection/generated/BitSet.swift create mode 100644 Sources/JavaKitCollection/generated/HashMap.swift create mode 100644 Sources/JavaKitCollection/generated/HashSet.swift create mode 100644 Sources/JavaKitCollection/generated/JavaCollection.swift create mode 100644 Sources/JavaKitCollection/generated/JavaDictionary.swift create mode 100644 Sources/JavaKitCollection/generated/JavaIterator.swift create mode 100644 Sources/JavaKitCollection/generated/JavaSet.swift create mode 100644 Sources/JavaKitCollection/generated/LinkedList.swift create mode 100644 Sources/JavaKitCollection/generated/ListIterator.swift create mode 100644 Sources/JavaKitCollection/generated/PriorityQueue.swift create mode 100644 Sources/JavaKitCollection/generated/Queue.swift create mode 100644 Sources/JavaKitCollection/generated/RandomAccess.swift create mode 100644 Sources/JavaKitCollection/generated/Stack.swift create mode 100644 Sources/JavaKitCollection/generated/TreeMap.swift create mode 100644 Sources/JavaKitCollection/generated/TreeSet.swift diff --git a/.gitignore b/.gitignore index 381bd778..f56abda5 100644 --- a/.gitignore +++ b/.gitignore @@ -27,6 +27,3 @@ Package.resolved # Cache of project .gradletasknamecache - -# Ignore generated sources -**/generated/ diff --git a/Sources/JavaKitCollection/Java2Swift.config b/Sources/JavaKitCollection/Java2Swift.config index 50c23be8..e134a2e3 100644 --- a/Sources/JavaKitCollection/Java2Swift.config +++ b/Sources/JavaKitCollection/Java2Swift.config @@ -1,5 +1,22 @@ { "classes" : { - "java.util.Enumeration" : "Enumeration" + "java.util.Collection" : "JavaCollection", + "java.util.Enumeration" : "Enumeration", + "java.util.Iterator" : "JavaIterator", + "java.util.ListIterator" : "ListIterator", + "java.util.Queue" : "Queue", + "java.util.RandomAccess" : "RandomAccess", + "java.util.Set" : "JavaSet", + "java.util.ArrayDeque" : "ArrayDeque", + "java.util.ArrayList" : "ArrayList", + "java.util.BitSet" : "BitSet", + "java.util.Dictionary" : "JavaDictionary", + "java.util.HashMap" : "HashMap", + "java.util.HashSet" : "HashSet", + "java.util.LinkedList" : "LinkedList", + "java.util.PriorityQueue" : "PriorityQueue", + "java.util.Stack" : "Stack", + "java.util.TreeMap" : "TreeMap", + "java.util.TreeSet" : "TreeSet" } } diff --git a/Sources/JavaKitCollection/generated/ArrayDeque.swift b/Sources/JavaKitCollection/generated/ArrayDeque.swift new file mode 100644 index 00000000..af2fd314 --- /dev/null +++ b/Sources/JavaKitCollection/generated/ArrayDeque.swift @@ -0,0 +1,153 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaClass("java.util.ArrayDeque") +public struct ArrayDeque { + @JavaMethod + public init(_ arg0: Int32, environment: JNIEnvironment) + + @JavaMethod + public init(environment: JNIEnvironment) + + @JavaMethod + public init(_ arg0: JavaCollection?, environment: JNIEnvironment) + + @JavaMethod + public func remove() -> JavaObject? + + @JavaMethod + public func remove(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func size() -> Int32 + + @JavaMethod + public func clone() -> ArrayDeque? + + @JavaMethod + public func clone() throws -> JavaObject? + + @JavaMethod + public func clear() + + @JavaMethod + public func isEmpty() -> Bool + + @JavaMethod + public func add(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func toArray(_ arg0: [JavaObject?]) -> [JavaObject?] + + @JavaMethod + public func toArray() -> [JavaObject?] + + @JavaMethod + public func iterator() -> JavaIterator? + + @JavaMethod + public func contains(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func addAll(_ arg0: JavaCollection?) -> Bool + + @JavaMethod + public func peek() -> JavaObject? + + @JavaMethod + public func getFirst() -> JavaObject? + + @JavaMethod + public func getLast() -> JavaObject? + + @JavaMethod + public func element() -> JavaObject? + + @JavaMethod + public func addFirst(_ arg0: JavaObject?) + + @JavaMethod + public func addLast(_ arg0: JavaObject?) + + @JavaMethod + public func removeFirst() -> JavaObject? + + @JavaMethod + public func removeLast() -> JavaObject? + + @JavaMethod + public func removeAll(_ arg0: JavaCollection?) -> Bool + + @JavaMethod + public func retainAll(_ arg0: JavaCollection?) -> Bool + + @JavaMethod + public func poll() -> JavaObject? + + @JavaMethod + public func push(_ arg0: JavaObject?) + + @JavaMethod + public func pop() -> JavaObject? + + @JavaMethod + public func pollFirst() -> JavaObject? + + @JavaMethod + public func pollLast() -> JavaObject? + + @JavaMethod + public func offerLast(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func peekFirst() -> JavaObject? + + @JavaMethod + public func removeFirstOccurrence(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func offerFirst(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func peekLast() -> JavaObject? + + @JavaMethod + public func removeLastOccurrence(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func offer(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func descendingIterator() -> JavaIterator? + + @JavaMethod + public func toString() -> String + + @JavaMethod + public func containsAll(_ arg0: JavaCollection?) -> Bool + + @JavaMethod + public func equals(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func hashCode() -> Int32 + + @JavaMethod + public func getClass() -> JavaClass? + + @JavaMethod + public func notify() + + @JavaMethod + public func notifyAll() + + @JavaMethod + public func wait(_ arg0: Int64) throws + + @JavaMethod + public func wait(_ arg0: Int64, _ arg1: Int32) throws + + @JavaMethod + public func wait() throws +} diff --git a/Sources/JavaKitCollection/generated/ArrayList.swift b/Sources/JavaKitCollection/generated/ArrayList.swift new file mode 100644 index 00000000..fd400ae5 --- /dev/null +++ b/Sources/JavaKitCollection/generated/ArrayList.swift @@ -0,0 +1,135 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaClass("java.util.ArrayList", implements: RandomAccess.self) +public struct ArrayList { + @JavaMethod + public init(_ arg0: JavaCollection?, environment: JNIEnvironment) + + @JavaMethod + public init(environment: JNIEnvironment) + + @JavaMethod + public init(_ arg0: Int32, environment: JNIEnvironment) + + @JavaMethod + public func remove(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func remove(_ arg0: Int32) -> JavaObject? + + @JavaMethod + public func size() -> Int32 + + @JavaMethod + public func get(_ arg0: Int32) -> JavaObject? + + @JavaMethod + public func equals(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func hashCode() -> Int32 + + @JavaMethod + public func clone() -> JavaObject? + + @JavaMethod + public func indexOf(_ arg0: JavaObject?) -> Int32 + + @JavaMethod + public func clear() + + @JavaMethod + public func lastIndexOf(_ arg0: JavaObject?) -> Int32 + + @JavaMethod + public func isEmpty() -> Bool + + @JavaMethod + public func add(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func add(_ arg0: Int32, _ arg1: JavaObject?) + + @JavaMethod + public func toArray() -> [JavaObject?] + + @JavaMethod + public func toArray(_ arg0: [JavaObject?]) -> [JavaObject?] + + @JavaMethod + public func iterator() -> JavaIterator? + + @JavaMethod + public func contains(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func addAll(_ arg0: Int32, _ arg1: JavaCollection?) -> Bool + + @JavaMethod + public func addAll(_ arg0: JavaCollection?) -> Bool + + @JavaMethod + public func set(_ arg0: Int32, _ arg1: JavaObject?) -> JavaObject? + + @JavaMethod + public func ensureCapacity(_ arg0: Int32) + + @JavaMethod + public func trimToSize() + + @JavaMethod + public func getFirst() -> JavaObject? + + @JavaMethod + public func getLast() -> JavaObject? + + @JavaMethod + public func addFirst(_ arg0: JavaObject?) + + @JavaMethod + public func addLast(_ arg0: JavaObject?) + + @JavaMethod + public func removeFirst() -> JavaObject? + + @JavaMethod + public func removeLast() -> JavaObject? + + @JavaMethod + public func removeAll(_ arg0: JavaCollection?) -> Bool + + @JavaMethod + public func retainAll(_ arg0: JavaCollection?) -> Bool + + @JavaMethod + public func listIterator(_ arg0: Int32) -> ListIterator? + + @JavaMethod + public func listIterator() -> ListIterator? + + @JavaMethod + public func toString() -> String + + @JavaMethod + public func containsAll(_ arg0: JavaCollection?) -> Bool + + @JavaMethod + public func getClass() -> JavaClass? + + @JavaMethod + public func notify() + + @JavaMethod + public func notifyAll() + + @JavaMethod + public func wait(_ arg0: Int64) throws + + @JavaMethod + public func wait(_ arg0: Int64, _ arg1: Int32) throws + + @JavaMethod + public func wait() throws +} diff --git a/Sources/JavaKitCollection/generated/BitSet.swift b/Sources/JavaKitCollection/generated/BitSet.swift new file mode 100644 index 00000000..f9c0bda9 --- /dev/null +++ b/Sources/JavaKitCollection/generated/BitSet.swift @@ -0,0 +1,127 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaClass("java.util.BitSet") +public struct BitSet { + @JavaMethod + public init(environment: JNIEnvironment) + + @JavaMethod + public init(_ arg0: Int32, environment: JNIEnvironment) + + @JavaMethod + public func cardinality() -> Int32 + + @JavaMethod + public func nextSetBit(_ arg0: Int32) -> Int32 + + @JavaMethod + public func toLongArray() -> [Int64] + + @JavaMethod + public func previousSetBit(_ arg0: Int32) -> Int32 + + @JavaMethod + public func previousClearBit(_ arg0: Int32) -> Int32 + + @JavaMethod + public func intersects(_ arg0: BitSet?) -> Bool + + @JavaMethod + public func size() -> Int32 + + @JavaMethod + public func get(_ arg0: Int32, _ arg1: Int32) -> BitSet? + + @JavaMethod + public func get(_ arg0: Int32) -> Bool + + @JavaMethod + public func equals(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func length() -> Int32 + + @JavaMethod + public func toString() -> String + + @JavaMethod + public func hashCode() -> Int32 + + @JavaMethod + public func clone() -> JavaObject? + + @JavaMethod + public func clear(_ arg0: Int32) + + @JavaMethod + public func clear(_ arg0: Int32, _ arg1: Int32) + + @JavaMethod + public func clear() + + @JavaMethod + public func isEmpty() -> Bool + + @JavaMethod + public func set(_ arg0: Int32, _ arg1: Int32, _ arg2: Bool) + + @JavaMethod + public func set(_ arg0: Int32, _ arg1: Int32) + + @JavaMethod + public func set(_ arg0: Int32) + + @JavaMethod + public func set(_ arg0: Int32, _ arg1: Bool) + + @JavaMethod + public func flip(_ arg0: Int32, _ arg1: Int32) + + @JavaMethod + public func flip(_ arg0: Int32) + + @JavaMethod + public func nextClearBit(_ arg0: Int32) -> Int32 + + @JavaMethod + public func or(_ arg0: BitSet?) + + @JavaMethod + public func toByteArray() -> [Int8] + + @JavaMethod + public func and(_ arg0: BitSet?) + + @JavaMethod + public func xor(_ arg0: BitSet?) + + @JavaMethod + public func andNot(_ arg0: BitSet?) + + @JavaMethod + public func getClass() -> JavaClass? + + @JavaMethod + public func notify() + + @JavaMethod + public func notifyAll() + + @JavaMethod + public func wait(_ arg0: Int64) throws + + @JavaMethod + public func wait(_ arg0: Int64, _ arg1: Int32) throws + + @JavaMethod + public func wait() throws +} +extension JavaClass { + @JavaStaticMethod + public func valueOf(_ arg0: [Int64]) -> BitSet? + + @JavaStaticMethod + public func valueOf(_ arg0: [Int8]) -> BitSet? +} diff --git a/Sources/JavaKitCollection/generated/Enumeration.swift b/Sources/JavaKitCollection/generated/Enumeration.swift index 0ccf117b..be0936d3 100644 --- a/Sources/JavaKitCollection/generated/Enumeration.swift +++ b/Sources/JavaKitCollection/generated/Enumeration.swift @@ -4,6 +4,9 @@ import JavaRuntime @JavaInterface("java.util.Enumeration") public struct Enumeration { + @JavaMethod + public func asIterator() -> JavaIterator? + @JavaMethod public func hasMoreElements() -> Bool diff --git a/Sources/JavaKitCollection/generated/HashMap.swift b/Sources/JavaKitCollection/generated/HashMap.swift new file mode 100644 index 00000000..d4048dd0 --- /dev/null +++ b/Sources/JavaKitCollection/generated/HashMap.swift @@ -0,0 +1,94 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaClass("java.util.HashMap") +public struct HashMap { + @JavaMethod + public init(_ arg0: Int32, environment: JNIEnvironment) + + @JavaMethod + public init(_ arg0: Int32, _ arg1: Float, environment: JNIEnvironment) + + @JavaMethod + public init(environment: JNIEnvironment) + + @JavaMethod + public func remove(_ arg0: JavaObject?) -> JavaObject? + + @JavaMethod + public func remove(_ arg0: JavaObject?, _ arg1: JavaObject?) -> Bool + + @JavaMethod + public func size() -> Int32 + + @JavaMethod + public func get(_ arg0: JavaObject?) -> JavaObject? + + @JavaMethod + public func put(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject? + + @JavaMethod + public func values() -> JavaCollection? + + @JavaMethod + public func clone() -> JavaObject? + + @JavaMethod + public func clear() + + @JavaMethod + public func isEmpty() -> Bool + + @JavaMethod + public func replace(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject? + + @JavaMethod + public func replace(_ arg0: JavaObject?, _ arg1: JavaObject?, _ arg2: JavaObject?) -> Bool + + @JavaMethod + public func putIfAbsent(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject? + + @JavaMethod + public func containsKey(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func keySet() -> JavaSet? + + @JavaMethod + public func containsValue(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func getOrDefault(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject? + + @JavaMethod + public func equals(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func toString() -> String + + @JavaMethod + public func hashCode() -> Int32 + + @JavaMethod + public func getClass() -> JavaClass? + + @JavaMethod + public func notify() + + @JavaMethod + public func notifyAll() + + @JavaMethod + public func wait(_ arg0: Int64) throws + + @JavaMethod + public func wait(_ arg0: Int64, _ arg1: Int32) throws + + @JavaMethod + public func wait() throws +} +extension JavaClass { + @JavaStaticMethod + public func newHashMap(_ arg0: Int32) -> HashMap? where ObjectType == HashMap +} diff --git a/Sources/JavaKitCollection/generated/HashSet.swift b/Sources/JavaKitCollection/generated/HashSet.swift new file mode 100644 index 00000000..aa071dfd --- /dev/null +++ b/Sources/JavaKitCollection/generated/HashSet.swift @@ -0,0 +1,91 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaClass("java.util.HashSet", implements: JavaSet.self) +public struct HashSet { + @JavaMethod + public init(_ arg0: Int32, environment: JNIEnvironment) + + @JavaMethod + public init(_ arg0: Int32, _ arg1: Float, environment: JNIEnvironment) + + @JavaMethod + public init(_ arg0: JavaCollection?, environment: JNIEnvironment) + + @JavaMethod + public init(environment: JNIEnvironment) + + @JavaMethod + public func remove(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func size() -> Int32 + + @JavaMethod + public func clone() -> JavaObject? + + @JavaMethod + public func clear() + + @JavaMethod + public func isEmpty() -> Bool + + @JavaMethod + public func add(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func toArray(_ arg0: [JavaObject?]) -> [JavaObject?] + + @JavaMethod + public func toArray() -> [JavaObject?] + + @JavaMethod + public func iterator() -> JavaIterator? + + @JavaMethod + public func contains(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func equals(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func hashCode() -> Int32 + + @JavaMethod + public func removeAll(_ arg0: JavaCollection?) -> Bool + + @JavaMethod + public func toString() -> String + + @JavaMethod + public func addAll(_ arg0: JavaCollection?) -> Bool + + @JavaMethod + public func retainAll(_ arg0: JavaCollection?) -> Bool + + @JavaMethod + public func containsAll(_ arg0: JavaCollection?) -> Bool + + @JavaMethod + public func getClass() -> JavaClass? + + @JavaMethod + public func notify() + + @JavaMethod + public func notifyAll() + + @JavaMethod + public func wait(_ arg0: Int64) throws + + @JavaMethod + public func wait(_ arg0: Int64, _ arg1: Int32) throws + + @JavaMethod + public func wait() throws +} +extension JavaClass { + @JavaStaticMethod + public func newHashSet(_ arg0: Int32) -> HashSet? where ObjectType == HashSet +} diff --git a/Sources/JavaKitCollection/generated/JavaCollection.swift b/Sources/JavaKitCollection/generated/JavaCollection.swift new file mode 100644 index 00000000..84b44739 --- /dev/null +++ b/Sources/JavaKitCollection/generated/JavaCollection.swift @@ -0,0 +1,51 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaInterface("java.util.Collection") +public struct JavaCollection { + @JavaMethod + public func remove(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func size() -> Int32 + + @JavaMethod + public func equals(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func hashCode() -> Int32 + + @JavaMethod + public func clear() + + @JavaMethod + public func isEmpty() -> Bool + + @JavaMethod + public func add(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func toArray(_ arg0: [JavaObject?]) -> [JavaObject?] + + @JavaMethod + public func toArray() -> [JavaObject?] + + @JavaMethod + public func iterator() -> JavaIterator? + + @JavaMethod + public func contains(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func addAll(_ arg0: JavaCollection?) -> Bool + + @JavaMethod + public func removeAll(_ arg0: JavaCollection?) -> Bool + + @JavaMethod + public func retainAll(_ arg0: JavaCollection?) -> Bool + + @JavaMethod + public func containsAll(_ arg0: JavaCollection?) -> Bool +} diff --git a/Sources/JavaKitCollection/generated/JavaDictionary.swift b/Sources/JavaKitCollection/generated/JavaDictionary.swift new file mode 100644 index 00000000..c32b3038 --- /dev/null +++ b/Sources/JavaKitCollection/generated/JavaDictionary.swift @@ -0,0 +1,57 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaClass("java.util.Dictionary") +public struct JavaDictionary { + @JavaMethod + public init(environment: JNIEnvironment) + + @JavaMethod + public func remove(_ arg0: JavaObject?) -> JavaObject? + + @JavaMethod + public func size() -> Int32 + + @JavaMethod + public func get(_ arg0: JavaObject?) -> JavaObject? + + @JavaMethod + public func put(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject? + + @JavaMethod + public func isEmpty() -> Bool + + @JavaMethod + public func elements() -> Enumeration? + + @JavaMethod + public func keys() -> Enumeration? + + @JavaMethod + public func equals(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func toString() -> String + + @JavaMethod + public func hashCode() -> Int32 + + @JavaMethod + public func getClass() -> JavaClass? + + @JavaMethod + public func notify() + + @JavaMethod + public func notifyAll() + + @JavaMethod + public func wait(_ arg0: Int64) throws + + @JavaMethod + public func wait(_ arg0: Int64, _ arg1: Int32) throws + + @JavaMethod + public func wait() throws +} diff --git a/Sources/JavaKitCollection/generated/JavaIterator.swift b/Sources/JavaKitCollection/generated/JavaIterator.swift new file mode 100644 index 00000000..893e43a9 --- /dev/null +++ b/Sources/JavaKitCollection/generated/JavaIterator.swift @@ -0,0 +1,15 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaInterface("java.util.Iterator") +public struct JavaIterator { + @JavaMethod + public func remove() + + @JavaMethod + public func hasNext() -> Bool + + @JavaMethod + public func next() -> JavaObject? +} diff --git a/Sources/JavaKitCollection/generated/JavaSet.swift b/Sources/JavaKitCollection/generated/JavaSet.swift new file mode 100644 index 00000000..b1412c9d --- /dev/null +++ b/Sources/JavaKitCollection/generated/JavaSet.swift @@ -0,0 +1,91 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaInterface("java.util.Set", extends: JavaCollection.self) +public struct JavaSet { + @JavaMethod + public func remove(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func size() -> Int32 + + @JavaMethod + public func equals(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func hashCode() -> Int32 + + @JavaMethod + public func clear() + + @JavaMethod + public func isEmpty() -> Bool + + @JavaMethod + public func add(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func toArray() -> [JavaObject?] + + @JavaMethod + public func toArray(_ arg0: [JavaObject?]) -> [JavaObject?] + + @JavaMethod + public func iterator() -> JavaIterator? + + @JavaMethod + public func contains(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func addAll(_ arg0: JavaCollection?) -> Bool + + @JavaMethod + public func removeAll(_ arg0: JavaCollection?) -> Bool + + @JavaMethod + public func retainAll(_ arg0: JavaCollection?) -> Bool + + @JavaMethod + public func containsAll(_ arg0: JavaCollection?) -> Bool +} +extension JavaClass { + @JavaStaticMethod + public func copyOf(_ arg0: JavaCollection?) -> JavaSet? where ObjectType == JavaSet + + @JavaStaticMethod + public func of(_ arg0: JavaObject?, _ arg1: JavaObject?, _ arg2: JavaObject?, _ arg3: JavaObject?, _ arg4: JavaObject?, _ arg5: JavaObject?) -> JavaSet? where ObjectType == JavaSet + + @JavaStaticMethod + public func of(_ arg0: JavaObject?, _ arg1: JavaObject?, _ arg2: JavaObject?, _ arg3: JavaObject?, _ arg4: JavaObject?) -> JavaSet? where ObjectType == JavaSet + + @JavaStaticMethod + public func of(_ arg0: JavaObject?, _ arg1: JavaObject?, _ arg2: JavaObject?, _ arg3: JavaObject?) -> JavaSet? where ObjectType == JavaSet + + @JavaStaticMethod + public func of() -> JavaSet? where ObjectType == JavaSet + + @JavaStaticMethod + public func of(_ arg0: JavaObject?, _ arg1: JavaObject?, _ arg2: JavaObject?, _ arg3: JavaObject?, _ arg4: JavaObject?, _ arg5: JavaObject?, _ arg6: JavaObject?, _ arg7: JavaObject?, _ arg8: JavaObject?, _ arg9: JavaObject?) -> JavaSet? where ObjectType == JavaSet + + @JavaStaticMethod + public func of(_ arg0: JavaObject?, _ arg1: JavaObject?, _ arg2: JavaObject?, _ arg3: JavaObject?, _ arg4: JavaObject?, _ arg5: JavaObject?, _ arg6: JavaObject?, _ arg7: JavaObject?, _ arg8: JavaObject?) -> JavaSet? where ObjectType == JavaSet + + @JavaStaticMethod + public func of(_ arg0: JavaObject?, _ arg1: JavaObject?, _ arg2: JavaObject?, _ arg3: JavaObject?, _ arg4: JavaObject?, _ arg5: JavaObject?, _ arg6: JavaObject?, _ arg7: JavaObject?) -> JavaSet? where ObjectType == JavaSet + + @JavaStaticMethod + public func of(_ arg0: JavaObject?, _ arg1: JavaObject?, _ arg2: JavaObject?, _ arg3: JavaObject?, _ arg4: JavaObject?, _ arg5: JavaObject?, _ arg6: JavaObject?) -> JavaSet? where ObjectType == JavaSet + + @JavaStaticMethod + public func of(_ arg0: [JavaObject?]) -> JavaSet? where ObjectType == JavaSet + + @JavaStaticMethod + public func of(_ arg0: JavaObject?, _ arg1: JavaObject?, _ arg2: JavaObject?) -> JavaSet? where ObjectType == JavaSet + + @JavaStaticMethod + public func of(_ arg0: JavaObject?) -> JavaSet? where ObjectType == JavaSet + + @JavaStaticMethod + public func of(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaSet? where ObjectType == JavaSet +} diff --git a/Sources/JavaKitCollection/generated/LinkedList.swift b/Sources/JavaKitCollection/generated/LinkedList.swift new file mode 100644 index 00000000..cf7043c2 --- /dev/null +++ b/Sources/JavaKitCollection/generated/LinkedList.swift @@ -0,0 +1,177 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaClass("java.util.LinkedList") +public struct LinkedList { + @JavaMethod + public init(_ arg0: JavaCollection?, environment: JNIEnvironment) + + @JavaMethod + public init(environment: JNIEnvironment) + + @JavaMethod + public func remove(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func remove(_ arg0: Int32) -> JavaObject? + + @JavaMethod + public func remove() -> JavaObject? + + @JavaMethod + public func size() -> Int32 + + @JavaMethod + public func get(_ arg0: Int32) -> JavaObject? + + @JavaMethod + public func clone() -> JavaObject? + + @JavaMethod + public func indexOf(_ arg0: JavaObject?) -> Int32 + + @JavaMethod + public func clear() + + @JavaMethod + public func lastIndexOf(_ arg0: JavaObject?) -> Int32 + + @JavaMethod + public func add(_ arg0: Int32, _ arg1: JavaObject?) + + @JavaMethod + public func add(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func toArray(_ arg0: [JavaObject?]) -> [JavaObject?] + + @JavaMethod + public func toArray() -> [JavaObject?] + + @JavaMethod + public func contains(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func addAll(_ arg0: Int32, _ arg1: JavaCollection?) -> Bool + + @JavaMethod + public func addAll(_ arg0: JavaCollection?) -> Bool + + @JavaMethod + public func set(_ arg0: Int32, _ arg1: JavaObject?) -> JavaObject? + + @JavaMethod + public func peek() -> JavaObject? + + @JavaMethod + public func getFirst() -> JavaObject? + + @JavaMethod + public func getLast() -> JavaObject? + + @JavaMethod + public func element() -> JavaObject? + + @JavaMethod + public func addFirst(_ arg0: JavaObject?) + + @JavaMethod + public func addLast(_ arg0: JavaObject?) + + @JavaMethod + public func removeFirst() -> JavaObject? + + @JavaMethod + public func removeLast() -> JavaObject? + + @JavaMethod + public func listIterator(_ arg0: Int32) -> ListIterator? + + @JavaMethod + public func reversed() -> LinkedList? + + @JavaMethod + public func poll() -> JavaObject? + + @JavaMethod + public func push(_ arg0: JavaObject?) + + @JavaMethod + public func pop() -> JavaObject? + + @JavaMethod + public func pollFirst() -> JavaObject? + + @JavaMethod + public func pollLast() -> JavaObject? + + @JavaMethod + public func offerLast(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func peekFirst() -> JavaObject? + + @JavaMethod + public func removeFirstOccurrence(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func offerFirst(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func peekLast() -> JavaObject? + + @JavaMethod + public func removeLastOccurrence(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func offer(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func descendingIterator() -> JavaIterator? + + @JavaMethod + public func iterator() -> JavaIterator? + + @JavaMethod + public func equals(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func hashCode() -> Int32 + + @JavaMethod + public func listIterator() -> ListIterator? + + @JavaMethod + public func toString() -> String + + @JavaMethod + public func isEmpty() -> Bool + + @JavaMethod + public func removeAll(_ arg0: JavaCollection?) -> Bool + + @JavaMethod + public func retainAll(_ arg0: JavaCollection?) -> Bool + + @JavaMethod + public func containsAll(_ arg0: JavaCollection?) -> Bool + + @JavaMethod + public func getClass() -> JavaClass? + + @JavaMethod + public func notify() + + @JavaMethod + public func notifyAll() + + @JavaMethod + public func wait(_ arg0: Int64) throws + + @JavaMethod + public func wait(_ arg0: Int64, _ arg1: Int32) throws + + @JavaMethod + public func wait() throws +} diff --git a/Sources/JavaKitCollection/generated/ListIterator.swift b/Sources/JavaKitCollection/generated/ListIterator.swift new file mode 100644 index 00000000..a918ea16 --- /dev/null +++ b/Sources/JavaKitCollection/generated/ListIterator.swift @@ -0,0 +1,33 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaInterface("java.util.ListIterator", extends: JavaIterator.self) +public struct ListIterator { + @JavaMethod + public func remove() + + @JavaMethod + public func add(_ arg0: JavaObject?) + + @JavaMethod + public func hasNext() -> Bool + + @JavaMethod + public func next() -> JavaObject? + + @JavaMethod + public func set(_ arg0: JavaObject?) + + @JavaMethod + public func nextIndex() -> Int32 + + @JavaMethod + public func previousIndex() -> Int32 + + @JavaMethod + public func hasPrevious() -> Bool + + @JavaMethod + public func previous() -> JavaObject? +} diff --git a/Sources/JavaKitCollection/generated/PriorityQueue.swift b/Sources/JavaKitCollection/generated/PriorityQueue.swift new file mode 100644 index 00000000..7b70c7cd --- /dev/null +++ b/Sources/JavaKitCollection/generated/PriorityQueue.swift @@ -0,0 +1,99 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaClass("java.util.PriorityQueue") +public struct PriorityQueue { + @JavaMethod + public init(_ arg0: PriorityQueue?, environment: JNIEnvironment) + + @JavaMethod + public init(_ arg0: JavaCollection?, environment: JNIEnvironment) + + @JavaMethod + public init(_ arg0: Int32, environment: JNIEnvironment) + + @JavaMethod + public init(environment: JNIEnvironment) + + @JavaMethod + public func remove(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func size() -> Int32 + + @JavaMethod + public func clear() + + @JavaMethod + public func add(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func toArray(_ arg0: [JavaObject?]) -> [JavaObject?] + + @JavaMethod + public func toArray() -> [JavaObject?] + + @JavaMethod + public func iterator() -> JavaIterator? + + @JavaMethod + public func contains(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func peek() -> JavaObject? + + @JavaMethod + public func removeAll(_ arg0: JavaCollection?) -> Bool + + @JavaMethod + public func retainAll(_ arg0: JavaCollection?) -> Bool + + @JavaMethod + public func poll() -> JavaObject? + + @JavaMethod + public func offer(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func remove() -> JavaObject? + + @JavaMethod + public func addAll(_ arg0: JavaCollection?) -> Bool + + @JavaMethod + public func element() -> JavaObject? + + @JavaMethod + public func toString() -> String + + @JavaMethod + public func isEmpty() -> Bool + + @JavaMethod + public func containsAll(_ arg0: JavaCollection?) -> Bool + + @JavaMethod + public func equals(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func hashCode() -> Int32 + + @JavaMethod + public func getClass() -> JavaClass? + + @JavaMethod + public func notify() + + @JavaMethod + public func notifyAll() + + @JavaMethod + public func wait(_ arg0: Int64) throws + + @JavaMethod + public func wait(_ arg0: Int64, _ arg1: Int32) throws + + @JavaMethod + public func wait() throws +} diff --git a/Sources/JavaKitCollection/generated/Queue.swift b/Sources/JavaKitCollection/generated/Queue.swift new file mode 100644 index 00000000..33bf05f9 --- /dev/null +++ b/Sources/JavaKitCollection/generated/Queue.swift @@ -0,0 +1,66 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaInterface("java.util.Queue", extends: JavaCollection.self) +public struct Queue { + @JavaMethod + public func remove() -> JavaObject? + + @JavaMethod + public func add(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func peek() -> JavaObject? + + @JavaMethod + public func element() -> JavaObject? + + @JavaMethod + public func poll() -> JavaObject? + + @JavaMethod + public func offer(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func remove(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func size() -> Int32 + + @JavaMethod + public func equals(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func hashCode() -> Int32 + + @JavaMethod + public func clear() + + @JavaMethod + public func isEmpty() -> Bool + + @JavaMethod + public func toArray(_ arg0: [JavaObject?]) -> [JavaObject?] + + @JavaMethod + public func toArray() -> [JavaObject?] + + @JavaMethod + public func iterator() -> JavaIterator? + + @JavaMethod + public func contains(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func addAll(_ arg0: JavaCollection?) -> Bool + + @JavaMethod + public func removeAll(_ arg0: JavaCollection?) -> Bool + + @JavaMethod + public func retainAll(_ arg0: JavaCollection?) -> Bool + + @JavaMethod + public func containsAll(_ arg0: JavaCollection?) -> Bool +} diff --git a/Sources/JavaKitCollection/generated/RandomAccess.swift b/Sources/JavaKitCollection/generated/RandomAccess.swift new file mode 100644 index 00000000..0084ceed --- /dev/null +++ b/Sources/JavaKitCollection/generated/RandomAccess.swift @@ -0,0 +1,8 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaInterface("java.util.RandomAccess") +public struct RandomAccess { + +} diff --git a/Sources/JavaKitCollection/generated/Stack.swift b/Sources/JavaKitCollection/generated/Stack.swift new file mode 100644 index 00000000..6d528886 --- /dev/null +++ b/Sources/JavaKitCollection/generated/Stack.swift @@ -0,0 +1,189 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaClass("java.util.Stack") +public struct Stack { + @JavaMethod + public init(environment: JNIEnvironment) + + @JavaMethod + public func empty() -> Bool + + @JavaMethod + public func peek() -> JavaObject? + + @JavaMethod + public func search(_ arg0: JavaObject?) -> Int32 + + @JavaMethod + public func push(_ arg0: JavaObject?) -> JavaObject? + + @JavaMethod + public func pop() -> JavaObject? + + @JavaMethod + public func addElement(_ arg0: JavaObject?) + + @JavaMethod + public func removeElementAt(_ arg0: Int32) + + @JavaMethod + public func removeElement(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func insertElementAt(_ arg0: JavaObject?, _ arg1: Int32) + + @JavaMethod + public func removeAllElements() + + @JavaMethod + public func firstElement() -> JavaObject? + + @JavaMethod + public func lastElement() -> JavaObject? + + @JavaMethod + public func setElementAt(_ arg0: JavaObject?, _ arg1: Int32) + + @JavaMethod + public func remove(_ arg0: Int32) -> JavaObject? + + @JavaMethod + public func remove(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func size() -> Int32 + + @JavaMethod + public func get(_ arg0: Int32) -> JavaObject? + + @JavaMethod + public func equals(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func toString() -> String + + @JavaMethod + public func hashCode() -> Int32 + + @JavaMethod + public func clone() -> JavaObject? + + @JavaMethod + public func indexOf(_ arg0: JavaObject?, _ arg1: Int32) -> Int32 + + @JavaMethod + public func indexOf(_ arg0: JavaObject?) -> Int32 + + @JavaMethod + public func clear() + + @JavaMethod + public func lastIndexOf(_ arg0: JavaObject?, _ arg1: Int32) -> Int32 + + @JavaMethod + public func lastIndexOf(_ arg0: JavaObject?) -> Int32 + + @JavaMethod + public func isEmpty() -> Bool + + @JavaMethod + public func add(_ arg0: Int32, _ arg1: JavaObject?) + + @JavaMethod + public func add(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func toArray(_ arg0: [JavaObject?]) -> [JavaObject?] + + @JavaMethod + public func toArray() -> [JavaObject?] + + @JavaMethod + public func iterator() -> JavaIterator? + + @JavaMethod + public func contains(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func elements() -> Enumeration? + + @JavaMethod + public func addAll(_ arg0: Int32, _ arg1: JavaCollection?) -> Bool + + @JavaMethod + public func addAll(_ arg0: JavaCollection?) -> Bool + + @JavaMethod + public func set(_ arg0: Int32, _ arg1: JavaObject?) -> JavaObject? + + @JavaMethod + public func capacity() -> Int32 + + @JavaMethod + public func ensureCapacity(_ arg0: Int32) + + @JavaMethod + public func trimToSize() + + @JavaMethod + public func elementAt(_ arg0: Int32) -> JavaObject? + + @JavaMethod + public func removeAll(_ arg0: JavaCollection?) -> Bool + + @JavaMethod + public func retainAll(_ arg0: JavaCollection?) -> Bool + + @JavaMethod + public func listIterator() -> ListIterator? + + @JavaMethod + public func listIterator(_ arg0: Int32) -> ListIterator? + + @JavaMethod + public func containsAll(_ arg0: JavaCollection?) -> Bool + + @JavaMethod + public func setSize(_ arg0: Int32) + + @JavaMethod + public func copyInto(_ arg0: [JavaObject?]) + + @JavaMethod + public func getClass() -> JavaClass? + + @JavaMethod + public func notify() + + @JavaMethod + public func notifyAll() + + @JavaMethod + public func wait(_ arg0: Int64) throws + + @JavaMethod + public func wait(_ arg0: Int64, _ arg1: Int32) throws + + @JavaMethod + public func wait() throws + + @JavaMethod + public func getFirst() -> JavaObject? + + @JavaMethod + public func getLast() -> JavaObject? + + @JavaMethod + public func addFirst(_ arg0: JavaObject?) + + @JavaMethod + public func addLast(_ arg0: JavaObject?) + + @JavaMethod + public func removeFirst() -> JavaObject? + + @JavaMethod + public func removeLast() -> JavaObject? +} diff --git a/Sources/JavaKitCollection/generated/TreeMap.swift b/Sources/JavaKitCollection/generated/TreeMap.swift new file mode 100644 index 00000000..f029c220 --- /dev/null +++ b/Sources/JavaKitCollection/generated/TreeMap.swift @@ -0,0 +1,108 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaClass("java.util.TreeMap") +public struct TreeMap { + @JavaMethod + public init(environment: JNIEnvironment) + + @JavaMethod + public func remove(_ arg0: JavaObject?) -> JavaObject? + + @JavaMethod + public func size() -> Int32 + + @JavaMethod + public func get(_ arg0: JavaObject?) -> JavaObject? + + @JavaMethod + public func put(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject? + + @JavaMethod + public func values() -> JavaCollection? + + @JavaMethod + public func clone() -> JavaObject? + + @JavaMethod + public func clear() + + @JavaMethod + public func replace(_ arg0: JavaObject?, _ arg1: JavaObject?, _ arg2: JavaObject?) -> Bool + + @JavaMethod + public func replace(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject? + + @JavaMethod + public func putIfAbsent(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject? + + @JavaMethod + public func containsKey(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func keySet() -> JavaSet? + + @JavaMethod + public func containsValue(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func firstKey() -> JavaObject? + + @JavaMethod + public func putFirst(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject? + + @JavaMethod + public func putLast(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject? + + @JavaMethod + public func lowerKey(_ arg0: JavaObject?) -> JavaObject? + + @JavaMethod + public func floorKey(_ arg0: JavaObject?) -> JavaObject? + + @JavaMethod + public func ceilingKey(_ arg0: JavaObject?) -> JavaObject? + + @JavaMethod + public func higherKey(_ arg0: JavaObject?) -> JavaObject? + + @JavaMethod + public func lastKey() -> JavaObject? + + @JavaMethod + public func equals(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func toString() -> String + + @JavaMethod + public func hashCode() -> Int32 + + @JavaMethod + public func isEmpty() -> Bool + + @JavaMethod + public func getClass() -> JavaClass? + + @JavaMethod + public func notify() + + @JavaMethod + public func notifyAll() + + @JavaMethod + public func wait(_ arg0: Int64) throws + + @JavaMethod + public func wait(_ arg0: Int64, _ arg1: Int32) throws + + @JavaMethod + public func wait() throws + + @JavaMethod + public func remove(_ arg0: JavaObject?, _ arg1: JavaObject?) -> Bool + + @JavaMethod + public func getOrDefault(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject? +} diff --git a/Sources/JavaKitCollection/generated/TreeSet.swift b/Sources/JavaKitCollection/generated/TreeSet.swift new file mode 100644 index 00000000..9633750e --- /dev/null +++ b/Sources/JavaKitCollection/generated/TreeSet.swift @@ -0,0 +1,126 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaClass("java.util.TreeSet") +public struct TreeSet { + @JavaMethod + public init(_ arg0: JavaCollection?, environment: JNIEnvironment) + + @JavaMethod + public init(environment: JNIEnvironment) + + @JavaMethod + public func remove(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func size() -> Int32 + + @JavaMethod + public func clone() -> JavaObject? + + @JavaMethod + public func floor(_ arg0: JavaObject?) -> JavaObject? + + @JavaMethod + public func clear() + + @JavaMethod + public func isEmpty() -> Bool + + @JavaMethod + public func add(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func iterator() -> JavaIterator? + + @JavaMethod + public func contains(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func last() -> JavaObject? + + @JavaMethod + public func addAll(_ arg0: JavaCollection?) -> Bool + + @JavaMethod + public func first() -> JavaObject? + + @JavaMethod + public func addFirst(_ arg0: JavaObject?) + + @JavaMethod + public func addLast(_ arg0: JavaObject?) + + @JavaMethod + public func lower(_ arg0: JavaObject?) -> JavaObject? + + @JavaMethod + public func pollFirst() -> JavaObject? + + @JavaMethod + public func pollLast() -> JavaObject? + + @JavaMethod + public func descendingIterator() -> JavaIterator? + + @JavaMethod + public func ceiling(_ arg0: JavaObject?) -> JavaObject? + + @JavaMethod + public func higher(_ arg0: JavaObject?) -> JavaObject? + + @JavaMethod + public func equals(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func hashCode() -> Int32 + + @JavaMethod + public func removeAll(_ arg0: JavaCollection?) -> Bool + + @JavaMethod + public func toString() -> String + + @JavaMethod + public func toArray(_ arg0: [JavaObject?]) -> [JavaObject?] + + @JavaMethod + public func toArray() -> [JavaObject?] + + @JavaMethod + public func retainAll(_ arg0: JavaCollection?) -> Bool + + @JavaMethod + public func containsAll(_ arg0: JavaCollection?) -> Bool + + @JavaMethod + public func getClass() -> JavaClass? + + @JavaMethod + public func notify() + + @JavaMethod + public func notifyAll() + + @JavaMethod + public func wait(_ arg0: Int64) throws + + @JavaMethod + public func wait(_ arg0: Int64, _ arg1: Int32) throws + + @JavaMethod + public func wait() throws + + @JavaMethod + public func removeFirst() -> JavaObject? + + @JavaMethod + public func removeLast() -> JavaObject? + + @JavaMethod + public func getFirst() -> JavaObject? + + @JavaMethod + public func getLast() -> JavaObject? +} diff --git a/Sources/JavaKitJar/generated/Attributes.swift b/Sources/JavaKitJar/generated/Attributes.swift index c0bb5f6f..69827d34 100644 --- a/Sources/JavaKitJar/generated/Attributes.swift +++ b/Sources/JavaKitJar/generated/Attributes.swift @@ -1,5 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import JavaKit +import JavaKitCollection import JavaRuntime @JavaClass("java.util.jar.Attributes") @@ -28,6 +29,9 @@ public struct Attributes { @JavaMethod public func equals(_ arg0: JavaObject?) -> Bool + @JavaMethod + public func values() -> JavaCollection? + @JavaMethod public func hashCode() -> Int32 @@ -46,6 +50,9 @@ public struct Attributes { @JavaMethod public func containsKey(_ arg0: JavaObject?) -> Bool + @JavaMethod + public func keySet() -> JavaSet? + @JavaMethod public func containsValue(_ arg0: JavaObject?) -> Bool diff --git a/Sources/JavaKitReflection/generated/Constructor.swift b/Sources/JavaKitReflection/generated/Constructor.swift index b7900cd7..f3d1bb55 100644 --- a/Sources/JavaKitReflection/generated/Constructor.swift +++ b/Sources/JavaKitReflection/generated/Constructor.swift @@ -1,5 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import JavaKit +import JavaKitCollection import JavaRuntime @JavaClass("java.lang.reflect.Constructor", extends: Executable.self) diff --git a/Sources/JavaKitReflection/generated/Executable.swift b/Sources/JavaKitReflection/generated/Executable.swift index 9084b84f..4c337cbe 100644 --- a/Sources/JavaKitReflection/generated/Executable.swift +++ b/Sources/JavaKitReflection/generated/Executable.swift @@ -1,5 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import JavaKit +import JavaKitCollection import JavaRuntime @JavaClass("java.lang.reflect.Executable", extends: AccessibleObject.self, implements: GenericDeclaration.self) diff --git a/Sources/JavaKitReflection/generated/Field.swift b/Sources/JavaKitReflection/generated/Field.swift index fec0cb9a..72ab10a9 100644 --- a/Sources/JavaKitReflection/generated/Field.swift +++ b/Sources/JavaKitReflection/generated/Field.swift @@ -1,5 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import JavaKit +import JavaKitCollection import JavaRuntime @JavaClass("java.lang.reflect.Field", extends: AccessibleObject.self) diff --git a/Sources/JavaKitReflection/generated/Method.swift b/Sources/JavaKitReflection/generated/Method.swift index f438a327..2c6e1a46 100644 --- a/Sources/JavaKitReflection/generated/Method.swift +++ b/Sources/JavaKitReflection/generated/Method.swift @@ -1,5 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import JavaKit +import JavaKitCollection import JavaRuntime @JavaClass("java.lang.reflect.Method", extends: Executable.self) diff --git a/Sources/JavaKitReflection/generated/Parameter.swift b/Sources/JavaKitReflection/generated/Parameter.swift index 9a928f46..36f68dd0 100644 --- a/Sources/JavaKitReflection/generated/Parameter.swift +++ b/Sources/JavaKitReflection/generated/Parameter.swift @@ -1,5 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import JavaKit +import JavaKitCollection import JavaRuntime @JavaClass("java.lang.reflect.Parameter") From 5ad8abebe511537b12cb5da0a5cd798c0323344f Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Thu, 17 Oct 2024 17:01:05 -0700 Subject: [PATCH 103/426] Use slashes rather than dots in explicit `FindClass` JNI calls --- Sources/JavaKit/BridgedValues/JavaValue+Array.swift | 2 +- Sources/JavaKit/BridgedValues/JavaValue+String.swift | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/JavaKit/BridgedValues/JavaValue+Array.swift b/Sources/JavaKit/BridgedValues/JavaValue+Array.swift index 26996578..3db30789 100644 --- a/Sources/JavaKit/BridgedValues/JavaValue+Array.swift +++ b/Sources/JavaKit/BridgedValues/JavaValue+Array.swift @@ -93,7 +93,7 @@ extension Array: JavaValue where Element: JavaValue { public static func jniNewArray(in environment: JNIEnvironment) -> JNINewArray { return { environment, size in // FIXME: We should have a bridged JavaArray that we can use here. - let arrayClass = environment.interface.FindClass(environment, "java.lang.Array") + let arrayClass = environment.interface.FindClass(environment, "java/lang/Array") return environment.interface.NewObjectArray(environment, size, arrayClass, nil) } } diff --git a/Sources/JavaKit/BridgedValues/JavaValue+String.swift b/Sources/JavaKit/BridgedValues/JavaValue+String.swift index 5c9ca117..e9c11e64 100644 --- a/Sources/JavaKit/BridgedValues/JavaValue+String.swift +++ b/Sources/JavaKit/BridgedValues/JavaValue+String.swift @@ -64,7 +64,7 @@ extension String: JavaValue { public static func jniNewArray(in environment: JNIEnvironment) -> JNINewArray { return { environment, size in // FIXME: Introduce a JavaString class that we can use for this. - let stringClass = environment.interface.FindClass(environment, "java.lang.String") + let stringClass = environment.interface.FindClass(environment, "java/lang/String") return environment.interface.NewObjectArray(environment, size, stringClass, nil) } } From 91646f3b8eb2a5c0d0bf1a3df2f014f64487aa54 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Thu, 17 Oct 2024 17:16:29 -0700 Subject: [PATCH 104/426] Java2Swift: Add a test importing part of ArrayList with generic List return --- Tests/Java2SwiftTests/Java2SwiftTests.swift | 23 ++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/Tests/Java2SwiftTests/Java2SwiftTests.swift b/Tests/Java2SwiftTests/Java2SwiftTests.swift index bac88d47..8a6aee8d 100644 --- a/Tests/Java2SwiftTests/Java2SwiftTests.swift +++ b/Tests/Java2SwiftTests/Java2SwiftTests.swift @@ -25,7 +25,7 @@ var jvm: JavaVirtualMachine { } class Java2SwiftTests: XCTestCase { - func testJavaLangObjectMapping() async throws { + func testJavaLangObjectMapping() throws { try assertTranslatedClass( JavaObject.self, swiftTypeName: "MyJavaObject", @@ -46,6 +46,27 @@ class Java2SwiftTests: XCTestCase { ] ) } + + func testGenericCollections() throws { + try assertTranslatedClass( + MyArrayList.self, + swiftTypeName: "JavaArrayList", + translatedClasses: [ + "java.lang.Object": ("JavaObject", nil, true), + "java.util.List": ("JavaList", nil, true), + ], + expectedChunks: [ + """ + @JavaMethod + public func subList(_ arg0: Int32, _ arg1: Int32) -> JavaList? + """ + ] + ) + } +} + +@JavaClass("java.util.ArrayList") +public struct MyArrayList { } /// Translate a Java class and assert that the translated output contains From 26acffb8e5df68606b6158edc891ad6778830a0f Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Thu, 17 Oct 2024 17:23:25 -0700 Subject: [PATCH 105/426] Stop emitting the Java Enumeration type into two places --- Sources/JavaKit/Java2Swift.config | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Sources/JavaKit/Java2Swift.config b/Sources/JavaKit/Java2Swift.config index b8c36594..7626a380 100644 --- a/Sources/JavaKit/Java2Swift.config +++ b/Sources/JavaKit/Java2Swift.config @@ -4,7 +4,6 @@ "java.lang.Exception" : "Exception", "java.lang.Object" : "JavaObject", "java.lang.RuntimeException" : "RuntimeException", - "java.lang.Throwable" : "Throwable", - "java.util.Enumeration" : "Enumeration" + "java.lang.Throwable" : "Throwable" } } From 9ef273fb53b9eed6f41759918ccf2accb994f109 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Thu, 17 Oct 2024 17:25:13 -0700 Subject: [PATCH 106/426] Import java.util.List since it's used a lot --- Sources/JavaKitCollection/Java2Swift.config | 2 +- .../generated/ArrayList.swift | 8 +- .../JavaKitCollection/generated/List.swift | 142 ++++++++++++++++++ .../JavaKitCollection/generated/Stack.swift | 6 + Tests/Java2SwiftTests/Java2SwiftTests.swift | 21 +++ 5 files changed, 177 insertions(+), 2 deletions(-) create mode 100644 Sources/JavaKitCollection/generated/List.swift diff --git a/Sources/JavaKitCollection/Java2Swift.config b/Sources/JavaKitCollection/Java2Swift.config index e134a2e3..a809cb8c 100644 --- a/Sources/JavaKitCollection/Java2Swift.config +++ b/Sources/JavaKitCollection/Java2Swift.config @@ -3,6 +3,7 @@ "java.util.Collection" : "JavaCollection", "java.util.Enumeration" : "Enumeration", "java.util.Iterator" : "JavaIterator", + "java.util.List" : "List", "java.util.ListIterator" : "ListIterator", "java.util.Queue" : "Queue", "java.util.RandomAccess" : "RandomAccess", @@ -13,7 +14,6 @@ "java.util.Dictionary" : "JavaDictionary", "java.util.HashMap" : "HashMap", "java.util.HashSet" : "HashSet", - "java.util.LinkedList" : "LinkedList", "java.util.PriorityQueue" : "PriorityQueue", "java.util.Stack" : "Stack", "java.util.TreeMap" : "TreeMap", diff --git a/Sources/JavaKitCollection/generated/ArrayList.swift b/Sources/JavaKitCollection/generated/ArrayList.swift index fd400ae5..765f4d9f 100644 --- a/Sources/JavaKitCollection/generated/ArrayList.swift +++ b/Sources/JavaKitCollection/generated/ArrayList.swift @@ -2,7 +2,7 @@ import JavaKit import JavaRuntime -@JavaClass("java.util.ArrayList", implements: RandomAccess.self) +@JavaClass("java.util.ArrayList", implements: List.self, RandomAccess.self) public struct ArrayList { @JavaMethod public init(_ arg0: JavaCollection?, environment: JNIEnvironment) @@ -52,6 +52,9 @@ public struct ArrayList { @JavaMethod public func add(_ arg0: Int32, _ arg1: JavaObject?) + @JavaMethod + public func subList(_ arg0: Int32, _ arg1: Int32) -> List? + @JavaMethod public func toArray() -> [JavaObject?] @@ -132,4 +135,7 @@ public struct ArrayList { @JavaMethod public func wait() throws + + @JavaMethod + public func reversed() -> List? } diff --git a/Sources/JavaKitCollection/generated/List.swift b/Sources/JavaKitCollection/generated/List.swift new file mode 100644 index 00000000..fb323301 --- /dev/null +++ b/Sources/JavaKitCollection/generated/List.swift @@ -0,0 +1,142 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaInterface("java.util.List") +public struct List { + @JavaMethod + public func remove(_ arg0: Int32) -> JavaObject? + + @JavaMethod + public func remove(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func size() -> Int32 + + @JavaMethod + public func get(_ arg0: Int32) -> JavaObject? + + @JavaMethod + public func equals(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func hashCode() -> Int32 + + @JavaMethod + public func indexOf(_ arg0: JavaObject?) -> Int32 + + @JavaMethod + public func clear() + + @JavaMethod + public func lastIndexOf(_ arg0: JavaObject?) -> Int32 + + @JavaMethod + public func isEmpty() -> Bool + + @JavaMethod + public func add(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func add(_ arg0: Int32, _ arg1: JavaObject?) + + @JavaMethod + public func subList(_ arg0: Int32, _ arg1: Int32) -> List? + + @JavaMethod + public func toArray() -> [JavaObject?] + + @JavaMethod + public func toArray(_ arg0: [JavaObject?]) -> [JavaObject?] + + @JavaMethod + public func iterator() -> JavaIterator? + + @JavaMethod + public func contains(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func addAll(_ arg0: Int32, _ arg1: JavaCollection?) -> Bool + + @JavaMethod + public func addAll(_ arg0: JavaCollection?) -> Bool + + @JavaMethod + public func set(_ arg0: Int32, _ arg1: JavaObject?) -> JavaObject? + + @JavaMethod + public func getFirst() -> JavaObject? + + @JavaMethod + public func getLast() -> JavaObject? + + @JavaMethod + public func addFirst(_ arg0: JavaObject?) + + @JavaMethod + public func addLast(_ arg0: JavaObject?) + + @JavaMethod + public func removeFirst() -> JavaObject? + + @JavaMethod + public func removeLast() -> JavaObject? + + @JavaMethod + public func removeAll(_ arg0: JavaCollection?) -> Bool + + @JavaMethod + public func retainAll(_ arg0: JavaCollection?) -> Bool + + @JavaMethod + public func listIterator() -> ListIterator? + + @JavaMethod + public func listIterator(_ arg0: Int32) -> ListIterator? + + @JavaMethod + public func reversed() -> List? + + @JavaMethod + public func containsAll(_ arg0: JavaCollection?) -> Bool +} +extension JavaClass { + @JavaStaticMethod + public func copyOf(_ arg0: JavaCollection?) -> List? where ObjectType == List + + @JavaStaticMethod + public func of(_ arg0: JavaObject?, _ arg1: JavaObject?, _ arg2: JavaObject?, _ arg3: JavaObject?, _ arg4: JavaObject?, _ arg5: JavaObject?, _ arg6: JavaObject?) -> List? where ObjectType == List + + @JavaStaticMethod + public func of(_ arg0: JavaObject?, _ arg1: JavaObject?) -> List? where ObjectType == List + + @JavaStaticMethod + public func of(_ arg0: JavaObject?) -> List? where ObjectType == List + + @JavaStaticMethod + public func of() -> List? where ObjectType == List + + @JavaStaticMethod + public func of(_ arg0: JavaObject?, _ arg1: JavaObject?, _ arg2: JavaObject?, _ arg3: JavaObject?, _ arg4: JavaObject?, _ arg5: JavaObject?, _ arg6: JavaObject?, _ arg7: JavaObject?, _ arg8: JavaObject?) -> List? where ObjectType == List + + @JavaStaticMethod + public func of(_ arg0: JavaObject?, _ arg1: JavaObject?, _ arg2: JavaObject?, _ arg3: JavaObject?) -> List? where ObjectType == List + + @JavaStaticMethod + public func of(_ arg0: JavaObject?, _ arg1: JavaObject?, _ arg2: JavaObject?, _ arg3: JavaObject?, _ arg4: JavaObject?) -> List? where ObjectType == List + + @JavaStaticMethod + public func of(_ arg0: JavaObject?, _ arg1: JavaObject?, _ arg2: JavaObject?) -> List? where ObjectType == List + + @JavaStaticMethod + public func of(_ arg0: JavaObject?, _ arg1: JavaObject?, _ arg2: JavaObject?, _ arg3: JavaObject?, _ arg4: JavaObject?, _ arg5: JavaObject?) -> List? where ObjectType == List + + @JavaStaticMethod + public func of(_ arg0: JavaObject?, _ arg1: JavaObject?, _ arg2: JavaObject?, _ arg3: JavaObject?, _ arg4: JavaObject?, _ arg5: JavaObject?, _ arg6: JavaObject?, _ arg7: JavaObject?) -> List? where ObjectType == List + + @JavaStaticMethod + public func of(_ arg0: [JavaObject?]) -> List? where ObjectType == List + + @JavaStaticMethod + public func of(_ arg0: JavaObject?, _ arg1: JavaObject?, _ arg2: JavaObject?, _ arg3: JavaObject?, _ arg4: JavaObject?, _ arg5: JavaObject?, _ arg6: JavaObject?, _ arg7: JavaObject?, _ arg8: JavaObject?, _ arg9: JavaObject?) -> List? where ObjectType == List +} diff --git a/Sources/JavaKitCollection/generated/Stack.swift b/Sources/JavaKitCollection/generated/Stack.swift index 6d528886..65d92872 100644 --- a/Sources/JavaKitCollection/generated/Stack.swift +++ b/Sources/JavaKitCollection/generated/Stack.swift @@ -94,6 +94,9 @@ public struct Stack { @JavaMethod public func add(_ arg0: JavaObject?) -> Bool + @JavaMethod + public func subList(_ arg0: Int32, _ arg1: Int32) -> List? + @JavaMethod public func toArray(_ arg0: [JavaObject?]) -> [JavaObject?] @@ -186,4 +189,7 @@ public struct Stack { @JavaMethod public func removeLast() -> JavaObject? + + @JavaMethod + public func reversed() -> List? } diff --git a/Tests/Java2SwiftTests/Java2SwiftTests.swift b/Tests/Java2SwiftTests/Java2SwiftTests.swift index 8a6aee8d..b3418ff2 100644 --- a/Tests/Java2SwiftTests/Java2SwiftTests.swift +++ b/Tests/Java2SwiftTests/Java2SwiftTests.swift @@ -63,12 +63,33 @@ class Java2SwiftTests: XCTestCase { ] ) } + + func testLinkedList() throws { + try assertTranslatedClass( + MyLinkedList.self, + swiftTypeName: "JavaLinkedList", + translatedClasses: [ + "java.lang.Object": ("JavaObject", nil, true), + "java.util.List": ("JavaList", nil, true), + ], + expectedChunks: [ + """ + @JavaMethod + public func subList(_ arg0: Int32, _ arg1: Int32) -> JavaList? + """ + ] + ) + } } @JavaClass("java.util.ArrayList") public struct MyArrayList { } +@JavaClass("java.util.LinkedList") +public struct MyLinkedList { +} + /// Translate a Java class and assert that the translated output contains /// each of the expected "chunks" of text. func assertTranslatedClass( From f9c84cb2822306d38ea47a4492059ae59c9859b0 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Fri, 18 Oct 2024 10:10:52 +0900 Subject: [PATCH 107/426] Use BuildUtils.javaLibraryPaths in SwiftKit build. (#91) --- Samples/SwiftKitSampleApp/build.gradle | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Samples/SwiftKitSampleApp/build.gradle b/Samples/SwiftKitSampleApp/build.gradle index 1f2343b2..e1b3d78d 100644 --- a/Samples/SwiftKitSampleApp/build.gradle +++ b/Samples/SwiftKitSampleApp/build.gradle @@ -12,6 +12,8 @@ // //===----------------------------------------------------------------------===// +import org.swift.swiftkit.gradle.BuildUtils + plugins { id("build-logic.java-application-conventions") } @@ -82,10 +84,7 @@ application { "--enable-native-access=ALL-UNNAMED", // Include the library paths where our dylibs are that we want to load and call - "-Djava.library.path=" + [ - "$rootDir/.build/arm64-apple-macosx/debug/", - "/usr/lib/swift/" - ].join(":"), + "-Djava.library.path=" + BuildUtils.javaLibraryPaths().join(":"), // Enable tracing downcalls (to Swift) "-Djextract.trace.downcalls=true" From f7129441a531cb7353b480043114bbe1b1896fce Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Thu, 17 Oct 2024 21:07:47 -0700 Subject: [PATCH 108/426] Package: add missing dependency --- Package.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Package.swift b/Package.swift index a6ca8cf8..0f492710 100644 --- a/Package.swift +++ b/Package.swift @@ -196,7 +196,7 @@ let package = Package( ), .target( name: "JavaKitReflection", - dependencies: ["JavaKit"], + dependencies: ["JavaKit", "JavaKitCollection"], exclude: ["Java2Swift.config"], swiftSettings: [ .swiftLanguageMode(.v5), From b7966238be68aea93317e3ecc2a1bf8ba892b056 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Thu, 17 Oct 2024 21:08:38 -0700 Subject: [PATCH 109/426] Update license ignore file --- .licenseignore | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/.licenseignore b/.licenseignore index cb3be0cf..5d0e3172 100644 --- a/.licenseignore +++ b/.licenseignore @@ -33,15 +33,7 @@ Makefile **/*.html **/CMakeLists.txt **/*.jar +**/generated/*.swift gradle/wrapper/gradle-wrapper.properties gradlew gradlew.bat -**/*.swift2java -Sources/JavaKit/generated/* -Sources/JavaKitJar/generated/* -Sources/JavaKitNetwork/generated/* -Sources/JavaKitReflection/generated/* -Sources/_Subprocess/* -Sources/_Subprocess/**/* -Sources/_SubprocessCShims/* -Sources/_SubprocessCShims/**/* From cce97fd035c830699b86905ed30b738dd33e99d1 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Thu, 17 Oct 2024 21:27:18 -0700 Subject: [PATCH 110/426] Make JavaIterator a Swift Iterator and Java list a Swift Sequence We should generalize this to all of the various Java collection types. --- .../JavaIterator+Iterator.swift | 27 +++++++++++++++++++ Sources/JavaKitCollection/List+Sequence.swift | 23 ++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 Sources/JavaKitCollection/JavaIterator+Iterator.swift create mode 100644 Sources/JavaKitCollection/List+Sequence.swift diff --git a/Sources/JavaKitCollection/JavaIterator+Iterator.swift b/Sources/JavaKitCollection/JavaIterator+Iterator.swift new file mode 100644 index 00000000..add2a48b --- /dev/null +++ b/Sources/JavaKitCollection/JavaIterator+Iterator.swift @@ -0,0 +1,27 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// +import JavaKit + +extension JavaIterator: IteratorProtocol { + public typealias Element = E + + public func next() -> E? { + if hasNext() { + let nextResult: JavaObject? = next() + return nextResult.map { $0.as(E.self)! } + } + + return nil + } +} diff --git a/Sources/JavaKitCollection/List+Sequence.swift b/Sources/JavaKitCollection/List+Sequence.swift new file mode 100644 index 00000000..b3629569 --- /dev/null +++ b/Sources/JavaKitCollection/List+Sequence.swift @@ -0,0 +1,23 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +extension List: Sequence { + public typealias Element = E + public typealias Iterator = JavaIterator + + public func makeIterator() -> Iterator { + return self.iterator()!.as(JavaIterator.self)! + } +} + From 98233019cb169f44f6ee3dab8a6901bc5b84612b Mon Sep 17 00:00:00 2001 From: AbdAlRahman Gad <89566409+AbdAlRahmanGad@users.noreply.github.com> Date: Fri, 18 Oct 2024 10:45:28 +0300 Subject: [PATCH 111/426] java2swift: add non-optional-returning `as` function to `JavaClassMacro` (#74) Co-authored-by: Konrad `ktoso` Malawski --- Sources/JavaKit/Macros.swift | 6 ++++-- Sources/JavaKitMacros/JavaClassMacro.swift | 8 ++++++++ Tests/JavaKitMacroTests/JavaClassMacroTests.swift | 5 +++++ 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/Sources/JavaKit/Macros.swift b/Sources/JavaKit/Macros.swift index 51d62739..347a3ebf 100644 --- a/Sources/JavaKit/Macros.swift +++ b/Sources/JavaKit/Macros.swift @@ -37,7 +37,8 @@ named(javaThis), named(javaEnvironment), named(init(javaHolder:)), - named(JavaSuperclass) + named(JavaSuperclass), + named(`as`) ) @attached(extension, conformances: AnyJavaObject) @attached(peer) @@ -73,7 +74,8 @@ public macro JavaClass( named(javaThis), named(javaEnvironment), named(init(javaHolder:)), - named(JavaSuperclass) + named(JavaSuperclass), + named(`as`) ) @attached(extension, conformances: AnyJavaObject) public macro JavaInterface(_ fullClassName: String, extends: (any AnyJavaObject.Type)?...) = diff --git a/Sources/JavaKitMacros/JavaClassMacro.swift b/Sources/JavaKitMacros/JavaClassMacro.swift index 23d6d4fc..3cee441d 100644 --- a/Sources/JavaKitMacros/JavaClassMacro.swift +++ b/Sources/JavaKitMacros/JavaClassMacro.swift @@ -87,6 +87,13 @@ extension JavaClassMacro: MemberMacro { } """ + let nonOptionalAs: DeclSyntax = """ + /// Casting to ``\(raw: superclass)`` will never be nil because ``\(raw: className.split(separator: ".").last!)`` extends it. + public func `as`(_: \(raw: superclass).Type) -> \(raw: superclass) { + return \(raw: superclass)(javaHolder: javaHolder) + } + """ + return [ fullJavaClassNameMember, superclassTypealias, @@ -94,6 +101,7 @@ extension JavaClassMacro: MemberMacro { javaThisMember, javaEnvironmentMember, initMember, + nonOptionalAs, ] } } diff --git a/Tests/JavaKitMacroTests/JavaClassMacroTests.swift b/Tests/JavaKitMacroTests/JavaClassMacroTests.swift index 72ff432d..cc0ad31b 100644 --- a/Tests/JavaKitMacroTests/JavaClassMacroTests.swift +++ b/Tests/JavaKitMacroTests/JavaClassMacroTests.swift @@ -78,6 +78,11 @@ class JavaKitMacroTests: XCTestCase { public init(javaHolder: JavaObjectHolder) { self.javaHolder = javaHolder } + + /// Casting to ``JavaObject`` will never be nil because ``HelloWorld`` extends it. + public func `as`(_: JavaObject.Type) -> JavaObject { + return JavaObject(javaHolder: javaHolder) + } } """, macros: Self.javaKitMacros From a95410726e78d7dfd119644ac5b82f9e00d7b7da Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Fri, 18 Oct 2024 10:08:04 -0700 Subject: [PATCH 112/426] Java2Swift: Rename `-jar-file` option to `-jar` --- Sources/Java2Swift/JavaToSwift.swift | 8 ++++---- USER_GUIDE.md | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Sources/Java2Swift/JavaToSwift.swift b/Sources/Java2Swift/JavaToSwift.swift index 1fd25ca9..1b67cc9f 100644 --- a/Sources/Java2Swift/JavaToSwift.swift +++ b/Sources/Java2Swift/JavaToSwift.swift @@ -41,7 +41,7 @@ struct JavaToSwift: ParsableCommand { help: "Specifies that the input is a Jar file whose public classes will be loaded. The output of Java2Swift will be a configuration file (Java2Swift.config) that can be used as input to a subsequent Java2Swift invocation to generate wrappers for those public classes." ) - var jarFile: Bool = false + var jar: Bool = false @Option( name: [.customLong("cp"), .customLong("classpath")], @@ -54,7 +54,7 @@ struct JavaToSwift: ParsableCommand { @Argument( help: - "The input file, which is either a Java2Swift configuration file or (if '-jar-file' was specified) a Jar file." + "The input file, which is either a Java2Swift configuration file or (if '-jar' was specified) a Jar file." ) var input: String @@ -72,7 +72,7 @@ struct JavaToSwift: ParsableCommand { mutating func run() throws { // Determine the mode in which we'll execute. let generationMode: GenerationMode - if jarFile { + if jar { generationMode = .configuration(jarFile: input) } else { let config = try JavaTranslator.readConfiguration(from: URL(fileURLWithPath: input)) @@ -100,7 +100,7 @@ struct JavaToSwift: ParsableCommand { var classPathPieces: [String] = classpath switch generationMode { case .configuration(jarFile: let jarFile): - // * Jar file (in `-jar-file` mode) + // * Jar file (in `-jar` mode) classPathPieces.append(jarFile) case .classWrappers(let config): // * Class path specified in the configuration file (if any) diff --git a/USER_GUIDE.md b/USER_GUIDE.md index 92de4a23..b35e0ff7 100644 --- a/USER_GUIDE.md +++ b/USER_GUIDE.md @@ -297,11 +297,11 @@ swift run Java2Swift to produce help output like the following: ``` -USAGE: Java2Swift --module-name [--depends-on ...] [--jar-file] [--cp ...] [--output-directory ] +USAGE: Java2Swift --module-name [--depends-on ...] [--jar] [--cp ...] [--output-directory ] ARGUMENTS: The input file, which is either a Java2Swift - configuration file or (if '-jar-file' was specified) + configuration file or (if '-jar' was specified) a Jar file. OPTIONS: @@ -315,7 +315,7 @@ OPTIONS: There should be one of these options for each Swift module that this module depends on (transitively) that contains wrapped Java sources. - --jar-file Specifies that the input is a Jar file whose public + --jar Specifies that the input is a Jar file whose public classes will be loaded. The output of Java2Swift will be a configuration file (Java2Swift.config) that can be used as input to a subsequent Java2Swift @@ -354,7 +354,7 @@ warning: Unable to translate 'java.util.jar.JarInputStream' method 'transferTo': The result of such warnings is that certain information won't be statically available in Swift, e.g., the superclass won't be known (so we will assume it is `JavaObject`), or the specified constructors or methods won't be translated. If you don't need these APIs, the warnings can be safely ignored. The APIs can still be called dynamically via JNI. -The `--jar-file` option changes the operation of `Java2Swift`. Instead of wrapping Java classes in Swift, it scans the given input Jar file to find all public classes and outputs a configuration file `Java2Swift.config` mapping all of the Java classes in the Jar file to Swift types. The `--jar-file` mode is expected to be used to help import a Java library into Swift wholesale, after which Java2Swift should invoked again given the generated configuration file. +The `--jar` option changes the operation of `Java2Swift`. Instead of wrapping Java classes in Swift, it scans the given input Jar file to find all public classes and outputs a configuration file `Java2Swift.config` mapping all of the Java classes in the Jar file to Swift types. The `--jar` mode is expected to be used to help import a Java library into Swift wholesale, after which Java2Swift should invoked again given the generated configuration file. ### Under construction: Create a Java class to wrap the Swift library From 8cc89d988d90efce1de5eaea179eb4c3bc4ca6d8 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Fri, 18 Oct 2024 11:38:13 -0700 Subject: [PATCH 113/426] Java2Swift: Provide defaults for the output directory and create it before writing files --- Sources/Java2Swift/JavaToSwift.swift | 63 +++++++++++++++++++++++----- 1 file changed, 53 insertions(+), 10 deletions(-) diff --git a/Sources/Java2Swift/JavaToSwift.swift b/Sources/Java2Swift/JavaToSwift.swift index 1b67cc9f..a4c64277 100644 --- a/Sources/Java2Swift/JavaToSwift.swift +++ b/Sources/Java2Swift/JavaToSwift.swift @@ -50,7 +50,7 @@ struct JavaToSwift: ParsableCommand { var classpath: [String] = [] @Option(name: .shortAndLong, help: "The directory in which to output the generated Swift files or the Java2Swift configuration file.") - var outputDirectory: String = "." + var outputDirectory: String? = nil @Argument( help: @@ -58,6 +58,41 @@ struct JavaToSwift: ParsableCommand { ) var input: String + /// Whether we have ensured that the output directory exists. + var createdOutputDirectory: Bool = false + + /// The output directory in which to place the generated files, which will + /// be the specified directory (--output-directory or -o option) if given, + /// or a default directory derived from the other command-line arguments. + /// + /// Returns `nil` only when we should emit the files to standard output. + var actualOutputDirectory: Foundation.URL? { + if let outputDirectory { + if outputDirectory == "-" { + return nil + } + + return URL(fileURLWithPath: outputDirectory) + } + + // Put the result into Sources/\(moduleName). + let baseDir = URL(fileURLWithPath: ".") + .appendingPathComponent("Sources", isDirectory: true) + .appendingPathComponent(moduleName, isDirectory: true) + + // For generated Swift sources, put them into a "generated" subdirectory. + // The configuration file goes at the top level. + let outputDir: Foundation.URL + if jar { + outputDir = baseDir + } else { + outputDir = baseDir + .appendingPathComponent("generated", isDirectory: true) + } + + return outputDir + } + /// Describes what kind of generation action is being performed by /// Java2Swift. enum GenerationMode { @@ -209,23 +244,31 @@ struct JavaToSwift: ParsableCommand { } } - func writeContents(_ contents: String, to filename: String, description: String) throws { - if outputDirectory == "-" { + mutating func writeContents(_ contents: String, to filename: String, description: String) throws { + guard let outputDir = actualOutputDirectory else { print("// \(filename) - \(description)") print(contents) return } - print("Writing \(description) to '\(filename)'...", terminator: "") - try contents.write( - to: Foundation.URL(fileURLWithPath: outputDirectory).appendingPathComponent(filename), - atomically: true, - encoding: .utf8 - ) + // If we haven't tried to create the output directory yet, do so now before + // we write any files to it. + if !createdOutputDirectory { + try FileManager.default.createDirectory( + at: outputDir, + withIntermediateDirectories: true + ) + createdOutputDirectory = true + } + + // Write the file: + let file = outputDir.appendingPathComponent(filename) + print("Writing \(description) to '\(file.path)'...", terminator: "") + try contents.write(to: file, atomically: true, encoding: .utf8) print(" done.") } - func emitConfiguration( + mutating func emitConfiguration( forJarFile jarFileName: String, classPath: String, environment: JNIEnvironment From fc423ab50f1953273d182913a65171f4682526fe Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Fri, 18 Oct 2024 10:06:48 -0700 Subject: [PATCH 114/426] Add JavaSieve example that shows using a Java library (as a Jar) from Swift --- Samples/JavaSieve/.gitignore | 8 ++ Samples/JavaSieve/Package.swift | 83 +++++++++++ Samples/JavaSieve/README.md | 32 +++++ .../Sources/JavaMath/Java2Swift.config | 9 ++ .../JavaSieve/Sources/JavaMath/dummy.swift | 13 ++ .../Sources/JavaSieve/Java2Swift.config | 30 ++++ .../JavaSieve/Sources/JavaSieve/main.swift | 26 ++++ USER_GUIDE.md | 131 +++++++++++++++++- 8 files changed, 328 insertions(+), 4 deletions(-) create mode 100644 Samples/JavaSieve/.gitignore create mode 100644 Samples/JavaSieve/Package.swift create mode 100644 Samples/JavaSieve/README.md create mode 100644 Samples/JavaSieve/Sources/JavaMath/Java2Swift.config create mode 100644 Samples/JavaSieve/Sources/JavaMath/dummy.swift create mode 100644 Samples/JavaSieve/Sources/JavaSieve/Java2Swift.config create mode 100644 Samples/JavaSieve/Sources/JavaSieve/main.swift diff --git a/Samples/JavaSieve/.gitignore b/Samples/JavaSieve/.gitignore new file mode 100644 index 00000000..0023a534 --- /dev/null +++ b/Samples/JavaSieve/.gitignore @@ -0,0 +1,8 @@ +.DS_Store +/.build +/Packages +xcuserdata/ +DerivedData/ +.swiftpm/configuration/registries.json +.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata +.netrc diff --git a/Samples/JavaSieve/Package.swift b/Samples/JavaSieve/Package.swift new file mode 100644 index 00000000..2420dcf1 --- /dev/null +++ b/Samples/JavaSieve/Package.swift @@ -0,0 +1,83 @@ +// swift-tools-version: 6.0 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +import class Foundation.FileManager +import class Foundation.ProcessInfo + +// Note: the JAVA_HOME environment variable must be set to point to where +// Java is installed, e.g., +// Library/Java/JavaVirtualMachines/openjdk-21.jdk/Contents/Home. +func findJavaHome() -> String { + if let home = ProcessInfo.processInfo.environment["JAVA_HOME"] { + return home + } + + // This is a workaround for envs (some IDEs) which have trouble with + // picking up env variables during the build process + let path = "\(FileManager.default.homeDirectoryForCurrentUser.path()).java_home" + if let home = try? String(contentsOfFile: path, encoding: .utf8) { + if let lastChar = home.last, lastChar.isNewline { + return String(home.dropLast()) + } + + return home + } + + fatalError("Please set the JAVA_HOME environment variable to point to where Java is installed.") +} +let javaHome = findJavaHome() + +let javaIncludePath = "\(javaHome)/include" +#if os(Linux) + let javaPlatformIncludePath = "\(javaIncludePath)/linux" +#elseif os(macOS) + let javaPlatformIncludePath = "\(javaIncludePath)/darwin" +#else + // TODO: Handle windows as well + #error("Currently only macOS and Linux platforms are supported, this may change in the future.") +#endif + +let package = Package( + name: "JavaSieve", + platforms: [ + .macOS(.v10_15), + ], + dependencies: [ + .package(name: "swift-java", path: "../../"), + ], + targets: [ + .target( + name: "JavaMath", + dependencies: [ + .product(name: "JavaKit", package: "swift-java"), + .product(name: "JavaKitJar", package: "swift-java"), + ], + swiftSettings: [ + .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) + ], + plugins: [ + .plugin(name: "Java2SwiftPlugin", package: "swift-java"), + ] + ), + + // Targets are the basic building blocks of a package, defining a module or a test suite. + // Targets can depend on other targets in this package and products from dependencies. + .executableTarget( + name: "JavaSieve", + dependencies: [ + "JavaMath", + .product(name: "JavaKit", package: "swift-java"), + .product(name: "JavaKitCollection", package: "swift-java"), + .product(name: "JavaKitVM", package: "swift-java"), + ], + swiftSettings: [ + .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) + ], + plugins: [ + .plugin(name: "Java2SwiftPlugin", package: "swift-java"), + ] + ), + ] +) diff --git a/Samples/JavaSieve/README.md b/Samples/JavaSieve/README.md new file mode 100644 index 00000000..b8dc3c9a --- /dev/null +++ b/Samples/JavaSieve/README.md @@ -0,0 +1,32 @@ +# JavaKit Example: Using a Java library from Swift + +This package contains an example program that demonstrates importing a Java library distributed as a Jar file into Swift and using some APIs from that library. It demonstrates how to: + +* Use the Java2Swift tool to discover the classes in a Jar file and make them available in Swift +* Layer Swift wrappers for Java classes as separate Swift modules using Java2Swift +* Access static methods of Java classes from Swift + +This example wraps an [open-source Java library](https://github.com/gazman-sdk/quadratic-sieve-Java) implementing the [Sieve of Eratosthenes](https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes) algorithm for finding prime numbers, among other algorithms. To get started, clone that repository and build a Jar file containing the library: + +``` +git clone https://github.com/gazman-sdk/quadratic-sieve-Java +cd quadratic-sieve-Java +sh ./gradlew jar +``` + +Then, copy the resulting Jar file (`./build/libs/QuadraticSieve-1.0.jar`) into the `Samples/JavaSieve` directory. + +Now we're ready to build and run the Swift program from `Samples/JavaSieve`: + +``` +swift run JavaSieve +``` + +The core of the example code is in `Sources/JavaSieve/main.swift`, using the static Java method `SieveOfEratosthenes.findPrimes`: + +```swift +let sieveClass = try JavaClass(in: jvm.environment()) +for prime in sieveClass.findPrimes(100)! { + print("Found prime: \(prime.intValue())") +} +``` diff --git a/Samples/JavaSieve/Sources/JavaMath/Java2Swift.config b/Samples/JavaSieve/Sources/JavaMath/Java2Swift.config new file mode 100644 index 00000000..28e56a35 --- /dev/null +++ b/Samples/JavaSieve/Sources/JavaMath/Java2Swift.config @@ -0,0 +1,9 @@ +{ + "classes" : { + "java.math.BigDecimal" : "BigDecimal", + "java.math.BigInteger" : "BigInteger", + "java.math.MathContext" : "MathContext", + "java.math.RoundingMode" : "RoundingMode", + "java.lang.Integer" : "JavaInteger", + } +} diff --git a/Samples/JavaSieve/Sources/JavaMath/dummy.swift b/Samples/JavaSieve/Sources/JavaMath/dummy.swift new file mode 100644 index 00000000..76f848f9 --- /dev/null +++ b/Samples/JavaSieve/Sources/JavaMath/dummy.swift @@ -0,0 +1,13 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// diff --git a/Samples/JavaSieve/Sources/JavaSieve/Java2Swift.config b/Samples/JavaSieve/Sources/JavaSieve/Java2Swift.config new file mode 100644 index 00000000..aa88865f --- /dev/null +++ b/Samples/JavaSieve/Sources/JavaSieve/Java2Swift.config @@ -0,0 +1,30 @@ +{ + "classPath" : "QuadraticSieve-1.0.jar", + "classes" : { + "com.gazman.quadratic_sieve.QuadraticSieve" : "QuadraticSieve", + "com.gazman.quadratic_sieve.core.BaseFact" : "BaseFact", + "com.gazman.quadratic_sieve.core.matrix.GaussianEliminationMatrix" : "GaussianEliminationMatrix", + "com.gazman.quadratic_sieve.core.matrix.Matrix" : "Matrix", + "com.gazman.quadratic_sieve.core.poly.PolyMiner" : "PolyMiner", + "com.gazman.quadratic_sieve.core.poly.WheelPool" : "WheelPool", + "com.gazman.quadratic_sieve.core.siever.BSmoothData" : "BSmoothData", + "com.gazman.quadratic_sieve.core.siever.BSmoothDataPool" : "BSmoothDataPool", + "com.gazman.quadratic_sieve.core.siever.Siever" : "Siever", + "com.gazman.quadratic_sieve.core.siever.VectorExtractor" : "VectorExtractor", + "com.gazman.quadratic_sieve.data.BSmooth" : "BSmooth", + "com.gazman.quadratic_sieve.data.DataQueue" : "DataQueue", + "com.gazman.quadratic_sieve.data.MagicNumbers" : "MagicNumbers", + "com.gazman.quadratic_sieve.data.PolynomialData" : "PolynomialData", + "com.gazman.quadratic_sieve.data.PrimeBase" : "PrimeBase", + "com.gazman.quadratic_sieve.data.VectorData" : "VectorData", + "com.gazman.quadratic_sieve.data.VectorWorkData" : "VectorWorkData", + "com.gazman.quadratic_sieve.debug.Analytics" : "Analytics", + "com.gazman.quadratic_sieve.debug.AssertUtils" : "AssertUtils", + "com.gazman.quadratic_sieve.debug.Logger" : "Logger", + "com.gazman.quadratic_sieve.fact.TrivialDivision" : "TrivialDivision", + "com.gazman.quadratic_sieve.primes.BigPrimes" : "BigPrimes", + "com.gazman.quadratic_sieve.primes.SieveOfEratosthenes" : "SieveOfEratosthenes", + "com.gazman.quadratic_sieve.utils.MathUtils" : "MathUtils", + "com.gazman.quadratic_sieve.wheel.Wheel" : "Wheel" + } +} diff --git a/Samples/JavaSieve/Sources/JavaSieve/main.swift b/Samples/JavaSieve/Sources/JavaSieve/main.swift new file mode 100644 index 00000000..f2f24a53 --- /dev/null +++ b/Samples/JavaSieve/Sources/JavaSieve/main.swift @@ -0,0 +1,26 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import JavaKit +import JavaKitVM + +let jvm = try JavaVirtualMachine.shared(classPath: ["QuadraticSieve-1.0.jar"]) +do { + let sieveClass = try JavaClass(in: jvm.environment()) + for prime in sieveClass.findPrimes(100)! { + print("Found prime: \(prime.intValue())") + } +} catch { + print("Failure: \(error)") +} diff --git a/USER_GUIDE.md b/USER_GUIDE.md index b35e0ff7..b156f3e6 100644 --- a/USER_GUIDE.md +++ b/USER_GUIDE.md @@ -11,7 +11,7 @@ Before using this package, set the `JAVA_HOME` environment variable to point at Existing Java libraries can be wrapped for use in Swift with the `Java2Swift` tool. In a Swift program, the most direct way to access a Java API is to use the SwiftPM plugin to provide Swift wrappers for the Java classes. To do so, add a configuration file `Java2Swift.config` into the source directory for the Swift target. This is a JSON file that specifies Java classes and the Swift type name that should be generated to wrap them. For example, the following file maps `java.math.BigInteger` to a Swift type named `BigInteger`: -``` +```json { "classes" : { "java.math.BigInteger" : "BigInteger" @@ -91,6 +91,132 @@ if bigInt.isProbablePrime(10) { Swift ensures that the Java garbage collector will keep the object alive until `bigInt` (and any copies of it) are been destroyed. +### Importing a Jar file into Swift + +Java libraries are often distributed as Jar files. The `Java2Swift` tool can inspect a Jar file to create a `Java2Swift.config` file that will wrap all of the public classes for use in Swift. Following the example in `swift-java/Samples/JavaSieve`, we will wrap a small [Java library for computing prime numbers](https://github.com/gazman-sdk/quadratic-sieve-Java) for use in Swift. Assuming we have a Jar file `QuadraticSieve-1.0.jar` in the package directory, run the following command: + +```swift +swift run Java2Swift --module-name JavaSieve --jar QuadraticSieve-1.0.jar +``` + +The resulting configuration file will look something like this: + +```json +{ + "classPath" : "QuadraticSieve-1.0.jar", + "classes" : { + "com.gazman.quadratic_sieve.QuadraticSieve" : "QuadraticSieve", + "com.gazman.quadratic_sieve.core.BaseFact" : "BaseFact", + "com.gazman.quadratic_sieve.core.matrix.GaussianEliminationMatrix" : "GaussianEliminationMatrix", + "com.gazman.quadratic_sieve.core.matrix.Matrix" : "Matrix", + "com.gazman.quadratic_sieve.core.poly.PolyMiner" : "PolyMiner", + "com.gazman.quadratic_sieve.core.poly.WheelPool" : "WheelPool", + "com.gazman.quadratic_sieve.core.siever.BSmoothData" : "BSmoothData", + "com.gazman.quadratic_sieve.core.siever.BSmoothDataPool" : "BSmoothDataPool", + "com.gazman.quadratic_sieve.core.siever.Siever" : "Siever", + "com.gazman.quadratic_sieve.core.siever.VectorExtractor" : "VectorExtractor", + "com.gazman.quadratic_sieve.data.BSmooth" : "BSmooth", + "com.gazman.quadratic_sieve.data.DataQueue" : "DataQueue", + "com.gazman.quadratic_sieve.data.MagicNumbers" : "MagicNumbers", + "com.gazman.quadratic_sieve.data.PolynomialData" : "PolynomialData", + "com.gazman.quadratic_sieve.data.PrimeBase" : "PrimeBase", + "com.gazman.quadratic_sieve.data.VectorData" : "VectorData", + "com.gazman.quadratic_sieve.data.VectorWorkData" : "VectorWorkData", + "com.gazman.quadratic_sieve.debug.Analytics" : "Analytics", + "com.gazman.quadratic_sieve.debug.AssertUtils" : "AssertUtils", + "com.gazman.quadratic_sieve.debug.Logger" : "Logger", + "com.gazman.quadratic_sieve.fact.TrivialDivision" : "TrivialDivision", + "com.gazman.quadratic_sieve.primes.BigPrimes" : "BigPrimes", + "com.gazman.quadratic_sieve.primes.SieveOfEratosthenes" : "SieveOfEratosthenes", + "com.gazman.quadratic_sieve.utils.MathUtils" : "MathUtils", + "com.gazman.quadratic_sieve.wheel.Wheel" : "Wheel" + } +} +``` + +As with the previous `JavaProbablyPrime` sample, the `JavaSieve` target in `Package.swift` should depend on the `swift-java` package modules (`JavaKit`, `JavaKitVM`) and apply the `Java2Swift` plugin. This makes all of the Java classes found in the Jar file available to Swift within the `JavaSieve` target. + +If you inspect the build output, there are a number of warnings that look like this: + +```swift +warning: Unable to translate 'com.gazman.quadratic_sieve.QuadraticSieve' method 'generateN': Java class 'java.math.BigInteger' has not been translated into Swift +``` + +These warnings mean that some of the APIs in the Java library aren't available in Swift because their prerequisite types are missing. To address these warnings and get access to these APIs from Swift, we can wrap those Java classes. Expanding on the prior `JavaProbablyPrime` example, we define a new SwiftPM target `JavaMath` for the various types in the `java.math` package: + +```swift + .target( + name: "JavaMath", + dependencies: [ + .product(name: "JavaKit", package: "swift-java"), + ], + plugins: [ + .plugin(name: "Java2SwiftPlugin", package: "swift-java"), + ] + ), +``` + +Then define a a Java2Swift configuration file in `Sources/JavaMath/Java2Swift.config` to bring in the types we need: + +```json +{ + "classes" : { + "java.math.BigDecimal" : "BigDecimal", + "java.math.BigInteger" : "BigInteger", + "java.math.MathContext" : "MathContext", + "java.math.RoundingMode" : "RoundingMode", + "java.lang.Integer" : "JavaInteger", + } +} +``` + +Finally, make the `JavaSieve` target depend on `JavaMath` and rebuild: the warnings related to `java.math.BigInteger` and friends will go away, and Java APIs that depend on them will now be available in Swift! + +### Calling Java static methods from Swift + +There are a number of prime-generation facilities in the Java library we imported. However, we are going to focus on the simple Sieve of Eratosthenes, which is declared like this in Java: + +```java +public class SieveOfEratosthenes { + public static List findPrimes(int limit) { ... } +} +``` + +In Java, static methods are called as members of the class itself. For Swift to call a Java static method, it needs a representation of the Java class. This is expressed as an instance of the generic type `JavaClass`, which can be created in a particular JNI environment like this: + +```swift +let sieveClass = try JavaClass(in: jvm.environment()) +``` + +Now we can call Java's static methods on that class as instance methods on the `JavaClass` instance, e.g., + +```swift +let primes = sieveClass.findPrimes(100) // returns a List? +``` + +Putting it all together, we can define a main program in `Sources/JavaSieve/main.swift` that looks like this: + +```swift +import JavaKit +import JavaKitVM + +let jvm = try JavaVirtualMachine.shared(classPath: ["QuadraticSieve-1.0.jar"]) +do { + let sieveClass = try JavaClass(in: jvm.environment()) + for prime in sieveClass.findPrimes(100)! { + print("Found prime: \(prime.intValue())") + } +} catch { + print("Failure: \(error)") +} +``` + +Note that we are passing the Jar file in the `classPath` argument when initializing the `JavaVirtualMachine` instance. Otherwise, the program will fail with an error because it cannot find the Java class `com.gazman.quadratic_sieve.primes.SieveOfEratosthenes`. + +## Using Java libraries from Swift + +This section describes how Java libraries and mapped into Swift and their use from Swift. + ### Translation from Java classes into Swift Each Java class that can be used from Swift is translated to a Swift `struct` that provides information about the Java class itself and is populated with the Swift projection of each of its constructors, methods, and fields. For example, here is an excerpt of the Swift projection of [`java.util.jar.JarFile`](https://docs.oracle.com/javase/8/docs/api/java/util/jar/JarFile.html): @@ -521,6 +647,3 @@ public final class SomeModule ... { public static void globalFunction() { ... } } ``` - - - From b9122bde780a7b66080a6065707977718357cac1 Mon Sep 17 00:00:00 2001 From: Jack Rosen Date: Sun, 20 Oct 2024 01:44:58 -0400 Subject: [PATCH 115/426] java2swift: Add Support for Enum Cases (#76) * Add Support for Enum Cases * Fix building * Remove print * Update enum values to the new setup * Add new initializer from enum case * not throws or optional * Remove unnecessary addition of java.lang.Object mapping --------- Co-authored-by: Doug Gregor --- Sources/Java2SwiftLib/JavaTranslator.swift | 56 +++++++++++++++++++++ Tests/Java2SwiftTests/Java2SwiftTests.swift | 35 +++++++++++++ 2 files changed, 91 insertions(+) diff --git a/Sources/Java2SwiftLib/JavaTranslator.swift b/Sources/Java2SwiftLib/JavaTranslator.swift index 2b482b13..3b592715 100644 --- a/Sources/Java2SwiftLib/JavaTranslator.swift +++ b/Sources/Java2SwiftLib/JavaTranslator.swift @@ -234,11 +234,16 @@ extension JavaTranslator { // Fields var staticFields: [Field] = [] + var enumConstants: [Field] = [] members.append( contentsOf: javaClass.getFields().compactMap { $0.flatMap { field in if field.isStatic { staticFields.append(field) + + if field.isEnumConstant() { + enumConstants.append(field) + } return nil } @@ -252,6 +257,13 @@ extension JavaTranslator { } ) + if !enumConstants.isEmpty { + let enumName = "\(swiftTypeName)Cases" + members.append( + contentsOf: translateToEnumValue(name: enumName, enumFields: enumConstants) + ) + } + // Constructors members.append( contentsOf: javaClass.getConstructors().compactMap { @@ -447,6 +459,50 @@ extension JavaTranslator { """ } + package func translateToEnumValue(name: String, enumFields: [Field]) -> [DeclSyntax] { + let extensionSyntax: DeclSyntax = """ + public enum \(raw: name): Equatable { + \(raw: enumFields.map { "case \($0.getName())" }.joined(separator: "\n")) + } + """ + + let mappingSyntax: DeclSyntax = """ + public var enumValue: \(raw: name)? { + let classObj = self.javaClass + \(raw: enumFields.map { + // The equals method takes a java object, so we need to cast it here + """ + if self.equals(classObj.\($0.getName())?.as(JavaObject.self)) { + return \(name).\($0.getName()) + } + """ + }.joined(separator: " else ")) else { + return nil + } + } + """ + + let initSyntax: DeclSyntax = """ + public init(_ enumValue: \(raw: name), environment: JNIEnvironment) { + let classObj = try! JavaClass(in: environment) + switch enumValue { + \(raw: enumFields.map { + return """ + case .\($0.getName()): + if let \($0.getName()) = classObj.\($0.getName()) { + self = \($0.getName()) + } else { + fatalError("Enum value \($0.getName()) was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + """ + }.joined(separator: "\n")) + } + } + """ + + return [extensionSyntax, mappingSyntax, initSyntax] + } + // Translate a Java parameter list into Swift parameters. private func translateParameters(_ parameters: [Parameter?]) throws -> [FunctionParameterSyntax] { return try parameters.compactMap { javaParameter in diff --git a/Tests/Java2SwiftTests/Java2SwiftTests.swift b/Tests/Java2SwiftTests/Java2SwiftTests.swift index b3418ff2..579c74a8 100644 --- a/Tests/Java2SwiftTests/Java2SwiftTests.swift +++ b/Tests/Java2SwiftTests/Java2SwiftTests.swift @@ -24,6 +24,11 @@ var jvm: JavaVirtualMachine { } } +@JavaClass("java.time.Month") +public struct JavaMonth { + +} + class Java2SwiftTests: XCTestCase { func testJavaLangObjectMapping() throws { try assertTranslatedClass( @@ -47,6 +52,36 @@ class Java2SwiftTests: XCTestCase { ) } + func testEnum() async throws { + try assertTranslatedClass( + JavaMonth.self, + swiftTypeName: "Month", + expectedChunks: [ + "import JavaKit", + "enum MonthCases: Equatable", + "case APRIL", + "public var enumValue: MonthCases?", + """ + } else if self.equals(classObj.APRIL?.as(JavaObject.self)) { + return MonthCases.APRIL + } + """, + "public init(_ enumValue: MonthCases, environment: JNIEnvironment) {", + """ + case .APRIL: + if let APRIL = classObj.APRIL { + self = APRIL + } else { + fatalError("Enum value APRIL was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + """, + """ + @JavaStaticField + public var APRIL: Month? + """ + ]) + } + func testGenericCollections() throws { try assertTranslatedClass( MyArrayList.self, From bc5419403c9b19af8a8090eef2e5e687a440af51 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Tue, 22 Oct 2024 16:34:52 +0900 Subject: [PATCH 116/426] SwiftArena and invoking destroy on objects as arena is destroyed (#67) --- .github/workflows/pull_request.yml | 5 +- .gitignore | 6 + .licenseignore | 2 +- .../com/example/swift/HelloJava2Swift.java | 40 +-- .../com/example/swift/ManualMySwiftClass.java | 8 +- .../swift/generated/MySwiftClassTest.java | 4 +- .../org/swift/swiftkit/MySwiftClassTest.java | 11 +- .../org/swift/swiftkit/SwiftArenaTest.java | 78 +++++ .../ExampleSwiftLibrary/MySwiftLibrary.swift | 9 + .../Swift2JavaTranslator+Printing.swift | 122 ++++--- .../JExtractSwift/Swift2JavaTranslator.swift | 3 +- Sources/SwiftKitSwift/SwiftKit.swift | 1 + SwiftKit/build.gradle | 3 + .../org/swift/swiftkit/ManagedSwiftType.java | 1 - .../swift/swiftkit/MemorySegmentUtils.java | 39 +++ .../java/org/swift/swiftkit/SwiftAnyType.java | 66 ++++ .../java/org/swift/swiftkit/SwiftArena.java | 120 +++++-- .../org/swift/swiftkit/SwiftHeapObject.java | 9 +- .../org/swift/swiftkit/SwiftInstance.java | 42 +++ .../swift/swiftkit/SwiftInstanceCleanup.java | 52 +++ .../java/org/swift/swiftkit/SwiftKit.java | 316 +++++++----------- .../java/org/swift/swiftkit/SwiftValue.java | 19 ++ .../org/swift/swiftkit/SwiftValueLayout.java | 55 +++ .../swiftkit/SwiftValueWitnessTable.java | 228 +++++++++++++ .../swift/swiftkit/util/PlatformUtils.java | 38 +++ .../org/swift/swiftkit/util/StringUtils.java | 36 ++ .../swiftkit/SwiftRuntimeMetadataTest.java | 60 ++++ .../JExtractSwiftTests/FuncImportTests.swift | 27 +- .../swift/swiftkit/gradle/BuildUtils.groovy | 22 +- 29 files changed, 1085 insertions(+), 337 deletions(-) create mode 100644 Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/SwiftArenaTest.java create mode 100644 SwiftKit/src/main/java/org/swift/swiftkit/MemorySegmentUtils.java create mode 100644 SwiftKit/src/main/java/org/swift/swiftkit/SwiftAnyType.java create mode 100644 SwiftKit/src/main/java/org/swift/swiftkit/SwiftInstance.java create mode 100644 SwiftKit/src/main/java/org/swift/swiftkit/SwiftInstanceCleanup.java create mode 100644 SwiftKit/src/main/java/org/swift/swiftkit/SwiftValue.java create mode 100644 SwiftKit/src/main/java/org/swift/swiftkit/SwiftValueLayout.java create mode 100644 SwiftKit/src/main/java/org/swift/swiftkit/SwiftValueWitnessTable.java create mode 100644 SwiftKit/src/main/java/org/swift/swiftkit/util/PlatformUtils.java create mode 100644 SwiftKit/src/main/java/org/swift/swiftkit/util/StringUtils.java create mode 100644 SwiftKit/src/test/java/org/swift/swiftkit/SwiftRuntimeMetadataTest.java diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 251ba1b3..08ebc7b6 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -57,7 +57,10 @@ jobs: ${{ runner.os }}-swiftpm- # run the actual build - name: Gradle build - run: ./gradlew build --info --no-daemon + run: | + ./gradlew build -x test --no-daemon # skip tests + find . + ./gradlew build --info --no-daemon test-swift: name: Swift tests (swift:${{ matrix.swift_version }} jdk:${{matrix.jdk_vendor}} os:${{ matrix.os_version }}) diff --git a/.gitignore b/.gitignore index f56abda5..43b51002 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,9 @@ BuildLogic/out/ **/build/ lib/ +# Ignore JVM crash logs +**/*.log + # Ignore package resolved Package.resolved @@ -27,3 +30,6 @@ Package.resolved # Cache of project .gradletasknamecache + +# Ignore files generated by jextract, we always can re-generate them +*/**/*.java diff --git a/.licenseignore b/.licenseignore index 5d0e3172..02866b01 100644 --- a/.licenseignore +++ b/.licenseignore @@ -27,12 +27,12 @@ docker/* **/docker-compose.yaml **/docker/* **/.dockerignore -JavaSwiftKitDemo/src/main/java/com/example/swift/generated/* Makefile **/Makefile **/*.html **/CMakeLists.txt **/*.jar +**/generated/*.java **/generated/*.swift gradle/wrapper/gradle-wrapper.properties gradlew diff --git a/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java b/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java index 28054047..51dd48b1 100644 --- a/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java +++ b/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java @@ -19,12 +19,11 @@ import com.example.swift.generated.MySwiftClass; // Import javakit/swiftkit support libraries +import org.swift.swiftkit.SwiftArena; import org.swift.swiftkit.SwiftKit; - +import org.swift.swiftkit.SwiftValueWitnessTable; import java.lang.foreign.*; -import java.util.List; - public class HelloJava2Swift { @@ -32,41 +31,24 @@ public static void main(String[] args) { boolean traceDowncalls = Boolean.getBoolean("jextract.trace.downcalls"); System.out.println("Property: jextract.trace.downcalls = " + traceDowncalls); - final var dylibNames = List.of( - "swiftCore", - "JavaKitExample" - ); - - - System.out.println("Loading libraries..."); - - for (var lib : dylibNames) { - System.out.printf("Loading: %s... ", lib); - System.loadLibrary(lib); - System.out.println("ok."); - } + System.out.printf("java.library.path = %s\n", System.getProperty("java.library.path")); examples(); } static void examples() { - ExampleSwiftLibrary.helloWorld(); + ExampleSwiftLibrary.helloWorld(); - ExampleSwiftLibrary.globalTakeInt(1337); + ExampleSwiftLibrary.globalTakeInt(1337); - MySwiftClass obj = new MySwiftClass(2222, 7777); + MySwiftClass obj = new MySwiftClass(2222, 7777); - SwiftKit.retain(obj.$memorySegment()); - System.out.println("[java] obj ref count = " + SwiftKit.retainCount(obj.$memorySegment())); + SwiftKit.retain(obj.$memorySegment()); + System.out.println("[java] obj ref count = " + SwiftKit.retainCount(obj.$memorySegment())); - obj.voidMethod(); - obj.takeIntMethod(42); + obj.voidMethod(); + obj.takeIntMethod(42); - MemorySegment swiftType = SwiftKit.getTypeByMangledNameInEnvironment("SiSg"); - System.out.println("Memory layout for Swift.Int?:"); - System.out.println(" size = " + SwiftKit.sizeOfSwiftType(swiftType)); - System.out.println(" stride = " + SwiftKit.strideOfSwiftType(swiftType)); - System.out.println(" alignment = " + SwiftKit.alignmentOfSwiftType(swiftType)); - System.out.println(" Java layout = " + SwiftKit.layoutOfSwiftType(swiftType)); + System.out.println("DONE."); } } diff --git a/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/ManualMySwiftClass.java b/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/ManualMySwiftClass.java index 0a40f293..9aa63f22 100644 --- a/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/ManualMySwiftClass.java +++ b/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/ManualMySwiftClass.java @@ -27,7 +27,7 @@ public final class ManualMySwiftClass extends Manual_MySwiftClass implements Man // 000000000003f4a8 S type metadata for JavaKitExample.MySwiftSlice // strip the _$s // drop the N - public static final String TYPE_METADATA_NAME = "14JavaKitExample12MySwiftClassC"; + public static final String TYPE_MANGLED_NAME = "14JavaKitExample12MySwiftClassC"; private final MemorySegment self; @@ -167,13 +167,13 @@ static MemorySegment __allocating_init_len_cap(long len, long cap) { if (ManualJavaKitExample.TRACE_DOWNCALLS) { ManualJavaKitExample.traceDowncall("MySwiftClass.__allocating_init(len:cap:)", len, cap); } - ManualJavaKitExample.trace("type name = " + TYPE_METADATA_NAME); + ManualJavaKitExample.trace("type name = " + TYPE_MANGLED_NAME); // FIXME: problems with _getTypeByName because of the String memory repr - // final MemorySegment type = SwiftKit.getTypeByMangledNameInEnvironment(TYPE_METADATA_NAME); + // final MemorySegment type = SwiftKit.getTypeByMangledNameInEnvironment(TYPE_MANGLED_NAME); // we must get a method we can call like this into SwiftKit: - MemorySegment type = ManualJavaKitExample.swiftkit_getTypeByStringByteArray(TYPE_METADATA_NAME); + MemorySegment type = ManualJavaKitExample.swiftkit_getTypeByStringByteArray(TYPE_MANGLED_NAME); ManualJavaKitExample.trace("type = " + type); var address = (MemorySegment) mh$.invokeExact(len, cap, type); diff --git a/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/generated/MySwiftClassTest.java b/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/generated/MySwiftClassTest.java index 0f20c172..7495ff19 100644 --- a/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/generated/MySwiftClassTest.java +++ b/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/generated/MySwiftClassTest.java @@ -15,6 +15,7 @@ package com.example.swift.generated; import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.DisabledOnOs; import org.junit.jupiter.api.condition.OS; @@ -48,9 +49,10 @@ void test_MySwiftClass_makeIntMethod() { } @Test + @Disabled // TODO: Need var mangled names in interfaces void test_MySwiftClass_property_len() { MySwiftClass o = new MySwiftClass(12, 42); - var got = o.makeIntMethod(); + var got = o.getLen(); assertEquals(12, got); } diff --git a/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/MySwiftClassTest.java b/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/MySwiftClassTest.java index b04da744..1b98d1e0 100644 --- a/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/MySwiftClassTest.java +++ b/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/MySwiftClassTest.java @@ -27,17 +27,14 @@ public class MySwiftClassTest { @BeforeAll static void beforeAll() { - System.out.printf("java.library.path = %s\n", System.getProperty("java.library.path")); - - System.loadLibrary("swiftCore"); - System.loadLibrary("ExampleSwiftLibrary"); - - System.setProperty("jextract.trace.downcalls", "true"); + System.out.printf("java.library.path = %s\n", SwiftKit.getJavaLibraryPath()); + System.out.printf("jextract.trace.downcalls = %s\n", SwiftKit.getJextractTraceDowncalls()); } @Test void call_retain_retainCount_release() { - var obj = new MySwiftClass(1, 2); + var arena = SwiftArena.ofConfined(); + var obj = new MySwiftClass(arena, 1, 2); assertEquals(1, SwiftKit.retainCount(obj.$memorySegment())); // TODO: test directly on SwiftHeapObject inheriting obj diff --git a/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/SwiftArenaTest.java b/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/SwiftArenaTest.java new file mode 100644 index 00000000..4f4ab9df --- /dev/null +++ b/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/SwiftArenaTest.java @@ -0,0 +1,78 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package org.swift.swiftkit; + +import com.example.swift.generated.MySwiftClass; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.DisabledIf; +import org.swift.swiftkit.util.PlatformUtils; + +import static org.junit.jupiter.api.Assertions.*; +import static org.swift.swiftkit.SwiftKit.*; +import static org.swift.swiftkit.SwiftKit.retainCount; + +public class SwiftArenaTest { + + @BeforeAll + static void beforeAll() { + System.out.printf("java.library.path = %s\n", SwiftKit.getJavaLibraryPath()); + System.out.printf("jextract.trace.downcalls = %s\n", SwiftKit.getJextractTraceDowncalls()); + } + + static boolean isAmd64() { + return PlatformUtils.isAmd64(); + } + + // FIXME: The destroy witness table call hangs on x86_64 platforms during the destroy witness table call + // See: https://github.com/swiftlang/swift-java/issues/97 + @Test + @DisabledIf("isAmd64") + public void arena_releaseClassOnClose_class_ok() { + try (var arena = SwiftArena.ofConfined()) { + var obj = new MySwiftClass(arena,1, 2); + + retain(obj.$memorySegment()); + assertEquals(2, retainCount(obj.$memorySegment())); + + release(obj.$memorySegment()); + assertEquals(1, retainCount(obj.$memorySegment())); + } + + // TODO: should we zero out the $memorySegment perhaps? + } + + @Test + public void arena_releaseClassOnClose_class_leaked() { + String memorySegmentDescription = ""; + + try { + try (var arena = SwiftArena.ofConfined()) { + var obj = new MySwiftClass(arena,1, 2); + memorySegmentDescription = obj.$memorySegment().toString(); + + // Pretend that we "leaked" the class, something still holds a reference to it while we try to destroy it + retain(obj.$memorySegment()); + assertEquals(2, retainCount(obj.$memorySegment())); + } + + fail("Expected exception to be thrown while the arena is closed!"); + } catch (Exception ex) { + // The message should point out which objects "leaked": + assertTrue(ex.getMessage().contains(memorySegmentDescription)); + } + + } +} diff --git a/Sources/ExampleSwiftLibrary/MySwiftLibrary.swift b/Sources/ExampleSwiftLibrary/MySwiftLibrary.swift index 4928233e..5ad8e6fb 100644 --- a/Sources/ExampleSwiftLibrary/MySwiftLibrary.swift +++ b/Sources/ExampleSwiftLibrary/MySwiftLibrary.swift @@ -76,6 +76,15 @@ public class MySwiftClass { } } +@_silgen_name("swift_getTypeByMangledNameInEnvironment") +public func _getTypeByMangledNameInEnvironment( + _ name: UnsafePointer, + _ nameLength: UInt, + genericEnvironment: UnsafeRawPointer?, + genericArguments: UnsafeRawPointer?) + -> Any.Type? + + // ==== Internal helpers private func p(_ msg: String, file: String = #fileID, line: UInt = #line, function: String = #function) { diff --git a/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift b/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift index 46d89dae..1d20114a 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift @@ -100,6 +100,9 @@ extension Swift2JavaTranslator { printImports(&printer) printModuleClass(&printer) { printer in + + printStaticLibraryLoad(&printer) + // TODO: print all "static" methods for decl in importedGlobalFuncs { printFunctionDowncallMethods(&printer, decl) @@ -110,22 +113,27 @@ extension Swift2JavaTranslator { public func printImportedClass(_ printer: inout CodePrinter, _ decl: ImportedNominalType) { printHeader(&printer) printPackage(&printer) - printImports(&printer) // TODO print any imports the file may need, it we talk to other Swift modules + printImports(&printer) printClass(&printer, decl) { printer in - // Metadata + // Ensure we have loaded the library where the Swift type was declared before we attempt to resolve types in Swift + printStaticLibraryLoad(&printer) + + // Prepare type metadata, we're going to need these when invoking e.g. initializers so cache them in a static printer.print( """ - // FIXME: this detecting is somewhat off - public static final String TYPE_METADATA_NAME = "\(decl.swiftMangledName ?? "")"; - static final MemorySegment TYPE_METADATA = SwiftKit.getTypeByMangledNameInEnvironment(TYPE_METADATA_NAME); + public static final String TYPE_MANGLED_NAME = "\(decl.swiftMangledName ?? "")"; + public static final SwiftAnyType TYPE_METADATA = SwiftKit.getTypeByMangledNameInEnvironment(TYPE_MANGLED_NAME).get(); + public final SwiftAnyType $swiftType() { + return TYPE_METADATA; + } """ ) printer.print("") // Initializers for initDecl in decl.initializers { - printClassInitializer(&printer, initDecl) + printClassConstructors(&printer, initDecl) } // Properties @@ -137,6 +145,9 @@ extension Swift2JavaTranslator { for funcDecl in decl.methods { printFunctionDowncallMethods(&printer, funcDecl) } + + // Helper methods and default implementations + printHeapObjectToStringMethod(&printer, decl) } } @@ -168,20 +179,15 @@ extension Swift2JavaTranslator { } public func printClass(_ printer: inout CodePrinter, _ decl: ImportedNominalType, body: (inout CodePrinter) -> Void) { - printer.printTypeDecl("public final class \(decl.javaClassName)") { printer in + printer.printTypeDecl("public final class \(decl.javaClassName) implements SwiftHeapObject") { printer in // ==== Storage of the class - // FIXME: implement the self storage for the memory address and accessors printClassSelfProperty(&printer, decl) - // Constructor - printClassMemorySegmentConstructor(&printer, decl) - // Constants printClassConstants(printer: &printer) printTypeMappingDecls(&printer) // Layout of the class - // TODO: this is missing information until we can get @layout from Swift printClassMemoryLayout(&printer, decl) // Render the 'trace' functions etc @@ -247,8 +253,8 @@ extension Swift2JavaTranslator { """ static final SymbolLookup SYMBOL_LOOKUP = getSymbolLookup(); private static SymbolLookup getSymbolLookup() { - if (SwiftKit.isMacOS()) { - return SymbolLookup.libraryLookup(System.mapLibraryName(DYLIB_NAME), LIBRARY_ARENA) + if (PlatformUtils.isMacOS()) { + return SymbolLookup.libraryLookup(System.mapLibraryName(LIB_NAME), LIBRARY_ARENA) .or(SymbolLookup.loaderLookup()) .or(Linker.nativeLinker().defaultLookup()); } else { @@ -266,7 +272,7 @@ extension Swift2JavaTranslator { private func printClassConstants(printer: inout CodePrinter) { printer.print( """ - static final String DYLIB_NAME = "\(swiftModuleName)"; + static final String LIB_NAME = "\(swiftModuleName)"; static final Arena LIBRARY_ARENA = Arena.ofAuto(); """ ) @@ -282,17 +288,6 @@ extension Swift2JavaTranslator { ) } - private func printClassMemorySegmentConstructor(_ printer: inout CodePrinter, _ decl: ImportedNominalType) { - printer.print( - """ - /** Instances are created using static {@code init} methods rather than through the constructor directly. */ - private \(decl.javaClassName)(MemorySegment selfMemorySegment) { - this.selfMemorySegment = selfMemorySegment; - } - """ - ) - } - /// Print a property where we can store the "self" pointer of a class. private func printClassSelfProperty(_ printer: inout CodePrinter, _ decl: ImportedNominalType) { printer.print( @@ -308,31 +303,16 @@ extension Swift2JavaTranslator { } private func printClassMemoryLayout(_ printer: inout CodePrinter, _ decl: ImportedNominalType) { + // TODO: make use of the swift runtime to get the layout printer.print( """ private static final GroupLayout $LAYOUT = MemoryLayout.structLayout( SWIFT_POINTER - ); - - // TODO: depends on @layout in Swift, so we can't do these yet - private static final GroupLayout $CLASS_LAYOUT = MemoryLayout.structLayout( - // SWIFT_INT.withName("heapObject"), - // ... - // SWIFT_INT.withName("cap") - ).withName("\(decl.javaType)"); // TODO: is the name right? + ).withName("\(decl.swiftMangledName ?? decl.swiftTypeName)"); - /** - * When other types refer to this type, they refer to by a pointer, - * so the layout of a class is just a pointer - */ - public static final GroupLayout $layout() { + public final GroupLayout $layout() { return $LAYOUT; } - - /** The in-memory layout of this type */ - public static final GroupLayout $instanceLayout() { - return $CLASS_LAYOUT; - } """ ) } @@ -372,7 +352,6 @@ extension Swift2JavaTranslator { public static final ValueLayout.OfLong SWIFT_UINT = SWIFT_INT64; public static final AddressLayout SWIFT_SELF = SWIFT_POINTER; - public static final AddressLayout SWIFT_TYPE_METADATA_PTR = SWIFT_POINTER; """ ) } @@ -411,7 +390,7 @@ extension Swift2JavaTranslator { ) } - public func printClassInitializer(_ printer: inout CodePrinter, _ decl: ImportedFunc) { + public func printClassConstructors(_ printer: inout CodePrinter, _ decl: ImportedFunc) { guard let parentName = decl.parentName else { fatalError("init must be inside a parent type! Was: \(decl)") } @@ -424,32 +403,48 @@ extension Swift2JavaTranslator { printMethodDowncallHandleForAddrDesc(&printer) } - printClassInitializerConstructor(&printer, decl, parentName: parentName) + printClassInitializerConstructors(&printer, decl, parentName: parentName) } - public func printClassInitializerConstructor( + public func printClassInitializerConstructors( _ printer: inout CodePrinter, _ decl: ImportedFunc, parentName: TranslatedType ) { let descClassIdentifier = renderDescClassName(decl) + printer.print( """ /** * Create an instance of {@code \(parentName.unqualifiedJavaTypeName)}. * - * {@snippet lang=swift : - * \(decl.syntax ?? "") - * } + \(decl.renderCommentSnippet ?? " *") */ public \(parentName.unqualifiedJavaTypeName)(\(renderJavaParamDecls(decl, selfVariant: .wrapper))) { + this(/*arena=*/null, \(renderForwardParams(decl, selfVariant: .wrapper))); + } + """ + ) + + printer.print( + """ + /** + * Create an instance of {@code \(parentName.unqualifiedJavaTypeName)}. + * This instance is managed by the passed in {@link SwiftArena} and may not outlive the arena's lifetime. + * + \(decl.renderCommentSnippet ?? " *") + */ + public \(parentName.unqualifiedJavaTypeName)(SwiftArena arena, \(renderJavaParamDecls(decl, selfVariant: .wrapper))) { var mh$ = \(descClassIdentifier).HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall(\(renderForwardParams(decl, selfVariant: nil))); } - this.selfMemorySegment = (MemorySegment) mh$.invokeExact(\(renderForwardParams(decl, selfVariant: nil)), TYPE_METADATA); + this.selfMemorySegment = (MemorySegment) mh$.invokeExact(\(renderForwardParams(decl, selfVariant: nil)), TYPE_METADATA.$memorySegment()); + if (arena != null) { + arena.register(this); + } } catch (Throwable ex$) { throw new AssertionError("should not reach here", ex$); } @@ -458,6 +453,17 @@ extension Swift2JavaTranslator { ) } + public func printStaticLibraryLoad(_ printer: inout CodePrinter) { + printer.print( + """ + static { + System.loadLibrary("swiftCore"); + System.loadLibrary(LIB_NAME); + } + """ + ) + } + public func printFunctionDowncallMethods(_ printer: inout CodePrinter, _ decl: ImportedFunc) { printer.printSeparator(decl.identifier) @@ -821,4 +827,16 @@ extension Swift2JavaTranslator { printer.print(");"); } + public func printHeapObjectToStringMethod(_ printer: inout CodePrinter, _ decl: ImportedNominalType) { + printer.print( + """ + @Override + public String toString() { + return getClass().getSimpleName() + "(" + + SwiftKit.nameOfSwiftType($swiftType().$memorySegment(), true) + + ")@" + $memorySegment(); + } + """) + } + } diff --git a/Sources/JExtractSwift/Swift2JavaTranslator.swift b/Sources/JExtractSwift/Swift2JavaTranslator.swift index b57c19af..a954620b 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator.swift @@ -118,8 +118,9 @@ extension Swift2JavaTranslator { /// Default set Java imports for every generated file static let defaultJavaImports: Array = [ - // Support library in Java + "org.swift.swiftkit.*", "org.swift.swiftkit.SwiftKit", + "org.swift.swiftkit.util.*", // Necessary for native calls and type mapping "java.lang.foreign.*", diff --git a/Sources/SwiftKitSwift/SwiftKit.swift b/Sources/SwiftKitSwift/SwiftKit.swift index e034f6d0..9fdcdd80 100644 --- a/Sources/SwiftKitSwift/SwiftKit.swift +++ b/Sources/SwiftKitSwift/SwiftKit.swift @@ -18,6 +18,7 @@ // No annotations are necessary on the Swift side to perform the export. // FIXME: this is a workaround until we can pass String to Swift directly +@_silgen_name("getTypeByStringByteArray") public func getTypeByStringByteArray(_ name: UnsafePointer) -> Any.Type? { let string = String(cString: name) let type = _typeByName(string) diff --git a/SwiftKit/build.gradle b/SwiftKit/build.gradle index 5a6d15c0..3479e6c8 100644 --- a/SwiftKit/build.gradle +++ b/SwiftKit/build.gradle @@ -36,4 +36,7 @@ dependencies { tasks.test { useJUnitPlatform() + testLogging { + events("passed", "skipped", "failed") + } } diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/ManagedSwiftType.java b/SwiftKit/src/main/java/org/swift/swiftkit/ManagedSwiftType.java index 2abaf85a..da25ae4d 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/ManagedSwiftType.java +++ b/SwiftKit/src/main/java/org/swift/swiftkit/ManagedSwiftType.java @@ -19,7 +19,6 @@ public interface ManagedSwiftType { /** * The memory segment of `self` of the managed Swift object/value. - * @return */ public MemorySegment $memorySegment(); diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/MemorySegmentUtils.java b/SwiftKit/src/main/java/org/swift/swiftkit/MemorySegmentUtils.java new file mode 100644 index 00000000..c1ab8995 --- /dev/null +++ b/SwiftKit/src/main/java/org/swift/swiftkit/MemorySegmentUtils.java @@ -0,0 +1,39 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package org.swift.swiftkit; + +import java.lang.foreign.MemorySegment; +import java.lang.foreign.ValueLayout; + +public class MemorySegmentUtils { + /** + * Set the value of `target` to the {@link MemorySegment#address()} of the `memorySegment`, + * adjusting for the fact that Swift pointer may be 32 or 64 bit, depending on runtime. + * + * @param target the target to set a value on + * @param memorySegment the origin of the address value to write into `target` + */ + static void setSwiftPointerAddress(MemorySegment target, MemorySegment memorySegment) { + // Write the address of as the value of the newly created pointer. + // We need to type-safely set the pointer value which may be 64 or 32-bit. + if (SwiftValueLayout.SWIFT_INT == ValueLayout.JAVA_LONG) { + System.out.println("[setSwiftPointerAddress] address is long = " + memorySegment.address()); + target.set(ValueLayout.JAVA_LONG, /*offset=*/0, memorySegment.address()); + } else { + System.out.println("[setSwiftPointerAddress] address is int = " + memorySegment.address()); + target.set(ValueLayout.JAVA_INT, /*offset=*/0, (int) memorySegment.address()); + } + } +} diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftAnyType.java b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftAnyType.java new file mode 100644 index 00000000..6dcd1f6b --- /dev/null +++ b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftAnyType.java @@ -0,0 +1,66 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package org.swift.swiftkit; + +import java.lang.foreign.GroupLayout; +import java.lang.foreign.MemoryLayout; +import java.lang.foreign.MemorySegment; + +public final class SwiftAnyType { + + private static final GroupLayout $LAYOUT = MemoryLayout.structLayout( + SwiftValueLayout.SWIFT_POINTER + ); + + private final MemorySegment memorySegment; + + public SwiftAnyType(MemorySegment memorySegment) { + if (memorySegment.byteSize() == 0) { + throw new IllegalArgumentException("A Swift Any.Type cannot be null!"); + } + + this.memorySegment = memorySegment; + } + + public SwiftAnyType(SwiftHeapObject object) { + if (object.$layout().name().isEmpty()) { + throw new IllegalArgumentException("SwiftHeapObject must have a mangled name in order to obtain its SwiftType."); + } + + String mangledName = object.$layout().name().get(); + var type = SwiftKit.getTypeByMangledNameInEnvironment(mangledName); + if (type.isEmpty()) { + throw new IllegalArgumentException("A Swift Any.Type cannot be null!"); + } + this.memorySegment = type.get().memorySegment; + } + + + public MemorySegment $memorySegment() { + return memorySegment; + } + + public GroupLayout $layout() { + return $LAYOUT; + } + + @Override + public String toString() { + return "AnySwiftType{" + + "name=" + SwiftKit.nameOfSwiftType(memorySegment, true) + + ", memorySegment=" + memorySegment + + '}'; + } +} diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftArena.java b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftArena.java index 54c801b4..98bfd5ef 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftArena.java +++ b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftArena.java @@ -14,52 +14,124 @@ package org.swift.swiftkit; -import java.lang.foreign.Arena; -import java.lang.foreign.MemorySegment; -import java.util.concurrent.ConcurrentSkipListSet; - -public interface SwiftArena extends Arena { +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * A Swift arena manages Swift allocated memory for classes, structs, enums etc. + * When an arena is closed, it will destroy all managed swift objects in a way appropriate to their type. + *

+ * A confined arena has an associated owner thread that confines some operations to + * associated owner thread such as {@link #close()}. + */ +public interface SwiftArena extends AutoCloseable { + + static SwiftArena ofConfined() { + return new ConfinedSwiftMemorySession(Thread.currentThread()); + } - void release(MemorySegment segment); + /** + * Register a Swift reference counted heap object with this arena (such as a {@code class} or {@code actor}). + * Its memory should be considered managed by this arena, and be destroyed when the arena is closed. + */ + void register(SwiftHeapObject object); - void retain(MemorySegment segment); + /** + * Register a struct, enum or other non-reference counted Swift object. + * Its memory should be considered managed by this arena, and be destroyed when the arena is closed. + */ + void register(SwiftValue value); - long retainCount(MemorySegment segment); + /** + * Close the arena and make sure all objects it managed are released. + * Throws if unable to verify all resources have been release (e.g. over retained Swift classes) + */ + void close(); } -final class AutoSwiftArena implements SwiftArena { - Arena underlying; +final class ConfinedSwiftMemorySession implements SwiftArena { + +// final Arena underlying; + final Thread owner; + final SwiftResourceList resources; + + final int CLOSED = 0; + final int ACTIVE = 1; + final AtomicInteger state; - ConcurrentSkipListSet managedMemorySegments; + public ConfinedSwiftMemorySession(Thread owner) { + this.owner = owner; + resources = new ConfinedResourceList(); + state = new AtomicInteger(ACTIVE); + } + + public void checkValid() throws RuntimeException { + if (this.owner != null && this.owner != Thread.currentThread()) { + throw new WrongThreadException("ConfinedSwift arena is confined to %s but was closed from %s!".formatted(this.owner, Thread.currentThread())); + } else if (this.state.get() < ACTIVE) { + throw new RuntimeException("Arena is already closed!"); + } + } @Override - public MemorySegment allocate(long byteSize, long byteAlignment) { - return null; + public void register(SwiftHeapObject object) { + this.resources.add(new SwiftHeapObjectCleanup(object)); } @Override - public MemorySegment.Scope scope() { - return null; + public void register(SwiftValue value) { + this.resources.add(new SwiftValueCleanup(value.$memorySegment())); } @Override public void close() { + checkValid(); + // Cleanup all resources + if (this.state.compareAndExchange(ACTIVE, CLOSED) == ACTIVE) { + this.resources.cleanup(); + } // else, was already closed; do nothing } - @Override - public void release(MemorySegment segment) { - SwiftKit.release(segment); + /** + * Represents a list of resources that need a cleanup, e.g. allocated classes/structs. + */ + static abstract class SwiftResourceList implements Runnable { + // TODO: Could use intrusive linked list to avoid one indirection here + final List resourceCleanups = new LinkedList<>(); + + abstract void add(SwiftInstanceCleanup cleanup); + + public abstract void cleanup(); + + public final void run() { + cleanup(); // cleaner interop + } } - @Override - public void retain(MemorySegment segment) { - SwiftKit.retain(segment); + static final class ConfinedResourceList extends SwiftResourceList { + @Override + void add(SwiftInstanceCleanup cleanup) { + resourceCleanups.add(cleanup); + } + + @Override + public void cleanup() { + for (SwiftInstanceCleanup cleanup : resourceCleanups) { + cleanup.run(); + } + } } - @Override - public long retainCount(MemorySegment segment) { - return SwiftKit.retainCount(segment); + +} + +final class UnexpectedRetainCountException extends RuntimeException { + public UnexpectedRetainCountException(Object resource, long retainCount, int expectedRetainCount) { + super(("Attempting to cleanup managed memory segment %s, but it's retain count was different than [%d] (was %d)! " + + "This would result in destroying a swift object that is still retained by other code somewhere." + ).formatted(resource, expectedRetainCount, retainCount)); } } diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftHeapObject.java b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftHeapObject.java index 5d1945dd..a7add138 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftHeapObject.java +++ b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftHeapObject.java @@ -14,8 +14,9 @@ package org.swift.swiftkit; -import java.lang.foreign.MemorySegment; - -public interface SwiftHeapObject { - MemorySegment $self(); +/** + * Represents a wrapper around a Swift heap object, e.g. a {@code class} or an {@code actor}. + */ +public interface SwiftHeapObject extends SwiftInstance { + SwiftAnyType $swiftType(); } diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftInstance.java b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftInstance.java new file mode 100644 index 00000000..08cce158 --- /dev/null +++ b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftInstance.java @@ -0,0 +1,42 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package org.swift.swiftkit; + +import java.lang.foreign.GroupLayout; +import java.lang.foreign.MemorySegment; + +public interface SwiftInstance { + + /** + * The pointer to the instance in memory. I.e. the {@code self} of the Swift object or value. + */ + MemorySegment $memorySegment(); + + /** + * The in memory layout of an instance of this Swift type. + */ + GroupLayout $layout(); + + SwiftAnyType $swiftType(); + + /** + * Returns `true` if this swift instance is a reference type, i.e. a `class` or (`distributed`) `actor`. + * + * @return `true` if this instance is a reference type, `false` otherwise. + */ + default boolean isReferenceType() { + return this instanceof SwiftHeapObject; + } +} diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftInstanceCleanup.java b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftInstanceCleanup.java new file mode 100644 index 00000000..e28e0dd7 --- /dev/null +++ b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftInstanceCleanup.java @@ -0,0 +1,52 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package org.swift.swiftkit; + +import java.lang.foreign.MemorySegment; + +/** + * A Swift memory instance cleanup, e.g. count-down a reference count and destroy a class, or destroy struct/enum etc. + */ +sealed interface SwiftInstanceCleanup extends Runnable { +} + +record SwiftHeapObjectCleanup(SwiftHeapObject instance) implements SwiftInstanceCleanup { + + @Override + public void run() throws UnexpectedRetainCountException { + // Verify we're only destroying an object that's indeed not retained by anyone else: + long retainedCount = SwiftKit.retainCount(this.instance); + if (retainedCount > 1) { + throw new UnexpectedRetainCountException(this.instance, retainedCount, 1); + } + + // Destroy (and deinit) the object: + var ty = this.instance.$swiftType(); + System.out.println("x destroy instance = " + this.instance); + System.out.println("x destroy ty = " + ty); + + SwiftValueWitnessTable.destroy(ty, this.instance.$memorySegment()); + + // Invalidate the Java wrapper class, in order to prevent effectively use-after-free issues. + // FIXME: some trouble with setting the pointer to null, need to figure out an appropriate way to do this + } +} + +record SwiftValueCleanup(MemorySegment resource) implements SwiftInstanceCleanup { + @Override + public void run() { + throw new RuntimeException("not implemented yet"); + } +} diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftKit.java b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftKit.java index 821169b9..064be4ec 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftKit.java +++ b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftKit.java @@ -14,13 +14,16 @@ package org.swift.swiftkit; +import org.swift.swiftkit.util.PlatformUtils; + import java.lang.foreign.*; -import java.lang.foreign.MemoryLayout.PathElement; import java.lang.invoke.MethodHandle; import java.util.Arrays; +import java.util.Optional; import java.util.stream.Collectors; -import static java.lang.foreign.ValueLayout.JAVA_BYTE; +import static org.swift.swiftkit.util.StringUtils.stripPrefix; +import static org.swift.swiftkit.util.StringUtils.stripSuffix; public class SwiftKit { @@ -32,17 +35,14 @@ public class SwiftKit { static { System.loadLibrary(STDLIB_DYLIB_NAME); + System.loadLibrary("SwiftKitSwift"); } - public static final AddressLayout SWIFT_POINTER = ValueLayout.ADDRESS - .withTargetLayout(MemoryLayout.sequenceLayout(java.lang.Long.MAX_VALUE, JAVA_BYTE)); - static final SymbolLookup SYMBOL_LOOKUP = getSymbolLookup(); private static SymbolLookup getSymbolLookup() { - if (isMacOS()) { - // FIXME: why does this not find just by name on macOS? - // SymbolLookup.libraryLookup(System.mapLibraryName(STDLIB_DYLIB_NAME), LIBRARY_ARENA) + if (PlatformUtils.isMacOS()) { + // On Apple platforms we need to lookup using the complete path return SymbolLookup.libraryLookup(STDLIB_MACOS_DYLIB_PATH, LIBRARY_ARENA) .or(SymbolLookup.loaderLookup()) .or(Linker.nativeLinker().defaultLookup()); @@ -51,26 +51,15 @@ private static SymbolLookup getSymbolLookup() { .or(Linker.nativeLinker().defaultLookup()); } } - public SwiftKit() { - } - public static boolean isLinux() { - return System.getProperty("os.name").toLowerCase().contains("linux"); - } - - public static boolean isMacOS() { - return System.getProperty("os.name").toLowerCase().contains("mac"); - } - - public static boolean isWindows() { - return System.getProperty("os.name").toLowerCase().contains("windows"); + public SwiftKit() { } static void traceDowncall(String name, Object... args) { String traceArgs = Arrays.stream(args) .map(Object::toString) .collect(Collectors.joining(", ")); - System.out.printf("%s(%s)\n", name, traceArgs); + System.out.printf("[java] Downcall: %s(%s)\n", name, traceArgs); } static MemorySegment findOrThrow(String symbol) { @@ -78,31 +67,42 @@ static MemorySegment findOrThrow(String symbol) { .orElseThrow(() -> new UnsatisfiedLinkError("unresolved symbol: %s".formatted(symbol))); } + public static String getJavaLibraryPath() { + return System.getProperty("java.library.path"); + } + + public static boolean getJextractTraceDowncalls() { + return Boolean.getBoolean("jextract.trace.downcalls"); + } + // ==== ------------------------------------------------------------------------------------------------------------ // free - /** - * Descriptor for the free C runtime function. - */ - public static final FunctionDescriptor free$descriptor = FunctionDescriptor.ofVoid( - ValueLayout.ADDRESS - ); - /** - * Address of the free C runtime function. - */ - public static final MemorySegment free$addr = findOrThrow("free"); + static abstract class free { + /** + * Descriptor for the free C runtime function. + */ + public static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( + ValueLayout.ADDRESS + ); - /** - * Handle for the free C runtime function. - */ - public static final MethodHandle free$handle = Linker.nativeLinker().downcallHandle(free$addr, free$descriptor); + /** + * Address of the free C runtime function. + */ + public static final MemorySegment ADDR = findOrThrow("free"); + + /** + * Handle for the free C runtime function. + */ + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + } /** * free the given pointer */ public static void cFree(MemorySegment pointer) { try { - free$handle.invokeExact(pointer); + free.HANDLE.invokeExact(pointer); } catch (Throwable ex$) { throw new AssertionError("should not reach here", ex$); } @@ -136,7 +136,7 @@ public static long retainCount(MemorySegment object) { } public static long retainCount(SwiftHeapObject object) { - return retainCount(object.$self()); + return retainCount(object.$memorySegment()); } // ==== ------------------------------------------------------------------------------------------------------------ @@ -165,8 +165,8 @@ public static void retain(MemorySegment object) { } } - public static long retain(SwiftHeapObject object) { - return retainCount(object.$self()); + public static void retain(SwiftHeapObject object) { + retain(object.$memorySegment()); } // ==== ------------------------------------------------------------------------------------------------------------ @@ -187,7 +187,7 @@ public static void release(MemorySegment object) { var mh$ = swift_release.HANDLE; try { if (TRACE_DOWNCALLS) { - traceDowncall("swift_release_retain", object); + traceDowncall("swift_release", object); } mh$.invokeExact(object); } catch (Throwable ex$) { @@ -196,10 +196,11 @@ public static void release(MemorySegment object) { } public static long release(SwiftHeapObject object) { - return retainCount(object.$self()); + return retainCount(object.$memorySegment()); } // ==== ------------------------------------------------------------------------------------------------------------ + // getTypeByName /** * {@snippet lang = swift: @@ -222,7 +223,7 @@ public static MemorySegment getTypeByName(String string) { var mh$ = swift_getTypeByName.HANDLE; try { if (TRACE_DOWNCALLS) { - traceDowncall("_swift_getTypeByName"); + traceDowncall("_typeByName"); } // TODO: A bit annoying to generate, we need an arena for the conversion... try (Arena arena = Arena.ofConfined()) { @@ -247,7 +248,7 @@ public static MemorySegment getTypeByName(String string) { */ private static class swift_getTypeByMangledNameInEnvironment { public static final FunctionDescriptor DESC = FunctionDescriptor.of( - /*returns=*/SWIFT_POINTER, + /*returns=*/SwiftValueLayout.SWIFT_POINTER, ValueLayout.ADDRESS, ValueLayout.JAVA_INT, ValueLayout.ADDRESS, @@ -259,200 +260,119 @@ private static class swift_getTypeByMangledNameInEnvironment { public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } - public static MemorySegment getTypeByMangledNameInEnvironment(String string) { + private static class getTypeByStringByteArray { + public static final FunctionDescriptor DESC = FunctionDescriptor.of( + /*returns=*/SwiftValueLayout.SWIFT_POINTER, + ValueLayout.ADDRESS + ); + + public static final MemorySegment ADDR = findOrThrow("getTypeByStringByteArray"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + } + + /** + * Get a Swift {@code Any.Type} wrapped by {@link SwiftAnyType} which represents the type metadata available at runtime. + * + * @param mangledName The mangled type name (often prefixed with {@code $s}). + * @return the Swift Type wrapper object + */ + public static Optional getTypeByMangledNameInEnvironment(String mangledName) { + System.out.println("Get Any.Type for mangled name: " + mangledName); + var mh$ = swift_getTypeByMangledNameInEnvironment.HANDLE; try { - if (string.endsWith("CN")) { - string = string.substring(0, string.length() - 2); - } + // Strip the generic "$s" prefix always + mangledName = stripPrefix(mangledName, "$s"); + // Ma is the "metadata accessor" mangled names of types we get from swiftinterface + // contain this, but we don't need it for type lookup + mangledName = stripSuffix(mangledName, "Ma"); + mangledName = stripSuffix(mangledName, "CN"); if (TRACE_DOWNCALLS) { - traceDowncall(string); + traceDowncall("swift_getTypeByMangledNameInEnvironment", mangledName); } try (Arena arena = Arena.ofConfined()) { - MemorySegment stringMemorySegment = arena.allocateFrom(string); + MemorySegment stringMemorySegment = arena.allocateFrom(mangledName); - return (MemorySegment) mh$.invokeExact(stringMemorySegment, string.length(), MemorySegment.NULL, MemorySegment.NULL); + var memorySegment = (MemorySegment) mh$.invokeExact(stringMemorySegment, mangledName.length(), MemorySegment.NULL, MemorySegment.NULL); + + if (memorySegment.address() == 0) { + return Optional.empty(); + } + + var wrapper = new SwiftAnyType(memorySegment); + return Optional.of(wrapper); } } catch (Throwable ex$) { throw new AssertionError("should not reach here", ex$); } } - /** - * The value layout for Swift's Int type, which is a signed type that follows - * the size of a pointer (aka C's ptrdiff_t). - */ - public static ValueLayout SWIFT_INT = (ValueLayout.ADDRESS.byteSize() == 4) ? - ValueLayout.JAVA_INT : ValueLayout.JAVA_LONG; - - /** - * The value layout for Swift's UInt type, which is an unsigned type that follows - * the size of a pointer (aka C's size_t). Java does not have unsigned integer - * types in general, so we use the layout for Swift's Int. - */ - public static ValueLayout SWIFT_UINT = SWIFT_INT; - /** * Read a Swift.Int value from memory at the given offset and translate it into a Java long. *

* This function copes with the fact that a Swift.Int might be 32 or 64 bits. */ - public static final long getSwiftInt(MemorySegment memorySegment, long offset) { - if (SWIFT_INT == ValueLayout.JAVA_LONG) { + public static long getSwiftInt(MemorySegment memorySegment, long offset) { + if (SwiftValueLayout.SWIFT_INT == ValueLayout.JAVA_LONG) { return memorySegment.get(ValueLayout.JAVA_LONG, offset); } else { return memorySegment.get(ValueLayout.JAVA_INT, offset); } } - /** - * Value witness table layout. - */ - public static final MemoryLayout valueWitnessTableLayout = MemoryLayout.structLayout( - ValueLayout.ADDRESS.withName("initializeBufferWithCopyOfBuffer"), - ValueLayout.ADDRESS.withName("destroy"), - ValueLayout.ADDRESS.withName("initializeWithCopy"), - ValueLayout.ADDRESS.withName("assignWithCopy"), - ValueLayout.ADDRESS.withName("initializeWithTake"), - ValueLayout.ADDRESS.withName("assignWithTake"), - ValueLayout.ADDRESS.withName("getEnumTagSinglePayload"), - ValueLayout.ADDRESS.withName("storeEnumTagSinglePayload"), - SwiftKit.SWIFT_INT.withName("size"), - SwiftKit.SWIFT_INT.withName("stride"), - SwiftKit.SWIFT_UINT.withName("flags"), - SwiftKit.SWIFT_UINT.withName("extraInhabitantCount") - ).withName("SwiftValueWitnessTable"); - - /** - * Offset for the "size" field within the value witness table. - */ - static final long valueWitnessTable$size$offset = - valueWitnessTableLayout.byteOffset(PathElement.groupElement("size")); - - /** - * Offset for the "stride" field within the value witness table. - */ - static final long valueWitnessTable$stride$offset = - valueWitnessTableLayout.byteOffset(PathElement.groupElement("stride")); - /** - * Offset for the "flags" field within the value witness table. - */ - static final long valueWitnessTable$flags$offset = - valueWitnessTableLayout.byteOffset(PathElement.groupElement("flags")); - /** - * Type metadata pointer. - */ - public static final StructLayout fullTypeMetadataLayout = MemoryLayout.structLayout( - SWIFT_POINTER.withName("vwt") - ).withName("SwiftFullTypeMetadata"); - - /** - * Offset for the "vwt" field within the full type metadata. - */ - static final long fullTypeMetadata$vwt$offset = - fullTypeMetadataLayout.byteOffset(PathElement.groupElement("vwt")); + private static class swift_getTypeName { - /** - * Given the address of Swift type metadata for a type, return the addres - * of the "full" type metadata that can be accessed via fullTypeMetadataLayout. - */ - public static MemorySegment fullTypeMetadata(MemorySegment typeMetadata) { - return MemorySegment.ofAddress(typeMetadata.address() - SWIFT_POINTER.byteSize()) - .reinterpret(fullTypeMetadataLayout.byteSize()); - } - - /** - * Given the address of Swift type's metadata, return the address that - * references the value witness table for the type. - */ - public static MemorySegment valueWitnessTable(MemorySegment typeMetadata) { - return fullTypeMetadata(typeMetadata).get(SWIFT_POINTER, fullTypeMetadata$vwt$offset); - } - - /** - * Determine the size of a Swift type given its type metadata. - */ - public static long sizeOfSwiftType(MemorySegment typeMetadata) { - return getSwiftInt(valueWitnessTable(typeMetadata), valueWitnessTable$size$offset); - } + /** + * Descriptor for the swift_getTypeName runtime function. + */ + public static final FunctionDescriptor DESC = FunctionDescriptor.of( + /*returns=*/MemoryLayout.structLayout( + SwiftValueLayout.SWIFT_POINTER.withName("utf8Chars"), + SwiftValueLayout.SWIFT_INT.withName("length") + ), + ValueLayout.ADDRESS, + ValueLayout.JAVA_BOOLEAN + ); - /** - * Determine the stride of a Swift type given its type metadata, which is - * how many bytes are between successive elements of this type within an - * array. It is >= the size. - */ - public static long strideOfSwiftType(MemorySegment typeMetadata) { - return getSwiftInt(valueWitnessTable(typeMetadata), valueWitnessTable$stride$offset); - } + /** + * Address of the swift_getTypeName runtime function. + */ + public static final MemorySegment ADDR = findOrThrow("swift_getTypeName"); - /** - * Determine the alignment of the given Swift type. - */ - public static long alignmentOfSwiftType(MemorySegment typeMetadata) { - long flags = getSwiftInt(valueWitnessTable(typeMetadata), valueWitnessTable$flags$offset); - return (flags & 0xFF) + 1; + /** + * Handle for the swift_getTypeName runtime function. + */ + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } - /** - * Descriptor for the swift_getTypeName runtime function. - */ - public static final FunctionDescriptor swift_getTypeName$descriptor = FunctionDescriptor.of( - /*returns=*/MemoryLayout.structLayout( - SWIFT_POINTER.withName("utf8Chars"), - SWIFT_INT.withName("length") - ), - ValueLayout.ADDRESS, - ValueLayout.JAVA_BOOLEAN - ); - - /** - * Address of the swift_getTypeName runtime function. - */ - public static final MemorySegment swift_getTypeName$addr = findOrThrow("swift_getTypeName"); - - /** - * Handle for the swift_getTypeName runtime function. - */ - public static final MethodHandle swift_getTypeName$handle = Linker.nativeLinker().downcallHandle(swift_getTypeName$addr, swift_getTypeName$descriptor); - /** * Produce the name of the Swift type given its Swift type metadata. *

- * If 'qualified' is true, leave all of the qualification in place to + * If 'qualified' is true, leave all the qualification in place to * disambiguate the type, producing a more complete (but longer) type name. + * + * @param typeMetadata the memory segment must point to a Swift metadata, + * e.g. the result of a {@link swift_getTypeByMangledNameInEnvironment} call */ public static String nameOfSwiftType(MemorySegment typeMetadata, boolean qualified) { - try { - try (Arena arena = Arena.ofConfined()) { - MemorySegment charsAndLength = (MemorySegment) swift_getTypeName$handle.invokeExact((SegmentAllocator) arena, typeMetadata, qualified); - MemorySegment utf8Chars = charsAndLength.get(SWIFT_POINTER, 0); - String typeName = utf8Chars.getString(0); - cFree(utf8Chars); - return typeName; - } + MethodHandle mh = swift_getTypeName.HANDLE; + + try (Arena arena = Arena.ofConfined()) { + MemorySegment charsAndLength = (MemorySegment) mh.invokeExact((SegmentAllocator) arena, typeMetadata, qualified); + MemorySegment utf8Chars = charsAndLength.get(SwiftValueLayout.SWIFT_POINTER, 0); + String typeName = utf8Chars.getString(0); + + // FIXME: this free is not always correct: + // java(80175,0x17008f000) malloc: *** error for object 0x600000362610: pointer being freed was not allocated + // cFree(utf8Chars); + + return typeName; } catch (Throwable ex$) { throw new AssertionError("should not reach here", ex$); } } - /** - * Produce a layout that describes a Swift type based on its - * type metadata. The resulting layout is completely opaque to Java, but - * has appropriate size/alignment to model the memory associated with a - * Swift type. - *

- * In the future, this layout could be extended to provide more detail, - * such as the fields of a Swift struct. - */ - public static MemoryLayout layoutOfSwiftType(MemorySegment typeMetadata) { - long size = sizeOfSwiftType(typeMetadata); - long stride = strideOfSwiftType(typeMetadata); - return MemoryLayout.structLayout( - MemoryLayout.sequenceLayout(size, JAVA_BYTE) - .withByteAlignment(alignmentOfSwiftType(typeMetadata)), - MemoryLayout.paddingLayout(stride - size) - ).withName(nameOfSwiftType(typeMetadata, true)); - } } diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValue.java b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValue.java new file mode 100644 index 00000000..9387fa85 --- /dev/null +++ b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValue.java @@ -0,0 +1,19 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package org.swift.swiftkit; + +public interface SwiftValue extends SwiftInstance { + SwiftAnyType $swiftType(); +} diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValueLayout.java b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValueLayout.java new file mode 100644 index 00000000..565b6da5 --- /dev/null +++ b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValueLayout.java @@ -0,0 +1,55 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package org.swift.swiftkit; + +import java.lang.foreign.AddressLayout; +import java.lang.foreign.MemoryLayout; +import java.lang.foreign.ValueLayout; + +import static java.lang.foreign.ValueLayout.*; + +/** + * Similar to {@link java.lang.foreign.ValueLayout} however with some Swift specifics. + */ +public class SwiftValueLayout { + + /** + * The width of a pointer on the current platform. + */ + public static long addressByteSize() { + return ValueLayout.ADDRESS.byteSize(); + } + + /** + * The value layout for Swift's {@code Int} type, which is a signed type that follows + * the size of a pointer (aka C's {@code ptrdiff_t}). + */ + public static ValueLayout SWIFT_INT = (ValueLayout.ADDRESS.byteSize() == 4) ? + ValueLayout.JAVA_INT : ValueLayout.JAVA_LONG; + + + /** + * The value layout for Swift's {@code UInt} type, which is an unsigned type that follows + * the size of a pointer (aka C's {@code size_t}). + *

+ * Java does not have unsigned integer types, so we use the layout for Swift's {@code Int}. + */ + public static ValueLayout SWIFT_UINT = SWIFT_INT; + + + public static final AddressLayout SWIFT_POINTER = ValueLayout.ADDRESS + .withTargetLayout(MemoryLayout.sequenceLayout(Long.MAX_VALUE, JAVA_BYTE)); + +} diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValueWitnessTable.java b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValueWitnessTable.java new file mode 100644 index 00000000..826a4fa2 --- /dev/null +++ b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValueWitnessTable.java @@ -0,0 +1,228 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package org.swift.swiftkit; + +import java.lang.foreign.*; +import java.lang.invoke.MethodHandle; + +import static java.lang.foreign.ValueLayout.JAVA_BYTE; +import static org.swift.swiftkit.SwiftKit.getSwiftInt; + +public abstract class SwiftValueWitnessTable { + + /** + * Value witness table layout. + */ + public static final MemoryLayout $LAYOUT = MemoryLayout.structLayout( + ValueLayout.ADDRESS.withName("initializeBufferWithCopyOfBuffer"), + ValueLayout.ADDRESS.withName("destroy"), + ValueLayout.ADDRESS.withName("initializeWithCopy"), + ValueLayout.ADDRESS.withName("assignWithCopy"), + ValueLayout.ADDRESS.withName("initializeWithTake"), + ValueLayout.ADDRESS.withName("assignWithTake"), + ValueLayout.ADDRESS.withName("getEnumTagSinglePayload"), + ValueLayout.ADDRESS.withName("storeEnumTagSinglePayload"), + SwiftValueLayout.SWIFT_INT.withName("size"), + SwiftValueLayout.SWIFT_INT.withName("stride"), + SwiftValueLayout.SWIFT_UINT.withName("flags"), + SwiftValueLayout.SWIFT_UINT.withName("extraInhabitantCount") + ).withName("SwiftValueWitnessTable"); + + + /** + * Type metadata pointer. + */ + private static final StructLayout fullTypeMetadataLayout = MemoryLayout.structLayout( + SwiftValueLayout.SWIFT_POINTER.withName("vwt") + ).withName("SwiftFullTypeMetadata"); + + /** + * Offset for the "vwt" field within the full type metadata. + */ + private static final long fullTypeMetadata$vwt$offset = + fullTypeMetadataLayout.byteOffset( + MemoryLayout.PathElement.groupElement("vwt")); + + /** + * Given the address of Swift type metadata for a type, return the addres + * of the "full" type metadata that can be accessed via fullTypeMetadataLayout. + */ + public static MemorySegment fullTypeMetadata(MemorySegment typeMetadata) { + return MemorySegment.ofAddress(typeMetadata.address() - SwiftValueLayout.SWIFT_POINTER.byteSize()) + .reinterpret(fullTypeMetadataLayout.byteSize()); + } + + /** + * Given the address of Swift type's metadata, return the address that + * references the value witness table for the type. + */ + public static MemorySegment valueWitnessTable(MemorySegment typeMetadata) { + return fullTypeMetadata(typeMetadata) + .get(SwiftValueLayout.SWIFT_POINTER, SwiftValueWitnessTable.fullTypeMetadata$vwt$offset); +// .get(ValueLayout.ADDRESS, SwiftValueWitnessTable.fullTypeMetadata$vwt$offset); + } + + + /** + * Offset for the "size" field within the value witness table. + */ + static final long $size$offset = + $LAYOUT.byteOffset(MemoryLayout.PathElement.groupElement("size")); + + /** + * Determine the size of a Swift type given its type metadata. + * + * @param typeMetadata the memory segment must point to a Swift metadata + */ + public static long sizeOfSwiftType(MemorySegment typeMetadata) { + return getSwiftInt(valueWitnessTable(typeMetadata), SwiftValueWitnessTable.$size$offset); + } + + + /** + * Offset for the "stride" field within the value witness table. + */ + static final long $stride$offset = + $LAYOUT.byteOffset(MemoryLayout.PathElement.groupElement("stride")); + + /** + * Determine the stride of a Swift type given its type metadata, which is + * how many bytes are between successive elements of this type within an + * array. + *

+ * It is >= the size. + * + * @param typeMetadata the memory segment must point to a Swift metadata + */ + public static long strideOfSwiftType(MemorySegment typeMetadata) { + return getSwiftInt(valueWitnessTable(typeMetadata), SwiftValueWitnessTable.$stride$offset); + } + + + /** + * Determine the alignment of the given Swift type. + * + * @param typeMetadata the memory segment must point to a Swift metadata + */ + public static long alignmentOfSwiftType(MemorySegment typeMetadata) { + long flags = getSwiftInt(valueWitnessTable(typeMetadata), SwiftValueWitnessTable.$flags$offset); + return (flags & 0xFF) + 1; + } + + /** + * Produce a layout that describes a Swift type based on its + * type metadata. The resulting layout is completely opaque to Java, but + * has appropriate size/alignment to model the memory associated with a + * Swift type. + *

+ * In the future, this layout could be extended to provide more detail, + * such as the fields of a Swift struct. + * + * @param typeMetadata the memory segment must point to a Swift metadata + */ + public static MemoryLayout layoutOfSwiftType(MemorySegment typeMetadata) { + long size = sizeOfSwiftType(typeMetadata); + long stride = strideOfSwiftType(typeMetadata); + long padding = stride - size; + + // constructing a zero-length paddingLayout is illegal, so we avoid doing so + MemoryLayout[] layouts = padding == 0 ? + new MemoryLayout[]{ + MemoryLayout.sequenceLayout(size, JAVA_BYTE) + .withByteAlignment(alignmentOfSwiftType(typeMetadata)) + } : + new MemoryLayout[]{ + MemoryLayout.sequenceLayout(size, JAVA_BYTE) + .withByteAlignment(alignmentOfSwiftType(typeMetadata)), + MemoryLayout.paddingLayout(stride - size) + }; + + return MemoryLayout.structLayout( + layouts + ).withName(SwiftKit.nameOfSwiftType(typeMetadata, true)); + } + + + /** + * Offset for the "flags" field within the value witness table. + */ + static final long $flags$offset = + $LAYOUT.byteOffset(MemoryLayout.PathElement.groupElement("flags")); + + /** + * {@snippet lang = C: + * ///void(*destroy)(T *object, witness_t *self); + * /// + * /// Given a valid object of this type, destroy it, leaving it as an + * /// invalid object. This is useful when generically destroying + * /// an object which has been allocated in-line, such as an array, + * /// struct,or tuple element. + * FUNCTION_VALUE_WITNESS(destroy, + * Destroy, + * VOID_TYPE, + * (MUTABLE_VALUE_TYPE, TYPE_TYPE)) + *} + */ + private static class destroy { + + static final long $offset = + $LAYOUT.byteOffset(MemoryLayout.PathElement.groupElement("destroy")); + + static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( + ValueLayout.ADDRESS, // witness table functions expect a pointer to self pointer + ValueLayout.ADDRESS // pointer to the witness table + ); + + /** + * Function pointer for the destroy operation + */ + static MemorySegment addr(SwiftAnyType ty) { + // Get the value witness table of the type + final var vwt = SwiftValueWitnessTable.valueWitnessTable(ty.$memorySegment()); + + // Get the address of the destroy function stored at the offset of the witness table + long funcAddress = getSwiftInt(vwt, destroy.$offset); + return MemorySegment.ofAddress(funcAddress); + } + + static MethodHandle handle(SwiftAnyType ty) { + return Linker.nativeLinker().downcallHandle(addr(ty), DESC); + } + } + + + /** + * Destroy the value/object. + *

+ * This includes deallocating the Swift managed memory for the object. + */ + public static void destroy(SwiftAnyType type, MemorySegment object) { + var fullTypeMetadata = fullTypeMetadata(type.$memorySegment()); + var wtable = valueWitnessTable(fullTypeMetadata); + + var mh = destroy.handle(type); + + try (var arena = Arena.ofConfined()) { + // we need to make a pointer to the self pointer when calling witness table functions: + MemorySegment indirect = arena.allocate(SwiftValueLayout.SWIFT_POINTER); // TODO: remove this and just have classes have this always anyway + MemorySegmentUtils.setSwiftPointerAddress(indirect, object); + + mh.invokeExact(indirect, wtable); + } catch (Throwable th) { + throw new AssertionError("Failed to destroy '" + type + "' at " + object, th); + } + } + +} diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/util/PlatformUtils.java b/SwiftKit/src/main/java/org/swift/swiftkit/util/PlatformUtils.java new file mode 100644 index 00000000..2c51143f --- /dev/null +++ b/SwiftKit/src/main/java/org/swift/swiftkit/util/PlatformUtils.java @@ -0,0 +1,38 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package org.swift.swiftkit.util; + +public class PlatformUtils { + public static boolean isLinux() { + return System.getProperty("os.name").toLowerCase().contains("linux"); + } + + public static boolean isMacOS() { + return System.getProperty("os.name").toLowerCase().contains("mac"); + } + + public static boolean isWindows() { + return System.getProperty("os.name").toLowerCase().contains("windows"); + } + + public static boolean isAarch64() { + return System.getProperty("os.arch").equals("aarm64"); + } + + public static boolean isAmd64() { + String arch = System.getProperty("os.arch"); + return arch.equals("amd64") || arch.equals("x86_64"); + } +} diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/util/StringUtils.java b/SwiftKit/src/main/java/org/swift/swiftkit/util/StringUtils.java new file mode 100644 index 00000000..6753ea73 --- /dev/null +++ b/SwiftKit/src/main/java/org/swift/swiftkit/util/StringUtils.java @@ -0,0 +1,36 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package org.swift.swiftkit.util; + +public class StringUtils { + public static String stripPrefix(String mangledName, String prefix) { + if (mangledName.startsWith(prefix)) { + return mangledName.substring(prefix.length()); + } + return mangledName; + } + + public static String stripSuffix(String mangledName, String suffix) { + if (mangledName.endsWith(suffix)) { + return mangledName.substring(0, mangledName.length() - suffix.length()); + } + return mangledName; + } + + public static String hexString(long number) { + return String.format("0x%02x", number); + } + +} diff --git a/SwiftKit/src/test/java/org/swift/swiftkit/SwiftRuntimeMetadataTest.java b/SwiftKit/src/test/java/org/swift/swiftkit/SwiftRuntimeMetadataTest.java new file mode 100644 index 00000000..5354cc4f --- /dev/null +++ b/SwiftKit/src/test/java/org/swift/swiftkit/SwiftRuntimeMetadataTest.java @@ -0,0 +1,60 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package org.swift.swiftkit; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class SwiftRuntimeMetadataTest { + + @Test + public void integer_layout_metadata() { + SwiftAnyType swiftType = SwiftKit.getTypeByMangledNameInEnvironment("Si").get(); + + if (SwiftValueLayout.addressByteSize() == 4) { + // 32-bit platform + Assertions.assertEquals(8, SwiftValueWitnessTable.sizeOfSwiftType(swiftType.$memorySegment())); + Assertions.assertEquals(8, SwiftValueWitnessTable.strideOfSwiftType(swiftType.$memorySegment())); + Assertions.assertEquals(8, SwiftValueWitnessTable.alignmentOfSwiftType(swiftType.$memorySegment())); + Assertions.assertEquals("[8%[9:b1]x7](Swift.Int)", SwiftValueWitnessTable.layoutOfSwiftType(swiftType.$memorySegment()).toString()); + } else { + // 64-bit platform + Assertions.assertEquals(8, SwiftValueWitnessTable.sizeOfSwiftType(swiftType.$memorySegment())); + Assertions.assertEquals(8, SwiftValueWitnessTable.strideOfSwiftType(swiftType.$memorySegment())); + Assertions.assertEquals(8, SwiftValueWitnessTable.alignmentOfSwiftType(swiftType.$memorySegment())); + Assertions.assertEquals("[8%[8:b1]](Swift.Int)", SwiftValueWitnessTable.layoutOfSwiftType(swiftType.$memorySegment()).toString()); + } + } + + @Test + public void optional_integer_layout_metadata() { + SwiftAnyType swiftType = SwiftKit.getTypeByMangledNameInEnvironment("SiSg").get(); + + if (SwiftValueLayout.addressByteSize() == 4) { + // 64-bit platform + Assertions.assertEquals(9, SwiftValueWitnessTable.sizeOfSwiftType(swiftType.$memorySegment())); + Assertions.assertEquals(16, SwiftValueWitnessTable.strideOfSwiftType(swiftType.$memorySegment())); + Assertions.assertEquals(8, SwiftValueWitnessTable.alignmentOfSwiftType(swiftType.$memorySegment())); + Assertions.assertEquals("[8%[9:b1]x7](Swift.Optional)", SwiftValueWitnessTable.layoutOfSwiftType(swiftType.$memorySegment()).toString()); + } else { + // 64-bit platform + Assertions.assertEquals(9, SwiftValueWitnessTable.sizeOfSwiftType(swiftType.$memorySegment())); + Assertions.assertEquals(16, SwiftValueWitnessTable.strideOfSwiftType(swiftType.$memorySegment())); + Assertions.assertEquals(8, SwiftValueWitnessTable.alignmentOfSwiftType(swiftType.$memorySegment())); + Assertions.assertEquals("[8%[9:b1]x7](Swift.Optional)", SwiftValueWitnessTable.layoutOfSwiftType(swiftType.$memorySegment()).toString()); + } + } + +} diff --git a/Tests/JExtractSwiftTests/FuncImportTests.swift b/Tests/JExtractSwiftTests/FuncImportTests.swift index 80f04f7d..3b2ef4f4 100644 --- a/Tests/JExtractSwiftTests/FuncImportTests.swift +++ b/Tests/JExtractSwiftTests/FuncImportTests.swift @@ -403,7 +403,7 @@ final class MethodImportTests { }! let output = CodePrinter.toString { printer in - st.printClassInitializerConstructor(&printer, initDecl, parentName: initDecl.parentName!) + st.printClassInitializerConstructors(&printer, initDecl, parentName: initDecl.parentName!) } assertOutput( @@ -418,15 +418,28 @@ final class MethodImportTests { * } */ public MySwiftClass(long len, long cap) { + this(/*arena=*/null, len, cap); + } + /** + * Create an instance of {@code MySwiftClass}. + * This instance is managed by the passed in {@link SwiftArena} and may not outlive the arena's lifetime. + * + * {@snippet lang=swift : + * public init(len: Swift.Int, cap: Swift.Int) + * } + */ + public MySwiftClass(SwiftArena arena, long len, long cap) { var mh$ = init_len_cap.HANDLE; try { - if (TRACE_DOWNCALLS) { - traceDowncall(len, cap); - } - - this.selfMemorySegment = (MemorySegment) mh$.invokeExact(len, cap, TYPE_METADATA); + if (TRACE_DOWNCALLS) { + traceDowncall(len, cap); + } + this.selfMemorySegment = (MemorySegment) mh$.invokeExact(len, cap, TYPE_METADATA.$memorySegment()); + if (arena != null) { + arena.register(this); + } } catch (Throwable ex$) { - throw new AssertionError(\"should not reach here\", ex$); + throw new AssertionError("should not reach here", ex$); } } """ diff --git a/buildSrc/src/main/groovy/org/swift/swiftkit/gradle/BuildUtils.groovy b/buildSrc/src/main/groovy/org/swift/swiftkit/gradle/BuildUtils.groovy index 3f50890d..e6a29ae9 100644 --- a/buildSrc/src/main/groovy/org/swift/swiftkit/gradle/BuildUtils.groovy +++ b/buildSrc/src/main/groovy/org/swift/swiftkit/gradle/BuildUtils.groovy @@ -21,20 +21,28 @@ final class BuildUtils { def osName = System.getProperty("os.name") def osArch = System.getProperty("os.arch") def isLinux = osName.toLowerCase(Locale.getDefault()).contains("linux") + def base = rootDir == null ? "" : "${rootDir}/" + System.out.println("Root dir is = ${rootDir}") return [ isLinux ? - /* Linux */(osArch == "amd64" || osArch == "amd64" ? - "${rootDir}/.build/x86_64-unknown-linux-gnu/debug/" : - "${rootDir}/.build/${osArch}-unknown-linux-gnu/debug/") : - /* macOS */(osArch == "aarch64" ? - "${rootDir}/.build/arm64-apple-macosx/debug/" : - "${rootDir}/.build/${osArch}-apple-macosx/debug/"), + /* Linux */ (osArch == "amd64" || osArch == "x86_64" ? + "${base}.build/x86_64-unknown-linux-gnu/debug/" : + "${base}.build/${osArch}-unknown-linux-gnu/debug/") : + /* macOS */ (osArch == "aarch64" ? + "${base}.build/arm64-apple-macosx/debug/" : + "${base}.build/${osArch}-apple-macosx/debug/"), + isLinux ? + /* Linux */ (osArch == "amd64" || osArch == "x86_64" ? + "${base}../../.build/x86_64-unknown-linux-gnu/debug/" : + "${base}../../.build/${osArch}-unknown-linux-gnu/debug/") : + /* macOS */ (osArch == "aarch64" ? + "${base}../../.build/arm64-apple-macosx/debug/" : + "${base}../../.build/${osArch}-apple-macosx/debug/"), isLinux ? "/usr/lib/swift/linux" : // assume macOS "/usr/lib/swift/" ] } - } From df89d7ea3e829693c045dfccddf13c006b914389 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Tue, 22 Oct 2024 17:09:43 +0900 Subject: [PATCH 117/426] cache JDK, speedup downloads and CI time (#98) --- .github/workflows/pull_request.yml | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 08ebc7b6..6590c553 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -30,12 +30,21 @@ jobs: - uses: actions/checkout@v4 - name: Install System Dependencies run: apt-get -qq update && apt-get -qq install -y make curl wget + - name: Cache JDK + id: cache-jdk + uses: actions/cache@v4 + continue-on-error: true + with: + path: /usr/lib/jvm/default-jdk/ + key: ${{ runner.os }}-jdk-${{ matrix.jdk_vendor }}-${{ hashFiles('/usr/lib/jvm/default-jdk/*') }} + restore-keys: | + ${{ runner.os }}-jdk- - name: Install JDK + if: steps.cache-jdk.outputs.cache-hit != 'true' run: "bash -xc 'JDK_VENDOR=${{ matrix.jdk_vendor }} ./docker/install_jdk.sh'" # TODO: not using setup-java since incompatible with the swiftlang/swift base image - name: Install Untested Nightly Swift run: "bash -xc './docker/install_untested_nightly_swift.sh'" - # setup caches - name: Cache local Gradle repository uses: actions/cache@v4 continue-on-error: true @@ -79,11 +88,21 @@ jobs: - uses: actions/checkout@v4 - name: Install System Dependencies run: apt-get -qq update && apt-get -qq install -y make curl wget + - name: Cache JDK + id: cache-jdk + uses: actions/cache@v4 + continue-on-error: true + with: + path: /usr/lib/jvm/default-jdk/ + key: ${{ runner.os }}-jdk-${{ matrix.jdk_vendor }}-${{ hashFiles('/usr/lib/jvm/default-jdk/*') }} + restore-keys: | + ${{ runner.os }}-jdk- - name: Install JDK + if: steps.cache-jdk.outputs.cache-hit != 'true' run: "bash -xc 'JDK_VENDOR=${{ matrix.jdk_vendor }} ./docker/install_jdk.sh'" + # TODO: not using setup-java since incompatible with the swiftlang/swift base image - name: Install Untested Nightly Swift run: "bash -xc './docker/install_untested_nightly_swift.sh'" - # setup caches - name: Cache local Gradle repository uses: actions/cache@v4 continue-on-error: true From 99651732362ba38819567b3a76ee0a3efb66b172 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Tue, 22 Oct 2024 17:18:39 +0900 Subject: [PATCH 118/426] Cleanup in MemorySegmentUtils --- .../src/main/java/org/swift/swiftkit/MemorySegmentUtils.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/MemorySegmentUtils.java b/SwiftKit/src/main/java/org/swift/swiftkit/MemorySegmentUtils.java index c1ab8995..660a5500 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/MemorySegmentUtils.java +++ b/SwiftKit/src/main/java/org/swift/swiftkit/MemorySegmentUtils.java @@ -29,10 +29,8 @@ static void setSwiftPointerAddress(MemorySegment target, MemorySegment memorySeg // Write the address of as the value of the newly created pointer. // We need to type-safely set the pointer value which may be 64 or 32-bit. if (SwiftValueLayout.SWIFT_INT == ValueLayout.JAVA_LONG) { - System.out.println("[setSwiftPointerAddress] address is long = " + memorySegment.address()); target.set(ValueLayout.JAVA_LONG, /*offset=*/0, memorySegment.address()); } else { - System.out.println("[setSwiftPointerAddress] address is int = " + memorySegment.address()); target.set(ValueLayout.JAVA_INT, /*offset=*/0, (int) memorySegment.address()); } } From 6964e71ae5f56808560af9baa68dc76bdaef97b8 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Tue, 22 Oct 2024 23:31:47 +0900 Subject: [PATCH 119/426] implement () -> () as Runnable downcalls and upcalls (#100) --- .github/workflows/pull_request.yml | 3 +- .gitignore | 2 +- .../main/java/com/example/swift/CallMe.java | 25 -- .../example/swift/ManualJavaKitExample.java | 344 ------------------ .../com/example/swift/ManualMySwiftClass.java | 200 ---------- .../example/swift/Manual_MySwiftClass.java | 304 ---------------- .../GeneratedJavaKitExampleModuleTest.java | 31 +- .../ExampleSwiftLibrary/MySwiftLibrary.swift | 4 + Sources/JExtractSwift/CodePrinter.swift | 16 + Sources/JExtractSwift/ImportedDecls.swift | 9 +- Sources/JExtractSwift/JavaType+Printing.swift | 47 +++ .../Swift2JavaTranslator+Printing.swift | 45 ++- Sources/JavaTypes/JavaType+SwiftNames.swift | 12 + .../FuncCallbackImportTests.swift | 84 +++++ ...ortTests.swift => MethodImportTests.swift} | 0 .../swift/swiftkit/gradle/BuildUtils.groovy | 1 - 16 files changed, 239 insertions(+), 888 deletions(-) delete mode 100644 Samples/SwiftKitSampleApp/src/main/java/com/example/swift/CallMe.java delete mode 100644 Samples/SwiftKitSampleApp/src/main/java/com/example/swift/ManualJavaKitExample.java delete mode 100644 Samples/SwiftKitSampleApp/src/main/java/com/example/swift/ManualMySwiftClass.java delete mode 100644 Samples/SwiftKitSampleApp/src/main/java/com/example/swift/Manual_MySwiftClass.java create mode 100644 Sources/JExtractSwift/JavaType+Printing.swift create mode 100644 Tests/JExtractSwiftTests/FuncCallbackImportTests.swift rename Tests/JExtractSwiftTests/{FuncImportTests.swift => MethodImportTests.swift} (100%) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 6590c553..0005f1c4 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -67,8 +67,7 @@ jobs: # run the actual build - name: Gradle build run: | - ./gradlew build -x test --no-daemon # skip tests - find . + ./gradlew build -x test --no-daemon # just build ./gradlew build --info --no-daemon test-swift: diff --git a/.gitignore b/.gitignore index 43b51002..5055eec2 100644 --- a/.gitignore +++ b/.gitignore @@ -32,4 +32,4 @@ Package.resolved .gradletasknamecache # Ignore files generated by jextract, we always can re-generate them -*/**/*.java +*/**/src/generated/java/**/* diff --git a/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/CallMe.java b/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/CallMe.java deleted file mode 100644 index e3e10815..00000000 --- a/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/CallMe.java +++ /dev/null @@ -1,25 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of Swift.org project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -package com.example.swift; - -public class CallMe { - public static String callMeStatic() { - return "[java] Swift called Java via Panama!"; - } - - public String callMe() { - return "[java] Swift called Java via Panama!"; - } -} diff --git a/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/ManualJavaKitExample.java b/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/ManualJavaKitExample.java deleted file mode 100644 index 1d9cfa77..00000000 --- a/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/ManualJavaKitExample.java +++ /dev/null @@ -1,344 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of Swift.org project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -package com.example.swift; - -import java.lang.invoke.*; -import java.lang.foreign.*; -import java.util.*; -import java.util.stream.*; - -import static java.lang.foreign.ValueLayout.*; - -/** - * Generated by {@code jextract-swift}. // TODO: will be... :-) - */ -public class ManualJavaKitExample { - - ManualJavaKitExample() { - // Should not be called directly - } - - static final String DYLIB_NAME = "JavaKitExample"; - static final Arena LIBRARY_ARENA = Arena.ofAuto(); - static final boolean TRACE_DOWNCALLS = Boolean.getBoolean("jextract.trace.downcalls"); - - static void traceDowncall(Object... args) { - var ex = new RuntimeException(); - - String traceArgs = Arrays.stream(args) - .map(Object::toString) - .collect(Collectors.joining(", ")); - System.out.printf("[java][%s:%d] %s(%s)\n", - ex.getStackTrace()[1].getFileName(), - ex.getStackTrace()[1].getLineNumber(), - ex.getStackTrace()[1].getMethodName(), - traceArgs); - } - - static void trace(Object... args) { - var ex = new RuntimeException(); - - String traceArgs = Arrays.stream(args) - .map(Object::toString) - .collect(Collectors.joining(", ")); - System.out.printf("[java][%s:%d] %s: %s\n", - ex.getStackTrace()[1].getFileName(), - ex.getStackTrace()[1].getLineNumber(), - ex.getStackTrace()[1].getMethodName(), - traceArgs); - } - - static MemorySegment findOrThrow(String symbol) { - return SYMBOL_LOOKUP.find(symbol) - .orElseThrow(() -> new UnsatisfiedLinkError("unresolved symbol: %s".formatted(symbol))); - } - - static MethodHandle upcallHandle(Class fi, String name, FunctionDescriptor fdesc) { - try { - return MethodHandles.lookup().findVirtual(fi, name, fdesc.toMethodType()); - } catch (ReflectiveOperationException ex) { - throw new AssertionError(ex); - } - } - - static MemoryLayout align(MemoryLayout layout, long align) { - return switch (layout) { - case PaddingLayout p -> p; - case ValueLayout v -> v.withByteAlignment(align); - case GroupLayout g -> { - MemoryLayout[] alignedMembers = g.memberLayouts().stream() - .map(m -> align(m, align)).toArray(MemoryLayout[]::new); - yield g instanceof StructLayout ? - MemoryLayout.structLayout(alignedMembers) : MemoryLayout.unionLayout(alignedMembers); - } - case SequenceLayout s -> MemoryLayout.sequenceLayout(s.elementCount(), align(s.elementLayout(), align)); - }; - } - - static final SymbolLookup SYMBOL_LOOKUP = - SymbolLookup.libraryLookup(System.mapLibraryName(DYLIB_NAME), LIBRARY_ARENA) - .or(SymbolLookup.loaderLookup()) - .or(Linker.nativeLinker().defaultLookup()); - - // TODO: rather than the C ones offer the Swift mappings - public static final ValueLayout.OfBoolean C_BOOL = ValueLayout.JAVA_BOOLEAN; - public static final ValueLayout.OfByte C_CHAR = ValueLayout.JAVA_BYTE; - public static final ValueLayout.OfShort C_SHORT = ValueLayout.JAVA_SHORT; - public static final ValueLayout.OfInt C_INT = ValueLayout.JAVA_INT; - public static final ValueLayout.OfLong C_LONG_LONG = ValueLayout.JAVA_LONG; - public static final ValueLayout.OfFloat C_FLOAT = ValueLayout.JAVA_FLOAT; - public static final ValueLayout.OfDouble C_DOUBLE = ValueLayout.JAVA_DOUBLE; - public static final AddressLayout C_POINTER = ValueLayout.ADDRESS - .withTargetLayout(MemoryLayout.sequenceLayout(java.lang.Long.MAX_VALUE, JAVA_BYTE)); - public static final ValueLayout.OfLong C_LONG = ValueLayout.JAVA_LONG; - - public static final ValueLayout.OfBoolean SWIFT_BOOL = ValueLayout.JAVA_BOOLEAN; - public static final ValueLayout.OfByte SWIFT_INT8 = ValueLayout.JAVA_BYTE; - public static final ValueLayout.OfChar SWIFT_UINT16 = ValueLayout.JAVA_CHAR; - public static final ValueLayout.OfShort SWIFT_INT16 = ValueLayout.JAVA_SHORT; - public static final ValueLayout.OfInt SWIFT_INT32 = ValueLayout.JAVA_INT; - public static final ValueLayout.OfLong SWIFT_INT64 = ValueLayout.JAVA_LONG; - public static final ValueLayout.OfFloat SWIFT_FLOAT = ValueLayout.JAVA_FLOAT; - public static final ValueLayout.OfDouble SWIFT_DOUBLE = ValueLayout.JAVA_DOUBLE; - public static final AddressLayout SWIFT_POINTER = ValueLayout.ADDRESS; - // On the platform this was generated on, Int was Int64 - public static final SequenceLayout SWIFT_BYTE_ARRAY = - MemoryLayout.sequenceLayout(8, JAVA_BYTE); - public static final ValueLayout.OfLong SWIFT_INT = SWIFT_INT64; - public static final ValueLayout.OfLong SWIFT_UINT = SWIFT_INT64; - public static final AddressLayout SWIFT_TYPE_METADATA_PTR = SWIFT_POINTER; - - // ----------------------------------------------------------------------------------------------------------------- - // helloWorld() - - // sil [ossa] @$s14JavaKitExample10helloWorldyyF : $@convention(thin) () -> () { - private static class helloWorld { - public static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid(); - - public static final MemorySegment ADDR = ManualJavaKitExample.findOrThrow("$s14JavaKitExample10helloWorldyyF"); - - public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); - } - - /** - * Function descriptor for: - * {@snippet lang = swift: - * public func useMySwiftSlice(slice: MySwiftLibrary.MySwiftSlice) - *} - */ - public static FunctionDescriptor helloWorld$descriptor() { - return helloWorld.DESC; - } - - /** - * Downcall method handle for: - * {@snippet lang = swift: - * public func useMySwiftSlice(slice: MySwiftLibrary.MySwiftSlice) - *} - */ - public static MethodHandle helloWorld$handle() { - return helloWorld.HANDLE; - } - - /** - * Address for: - * {@snippet lang = swift: - * public func useMySwiftSlice(slice: MySwiftLibrary.MySwiftSlice) - *} - */ - public static MemorySegment helloWorld$address() { - return helloWorld.ADDR; - } - - /** - * {@snippet lang = swift: - * public func useMySwiftSlice(slice: MySwiftLibrary.MySwiftSlice) - *} - */ - public static void helloWorld() { - var mh$ = helloWorld.HANDLE; - try { - if (TRACE_DOWNCALLS) { - traceDowncall(); - } - mh$.invokeExact(); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - } - - // ==== -------------------------------------------------- - // 0000000000031934 T JavaKitExample.globalCallJavaCallback(callMe: () -> ()) -> () - // 0000000000031934 T _$s14JavaKitExample010globalCallA8Callback6callMeyyyXE_tF - - private static class globalCallJavaCallback { - public static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( - ADDRESS // Runnable / () -> () - ); - - public static final MemorySegment ADDR = ManualJavaKitExample.findOrThrow("$s14JavaKitExample010globalCallA8Callback6callMeyyyXE_tF"); - - public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); - } - - - public static void globalCallJavaCallback(Runnable callMe) { - var mh$ = globalCallJavaCallback.HANDLE; - - try { - // signature of 'void run()' - FunctionDescriptor callMe_run_desc = FunctionDescriptor.ofVoid( - ); - MethodHandle callMe_run_handle = MethodHandles.lookup() - .findVirtual(Runnable.class, - "run", - callMe_run_desc.toMethodType()); - callMe_run_handle = callMe_run_handle.bindTo(callMe); // set the first parameter to the Runnable as the "this" of the callback pretty much - - try (Arena arena = Arena.ofConfined()) { - Linker linker = Linker.nativeLinker(); // the () -> () is not escaping, we can destroy along with the confined arena - MemorySegment runFunc = linker.upcallStub(callMe_run_handle, callMe_run_desc, arena); - mh$.invokeExact(runFunc); - } - - } catch (NoSuchMethodException | IllegalAccessException e) { - throw new RuntimeException(e); - } catch (Throwable e) { - throw new AssertionError(e); - } - } - - - // ----------------------------------------------------------------------------------------------------------------- - // FIXME: this must move into SwiftKit and call _typeByName with a Swift.String - - /// 00000000000255a4 T _$s14JavaKitExample33swiftkit_getTypeByStringByteArrayyypXpSgSPys5UInt8VGF - /// 00000000000255a4 T JavaKitExample.swiftkit_getTypeByStringByteArray(Swift.UnsafePointer) -> Any.Type? - private static class swiftkit_getTypeByStringByteArray { - public static final FunctionDescriptor DESC = FunctionDescriptor.of( - /* -> */ ValueLayout.ADDRESS, - ValueLayout.ADDRESS - ); - - public static final MemorySegment ADDR = ManualJavaKitExample.findOrThrow("$s14JavaKitExample33swiftkit_getTypeByStringByteArrayyypXpSgSPys5UInt8VGF"); - - public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); - } - - public static FunctionDescriptor swiftkit_getTypeByStringByteArray$descriptor() { - return swiftkit_getTypeByStringByteArray.DESC; - } - - public static MethodHandle swiftkit_getTypeByStringByteArray$handle() { - return swiftkit_getTypeByStringByteArray.HANDLE; - } - - public static MemorySegment swiftkit_getTypeByStringByteArray$address() { - return swiftkit_getTypeByStringByteArray.ADDR; - } - - public static MemorySegment swiftkit_getTypeByStringByteArray(String mangledName) { - var mh$ = swiftkit_getTypeByStringByteArray.HANDLE; - try { - if (TRACE_DOWNCALLS) { - traceDowncall("swiftkit_getTypeByStringByteArray", mangledName); - } - try (Arena arena = Arena.ofConfined()) { - MemorySegment mangledNameMS = arena.allocateFrom(mangledName); - return (MemorySegment) mh$.invokeExact(mangledNameMS); - } - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - } - -// // ----------------------------------------------------------------------------------------------------------------- -// // useMySwiftSlice_getLen(slice: MySwiftSlice) -// -// -// // JavaKitExample.useMySwiftSlice_getLen(slice: JavaKitExample.MySwiftSlice) -> Swift.Int -// private static class useMySwiftSlice_getLen { -// public static final FunctionDescriptor DESC = FunctionDescriptor.of( -// /* -> */ JavaKitExample.SWIFT_INT, -// JavaKitExample.SWIFT_POINTER // FIXME: not: MySwiftSlice.layout() -// ); -// -//// public static final MemorySegment ADDR = JavaKitExample.findOrThrow("$s14JavaKitExample22useMySwiftSlice_getLen5sliceSiAA0efG0V_tF"); -// -// // with inout -// public static final MemorySegment ADDR = JavaKitExample.findOrThrow("$s14JavaKitExample22useMySwiftSlice_getLen5sliceSiAA0efG0Vz_tF"); -// -// public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); -// } -// -// /** -// * Function descriptor for: -// * {@snippet lang=swift : -// * public func useMySwiftSlice(slice: MySwiftLibrary.MySwiftSlice) -// * } -// */ -// public static FunctionDescriptor useMySwiftSlice$descriptor() { -// return useMySwiftSlice_getLen.DESC; -// } -// -// /** -// * Downcall method handle for: -// * {@snippet lang=swift : -// * public func useMySwiftSlice(slice: MySwiftLibrary.MySwiftSlice) -// * } -// */ -// public static MethodHandle useMySwiftSlice$handle() { -// return useMySwiftSlice_getLen.HANDLE; -// } -// -// /** -// * Address for: -// * {@snippet lang=swift : -// * public func useMySwiftSlice(slice: MySwiftLibrary.MySwiftSlice) -// * } -// */ -// public static MemorySegment useMySwiftSlice$address() { -// return useMySwiftSlice_getLen.ADDR; -// } -// -// /** -// * {@snippet lang=swift : -// * public func useMySwiftSlice(slice: MySwiftLibrary.MySwiftSlice) -// * } -// */ -// public static long useMySwiftSlice_getLen(MemorySegment self) { -// var mh$ = useMySwiftSlice_getLen.HANDLE; -// try { -// if (TRACE_DOWNCALLS) { -// traceDowncall(self); -// } -// System.out.println("self = " + self); -// return (long) mh$.invokeExact(self); -// } catch (Throwable ex$) { -// throw new AssertionError("should not reach here", ex$); -// } -// } -// -// /** -// * {@snippet lang=swift : -// * public func useMySwiftSlice(slice: MySwiftLibrary.MySwiftSlice) -// * } -// */ -// public static long useMySwiftSlice_getLen(MySwiftSlice self) { -// return useMySwiftSlice_getLen(self.$memorySegment()); -// } - -} - diff --git a/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/ManualMySwiftClass.java b/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/ManualMySwiftClass.java deleted file mode 100644 index 9aa63f22..00000000 --- a/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/ManualMySwiftClass.java +++ /dev/null @@ -1,200 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of Swift.org project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -package com.example.swift; - -// ==== Extra convenience APIs ------------------------------------------------------------------------------------- -// TODO: Think about offering these or not, perhaps only as an option? - -import org.swift.swiftkit.ManagedSwiftType; - -import java.lang.foreign.*; -import java.lang.invoke.MethodHandle; - -public final class ManualMySwiftClass extends Manual_MySwiftClass implements ManagedSwiftType { - - // 000000000003f4a8 S type metadata for JavaKitExample.MySwiftSlice - // strip the _$s - // drop the N - public static final String TYPE_MANGLED_NAME = "14JavaKitExample12MySwiftClassC"; - - private final MemorySegment self; - - - ManualMySwiftClass(MemorySegment self) { - this.self = self; - } - - public MemorySegment $memorySegment() { - return self; - } - - public GroupLayout $layout() { - return Manual_MySwiftClass.layout(); - } - - public long len() { - return Manual_MySwiftClass.getLen(self); - } - public void len(long value) { - Manual_MySwiftClass.setLen(self, value); - } - - - // ----------------------------------------------------------------------------------------------------------------- - // init(len: Int, cap: Int) - - /** - * - * Normal init: - * {@snippet lang=Swift: - * 0000000000031d78 T JavaKitExample.MySwiftClass.init(len: Swift.Int, cap: Swift.Int) -> JavaKitExample.MySwiftClass - * 0000000000031d78 T _$s14JavaKitExample12MySwiftClassC3len3capACSi_Sitcfc - * } - * - * {@snippet lang=Swift: - * // MySwiftClass.init(len:cap:) - * sil [ossa] @$s14MySwiftLibrary0aB5ClassC3len3capACSi_Sitcfc : $@convention(method) (Int, Int, @owned MySwiftClass) -> @owned MySwiftClass { - * // %0 "len" - * // %1 "cap" - * // %2 "self" - * bb0(%0 : $Int, %1 : $Int, %2 : @owned $MySwiftClass): - * } - * } - */ - private static class __init_len_cap { - public static final FunctionDescriptor DESC = FunctionDescriptor.of( - /* -> */ ValueLayout.ADDRESS, - /* len = */len$layout(), - /* cap = */cap$layout(), - /* self = */ ValueLayout.ADDRESS - ); - - public static final MemorySegment ADDR = ManualJavaKitExample.findOrThrow("$s14JavaKitExample12MySwiftClassC3len3capACSi_Sitcfc"); - public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); - } - - public static FunctionDescriptor __init_len_cap$descriptor() { - return __init_len_cap.DESC; - } - - public static MethodHandle __init_len_cap$handle() { - return __init_len_cap.HANDLE; - } - - public static MemorySegment __init_len_cap$address() { - return __init_len_cap.ADDR; - } - - static MemorySegment __init_len_cap(Arena arena, long len, long cap) { - var mh$ = __init_len_cap.HANDLE; - try { - if (ManualJavaKitExample.TRACE_DOWNCALLS) { - ManualJavaKitExample.traceDowncall("init(len:cap:)", len, cap); - } - - // FIXME: get from Swift how wide this type should be, and alignment - MemorySegment alloc = arena.allocate(128); - - var address = (MemorySegment) mh$.invokeExact(len, cap, /*self*/alloc); - trace("address = " + address); - return address; - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - } - - - /** - * - * Allocating init: - * - * {@snippet lang=Swift: - * 0000000000031d28 T JavaKitExample.MySwiftClass.__allocating_init(len: Swift.Int, cap: Swift.Int) -> JavaKitExample.MySwiftClass - * 0000000000031d28 T _$s14JavaKitExample12MySwiftClassC3len3capACSi_SitcfC - * } - * - * {@snippet lang=Swift: - * // MySwiftClass.__allocating_init(len:cap:) - * sil [serialized] [exact_self_class] [ossa] @$s14MySwiftLibrary0aB5ClassC3len3capACSi_SitcfC : $@convention(method) (Int, Int, @thick MySwiftClass.Type) -> @owned MySwiftClass { - * // %0 "len" - * // %1 "cap" - * // %2 "$metatype" - * bb0(%0 : $Int, %1 : $Int, %2 : $@thick MySwiftClass.Type): - * } - * } - */ - private static class __allocating_init_len_cap { - public static final FunctionDescriptor DESC = FunctionDescriptor.of( - /* -> */ ValueLayout.ADDRESS, - /*len = */len$layout(), - /*cap = */ManualJavaKitExample.SWIFT_INT, // FIXME: cap$layout(), - /* type metadata = */ManualJavaKitExample.SWIFT_TYPE_METADATA_PTR - ); - - public static final MemorySegment ADDR = ManualJavaKitExample.findOrThrow("$s14JavaKitExample12MySwiftClassC3len3capACSi_SitcfC"); - public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); - } - - - - public static FunctionDescriptor __allocating_init_len_cap$descriptor() { - return __allocating_init_len_cap.DESC; - } - - public static MethodHandle __allocating_init_len_cap$handle() { - return __allocating_init_len_cap.HANDLE; - } - - public static MemorySegment __allocating_init_len_cap$address() { - return __allocating_init_len_cap.ADDR; - } - - static MemorySegment __allocating_init_len_cap(long len, long cap) { - var mh$ = __allocating_init_len_cap.HANDLE; - try { - if (ManualJavaKitExample.TRACE_DOWNCALLS) { - ManualJavaKitExample.traceDowncall("MySwiftClass.__allocating_init(len:cap:)", len, cap); - } - ManualJavaKitExample.trace("type name = " + TYPE_MANGLED_NAME); - - // FIXME: problems with _getTypeByName because of the String memory repr - // final MemorySegment type = SwiftKit.getTypeByMangledNameInEnvironment(TYPE_MANGLED_NAME); - // we must get a method we can call like this into SwiftKit: - - MemorySegment type = ManualJavaKitExample.swiftkit_getTypeByStringByteArray(TYPE_MANGLED_NAME); - ManualJavaKitExample.trace("type = " + type); - - var address = (MemorySegment) mh$.invokeExact(len, cap, type); - System.out.println("address = " + address); - return address; - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - } - - - // ----------------------------------------------------------------------------------------------------------------- - // ==== Initializer Java API - - public static ManualMySwiftClass init(Arena arena, long len, long cap) { - MemorySegment alloc = __init_len_cap(arena, len, cap); - return new ManualMySwiftClass(alloc); - } - - public static ManualMySwiftClass init(long len, long cap) { - MemorySegment alloc = __allocating_init_len_cap(len, cap); - return new ManualMySwiftClass(alloc); - } -} diff --git a/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/Manual_MySwiftClass.java b/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/Manual_MySwiftClass.java deleted file mode 100644 index f57ac9d8..00000000 --- a/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/Manual_MySwiftClass.java +++ /dev/null @@ -1,304 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of Swift.org project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -package com.example.swift; - -import java.lang.foreign.*; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.util.Arrays; -import java.util.function.Consumer; -import java.util.stream.Collectors; - -import static java.lang.foreign.MemoryLayout.PathElement.groupElement; -import static java.lang.foreign.ValueLayout.OfLong; - -/** - * {@snippet lang = Swift: - * public class MySwiftClass { - * var len: Int - * var cap: Int - * } - *} - */ -public class Manual_MySwiftClass { - - static final String DYLIB_NAME = "JavaKitExample"; - static final Arena LIBRARY_ARENA = Arena.ofAuto(); - static final boolean TRACE_DOWNCALLS = true || Boolean.getBoolean("jextract.trace.downcalls"); - - - static void traceDowncall(Object... args) { - var ex = new RuntimeException(); - - String traceArgs = Arrays.stream(args) - .map(Object::toString) - .collect(Collectors.joining(", ")); - System.out.printf("[java][%s:%d] %s(%s)\n", - ex.getStackTrace()[1].getFileName(), - ex.getStackTrace()[1].getLineNumber(), - ex.getStackTrace()[1].getMethodName(), - traceArgs); - } - - static void trace(Object... args) { - var ex = new RuntimeException(); - - String traceArgs = Arrays.stream(args) - .map(Object::toString) - .collect(Collectors.joining(", ")); - System.out.printf("[java][%s:%d] %s: %s\n", - ex.getStackTrace()[1].getFileName(), - ex.getStackTrace()[1].getLineNumber(), - ex.getStackTrace()[1].getMethodName(), - traceArgs); - } - - static MemorySegment findOrThrow(String symbol) { - return SYMBOL_LOOKUP.find(symbol) - .orElseThrow(() -> new UnsatisfiedLinkError("unresolved symbol: %s".formatted(symbol))); - } - - static MethodHandle upcallHandle(Class fi, String name, FunctionDescriptor fdesc) { - try { - return MethodHandles.lookup().findVirtual(fi, name, fdesc.toMethodType()); - } catch (ReflectiveOperationException ex) { - throw new AssertionError(ex); - } - } - - static MemoryLayout align(MemoryLayout layout, long align) { - return switch (layout) { - case PaddingLayout p -> p; - case ValueLayout v -> v.withByteAlignment(align); - case GroupLayout g -> { - MemoryLayout[] alignedMembers = g.memberLayouts().stream() - .map(m -> align(m, align)).toArray(MemoryLayout[]::new); - yield g instanceof StructLayout ? - MemoryLayout.structLayout(alignedMembers) : MemoryLayout.unionLayout(alignedMembers); - } - case SequenceLayout s -> MemoryLayout.sequenceLayout(s.elementCount(), align(s.elementLayout(), align)); - }; - } - - static final SymbolLookup SYMBOL_LOOKUP = - SymbolLookup.libraryLookup(System.mapLibraryName(DYLIB_NAME), LIBRARY_ARENA) - .or(SymbolLookup.loaderLookup()) - .or(Linker.nativeLinker().defaultLookup()); - - - Manual_MySwiftClass() { - // Should not be called directly - } - - - private static final GroupLayout $LAYOUT = MemoryLayout.structLayout( - ManualJavaKitExample.SWIFT_INT.withName("heapObject"), - ManualJavaKitExample.SWIFT_INT.withName("len"), - ManualJavaKitExample.SWIFT_INT.withName("cap") - ).withName("$MySwiftClass$31:1"); // TODO: is the name right? - - /** - * The layout of this class - */ - public static final GroupLayout layout() { - return $LAYOUT; - } - - // -------------------------------------------------------------------------------------------------------- - // ==== len - - private static final OfLong len$LAYOUT = (OfLong)$LAYOUT.select(groupElement("len")); - - private static class len$property { - public static final FunctionDescriptor DESC_GET = FunctionDescriptor.of( - /* -> */ManualJavaKitExample.SWIFT_INT, - /* self = */ ManualJavaKitExample.SWIFT_POINTER - ); - public static final FunctionDescriptor DESC_SET = FunctionDescriptor.ofVoid( - /* self = */ ManualJavaKitExample.SWIFT_POINTER, - ManualJavaKitExample.SWIFT_INT - ); - - private static final String BASE_NAME = "$s14JavaKitExample12MySwiftClassC3lenSiv"; - public static final MemorySegment ADDR_GET = ManualJavaKitExample.findOrThrow(BASE_NAME + "g"); - public static final MemorySegment ADDR_SET = ManualJavaKitExample.findOrThrow(BASE_NAME + "s"); - - public static final MethodHandle HANDLE_GET = Linker.nativeLinker().downcallHandle(ADDR_GET, DESC_GET); - public static final MethodHandle HANDLE_SET = Linker.nativeLinker().downcallHandle(ADDR_SET, DESC_SET); - } - - public static final OfLong len$layout() { - return len$LAYOUT; - } - - private static final long len$OFFSET = 8; - - public static final long len$offset() { - return len$OFFSET; - } - - public static FunctionDescriptor len$get$descriptor() { - return len$property.DESC_GET; - } - public static MethodHandle len$get$handle() { - return len$property.HANDLE_GET; - } - public static MemorySegment len$get$address() { - return len$property.ADDR_GET; - } - - public static long getLen(MemorySegment self) { - var mh$ = len$property.HANDLE_GET; - try { - if (TRACE_DOWNCALLS) { - traceDowncall("len$getter", self); - } - return (long) mh$.invokeExact(self); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - } - - public static long getLenRaw(MemorySegment self) { - // FIXME: seems wrong? - return self.get(len$LAYOUT, len$OFFSET); - } - - - public static FunctionDescriptor len$set$descriptor() { - return len$property.DESC_SET; - } - public static MethodHandle len$set$handle() { - return len$property.HANDLE_SET; - } - public static MemorySegment len$set$address() { - return len$property.ADDR_SET; - } - - - /** - * Setter for field: - * {@snippet lang = Swift : - * var len: Int { set } - * } - */ - public static void setLen(MemorySegment self, long fieldValue) { - var mh$ = len$property.HANDLE_SET; - try { - if (TRACE_DOWNCALLS) { - traceDowncall("len$setter", self, fieldValue); - } - mh$.invokeExact(self, fieldValue); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - } - public static void setLenRaw(MemorySegment self, long fieldValue) { - // FIXME: seems wrong? - self.set(len$LAYOUT, len$OFFSET, fieldValue); - } - - // -------------------------------------------------------------------------------------------------------- - // ==== len - - private static final OfLong cap$LAYOUT = (OfLong)$LAYOUT.select(groupElement("cap")); - - private static class cap$property { - public static final FunctionDescriptor DESC_GET = FunctionDescriptor.of( - /* -> */ManualJavaKitExample.SWIFT_INT, - /* self = */ ManualJavaKitExample.SWIFT_POINTER - ); - public static final FunctionDescriptor DESC_SET = FunctionDescriptor.ofVoid( - /* self = */ ManualJavaKitExample.SWIFT_POINTER, - ManualJavaKitExample.SWIFT_INT - ); - - private static final String BASE_NAME = "$s14JavaKitExample12MySwiftClassC3capSiv"; - public static final MemorySegment ADDR_GET = ManualJavaKitExample.findOrThrow(BASE_NAME + "g"); - public static final MemorySegment ADDR_SET = ManualJavaKitExample.findOrThrow(BASE_NAME + "s"); - - public static final MethodHandle HANDLE_GET = Linker.nativeLinker().downcallHandle(ADDR_GET, DESC_GET); - public static final MethodHandle HANDLE_SET = Linker.nativeLinker().downcallHandle(ADDR_SET, DESC_SET); - } - - public static final OfLong cap$layout() { - return cap$LAYOUT; - } - - private static final long cap$OFFSET = 16; - - public static final long cap$offset() { - return cap$OFFSET; - } - - public static FunctionDescriptor cap$get$descriptor() { - return cap$property.DESC_GET; - } - public static MethodHandle cap$get$handle() { - return cap$property.HANDLE_GET; - } - public static MemorySegment cap$get$address() { - return cap$property.ADDR_GET; - } - - - // ==== ------------------------------------------------------------------------------------------------------------ - - /** - * Obtains a slice of {@code arrayParam} which selects the array element at {@code index}. - * The returned segment has address {@code arrayParam.address() + index * layout().byteSize()} - */ - public static MemorySegment asSlice(MemorySegment array, long index) { - return array.asSlice(layout().byteSize() * index); - } - - /** - * The size (in bytes) of this struct - */ - public static long sizeof() { return layout().byteSize(); } - - /** - * Allocate a segment of size {@code layout().byteSize()} using {@code allocator} - */ - public static MemorySegment allocate(SegmentAllocator allocator) { - return allocator.allocate(layout()); - } - - /** - * Allocate an array of size {@code elementCount} using {@code allocator}. - * The returned segment has size {@code elementCount * layout().byteSize()}. - */ - public static MemorySegment allocateArray(long elementCount, SegmentAllocator allocator) { - return allocator.allocate(MemoryLayout.sequenceLayout(elementCount, layout())); - } - - /** - * Reinterprets {@code addr} using target {@code arena} and {@code cleanupAction} (if any). - * The returned segment has size {@code layout().byteSize()} - */ - public static MemorySegment reinterpret(MemorySegment addr, Arena arena, Consumer cleanup) { - return reinterpret(addr, 1, arena, cleanup); - } - - /** - * Reinterprets {@code addr} using target {@code arena} and {@code cleanupAction} (if any). - * The returned segment has size {@code elementCount * layout().byteSize()} - */ - public static MemorySegment reinterpret(MemorySegment addr, long elementCount, Arena arena, Consumer cleanup) { - return addr.reinterpret(layout().byteSize() * elementCount, arena, cleanup); - } -} - - diff --git a/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/generated/GeneratedJavaKitExampleModuleTest.java b/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/generated/GeneratedJavaKitExampleModuleTest.java index 9ec18ba6..9cceacf5 100644 --- a/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/generated/GeneratedJavaKitExampleModuleTest.java +++ b/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/generated/GeneratedJavaKitExampleModuleTest.java @@ -18,6 +18,9 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.DisabledOnOs; import org.junit.jupiter.api.condition.OS; +import org.swift.swiftkit.SwiftKit; + +import java.util.concurrent.CountDownLatch; import static org.junit.jupiter.api.Assertions.*; @@ -25,12 +28,8 @@ public class GeneratedJavaKitExampleModuleTest { @BeforeAll static void beforeAll() { - System.out.println("java.library.path = " + System.getProperty("java.library.path")); - - System.loadLibrary("swiftCore"); - System.loadLibrary("ExampleSwiftLibrary"); - - System.setProperty("jextract.trace.downcalls", "true"); + System.out.println("java.library.path = " + SwiftKit.getJavaLibraryPath()); + System.out.println("java.library.path = " + SwiftKit.getJextractTraceDowncalls()); } @Test @@ -47,4 +46,24 @@ void call_globalTakeInt() { assertNotNull(ExampleSwiftLibrary.globalTakeInt$address()); } + @Test + @SuppressWarnings({"Convert2Lambda", "Convert2MethodRef"}) + void call_globalCallMeRunnable() { + CountDownLatch countDownLatch = new CountDownLatch(3); + + ExampleSwiftLibrary.globalCallMeRunnable(new Runnable() { + @Override + public void run() { + countDownLatch.countDown(); + } + }); + assertEquals(2, countDownLatch.getCount()); + + ExampleSwiftLibrary.globalCallMeRunnable(() -> countDownLatch.countDown()); + assertEquals(1, countDownLatch.getCount()); + + ExampleSwiftLibrary.globalCallMeRunnable(countDownLatch::countDown); + assertEquals(0, countDownLatch.getCount()); + } + } diff --git a/Sources/ExampleSwiftLibrary/MySwiftLibrary.swift b/Sources/ExampleSwiftLibrary/MySwiftLibrary.swift index 5ad8e6fb..146601d0 100644 --- a/Sources/ExampleSwiftLibrary/MySwiftLibrary.swift +++ b/Sources/ExampleSwiftLibrary/MySwiftLibrary.swift @@ -35,6 +35,10 @@ public func globalTakeIntInt(i: Int, j: Int) { p("i:\(i), j:\(j)") } +public func globalCallMeRunnable(run: () -> ()) { + run() +} + public class MySwiftClass { public var len: Int diff --git a/Sources/JExtractSwift/CodePrinter.swift b/Sources/JExtractSwift/CodePrinter.swift index 56a61a42..308db69e 100644 --- a/Sources/JExtractSwift/CodePrinter.swift +++ b/Sources/JExtractSwift/CodePrinter.swift @@ -75,6 +75,22 @@ public struct CodePrinter { print("}", .sloc, function: function, file: file, line: line) } + public mutating func printParts( + _ parts: String..., + terminator: PrinterTerminator = .newLine, + function: String = #function, + file: String = #fileID, + line: UInt = #line + ) { + for part in parts { + guard part.trimmingCharacters(in: .whitespacesAndNewlines).count != 0 else { + continue + } + + self.print(part, terminator, function: function, file: file, line: line) + } + } + public mutating func print( _ text: Any, _ terminator: PrinterTerminator = .newLine, diff --git a/Sources/JExtractSwift/ImportedDecls.swift b/Sources/JExtractSwift/ImportedDecls.swift index d89ed77d..3999a0c9 100644 --- a/Sources/JExtractSwift/ImportedDecls.swift +++ b/Sources/JExtractSwift/ImportedDecls.swift @@ -106,10 +106,13 @@ public struct ImportedParam { extension ImportedParam { func renderParameterForwarding() -> String? { if type.javaType.isPrimitive { - return effectiveName + effectiveName + } else if type.javaType.isSwiftClosure { + // use the name of the upcall handle we'll have emitted by now + "\(effectiveName!)$" + } else { + "\(effectiveName!).$memorySegment()" } - - return "\(effectiveName!).$memorySegment()" } } diff --git a/Sources/JExtractSwift/JavaType+Printing.swift b/Sources/JExtractSwift/JavaType+Printing.swift new file mode 100644 index 00000000..39a348d9 --- /dev/null +++ b/Sources/JExtractSwift/JavaType+Printing.swift @@ -0,0 +1,47 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import Foundation +import SwiftBasicFormat +import SwiftParser +import SwiftSyntax +import JavaTypes + +extension JavaType { + /// Returns a 'handle' name to pass to the `invoke` call as well as the + /// `FunctionDescription` and `MethodHandle` of the downcall handle for this parameter. + /// + /// Pass the prior to `invoke`, and directly render the latter in the Java wrapper downcall function body. + func prepareClosureDowncallHandle(decl: ImportedFunc, parameter: String) -> String { + let varNameBase = "\(decl.baseIdentifier)_\(parameter)" + let handle = "\(varNameBase)_handle$" + let desc = "\(varNameBase)_desc$" + + if self == .javaLangRunnable { + return + """ + FunctionDescriptor \(desc) = FunctionDescriptor.ofVoid(); + MethodHandle \(handle) = MethodHandles.lookup() + .findVirtual(Runnable.class, "run", + \(desc).toMethodType()); + \(handle) = \(handle).bindTo(\(parameter)); + + Linker linker = Linker.nativeLinker(); + MemorySegment \(parameter)$ = linker.upcallStub(\(handle), \(desc), arena); + """ + } + + fatalError("Cannot render closure downcall handle for: \(self), in: \(decl), parameter: \(parameter)") + } +} diff --git a/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift b/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift index 1d20114a..c8b9bf09 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift @@ -648,13 +648,20 @@ extension Swift2JavaTranslator { return } + let needsArena = downcallNeedsConfinedArena(decl) let handleName = accessorKind.renderHandleFieldName - printer.print( + + printer.printParts( """ \(javaDocComment) public static \(returnTy) \(identifier)(\(renderJavaParamDecls(decl, selfVariant: selfVariant))) { var mh$ = \(decl.baseIdentifier).\(handleName); - try { + \(renderTry(withArena: needsArena)) + """, + """ + \(renderUpcallHandles(decl)) + """, + """ if (TRACE_DOWNCALLS) { traceDowncall(\(renderForwardParams(decl, selfVariant: .memorySegment))); } @@ -739,6 +746,27 @@ extension Swift2JavaTranslator { return res } + /// Do we need to construct an inline confined arena for the duration of the downcall? + public func downcallNeedsConfinedArena(_ decl: ImportedFunc) -> Bool { + for p in decl.parameters { + // We need to detect if any of the parameters is a closure we need to prepare + // an upcall handle for. + if p.type.javaType.isSwiftClosure { + return true + } + } + + return false + } + + public func renderTry(withArena: Bool) -> String { + if withArena { + "try (Arena arena = Arena.ofConfined()) {" + } else { + "try {" + } + } + public func renderJavaParamDecls(_ decl: ImportedFunc, selfVariant: SelfParameterVariant?) -> String { var ps: [String] = [] var pCounter = 0 @@ -757,6 +785,19 @@ extension Swift2JavaTranslator { return res } + public func renderUpcallHandles(_ decl: ImportedFunc) -> String { + var printer = CodePrinter() + for p in decl.parameters where p.type.javaType.isSwiftClosure { + if p.type.javaType == .javaLangRunnable { + let paramName = p.secondName ?? p.firstName ?? "_" + let handleDesc = p.type.javaType.prepareClosureDowncallHandle(decl: decl, parameter: paramName) + printer.print(handleDesc) + } + } + + return printer.contents + } + public func renderForwardParams(_ decl: ImportedFunc, selfVariant: SelfParameterVariant?) -> String { var ps: [String] = [] var pCounter = 0 diff --git a/Sources/JavaTypes/JavaType+SwiftNames.swift b/Sources/JavaTypes/JavaType+SwiftNames.swift index 4bef1e75..8577640e 100644 --- a/Sources/JavaTypes/JavaType+SwiftNames.swift +++ b/Sources/JavaTypes/JavaType+SwiftNames.swift @@ -30,6 +30,18 @@ extension JavaType { } } + public var isSwiftClosure: Bool { + switch self { + case .boolean, .byte, .char, .short, .int, .long, .float, .double, .void, + .array: + return false + case .class(package: "java.lang", name: "Runnable"): + return true + case .class: + return false + } + } + /// Produce the Swift type name for this Java type. public func swiftTypeName(resolver: JavaToSwiftClassNameResolver) rethrows -> String { switch self { diff --git a/Tests/JExtractSwiftTests/FuncCallbackImportTests.swift b/Tests/JExtractSwiftTests/FuncCallbackImportTests.swift new file mode 100644 index 00000000..90541263 --- /dev/null +++ b/Tests/JExtractSwiftTests/FuncCallbackImportTests.swift @@ -0,0 +1,84 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import JExtractSwift +import Testing + +final class FuncCallbackImportTests { + + static let class_interfaceFile = + """ + // swift-interface-format-version: 1.0 + // swift-compiler-version: Apple Swift version 6.0 effective-5.10 (swiftlang-6.0.0.7.6 clang-1600.0.24.1) + // swift-module-flags: -target arm64-apple-macosx15.0 -enable-objc-interop -enable-library-evolution -module-name MySwiftLibrary + import Darwin.C + import Darwin + import Swift + import _Concurrency + import _StringProcessing + import _SwiftConcurrencyShims + + // MANGLED NAME: $mockName + public func callMe(callback: () -> ()) + """ + + @Test("Import: public func callMe(callback: () -> ())") + func func_callMeFunc_Runnable() throws { + let st = Swift2JavaTranslator( + javaPackage: "com.example.swift", + swiftModuleName: "__FakeModule" + ) + st.log.logLevel = .error + + try st.analyze(swiftInterfacePath: "/fake/Fake.swiftinterface", text: Self.class_interfaceFile) + + let funcDecl = st.importedGlobalFuncs.first { $0.baseIdentifier == "callMe" }! + + let output = CodePrinter.toString { printer in + st.printFuncDowncallMethod(&printer, decl: funcDecl, selfVariant: nil) + } + + assertOutput( + output, + expected: + """ + /** + * Downcall to Swift: + * {@snippet lang=swift : + * public func callMe(callback: () -> ()) + * } + */ + public static void callMe(java.lang.Runnable callback) { + var mh$ = callMe.HANDLE; + try (Arena arena = Arena.ofConfined()) { + FunctionDescriptor callMe_callback_desc$ = FunctionDescriptor.ofVoid(); + MethodHandle callMe_callback_handle$ = MethodHandles.lookup() + .findVirtual(Runnable.class, "run", + callMe_callback_desc$.toMethodType()); + callMe_callback_handle$ = callMe_callback_handle$.bindTo(callback); + Linker linker = Linker.nativeLinker(); + MemorySegment callback$ = linker.upcallStub(callMe_callback_handle$, callMe_callback_desc$, arena); + if (TRACE_DOWNCALLS) { + traceDowncall(callback$); + } + mh$.invokeExact(callback$); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + """ + ) + } + +} diff --git a/Tests/JExtractSwiftTests/FuncImportTests.swift b/Tests/JExtractSwiftTests/MethodImportTests.swift similarity index 100% rename from Tests/JExtractSwiftTests/FuncImportTests.swift rename to Tests/JExtractSwiftTests/MethodImportTests.swift diff --git a/buildSrc/src/main/groovy/org/swift/swiftkit/gradle/BuildUtils.groovy b/buildSrc/src/main/groovy/org/swift/swiftkit/gradle/BuildUtils.groovy index e6a29ae9..2e09d11b 100644 --- a/buildSrc/src/main/groovy/org/swift/swiftkit/gradle/BuildUtils.groovy +++ b/buildSrc/src/main/groovy/org/swift/swiftkit/gradle/BuildUtils.groovy @@ -22,7 +22,6 @@ final class BuildUtils { def osArch = System.getProperty("os.arch") def isLinux = osName.toLowerCase(Locale.getDefault()).contains("linux") def base = rootDir == null ? "" : "${rootDir}/" - System.out.println("Root dir is = ${rootDir}") return [ isLinux ? From 63ced64b7158ded146f6509d4105abededdbf294 Mon Sep 17 00:00:00 2001 From: Tim Wang Date: Wed, 23 Oct 2024 14:51:24 +1100 Subject: [PATCH 120/426] Make the "environment" parameter to @JavaMethod initializers optional (#102) Co-authored-by: Tim Wang --- Package.swift | 42 ++++++------------- Samples/JavaProbablyPrime/Package.swift | 1 - .../Sources/JavaProbablyPrime/prime.swift | 1 - Samples/JavaSieve/Package.swift | 1 - Sources/Java2Swift/JavaToSwift.swift | 1 - Sources/Java2SwiftLib/JavaTranslator.swift | 11 +++-- .../JavaKitVM/JavaVirtualMachine.swift | 2 - .../{ => JavaKit}/JavaKitVM/LockedState.swift | 0 Sources/JavaKit/generated/Exception.swift | 8 ++-- Sources/JavaKit/generated/JavaError.swift | 8 ++-- Sources/JavaKit/generated/JavaObject.swift | 2 +- .../JavaKit/generated/RuntimeException.swift | 8 ++-- Sources/JavaKit/generated/Throwable.swift | 8 ++-- .../generated/ArrayDeque.swift | 6 +-- .../generated/ArrayList.swift | 6 +-- .../JavaKitCollection/generated/BitSet.swift | 4 +- .../JavaKitCollection/generated/HashMap.swift | 6 +-- .../JavaKitCollection/generated/HashSet.swift | 8 ++-- .../generated/JavaDictionary.swift | 2 +- .../generated/LinkedList.swift | 4 +- .../generated/PriorityQueue.swift | 8 ++-- .../JavaKitCollection/generated/Stack.swift | 2 +- .../JavaKitCollection/generated/TreeMap.swift | 2 +- .../JavaKitCollection/generated/TreeSet.swift | 4 +- Sources/JavaKitJar/generated/Attributes.swift | 6 +-- Sources/JavaKitJar/generated/JarEntry.swift | 4 +- Sources/JavaKitJar/generated/JarFile.swift | 4 +- Sources/JavaKitJar/generated/Manifest.swift | 4 +- Sources/JavaKitMacros/JavaMethodMacro.swift | 7 +++- Sources/JavaKitNetwork/generated/URI.swift | 10 ++--- Sources/JavaKitNetwork/generated/URL.swift | 8 ++-- .../generated/URLClassLoader.swift | 2 +- Tests/Java2SwiftTests/Java2SwiftTests.swift | 3 +- .../JavaClassMacroTests.swift | 22 ++++++++-- Tests/JavaKitTests/BasicRuntimeTests.swift | 1 - USER_GUIDE.md | 18 ++++---- 36 files changed, 119 insertions(+), 115 deletions(-) rename Sources/{ => JavaKit}/JavaKitVM/JavaVirtualMachine.swift (99%) rename Sources/{ => JavaKit}/JavaKitVM/LockedState.swift (100%) diff --git a/Package.swift b/Package.swift index 0f492710..5b34a2eb 100644 --- a/Package.swift +++ b/Package.swift @@ -77,11 +77,6 @@ let package = Package( targets: ["JavaKitReflection"] ), - .library( - name: "JavaKitVM", - targets: ["JavaKitVM"] - ), - .library( name: "JavaTypes", targets: ["JavaTypes"] @@ -165,6 +160,18 @@ let package = Package( swiftSettings: [ .swiftLanguageMode(.v5), .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) + ], + linkerSettings: [ + .unsafeFlags( + [ + "-L\(javaHome)/lib/server", + "-Xlinker", + "-rpath", + "-Xlinker", + "\(javaHome)/lib/server", + ] + ), + .linkedLibrary("jvm"), ] ), .target( @@ -203,27 +210,6 @@ let package = Package( .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) ] ), - .target( - name: "JavaKitVM", - dependencies: ["JavaKit"], - swiftSettings: [ - .swiftLanguageMode(.v5), - .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) - ], - linkerSettings: [ - .unsafeFlags( - [ - "-L\(javaHome)/lib/server", - "-Xlinker", - "-rpath", - "-Xlinker", - "\(javaHome)/lib/server", - ] - ), - .linkedLibrary("jvm"), - ] - ), - .plugin( name: "JavaCompilerPlugin", capability: .buildTool() @@ -272,7 +258,6 @@ let package = Package( "JavaKitJar", "JavaKitReflection", "JavaKitNetwork", - "JavaKitVM", "JavaTypes", ], swiftSettings: [ @@ -291,7 +276,6 @@ let package = Package( "JavaKit", "JavaKitJar", "JavaKitNetwork", - "JavaKitVM", "Java2SwiftLib", ], @@ -328,7 +312,7 @@ let package = Package( .testTarget( name: "JavaKitTests", - dependencies: ["JavaKit", "JavaKitNetwork", "JavaKitVM"], + dependencies: ["JavaKit", "JavaKitNetwork"], swiftSettings: [ .swiftLanguageMode(.v5) ] diff --git a/Samples/JavaProbablyPrime/Package.swift b/Samples/JavaProbablyPrime/Package.swift index 8cd2be18..b35788f8 100644 --- a/Samples/JavaProbablyPrime/Package.swift +++ b/Samples/JavaProbablyPrime/Package.swift @@ -27,7 +27,6 @@ let package = Package( name: "JavaProbablyPrime", dependencies: [ .product(name: "JavaKit", package: "swift-java"), - .product(name: "JavaKitVM", package: "swift-java"), .product(name: "ArgumentParser", package: "swift-argument-parser"), ], swiftSettings: [ diff --git a/Samples/JavaProbablyPrime/Sources/JavaProbablyPrime/prime.swift b/Samples/JavaProbablyPrime/Sources/JavaProbablyPrime/prime.swift index bd83c1ee..ddebb518 100644 --- a/Samples/JavaProbablyPrime/Sources/JavaProbablyPrime/prime.swift +++ b/Samples/JavaProbablyPrime/Sources/JavaProbablyPrime/prime.swift @@ -14,7 +14,6 @@ import ArgumentParser import JavaKit -import JavaKitVM @main struct ProbablyPrime: ParsableCommand { diff --git a/Samples/JavaSieve/Package.swift b/Samples/JavaSieve/Package.swift index 2420dcf1..35dcd19c 100644 --- a/Samples/JavaSieve/Package.swift +++ b/Samples/JavaSieve/Package.swift @@ -70,7 +70,6 @@ let package = Package( "JavaMath", .product(name: "JavaKit", package: "swift-java"), .product(name: "JavaKitCollection", package: "swift-java"), - .product(name: "JavaKitVM", package: "swift-java"), ], swiftSettings: [ .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) diff --git a/Sources/Java2Swift/JavaToSwift.swift b/Sources/Java2Swift/JavaToSwift.swift index a4c64277..ffb9a24f 100644 --- a/Sources/Java2Swift/JavaToSwift.swift +++ b/Sources/Java2Swift/JavaToSwift.swift @@ -19,7 +19,6 @@ import JavaKit import JavaKitJar import JavaKitNetwork import JavaKitReflection -import JavaKitVM import SwiftSyntax import SwiftSyntaxBuilder diff --git a/Sources/Java2SwiftLib/JavaTranslator.swift b/Sources/Java2SwiftLib/JavaTranslator.swift index 3b592715..b7eec617 100644 --- a/Sources/Java2SwiftLib/JavaTranslator.swift +++ b/Sources/Java2SwiftLib/JavaTranslator.swift @@ -410,7 +410,7 @@ extension JavaTranslator { extension JavaTranslator { /// Translates the given Java constructor into a Swift declaration. package func translateConstructor(_ javaConstructor: Constructor) throws -> DeclSyntax { - let parameters = try translateParameters(javaConstructor.getParameters()) + ["environment: JNIEnvironment"] + let parameters = try translateParameters(javaConstructor.getParameters()) + ["environment: JNIEnvironment? = nil"] let parametersStr = parameters.map { $0.description }.joined(separator: ", ") let throwsStr = javaConstructor.throwsCheckedException ? "throws" : "" @@ -483,8 +483,13 @@ extension JavaTranslator { """ let initSyntax: DeclSyntax = """ - public init(_ enumValue: \(raw: name), environment: JNIEnvironment) { - let classObj = try! JavaClass(in: environment) + public init(_ enumValue: \(raw: name), environment: JNIEnvironment? = nil) { + let _environment = if let environment { + environment + } else { + try! JavaVirtualMachine.shared().environment() + } + let classObj = try! JavaClass(in: _environment) switch enumValue { \(raw: enumFields.map { return """ diff --git a/Sources/JavaKitVM/JavaVirtualMachine.swift b/Sources/JavaKit/JavaKitVM/JavaVirtualMachine.swift similarity index 99% rename from Sources/JavaKitVM/JavaVirtualMachine.swift rename to Sources/JavaKit/JavaKitVM/JavaVirtualMachine.swift index d01580d7..52882a41 100644 --- a/Sources/JavaKitVM/JavaVirtualMachine.swift +++ b/Sources/JavaKit/JavaKitVM/JavaVirtualMachine.swift @@ -12,8 +12,6 @@ // //===----------------------------------------------------------------------===// -import JavaKit - typealias JavaVMPointer = UnsafeMutablePointer public final class JavaVirtualMachine: @unchecked Sendable { diff --git a/Sources/JavaKitVM/LockedState.swift b/Sources/JavaKit/JavaKitVM/LockedState.swift similarity index 100% rename from Sources/JavaKitVM/LockedState.swift rename to Sources/JavaKit/JavaKitVM/LockedState.swift diff --git a/Sources/JavaKit/generated/Exception.swift b/Sources/JavaKit/generated/Exception.swift index 79db057b..59a1f246 100644 --- a/Sources/JavaKit/generated/Exception.swift +++ b/Sources/JavaKit/generated/Exception.swift @@ -4,16 +4,16 @@ import JavaRuntime @JavaClass("java.lang.Exception", extends: Throwable.self) public struct Exception { @JavaMethod - public init(_ arg0: Throwable?, environment: JNIEnvironment) + public init(_ arg0: Throwable?, environment: JNIEnvironment? = nil) @JavaMethod - public init(_ arg0: String, _ arg1: Throwable?, environment: JNIEnvironment) + public init(_ arg0: String, _ arg1: Throwable?, environment: JNIEnvironment? = nil) @JavaMethod - public init(_ arg0: String, environment: JNIEnvironment) + public init(_ arg0: String, environment: JNIEnvironment? = nil) @JavaMethod - public init(environment: JNIEnvironment) + public init(environment: JNIEnvironment? = nil) @JavaMethod public func printStackTrace() diff --git a/Sources/JavaKit/generated/JavaError.swift b/Sources/JavaKit/generated/JavaError.swift index 483f5ab2..62abca63 100644 --- a/Sources/JavaKit/generated/JavaError.swift +++ b/Sources/JavaKit/generated/JavaError.swift @@ -4,16 +4,16 @@ import JavaRuntime @JavaClass("java.lang.Error", extends: Throwable.self) public struct JavaError { @JavaMethod - public init(_ arg0: Throwable?, environment: JNIEnvironment) + public init(_ arg0: Throwable?, environment: JNIEnvironment? = nil) @JavaMethod - public init(_ arg0: String, _ arg1: Throwable?, environment: JNIEnvironment) + public init(_ arg0: String, _ arg1: Throwable?, environment: JNIEnvironment? = nil) @JavaMethod - public init(_ arg0: String, environment: JNIEnvironment) + public init(_ arg0: String, environment: JNIEnvironment? = nil) @JavaMethod - public init(environment: JNIEnvironment) + public init(environment: JNIEnvironment? = nil) @JavaMethod public func printStackTrace() diff --git a/Sources/JavaKit/generated/JavaObject.swift b/Sources/JavaKit/generated/JavaObject.swift index 05b1b9c1..809d1418 100644 --- a/Sources/JavaKit/generated/JavaObject.swift +++ b/Sources/JavaKit/generated/JavaObject.swift @@ -4,7 +4,7 @@ import JavaRuntime @JavaClass("java.lang.Object") public struct JavaObject { @JavaMethod - public init(environment: JNIEnvironment) + public init(environment: JNIEnvironment? = nil) @JavaMethod public func equals(_ arg0: JavaObject?) -> Bool diff --git a/Sources/JavaKit/generated/RuntimeException.swift b/Sources/JavaKit/generated/RuntimeException.swift index dd1316b4..5686efd9 100644 --- a/Sources/JavaKit/generated/RuntimeException.swift +++ b/Sources/JavaKit/generated/RuntimeException.swift @@ -4,16 +4,16 @@ import JavaRuntime @JavaClass("java.lang.RuntimeException", extends: Exception.self) public struct RuntimeException { @JavaMethod - public init(_ arg0: Throwable?, environment: JNIEnvironment) + public init(_ arg0: Throwable?, environment: JNIEnvironment? = nil) @JavaMethod - public init(_ arg0: String, _ arg1: Throwable?, environment: JNIEnvironment) + public init(_ arg0: String, _ arg1: Throwable?, environment: JNIEnvironment? = nil) @JavaMethod - public init(_ arg0: String, environment: JNIEnvironment) + public init(_ arg0: String, environment: JNIEnvironment? = nil) @JavaMethod - public init(environment: JNIEnvironment) + public init(environment: JNIEnvironment? = nil) @JavaMethod public func printStackTrace() diff --git a/Sources/JavaKit/generated/Throwable.swift b/Sources/JavaKit/generated/Throwable.swift index 9622cf58..98a4fda2 100644 --- a/Sources/JavaKit/generated/Throwable.swift +++ b/Sources/JavaKit/generated/Throwable.swift @@ -4,16 +4,16 @@ import JavaRuntime @JavaClass("java.lang.Throwable") public struct Throwable { @JavaMethod - public init(_ arg0: Throwable?, environment: JNIEnvironment) + public init(_ arg0: Throwable?, environment: JNIEnvironment? = nil) @JavaMethod - public init(_ arg0: String, _ arg1: Throwable?, environment: JNIEnvironment) + public init(_ arg0: String, _ arg1: Throwable?, environment: JNIEnvironment? = nil) @JavaMethod - public init(_ arg0: String, environment: JNIEnvironment) + public init(_ arg0: String, environment: JNIEnvironment? = nil) @JavaMethod - public init(environment: JNIEnvironment) + public init(environment: JNIEnvironment? = nil) @JavaMethod public func printStackTrace() diff --git a/Sources/JavaKitCollection/generated/ArrayDeque.swift b/Sources/JavaKitCollection/generated/ArrayDeque.swift index af2fd314..85040ac7 100644 --- a/Sources/JavaKitCollection/generated/ArrayDeque.swift +++ b/Sources/JavaKitCollection/generated/ArrayDeque.swift @@ -5,13 +5,13 @@ import JavaRuntime @JavaClass("java.util.ArrayDeque") public struct ArrayDeque { @JavaMethod - public init(_ arg0: Int32, environment: JNIEnvironment) + public init(_ arg0: Int32, environment: JNIEnvironment? = nil) @JavaMethod - public init(environment: JNIEnvironment) + public init(environment: JNIEnvironment? = nil) @JavaMethod - public init(_ arg0: JavaCollection?, environment: JNIEnvironment) + public init(_ arg0: JavaCollection?, environment: JNIEnvironment? = nil) @JavaMethod public func remove() -> JavaObject? diff --git a/Sources/JavaKitCollection/generated/ArrayList.swift b/Sources/JavaKitCollection/generated/ArrayList.swift index 765f4d9f..2b8f1608 100644 --- a/Sources/JavaKitCollection/generated/ArrayList.swift +++ b/Sources/JavaKitCollection/generated/ArrayList.swift @@ -5,13 +5,13 @@ import JavaRuntime @JavaClass("java.util.ArrayList", implements: List.self, RandomAccess.self) public struct ArrayList { @JavaMethod - public init(_ arg0: JavaCollection?, environment: JNIEnvironment) + public init(_ arg0: JavaCollection?, environment: JNIEnvironment? = nil) @JavaMethod - public init(environment: JNIEnvironment) + public init(environment: JNIEnvironment? = nil) @JavaMethod - public init(_ arg0: Int32, environment: JNIEnvironment) + public init(_ arg0: Int32, environment: JNIEnvironment? = nil) @JavaMethod public func remove(_ arg0: JavaObject?) -> Bool diff --git a/Sources/JavaKitCollection/generated/BitSet.swift b/Sources/JavaKitCollection/generated/BitSet.swift index f9c0bda9..d5371c67 100644 --- a/Sources/JavaKitCollection/generated/BitSet.swift +++ b/Sources/JavaKitCollection/generated/BitSet.swift @@ -5,10 +5,10 @@ import JavaRuntime @JavaClass("java.util.BitSet") public struct BitSet { @JavaMethod - public init(environment: JNIEnvironment) + public init(environment: JNIEnvironment? = nil) @JavaMethod - public init(_ arg0: Int32, environment: JNIEnvironment) + public init(_ arg0: Int32, environment: JNIEnvironment? = nil) @JavaMethod public func cardinality() -> Int32 diff --git a/Sources/JavaKitCollection/generated/HashMap.swift b/Sources/JavaKitCollection/generated/HashMap.swift index d4048dd0..8bd86744 100644 --- a/Sources/JavaKitCollection/generated/HashMap.swift +++ b/Sources/JavaKitCollection/generated/HashMap.swift @@ -5,13 +5,13 @@ import JavaRuntime @JavaClass("java.util.HashMap") public struct HashMap { @JavaMethod - public init(_ arg0: Int32, environment: JNIEnvironment) + public init(_ arg0: Int32, environment: JNIEnvironment? = nil) @JavaMethod - public init(_ arg0: Int32, _ arg1: Float, environment: JNIEnvironment) + public init(_ arg0: Int32, _ arg1: Float, environment: JNIEnvironment? = nil) @JavaMethod - public init(environment: JNIEnvironment) + public init(environment: JNIEnvironment? = nil) @JavaMethod public func remove(_ arg0: JavaObject?) -> JavaObject? diff --git a/Sources/JavaKitCollection/generated/HashSet.swift b/Sources/JavaKitCollection/generated/HashSet.swift index aa071dfd..ff194343 100644 --- a/Sources/JavaKitCollection/generated/HashSet.swift +++ b/Sources/JavaKitCollection/generated/HashSet.swift @@ -5,16 +5,16 @@ import JavaRuntime @JavaClass("java.util.HashSet", implements: JavaSet.self) public struct HashSet { @JavaMethod - public init(_ arg0: Int32, environment: JNIEnvironment) + public init(_ arg0: Int32, environment: JNIEnvironment? = nil) @JavaMethod - public init(_ arg0: Int32, _ arg1: Float, environment: JNIEnvironment) + public init(_ arg0: Int32, _ arg1: Float, environment: JNIEnvironment? = nil) @JavaMethod - public init(_ arg0: JavaCollection?, environment: JNIEnvironment) + public init(_ arg0: JavaCollection?, environment: JNIEnvironment? = nil) @JavaMethod - public init(environment: JNIEnvironment) + public init(environment: JNIEnvironment? = nil) @JavaMethod public func remove(_ arg0: JavaObject?) -> Bool diff --git a/Sources/JavaKitCollection/generated/JavaDictionary.swift b/Sources/JavaKitCollection/generated/JavaDictionary.swift index c32b3038..6e46c942 100644 --- a/Sources/JavaKitCollection/generated/JavaDictionary.swift +++ b/Sources/JavaKitCollection/generated/JavaDictionary.swift @@ -5,7 +5,7 @@ import JavaRuntime @JavaClass("java.util.Dictionary") public struct JavaDictionary { @JavaMethod - public init(environment: JNIEnvironment) + public init(environment: JNIEnvironment? = nil) @JavaMethod public func remove(_ arg0: JavaObject?) -> JavaObject? diff --git a/Sources/JavaKitCollection/generated/LinkedList.swift b/Sources/JavaKitCollection/generated/LinkedList.swift index cf7043c2..25abfbbf 100644 --- a/Sources/JavaKitCollection/generated/LinkedList.swift +++ b/Sources/JavaKitCollection/generated/LinkedList.swift @@ -5,10 +5,10 @@ import JavaRuntime @JavaClass("java.util.LinkedList") public struct LinkedList { @JavaMethod - public init(_ arg0: JavaCollection?, environment: JNIEnvironment) + public init(_ arg0: JavaCollection?, environment: JNIEnvironment? = nil) @JavaMethod - public init(environment: JNIEnvironment) + public init(environment: JNIEnvironment? = nil) @JavaMethod public func remove(_ arg0: JavaObject?) -> Bool diff --git a/Sources/JavaKitCollection/generated/PriorityQueue.swift b/Sources/JavaKitCollection/generated/PriorityQueue.swift index 7b70c7cd..ec1f2cca 100644 --- a/Sources/JavaKitCollection/generated/PriorityQueue.swift +++ b/Sources/JavaKitCollection/generated/PriorityQueue.swift @@ -5,16 +5,16 @@ import JavaRuntime @JavaClass("java.util.PriorityQueue") public struct PriorityQueue { @JavaMethod - public init(_ arg0: PriorityQueue?, environment: JNIEnvironment) + public init(_ arg0: PriorityQueue?, environment: JNIEnvironment? = nil) @JavaMethod - public init(_ arg0: JavaCollection?, environment: JNIEnvironment) + public init(_ arg0: JavaCollection?, environment: JNIEnvironment? = nil) @JavaMethod - public init(_ arg0: Int32, environment: JNIEnvironment) + public init(_ arg0: Int32, environment: JNIEnvironment? = nil) @JavaMethod - public init(environment: JNIEnvironment) + public init(environment: JNIEnvironment? = nil) @JavaMethod public func remove(_ arg0: JavaObject?) -> Bool diff --git a/Sources/JavaKitCollection/generated/Stack.swift b/Sources/JavaKitCollection/generated/Stack.swift index 65d92872..d3a883b5 100644 --- a/Sources/JavaKitCollection/generated/Stack.swift +++ b/Sources/JavaKitCollection/generated/Stack.swift @@ -5,7 +5,7 @@ import JavaRuntime @JavaClass("java.util.Stack") public struct Stack { @JavaMethod - public init(environment: JNIEnvironment) + public init(environment: JNIEnvironment? = nil) @JavaMethod public func empty() -> Bool diff --git a/Sources/JavaKitCollection/generated/TreeMap.swift b/Sources/JavaKitCollection/generated/TreeMap.swift index f029c220..49055dce 100644 --- a/Sources/JavaKitCollection/generated/TreeMap.swift +++ b/Sources/JavaKitCollection/generated/TreeMap.swift @@ -5,7 +5,7 @@ import JavaRuntime @JavaClass("java.util.TreeMap") public struct TreeMap { @JavaMethod - public init(environment: JNIEnvironment) + public init(environment: JNIEnvironment? = nil) @JavaMethod public func remove(_ arg0: JavaObject?) -> JavaObject? diff --git a/Sources/JavaKitCollection/generated/TreeSet.swift b/Sources/JavaKitCollection/generated/TreeSet.swift index 9633750e..7c1e0c86 100644 --- a/Sources/JavaKitCollection/generated/TreeSet.swift +++ b/Sources/JavaKitCollection/generated/TreeSet.swift @@ -5,10 +5,10 @@ import JavaRuntime @JavaClass("java.util.TreeSet") public struct TreeSet { @JavaMethod - public init(_ arg0: JavaCollection?, environment: JNIEnvironment) + public init(_ arg0: JavaCollection?, environment: JNIEnvironment? = nil) @JavaMethod - public init(environment: JNIEnvironment) + public init(environment: JNIEnvironment? = nil) @JavaMethod public func remove(_ arg0: JavaObject?) -> Bool diff --git a/Sources/JavaKitJar/generated/Attributes.swift b/Sources/JavaKitJar/generated/Attributes.swift index 69827d34..22aa68a4 100644 --- a/Sources/JavaKitJar/generated/Attributes.swift +++ b/Sources/JavaKitJar/generated/Attributes.swift @@ -6,13 +6,13 @@ import JavaRuntime @JavaClass("java.util.jar.Attributes") public struct Attributes { @JavaMethod - public init(_ arg0: Attributes?, environment: JNIEnvironment) + public init(_ arg0: Attributes?, environment: JNIEnvironment? = nil) @JavaMethod - public init(_ arg0: Int32, environment: JNIEnvironment) + public init(_ arg0: Int32, environment: JNIEnvironment? = nil) @JavaMethod - public init(environment: JNIEnvironment) + public init(environment: JNIEnvironment? = nil) @JavaMethod public func remove(_ arg0: JavaObject?) -> JavaObject? diff --git a/Sources/JavaKitJar/generated/JarEntry.swift b/Sources/JavaKitJar/generated/JarEntry.swift index 75a34d4e..5fae3e56 100644 --- a/Sources/JavaKitJar/generated/JarEntry.swift +++ b/Sources/JavaKitJar/generated/JarEntry.swift @@ -5,10 +5,10 @@ import JavaRuntime @JavaClass("java.util.jar.JarEntry") public struct JarEntry { @JavaMethod - public init(_ arg0: JarEntry?, environment: JNIEnvironment) + public init(_ arg0: JarEntry?, environment: JNIEnvironment? = nil) @JavaMethod - public init(_ arg0: String, environment: JNIEnvironment) + public init(_ arg0: String, environment: JNIEnvironment? = nil) @JavaMethod public func getRealName() -> String diff --git a/Sources/JavaKitJar/generated/JarFile.swift b/Sources/JavaKitJar/generated/JarFile.swift index e5d8eb6d..5dbfdcad 100644 --- a/Sources/JavaKitJar/generated/JarFile.swift +++ b/Sources/JavaKitJar/generated/JarFile.swift @@ -6,10 +6,10 @@ import JavaRuntime @JavaClass("java.util.jar.JarFile") public struct JarFile { @JavaMethod - public init(_ arg0: String, _ arg1: Bool, environment: JNIEnvironment) throws + public init(_ arg0: String, _ arg1: Bool, environment: JNIEnvironment? = nil) throws @JavaMethod - public init(_ arg0: String, environment: JNIEnvironment) throws + public init(_ arg0: String, environment: JNIEnvironment? = nil) throws @JavaMethod public func entries() -> Enumeration? diff --git a/Sources/JavaKitJar/generated/Manifest.swift b/Sources/JavaKitJar/generated/Manifest.swift index 7ea25ae1..1cd2ae64 100644 --- a/Sources/JavaKitJar/generated/Manifest.swift +++ b/Sources/JavaKitJar/generated/Manifest.swift @@ -5,10 +5,10 @@ import JavaRuntime @JavaClass("java.util.jar.Manifest") public struct Manifest { @JavaMethod - public init(_ arg0: Manifest?, environment: JNIEnvironment) + public init(_ arg0: Manifest?, environment: JNIEnvironment? = nil) @JavaMethod - public init(environment: JNIEnvironment) + public init(environment: JNIEnvironment? = nil) @JavaMethod public func equals(_ arg0: JavaObject?) -> Bool diff --git a/Sources/JavaKitMacros/JavaMethodMacro.swift b/Sources/JavaKitMacros/JavaMethodMacro.swift index dc08374d..c748f050 100644 --- a/Sources/JavaKitMacros/JavaMethodMacro.swift +++ b/Sources/JavaKitMacros/JavaMethodMacro.swift @@ -94,7 +94,12 @@ extension JavaMethodMacro: BodyMacro { return [ """ - self = \(raw: tryKeyword) Self.dynamicJavaNewObject(in: environment\(raw: arguments)) + let _environment = if let environment { + environment + } else { + \(raw: tryKeyword) JavaVirtualMachine.shared().environment() + } + self = \(raw: tryKeyword) Self.dynamicJavaNewObject(in: _environment\(raw: arguments)) """ ] } diff --git a/Sources/JavaKitNetwork/generated/URI.swift b/Sources/JavaKitNetwork/generated/URI.swift index 6fdad52c..3135e466 100644 --- a/Sources/JavaKitNetwork/generated/URI.swift +++ b/Sources/JavaKitNetwork/generated/URI.swift @@ -5,19 +5,19 @@ import JavaRuntime @JavaClass("java.net.URI") public struct URI { @JavaMethod - public init(_ arg0: String, _ arg1: String, _ arg2: String, _ arg3: String, _ arg4: String, environment: JNIEnvironment) throws + public init(_ arg0: String, _ arg1: String, _ arg2: String, _ arg3: String, _ arg4: String, environment: JNIEnvironment? = nil) throws @JavaMethod - public init(_ arg0: String, _ arg1: String, _ arg2: String, _ arg3: String, environment: JNIEnvironment) throws + public init(_ arg0: String, _ arg1: String, _ arg2: String, _ arg3: String, environment: JNIEnvironment? = nil) throws @JavaMethod - public init(_ arg0: String, _ arg1: String, _ arg2: String, environment: JNIEnvironment) throws + public init(_ arg0: String, _ arg1: String, _ arg2: String, environment: JNIEnvironment? = nil) throws @JavaMethod - public init(_ arg0: String, environment: JNIEnvironment) throws + public init(_ arg0: String, environment: JNIEnvironment? = nil) throws @JavaMethod - public init(_ arg0: String, _ arg1: String, _ arg2: String, _ arg3: Int32, _ arg4: String, _ arg5: String, _ arg6: String, environment: JNIEnvironment) throws + public init(_ arg0: String, _ arg1: String, _ arg2: String, _ arg3: Int32, _ arg4: String, _ arg5: String, _ arg6: String, environment: JNIEnvironment? = nil) throws @JavaMethod public func equals(_ arg0: JavaObject?) -> Bool diff --git a/Sources/JavaKitNetwork/generated/URL.swift b/Sources/JavaKitNetwork/generated/URL.swift index c98fa947..86c6c46a 100644 --- a/Sources/JavaKitNetwork/generated/URL.swift +++ b/Sources/JavaKitNetwork/generated/URL.swift @@ -5,16 +5,16 @@ import JavaRuntime @JavaClass("java.net.URL") public struct URL { @JavaMethod - public init(_ arg0: URL?, _ arg1: String, environment: JNIEnvironment) throws + public init(_ arg0: URL?, _ arg1: String, environment: JNIEnvironment? = nil) throws @JavaMethod - public init(_ arg0: String, environment: JNIEnvironment) throws + public init(_ arg0: String, environment: JNIEnvironment? = nil) throws @JavaMethod - public init(_ arg0: String, _ arg1: String, _ arg2: Int32, _ arg3: String, environment: JNIEnvironment) throws + public init(_ arg0: String, _ arg1: String, _ arg2: Int32, _ arg3: String, environment: JNIEnvironment? = nil) throws @JavaMethod - public init(_ arg0: String, _ arg1: String, _ arg2: String, environment: JNIEnvironment) throws + public init(_ arg0: String, _ arg1: String, _ arg2: String, environment: JNIEnvironment? = nil) throws @JavaMethod public func equals(_ arg0: JavaObject?) -> Bool diff --git a/Sources/JavaKitNetwork/generated/URLClassLoader.swift b/Sources/JavaKitNetwork/generated/URLClassLoader.swift index 6dd407f4..2f83d963 100644 --- a/Sources/JavaKitNetwork/generated/URLClassLoader.swift +++ b/Sources/JavaKitNetwork/generated/URLClassLoader.swift @@ -6,7 +6,7 @@ import JavaRuntime @JavaClass("java.net.URLClassLoader") public struct URLClassLoader { @JavaMethod - public init(_ arg0: [URL?], environment: JNIEnvironment) + public init(_ arg0: [URL?], environment: JNIEnvironment? = nil) @JavaMethod public func findResource(_ arg0: String) -> URL? diff --git a/Tests/Java2SwiftTests/Java2SwiftTests.swift b/Tests/Java2SwiftTests/Java2SwiftTests.swift index 579c74a8..e4ded5ab 100644 --- a/Tests/Java2SwiftTests/Java2SwiftTests.swift +++ b/Tests/Java2SwiftTests/Java2SwiftTests.swift @@ -14,7 +14,6 @@ import JavaKit import Java2SwiftLib -import JavaKitVM import XCTest // NOTE: Workaround for https://github.com/swiftlang/swift-java/issues/43 /// Handy reference to the JVM abstraction. @@ -66,7 +65,7 @@ class Java2SwiftTests: XCTestCase { return MonthCases.APRIL } """, - "public init(_ enumValue: MonthCases, environment: JNIEnvironment) {", + "public init(_ enumValue: MonthCases, environment: JNIEnvironment? = nil) {", """ case .APRIL: if let APRIL = classObj.APRIL { diff --git a/Tests/JavaKitMacroTests/JavaClassMacroTests.swift b/Tests/JavaKitMacroTests/JavaClassMacroTests.swift index cc0ad31b..82792df6 100644 --- a/Tests/JavaKitMacroTests/JavaClassMacroTests.swift +++ b/Tests/JavaKitMacroTests/JavaClassMacroTests.swift @@ -31,7 +31,10 @@ class JavaKitMacroTests: XCTestCase { @JavaClass("org.swift.example.HelloWorld") public struct HelloWorld { @JavaMethod - public init(_ value: Int32, environment: JNIEnvironment) + public init(environment: JNIEnvironment? = nil) + + @JavaMethod + public init(_ value: Int32, environment: JNIEnvironment? = nil) @JavaMethod public func isBigEnough(_: Int32) -> Bool @@ -43,8 +46,21 @@ class JavaKitMacroTests: XCTestCase { expandedSource: """ public struct HelloWorld { - public init(_ value: Int32, environment: JNIEnvironment) { - self = try! Self.dynamicJavaNewObject(in: environment, arguments: value.self) + public init(environment: JNIEnvironment? = nil) { + let _environment = if let environment { + environment + } else { + try! JavaVirtualMachine.shared().environment() + } + self = try! Self.dynamicJavaNewObject(in: _environment) + } + public init(_ value: Int32, environment: JNIEnvironment? = nil) { + let _environment = if let environment { + environment + } else { + try! JavaVirtualMachine.shared().environment() + } + self = try! Self.dynamicJavaNewObject(in: _environment, arguments: value.self) } public func isBigEnough(_: Int32) -> Bool { return try! dynamicJavaMethodCall(methodName: "isBigEnough", resultType: Bool.self) diff --git a/Tests/JavaKitTests/BasicRuntimeTests.swift b/Tests/JavaKitTests/BasicRuntimeTests.swift index 16669470..ad379a92 100644 --- a/Tests/JavaKitTests/BasicRuntimeTests.swift +++ b/Tests/JavaKitTests/BasicRuntimeTests.swift @@ -14,7 +14,6 @@ import JavaKit import JavaKitNetwork -import JavaKitVM import XCTest // NOTE: Workaround for https://github.com/swiftlang/swift-java/issues/43 /// Handy reference to the JVM abstraction. diff --git a/USER_GUIDE.md b/USER_GUIDE.md index b156f3e6..1e75b93d 100644 --- a/USER_GUIDE.md +++ b/USER_GUIDE.md @@ -47,7 +47,7 @@ If you build the project, there will be a generated file `BigInteger.swift` that @JavaClass("java.math.BigInteger") public struct BigInteger { @JavaMethod - public init(_ arg0: String, environment: JNIEnvironment) + public init(_ arg0: String, environment: JNIEnvironment? = nil) @JavaMethod public func toString() -> String @@ -225,7 +225,7 @@ Each Java class that can be used from Swift is translated to a Swift `struct` th @JavaClass("java.util.jar.JarFile", extends: ZipFile.self, implements: AutoCloseable.self) public struct JarFile { @JavaMethod - public init(_ arg0: String, _ arg1: Bool, environment: JNIEnvironment) + public init(_ arg0: String, _ arg1: Bool, environment: JNIEnvironment? = nil) @JavaMethod public func entries() -> Enumeration? @@ -259,7 +259,7 @@ Each of the public Java constructors, methods, and fields in the Java class will ```swift @JavaMethod - public init(_ arg0: String, _ arg1: Bool, environment: JNIEnvironment) + public init(_ arg0: String, _ arg1: Bool, environment: JNIEnvironment? = nil) ``` corresponds to the Java constructor: @@ -268,7 +268,9 @@ corresponds to the Java constructor: public JarFile(String arg0, bool arg1) ``` -The `environment` parameter is the pointer to the JNI environment (`JNIEnv*` in C) in which the underlying Java object lives. It is available to all methods that are written in or exposed to Java, either directly as a parameter (as in constructors) or on an instance of any type that's projected from Java through the `javaEnvironment` property of the `AnyJavaObject` conformance. Given a +The `environment` parameter is the pointer to the JNI environment (`JNIEnv*` in C) in which the underlying Java object lives. It is available to all methods that are written in or exposed to Java, +either directly as a parameter (as in constructors - in case of nil, the `JavaVirtualMachine.shared().environment()` value will be used) +or on an instance of any type that's projected from Java through the `javaEnvironment` property of the `AnyJavaObject` conformance. Given a Java environment, one can create a `JarFile` instance in Swift with, e.g., ```swift @@ -409,7 +411,7 @@ extension HelloSwift { Java native methods that throw any checked exception should be marked as `throws` in Swift. Swift will translate any thrown error into a Java exception. -The Swift implementations of Java `native` constructors and static methods require an additional Swift parameter `environment: JNIEnvironment`, which will receive the JNI environment in which the function is being executed. +The Swift implementations of Java `native` constructors and static methods require an additional Swift parameter `environment: JNIEnvironment? = nil`, which will receive the JNI environment in which the function is being executed. In case of nil, the `JavaVirtualMachine.shared().environment()` value will be used. ## Translating Java classes with `Java2Swift` @@ -541,7 +543,7 @@ import JavaKit @JavaClass("org.swift.javakit.HelloSwiftMain") struct HelloSwiftMain { @ImplementsJava - static func main(arguments: [String], environment: JNIEnvironment) { + static func main(arguments: [String], environment: JNIEnvironment? = nil) { print("Command line arguments are: \(arguments)") } } @@ -573,12 +575,12 @@ struct HelloSwiftMain: ParsableCommand { var verbose: Bool = false @ImplementsJava - static func main(arguments: [String], environment: JNIEnvironment) { + static func main(arguments: [String], environment: JNIEnvironment? = nil) { let command = Self.parseOrExit(arguments) command.run(environment: environment) } - func run(environment: JNIEnvironment) { + func run(environment: JNIEnvironment? = nil) { print("Verbose = \(verbose)") } } From a6efd5dae2b5dfc15bef18e339eabe74ccfdbb32 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Thu, 24 Oct 2024 00:10:33 +0900 Subject: [PATCH 121/426] remove some printlns (#104) remove some printlns --- .../src/main/java/org/swift/swiftkit/SwiftInstanceCleanup.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftInstanceCleanup.java b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftInstanceCleanup.java index e28e0dd7..a20a7599 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftInstanceCleanup.java +++ b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftInstanceCleanup.java @@ -34,8 +34,6 @@ public void run() throws UnexpectedRetainCountException { // Destroy (and deinit) the object: var ty = this.instance.$swiftType(); - System.out.println("x destroy instance = " + this.instance); - System.out.println("x destroy ty = " + ty); SwiftValueWitnessTable.destroy(ty, this.instance.$memorySegment()); From b1a82db2a2f4111b9d11398b0a26e1ad40d22935 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Wed, 23 Oct 2024 23:29:21 -0700 Subject: [PATCH 122/426] JavaKit: Rework `@ImplementsJava` to be more like `@implements` language feature (#105) --- Package.swift | 15 +- .../Java2SwiftPlugin/Java2SwiftPlugin.swift | 34 +++- Samples/JavaKitSampleApp/Package.swift | 41 ++++- .../Sources/JavaKitExample/Java2Swift.config | 5 +- .../JavaKitExample/JavaKitExample.swift | 55 +------ .../com/example/swift/HelloSubclass.java | 2 +- .../com/example/swift/HelloSwift.java | 10 +- .../com/example/swift/JavaKitSampleMain.java | 1 - Sources/Java2Swift/JavaToSwift.swift | 9 ++ Sources/Java2SwiftLib/JavaTranslator.swift | 127 +++++++++++---- Sources/JavaKit/JavaObject+MethodCalls.swift | 10 +- Sources/JavaKit/Macros.swift | 33 ++-- Sources/JavaKitMacros/GenerationMode.swift | 76 +++++++++ .../JavaKitMacros/ImplementsJavaMacro.swift | 144 ++++++++++++++++- Sources/JavaKitMacros/JavaClassMacro.swift | 147 ------------------ Sources/JavaKitMacros/JavaMethodMacro.swift | 16 ++ Sources/JavaKitMacros/MacroErrors.swift | 3 + .../JavaKitMacros/SwiftJNIMacrosPlugin.swift | 2 +- .../Constructor+Utilities.swift | 5 + .../JavaClass+Reflection.swift | 3 + .../JavaKitReflection/Method+Utilities.swift | 5 + .../FunctionDescriptorImportTests.swift | 10 +- .../VariableImportTests.swift | 6 +- Tests/Java2SwiftTests/Java2SwiftTests.swift | 2 +- Tests/JavaKitTests/BasicRuntimeTests.swift | 29 +--- USER_GUIDE.md | 142 ++++++++--------- 26 files changed, 557 insertions(+), 375 deletions(-) create mode 100644 Sources/JavaKitMacros/GenerationMode.swift diff --git a/Package.swift b/Package.swift index 5b34a2eb..e7f6353f 100644 --- a/Package.swift +++ b/Package.swift @@ -262,7 +262,8 @@ let package = Package( ], swiftSettings: [ .swiftLanguageMode(.v5), - .enableUpcomingFeature("BareSlashRegexLiterals") + .enableUpcomingFeature("BareSlashRegexLiterals"), + .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]), ] ), @@ -281,7 +282,8 @@ let package = Package( swiftSettings: [ .swiftLanguageMode(.v5), - .enableUpcomingFeature("BareSlashRegexLiterals") + .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]), + .enableUpcomingFeature("BareSlashRegexLiterals"), ] ), @@ -296,7 +298,8 @@ let package = Package( "JavaTypes", ], swiftSettings: [ - .swiftLanguageMode(.v5) + .swiftLanguageMode(.v5), + .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]), ] ), @@ -314,7 +317,8 @@ let package = Package( name: "JavaKitTests", dependencies: ["JavaKit", "JavaKitNetwork"], swiftSettings: [ - .swiftLanguageMode(.v5) + .swiftLanguageMode(.v5), + .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) ] ), @@ -341,7 +345,8 @@ let package = Package( name: "Java2SwiftTests", dependencies: ["Java2SwiftLib"], swiftSettings: [ - .swiftLanguageMode(.v5) + .swiftLanguageMode(.v5), + .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) ] ), diff --git a/Plugins/Java2SwiftPlugin/Java2SwiftPlugin.swift b/Plugins/Java2SwiftPlugin/Java2SwiftPlugin.swift index 30be39a9..37ee1b3a 100644 --- a/Plugins/Java2SwiftPlugin/Java2SwiftPlugin.swift +++ b/Plugins/Java2SwiftPlugin/Java2SwiftPlugin.swift @@ -93,12 +93,44 @@ struct Java2SwiftBuildToolPlugin: BuildToolPlugin { outputDirectory.appending(path: "\(swiftName).swift") } + // Find the Java .class files generated from prior plugins. + let compiledClassFiles = sourceModule.pluginGeneratedResources.filter { url in + url.pathExtension == "class" + } + + if let firstClassFile = compiledClassFiles.first { + // Keep stripping off parts of the path until we hit the "Java" part. + // That's where the class path starts. + var classpath = firstClassFile + while classpath.lastPathComponent != "Java" { + classpath.deleteLastPathComponent() + } + arguments += [ "--classpath", classpath.path() ] + + // For each of the class files, note that it can have Swift-native + // implementations. We figure this out based on the path. + for classFile in compiledClassFiles { + var classFile = classFile.deletingPathExtension() + var classNameComponents: [String] = [] + + while classFile.lastPathComponent != "Java" { + classNameComponents.append(classFile.lastPathComponent) + classFile.deleteLastPathComponent() + } + + let className = classNameComponents + .reversed() + .joined(separator: ".") + arguments += [ "--swift-native-implementation", className] + } + } + return [ .buildCommand( displayName: "Wrapping \(config.classes.count) Java classes target \(sourceModule.name) in Swift", executable: try context.tool(named: "Java2Swift").url, arguments: arguments, - inputFiles: [ configFile ], + inputFiles: [ configFile ] + compiledClassFiles, outputFiles: outputSwiftFiles ) ] diff --git a/Samples/JavaKitSampleApp/Package.swift b/Samples/JavaKitSampleApp/Package.swift index df2c65f1..1da05c29 100644 --- a/Samples/JavaKitSampleApp/Package.swift +++ b/Samples/JavaKitSampleApp/Package.swift @@ -4,6 +4,42 @@ import CompilerPluginSupport import PackageDescription +import class Foundation.FileManager +import class Foundation.ProcessInfo + +// Note: the JAVA_HOME environment variable must be set to point to where +// Java is installed, e.g., +// Library/Java/JavaVirtualMachines/openjdk-21.jdk/Contents/Home. +func findJavaHome() -> String { + if let home = ProcessInfo.processInfo.environment["JAVA_HOME"] { + return home + } + + // This is a workaround for envs (some IDEs) which have trouble with + // picking up env variables during the build process + let path = "\(FileManager.default.homeDirectoryForCurrentUser.path()).java_home" + if let home = try? String(contentsOfFile: path, encoding: .utf8) { + if let lastChar = home.last, lastChar.isNewline { + return String(home.dropLast()) + } + + return home + } + + fatalError("Please set the JAVA_HOME environment variable to point to where Java is installed.") +} +let javaHome = findJavaHome() + +let javaIncludePath = "\(javaHome)/include" +#if os(Linux) + let javaPlatformIncludePath = "\(javaIncludePath)/linux" +#elseif os(macOS) + let javaPlatformIncludePath = "\(javaIncludePath)/darwin" +#else + // TODO: Handle windows as well + #error("Currently only macOS and Linux platforms are supported, this may change in the future.") +#endif + let package = Package( name: "JavaKitSampleApp", platforms: [ @@ -34,11 +70,12 @@ let package = Package( .product(name: "JavaKitJar", package: "swift-java"), ], swiftSettings: [ - .swiftLanguageMode(.v5) + .swiftLanguageMode(.v5), + .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) ], plugins: [ + .plugin(name: "JavaCompilerPlugin", package: "swift-java"), .plugin(name: "Java2SwiftPlugin", package: "swift-java"), - .plugin(name: "JavaCompilerPlugin", package: "swift-java") ] ), ] diff --git a/Samples/JavaKitSampleApp/Sources/JavaKitExample/Java2Swift.config b/Samples/JavaKitSampleApp/Sources/JavaKitExample/Java2Swift.config index ec19d82b..5ccb042b 100644 --- a/Samples/JavaKitSampleApp/Sources/JavaKitExample/Java2Swift.config +++ b/Samples/JavaKitSampleApp/Sources/JavaKitExample/Java2Swift.config @@ -1,5 +1,8 @@ { "classes" : { - "java.util.ArrayList" : "ArrayList" + "java.util.ArrayList" : "ArrayList", + "com.example.swift.HelloSwift" : "HelloSwift", + "com.example.swift.HelloSubclass" : "HelloSubclass", + "com.example.swift.JavaKitSampleMain" : "JavaKitSampleMain" } } diff --git a/Samples/JavaKitSampleApp/Sources/JavaKitExample/JavaKitExample.swift b/Samples/JavaKitSampleApp/Sources/JavaKitExample/JavaKitExample.swift index 090c4356..aaaff0bb 100644 --- a/Samples/JavaKitSampleApp/Sources/JavaKitExample/JavaKitExample.swift +++ b/Samples/JavaKitSampleApp/Sources/JavaKitExample/JavaKitExample.swift @@ -18,31 +18,10 @@ enum SwiftWrappedError: Error { case message(String) } -@JavaClass("com.example.swift.HelloSwift") -struct HelloSwift { +@JavaImplementation("com.example.swift.HelloSwift") +extension HelloSwift: HelloSwiftNativeMethods { @JavaMethod - init(environment: JNIEnvironment) - - @JavaMethod - func sayHelloBack(_ i: Int32) -> Double - - @JavaMethod - func greet(_ name: String) - - @JavaMethod - func doublesToStrings(doubles: [Double]) -> [String] - - @JavaMethod - func throwMessage(message: String) throws - - @JavaField - var value: Double - - @JavaField - var name: String - - @ImplementsJava - func sayHello(i: Int32, _ j: Int32) -> Int32 { + func sayHello(_ i: Int32, _ j: Int32) -> Int32 { print("Hello from Swift!") let answer = self.sayHelloBack(i + j) print("Swift got back \(answer) from Java") @@ -65,7 +44,7 @@ struct HelloSwift { self.name = "a 🗑️-collected language" _ = self.sayHelloBack(42) - let strings = doublesToStrings(doubles: [3.14159, 2.71828]) + let strings = doublesToStrings([3.14159, 2.71828]) print("Converting doubles to strings: \(strings)") // Try downcasting @@ -83,11 +62,11 @@ struct HelloSwift { assert(!newHello.is(HelloSubclass.self)) // Create a new instance. - let helloSubFromSwift = HelloSubclass(greeting: "Hello from Swift", environment: javaEnvironment) + let helloSubFromSwift = HelloSubclass("Hello from Swift", environment: javaEnvironment) helloSubFromSwift.greetMe() do { - try throwMessage(message: "I am an error") + try throwMessage("I am an error") } catch { print("Caught Java error: \(error)") } @@ -95,30 +74,12 @@ struct HelloSwift { return i * j } - @ImplementsJava - func throwMessageFromSwift(message: String) throws -> String { + @JavaMethod + func throwMessageFromSwift(_ message: String) throws -> String { throw SwiftWrappedError.message(message) } } -extension JavaClass { - @JavaStaticField - var initialValue: Double -} - -@JavaClass("com.example.swift.HelloSubclass", extends: HelloSwift.self) -struct HelloSubclass { - @JavaField - var greeting: String - - @JavaMethod - func greetMe() - - @JavaMethod - init(greeting: String, environment: JNIEnvironment) -} - - func removeLast(arrayList: ArrayList>) { if let lastObject = arrayList.getLast() { _ = arrayList.remove(lastObject) diff --git a/Samples/JavaKitSampleApp/Sources/JavaKitExample/com/example/swift/HelloSubclass.java b/Samples/JavaKitSampleApp/Sources/JavaKitExample/com/example/swift/HelloSubclass.java index eb3cba32..2312d8f5 100644 --- a/Samples/JavaKitSampleApp/Sources/JavaKitExample/com/example/swift/HelloSubclass.java +++ b/Samples/JavaKitSampleApp/Sources/JavaKitExample/com/example/swift/HelloSubclass.java @@ -21,7 +21,7 @@ public HelloSubclass(String greeting) { this.greeting = greeting; } - private void greetMe() { + public void greetMe() { super.greet(greeting); } } diff --git a/Samples/JavaKitSampleApp/Sources/JavaKitExample/com/example/swift/HelloSwift.java b/Samples/JavaKitSampleApp/Sources/JavaKitExample/com/example/swift/HelloSwift.java index b4c87f71..f988bbb6 100644 --- a/Samples/JavaKitSampleApp/Sources/JavaKitExample/com/example/swift/HelloSwift.java +++ b/Samples/JavaKitSampleApp/Sources/JavaKitExample/com/example/swift/HelloSwift.java @@ -15,9 +15,9 @@ package com.example.swift; public class HelloSwift { - private double value; - private static double initialValue = 3.14159; - private String name = "Java"; + public double value; + public static double initialValue = 3.14159; + public String name = "Java"; static { System.loadLibrary("JavaKitExample"); @@ -31,7 +31,7 @@ public HelloSwift() { public native String throwMessageFromSwift(String message) throws Exception; // To be called back by the native code - private double sayHelloBack(int i) { + public double sayHelloBack(int i) { System.out.println("And hello back from " + name + "! You passed me " + i); return value; } @@ -40,7 +40,7 @@ public void greet(String name) { System.out.println("Salutations, " + name); } - String[] doublesToStrings(double[] doubles) { + public String[] doublesToStrings(double[] doubles) { int size = doubles.length; String[] strings = new String[size]; diff --git a/Samples/JavaKitSampleApp/Sources/JavaKitExample/com/example/swift/JavaKitSampleMain.java b/Samples/JavaKitSampleApp/Sources/JavaKitExample/com/example/swift/JavaKitSampleMain.java index 2b565608..9036b7a5 100644 --- a/Samples/JavaKitSampleApp/Sources/JavaKitExample/com/example/swift/JavaKitSampleMain.java +++ b/Samples/JavaKitSampleApp/Sources/JavaKitExample/com/example/swift/JavaKitSampleMain.java @@ -19,7 +19,6 @@ * For the Swift implementation refer to */ public class JavaKitSampleMain { - public static void main(String[] args) { int result = new HelloSubclass("Swift").sayHello(17, 25); System.out.println("sayHello(17, 25) = " + result); diff --git a/Sources/Java2Swift/JavaToSwift.swift b/Sources/Java2Swift/JavaToSwift.swift index ffb9a24f..1cc094c2 100644 --- a/Sources/Java2Swift/JavaToSwift.swift +++ b/Sources/Java2Swift/JavaToSwift.swift @@ -48,6 +48,11 @@ struct JavaToSwift: ParsableCommand { ) var classpath: [String] = [] + @Option( + help: "The names of Java classes whose declared native methods will be implemented in Swift." + ) + var swiftNativeImplementation: [String] = [] + @Option(name: .shortAndLong, help: "The directory in which to output the generated Swift files or the Java2Swift configuration file.") var outputDirectory: String? = nil @@ -181,6 +186,10 @@ struct JavaToSwift: ParsableCommand { environment: environment ) + // Keep track of all of the Java classes that will have + // Swift-native implementations. + translator.swiftNativeImplementations = Set(swiftNativeImplementation) + // Note all of the dependent configurations. for (swiftModuleName, dependentConfig) in dependentConfigs { translator.addConfiguration( diff --git a/Sources/Java2SwiftLib/JavaTranslator.swift b/Sources/Java2SwiftLib/JavaTranslator.swift index b7eec617..a5af9baa 100644 --- a/Sources/Java2SwiftLib/JavaTranslator.swift +++ b/Sources/Java2SwiftLib/JavaTranslator.swift @@ -39,6 +39,10 @@ package class JavaTranslator { /// import declarations. package var importedSwiftModules: Set = JavaTranslator.defaultImportedSwiftModules + /// The canonical names of Java classes whose declared 'native' + /// methods will be implemented in Swift. + package var swiftNativeImplementations: Set = [] + package init( swiftModuleName: String, environment: JNIEnvironment, @@ -229,9 +233,16 @@ extension JavaTranslator { interfacesStr = ", \(prefix): \(interfaces.joined(separator: ", "))" } + // The top-level declarations we will be returning. + var topLevelDecls: [DeclSyntax] = [] + // Members var members: [DeclSyntax] = [] - + + // Members that are native and will instead go into a NativeMethods + // protocol. + var nativeMembers: [DeclSyntax] = [] + // Fields var staticFields: [Field] = [] var enumConstants: [Field] = [] @@ -269,7 +280,21 @@ extension JavaTranslator { contentsOf: javaClass.getConstructors().compactMap { $0.flatMap { constructor in do { - return try translateConstructor(constructor) + let implementedInSwift = constructor.isNative && + constructor.getDeclaringClass()!.equals(javaClass.as(JavaObject.self)!) && + swiftNativeImplementations.contains(javaClass.getCanonicalName()) + + let translated = try translateConstructor( + constructor, + implementedInSwift: implementedInSwift + ) + + if implementedInSwift { + nativeMembers.append(translated) + return nil + } + + return translated } catch { logUntranslated("Unable to translate '\(fullName)' constructor: \(error)") return nil @@ -282,7 +307,7 @@ extension JavaTranslator { var staticMethods: [Method] = [] members.append( contentsOf: javaClass.getMethods().compactMap { - $0.flatMap { method in + $0.flatMap { (method) -> DeclSyntax? in // Save the static methods; they need to go on an extension of // JavaClass. if method.isStatic { @@ -290,9 +315,23 @@ extension JavaTranslator { return nil } + let implementedInSwift = method.isNative && + method.getDeclaringClass()!.equals(javaClass.as(JavaObject.self)!) && + swiftNativeImplementations.contains(javaClass.getCanonicalName()) + // Translate the method if we can. do { - return try translateMethod(method) + let translated = try translateMethod( + method, + implementedInSwift: implementedInSwift + ) + + if implementedInSwift { + nativeMembers.append(translated) + return nil + } + + return translated } catch { logUntranslated("Unable to translate '\(fullName)' method '\(method.getName())': \(error)") return nil @@ -347,10 +386,8 @@ extension JavaTranslator { // Format the class declaration. classDecl = classDecl.formatted(using: format).cast(DeclSyntax.self) - - if staticMethods.isEmpty && staticFields.isEmpty { - return [classDecl] - } + + topLevelDecls.append(classDecl) // Translate static members. var staticMembers: [DeclSyntax] = [] @@ -372,7 +409,7 @@ extension JavaTranslator { // Translate each static method. do { return try translateMethod( - method, + method, implementedInSwift: /*FIXME:*/false, genericParameterClause: genericParameterClause, whereClause: staticMemberWhereClause ) @@ -383,46 +420,74 @@ extension JavaTranslator { } ) - if staticMembers.isEmpty { - return [classDecl] - } + if !staticMembers.isEmpty { + // Specify the specialization arguments when needed. + let extSpecialization: String + if genericParameterClause.isEmpty { + extSpecialization = "<\(swiftTypeName)>" + } else { + extSpecialization = "" + } - // Specify the specialization arguments when needed. - let extSpecialization: String - if genericParameterClause.isEmpty { - extSpecialization = "<\(swiftTypeName)>" - } else { - extSpecialization = "" + let extDecl: DeclSyntax = + """ + extension JavaClass\(raw: extSpecialization) { + \(raw: staticMembers.map { $0.description }.joined(separator: "\n\n")) + } + """ + + topLevelDecls.append( + extDecl.formatted(using: format).cast(DeclSyntax.self) + ) } - let extDecl = - (""" - extension JavaClass\(raw: extSpecialization) { - \(raw: staticMembers.map { $0.description }.joined(separator: "\n\n")) + if !nativeMembers.isEmpty { + let protocolDecl: DeclSyntax = + """ + /// Describes the Java `native` methods for ``\(raw: swiftTypeName)``. + /// + /// To implement all of the `native` methods for \(raw: swiftTypeName) in Swift, + /// extend \(raw: swiftTypeName) to conform to this protocol and mark + /// each implementation of the protocol requirement with + /// `@JavaMethod`. + protocol \(raw: swiftTypeName)NativeMethods { + \(raw: nativeMembers.map { $0.description }.joined(separator: "\n\n")) + } + """ + + topLevelDecls.append( + protocolDecl.formatted(using: format).cast(DeclSyntax.self) + ) } - """ as DeclSyntax).formatted(using: format).cast(DeclSyntax.self) - return [classDecl, extDecl] + return topLevelDecls } } // MARK: Method and constructor translation extension JavaTranslator { /// Translates the given Java constructor into a Swift declaration. - package func translateConstructor(_ javaConstructor: Constructor) throws -> DeclSyntax { + package func translateConstructor( + _ javaConstructor: Constructor, + implementedInSwift: Bool + ) throws -> DeclSyntax { let parameters = try translateParameters(javaConstructor.getParameters()) + ["environment: JNIEnvironment? = nil"] let parametersStr = parameters.map { $0.description }.joined(separator: ", ") let throwsStr = javaConstructor.throwsCheckedException ? "throws" : "" + let javaMethodAttribute = implementedInSwift + ? "" + : "@JavaMethod\n" + let accessModifier = implementedInSwift ? "" : "public " return """ - @JavaMethod - public init(\(raw: parametersStr))\(raw: throwsStr) + \(raw: javaMethodAttribute)\(raw: accessModifier)init(\(raw: parametersStr))\(raw: throwsStr) """ } /// Translates the given Java method into a Swift declaration. package func translateMethod( _ javaMethod: Method, + implementedInSwift: Bool, genericParameterClause: String = "", whereClause: String = "" ) throws -> DeclSyntax { @@ -442,10 +507,12 @@ extension JavaTranslator { let throwsStr = javaMethod.throwsCheckedException ? "throws" : "" let swiftMethodName = javaMethod.getName().escapedSwiftName - let methodAttribute: AttributeSyntax = javaMethod.isStatic ? "@JavaStaticMethod" : "@JavaMethod"; + let methodAttribute: AttributeSyntax = implementedInSwift + ? "" + : javaMethod.isStatic ? "@JavaStaticMethod\n" : "@JavaMethod\n"; + let accessModifier = implementedInSwift ? "" : "public " return """ - \(methodAttribute) - public func \(raw: swiftMethodName)\(raw: genericParameterClause)(\(raw: parametersStr))\(raw: throwsStr)\(raw: resultTypeStr)\(raw: whereClause) + \(methodAttribute)\(raw: accessModifier)func \(raw: swiftMethodName)\(raw: genericParameterClause)(\(raw: parametersStr))\(raw: throwsStr)\(raw: resultTypeStr)\(raw: whereClause) """ } diff --git a/Sources/JavaKit/JavaObject+MethodCalls.swift b/Sources/JavaKit/JavaObject+MethodCalls.swift index e9b97bc2..0a48b8bd 100644 --- a/Sources/JavaKit/JavaObject+MethodCalls.swift +++ b/Sources/JavaKit/JavaObject+MethodCalls.swift @@ -20,13 +20,9 @@ private func methodMangling( parameterTypes: repeat (each Param).Type, resultType: JavaType ) -> String { - let parameterTypesArray = [JavaType].init(unsafeUninitializedCapacity: countArgs(repeat each parameterTypes)) { - buffer, - initializedCount in - for parameterType in repeat each parameterTypes { - buffer[initializedCount] = parameterType.javaType - initializedCount += 1 - } + var parameterTypesArray: [JavaType] = [] + for parameterType in repeat each parameterTypes { + parameterTypesArray.append(parameterType.javaType) } return MethodSignature( resultType: resultType, diff --git a/Sources/JavaKit/Macros.swift b/Sources/JavaKit/Macros.swift index 347a3ebf..12ae0c26 100644 --- a/Sources/JavaKit/Macros.swift +++ b/Sources/JavaKit/Macros.swift @@ -41,7 +41,6 @@ named(`as`) ) @attached(extension, conformances: AnyJavaObject) -@attached(peer) public macro JavaClass( _ fullClassName: String, extends: (any AnyJavaObject.Type)? = nil, @@ -143,23 +142,27 @@ public macro JavaMethod() = #externalMacro(module: "JavaKitMacros", type: "JavaM @attached(body) public macro JavaStaticMethod() = #externalMacro(module: "JavaKitMacros", type: "JavaMethodMacro") -/// Macro that exposes the given Swift method as a native method in Java. -/// -/// The macro must be used within a struct type marked with `@JavaClass`, and there -/// must be a corresponding Java method declared as `native` for it to be called from -/// Java. For example, given this Swift method: -/// -/// ```swift -/// @ImplementsJava -/// func sayHello(i: Int32, _ j: Int32) -> Int32 { -/// // swift implementation -/// } +/// Macro that marks extensions to specify that all of the @JavaMethod +/// methods are implementations of Java methods spelled as `native`. /// -/// inside a struct with `@JavaClass("com.example.swift.HelloSwift")`, the -/// corresponding `HelloSwift` Java class should have: +/// For example, given a Java native method such as the following in +/// a Java class `org.swift.example.Hello`: /// /// ```java /// public native int sayHello(int i, int j); /// ``` +/// +/// Assuming that the Java class with imported into Swift as `Hello`, t +/// the method can be implemented in Swift with the following: +/// +/// ```swift +/// @JavaImplementation +/// extension Hello { +/// @JavaMethod +/// func sayHello(i: Int32, _ j: Int32) -> Int32 { +/// // swift implementation +/// } +/// } +/// ``` @attached(peer) -public macro ImplementsJava() = #externalMacro(module: "JavaKitMacros", type: "ImplementsJavaMacro") +public macro JavaImplementation(_ fullClassName: String) = #externalMacro(module: "JavaKitMacros", type: "JavaImplementationMacro") diff --git a/Sources/JavaKitMacros/GenerationMode.swift b/Sources/JavaKitMacros/GenerationMode.swift new file mode 100644 index 00000000..d000d209 --- /dev/null +++ b/Sources/JavaKitMacros/GenerationMode.swift @@ -0,0 +1,76 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import SwiftSyntax +import SwiftSyntaxMacros + +/// The mode of code generation being used for macros. +enum GenerationMode { + /// This macro is describing a Java class in Swift. + case importFromJava + + /// This macro is describing a Swift type that will be represented by + /// a generated Java class. + case exportToJava + + /// This macro is describing an extension that is implementing the native + /// methods of a Java class. + case javaImplementation + + /// Determine the mode for Java class generation based on an attribute. + init?(attribute: AttributeSyntax) { + switch attribute.attributeName.trimmedDescription { + case "JavaClass", "JavaInterface": + self = .importFromJava + + case "ExportToJavaClass": + self = .exportToJava + + case "JavaImplementation": + self = .javaImplementation + + default: + return nil + } + } + + /// Determine the mode for Java class generation based on the the macro + /// expansion context. + init?(expansionContext: some MacroExpansionContext) { + for lexicalContext in expansionContext.lexicalContext { + // FIXME: swift-syntax probably needs an AttributedSyntax node for us + // to look at. For now, we can look at just structs and extensions. + let attributes: AttributeListSyntax + if let structSyntax = lexicalContext.as(StructDeclSyntax.self) { + attributes = structSyntax.attributes + } else if let extSyntax = lexicalContext.as(ExtensionDeclSyntax.self) { + attributes = extSyntax.attributes + } else { + continue + } + + // Look for the first attribute that is associated with a mode, and + // return that. + for attribute in attributes { + if case .attribute(let attribute) = attribute, + let mode = GenerationMode(attribute: attribute) { + self = mode + return + } + } + } + + return nil + } +} diff --git a/Sources/JavaKitMacros/ImplementsJavaMacro.swift b/Sources/JavaKitMacros/ImplementsJavaMacro.swift index 2d6d7159..b3057ae4 100644 --- a/Sources/JavaKitMacros/ImplementsJavaMacro.swift +++ b/Sources/JavaKitMacros/ImplementsJavaMacro.swift @@ -16,14 +16,152 @@ import SwiftSyntax import SwiftSyntaxBuilder import SwiftSyntaxMacros -enum ImplementsJavaMacro {} +enum JavaImplementationMacro {} -extension ImplementsJavaMacro: PeerMacro { +extension JavaImplementationMacro: PeerMacro { static func expansion( of node: AttributeSyntax, providingPeersOf declaration: some DeclSyntaxProtocol, in context: some MacroExpansionContext ) throws -> [DeclSyntax] { - [] + guard let extensionDecl = declaration.as(ExtensionDeclSyntax.self) else { + throw MacroErrors.javaImplementationRequiresExtension + } + + // Dig out the Java class name. + guard case .argumentList(let arguments) = node.arguments, + let wrapperTypeNameExpr = arguments.first?.expression, + let stringLiteral = wrapperTypeNameExpr.as(StringLiteralExprSyntax.self), + stringLiteral.segments.count == 1, + case let .stringSegment(classNameSegment)? = stringLiteral.segments.first + else { + throw MacroErrors.classNameNotStringLiteral + } + + // Check that the class name is fully-qualified, as it should be. + let className = classNameSegment.content.text + if className.firstIndex(of: ".") == nil { + throw MacroErrors.classNameNotFullyQualified(className) + } + + var exposedMembers: [DeclSyntax] = [] + for memberItem in extensionDecl.memberBlock.members { + let memberDecl = memberItem.decl + + guard let attributes = memberDecl.asProtocol(WithAttributesSyntax.self)?.attributes, + attributes.contains(where: { + guard case .attribute(let attribute) = $0 else { + return false + } + return attribute.attributeName.trimmedDescription == "JavaMethod" + }), + let memberFunc = memberDecl.as(FunctionDeclSyntax.self) + else { + continue + } + + let isStatic = memberFunc.modifiers.contains { modifier in + modifier.name.text == "static" + } + + // Static functions exposed to Java must have an "environment" parameter. + // We remove it from the signature of the native C function we expose. + var parametersClause = memberFunc.signature.parameterClause + let environmentIndex = parametersClause.parameters.indexOfParameter(named: "environment") + if isStatic { + guard let environmentIndex else { + throw MacroErrors.missingEnvironment + } + + parametersClause.parameters.remove(at: environmentIndex) + } + + // Map the parameters. + let cParameters: [FunctionParameterSyntax] = + [ + "environment: UnsafeMutablePointer!", + isStatic ? "thisClass: jclass" : "thisObj: jobject", + ] + + parametersClause.parameters.map { param in + param.with(\.type, "\(param.type).JNIType") + .with(\.trailingComma, nil) + } + + // Map the arguments. + let swiftArguments: [ExprSyntax] = memberFunc.signature.parameterClause.parameters.map { param in + let label = + if let argumentName = param.argumentName { + "\(argumentName):" + } else { + "" + } + + // The "environment" is passed through directly. + if let environmentIndex, memberFunc.signature.parameterClause.parameters[environmentIndex] == param { + return "\(raw: label)\(param.secondName ?? param.firstName)" + } + + return "\(raw: label)\(param.type)(fromJNI: \(param.secondName ?? param.firstName), in: environment!)" + } + + // Map the return type, if there is one. + let returnType = memberFunc.signature.returnClause?.type.trimmed + let cReturnType = + returnType.map { + "-> \($0).JNIType" + } ?? "" + + let swiftName = memberFunc.name.text + let cName = "Java_" + className.replacingOccurrences(of: ".", with: "_") + "_" + swiftName + let innerBody: CodeBlockItemListSyntax + let isThrowing = memberFunc.signature.effectSpecifiers?.throwsClause != nil + let tryClause: String = isThrowing ? "try " : "" + let getJNIValue: String = + returnType != nil + ? "\n .getJNIValue(in: environment)" + : "" + let swiftTypeName = extensionDecl.extendedType.trimmedDescription + if isStatic { + innerBody = """ + return \(raw: tryClause)\(raw: swiftTypeName).\(raw: swiftName)(\(raw: swiftArguments.map { $0.description }.joined(separator: ", ")))\(raw: getJNIValue) + """ + } else { + innerBody = """ + let obj = \(raw: swiftTypeName)(javaThis: thisObj, environment: environment!) + return \(raw: tryClause)obj.\(raw: swiftName)(\(raw: swiftArguments.map { $0.description }.joined(separator: ", ")))\(raw: getJNIValue) + """ + } + + let body: CodeBlockItemListSyntax + if isThrowing { + let dummyReturn: StmtSyntax + if let returnType { + dummyReturn = "return \(returnType).jniPlaceholderValue" + } else { + dummyReturn = "return ()" + } + body = """ + do { + \(innerBody) + } catch let error { + environment.throwAsException(error) + \(dummyReturn) + } + """ + } else { + body = innerBody + } + + exposedMembers.append( + """ + @_cdecl(\(literal: cName)) + func \(context.makeUniqueName(swiftName))(\(raw: cParameters.map{ $0.description }.joined(separator: ", ")))\(raw: cReturnType) { + \(body) + } + """ + ) + } + + return exposedMembers } } diff --git a/Sources/JavaKitMacros/JavaClassMacro.swift b/Sources/JavaKitMacros/JavaClassMacro.swift index 3cee441d..2f0783f1 100644 --- a/Sources/JavaKitMacros/JavaClassMacro.swift +++ b/Sources/JavaKitMacros/JavaClassMacro.swift @@ -126,150 +126,3 @@ extension JavaClassMacro: ExtensionMacro { return [AnyJavaObjectConformance.as(ExtensionDeclSyntax.self)!] } } - -extension JavaClassMacro: PeerMacro { - package static func expansion( - of node: AttributeSyntax, - providingPeersOf declaration: some DeclSyntaxProtocol, - in context: some MacroExpansionContext - ) throws -> [DeclSyntax] { - // Dig out the Java class name. - guard case .argumentList(let arguments) = node.arguments, - let wrapperTypeNameExpr = arguments.first?.expression, - let stringLiteral = wrapperTypeNameExpr.as(StringLiteralExprSyntax.self), - stringLiteral.segments.count == 1, - case let .stringSegment(classNameSegment)? = stringLiteral.segments.first - else { - throw MacroErrors.classNameNotStringLiteral - } - - // Check that the class name is fully-qualified, as it should be. - let className = classNameSegment.content.text - if className.firstIndex(of: ".") == nil { - throw MacroErrors.classNameNotFullyQualified(className) - } - - guard let swiftStruct = declaration.as(StructDeclSyntax.self) else { - throw MacroErrors.javaClassNotOnType - } - - var exposedMembers: [DeclSyntax] = [] - for memberItem in swiftStruct.memberBlock.members { - let memberDecl = memberItem.decl - - guard let attributes = memberDecl.asProtocol(WithAttributesSyntax.self)?.attributes, - attributes.contains(where: { - guard case .attribute(let attribute) = $0 else { - return false - } - return attribute.attributeName.trimmedDescription == "ImplementsJava" - }), - let memberFunc = memberDecl.as(FunctionDeclSyntax.self) - else { - continue - } - - let isStatic = memberFunc.modifiers.contains { modifier in - modifier.name.text == "static" - } - - // Static functions exposed to Java must have an "environment" parameter. - // We remove it from the signature of the native C function we expose. - var parametersClause = memberFunc.signature.parameterClause - let environmentIndex = parametersClause.parameters.indexOfParameter(named: "environment") - if isStatic { - guard let environmentIndex else { - throw MacroErrors.missingEnvironment - } - - parametersClause.parameters.remove(at: environmentIndex) - } - - // Map the parameters. - let cParameters: [FunctionParameterSyntax] = - [ - "environment: UnsafeMutablePointer!", - isStatic ? "thisClass: jclass" : "thisObj: jobject", - ] - + parametersClause.parameters.map { param in - param.with(\.type, "\(param.type).JNIType") - .with(\.trailingComma, nil) - } - - // Map the arguments. - let swiftArguments: [ExprSyntax] = memberFunc.signature.parameterClause.parameters.map { param in - let label = - if let argumentName = param.argumentName { - "\(argumentName):" - } else { - "" - } - - // The "environment" is passed through directly. - if let environmentIndex, memberFunc.signature.parameterClause.parameters[environmentIndex] == param { - return "\(raw: label)\(param.secondName ?? param.firstName)" - } - - return "\(raw: label)\(param.type)(fromJNI: \(param.secondName ?? param.firstName), in: environment!)" - } - - // Map the return type, if there is one. - let returnType = memberFunc.signature.returnClause?.type.trimmed - let cReturnType = - returnType.map { - "-> \($0).JNIType" - } ?? "" - - let swiftName = memberFunc.name.text - let cName = "Java_" + className.replacingOccurrences(of: ".", with: "_") + "_" + swiftName - let innerBody: CodeBlockItemListSyntax - let isThrowing = memberFunc.signature.effectSpecifiers?.throwsClause != nil - let tryClause: String = isThrowing ? "try " : "" - let getJNIValue: String = - returnType != nil - ? "\n .getJNIValue(in: environment)" - : "" - if isStatic { - innerBody = """ - return \(raw: tryClause)\(raw: swiftStruct.name.text).\(raw: swiftName)(\(raw: swiftArguments.map { $0.description }.joined(separator: ", ")))\(raw: getJNIValue) - """ - } else { - innerBody = """ - let obj = \(raw: swiftStruct.name.text)(javaThis: thisObj, environment: environment!) - return \(raw: tryClause)obj.\(raw: swiftName)(\(raw: swiftArguments.map { $0.description }.joined(separator: ", ")))\(raw: getJNIValue) - """ - } - - let body: CodeBlockItemListSyntax - if isThrowing { - let dummyReturn: StmtSyntax - if let returnType { - dummyReturn = "return \(returnType).jniPlaceholderValue" - } else { - dummyReturn = "return ()" - } - body = """ - do { - \(innerBody) - } catch let error { - environment.throwAsException(error) - \(dummyReturn) - } - """ - } else { - body = innerBody - } - - exposedMembers.append( - """ - @_cdecl(\(literal: cName)) - func \(context.makeUniqueName(swiftName))(\(raw: cParameters.map{ $0.description }.joined(separator: ", ")))\(raw: cReturnType) { - \(body) - } - """ - ) - } - - return exposedMembers - } -} diff --git a/Sources/JavaKitMacros/JavaMethodMacro.swift b/Sources/JavaKitMacros/JavaMethodMacro.swift index c748f050..f525c985 100644 --- a/Sources/JavaKitMacros/JavaMethodMacro.swift +++ b/Sources/JavaKitMacros/JavaMethodMacro.swift @@ -25,6 +25,22 @@ extension JavaMethodMacro: BodyMacro { providingBodyFor declaration: some DeclSyntaxProtocol & WithOptionalCodeBlockSyntax, in context: some MacroExpansionContext ) throws -> [CodeBlockItemSyntax] { + // @JavaMethod only provides an implementation when the method was + // imported from Java. + let mode = GenerationMode(expansionContext: context) + + // FIXME: nil is a workaround for the fact that extension JavaClass doesn't + // currently have the annotations we need. We should throw + // MacroErrors.macroOutOfContext(node.attributeName.trimmedDescription) + + switch mode { + case .javaImplementation, .exportToJava: + return declaration.body.map { Array($0.statements) } ?? [] + + case .importFromJava, nil: + break + } + // Handle initializers separately. if let initDecl = declaration.as(InitializerDeclSyntax.self) { return try bridgeInitializer(initDecl, in: context) diff --git a/Sources/JavaKitMacros/MacroErrors.swift b/Sources/JavaKitMacros/MacroErrors.swift index 7a9622c9..2fcbfa91 100644 --- a/Sources/JavaKitMacros/MacroErrors.swift +++ b/Sources/JavaKitMacros/MacroErrors.swift @@ -13,9 +13,12 @@ //===----------------------------------------------------------------------===// enum MacroErrors: Error { + case unrecognizedJavaClassMacro(String) + case javaImplementationRequiresExtension case classNameNotStringLiteral case classNameNotFullyQualified(String) case javaClassNotOnType case methodNotOnFunction case missingEnvironment + case macroOutOfContext(String) } diff --git a/Sources/JavaKitMacros/SwiftJNIMacrosPlugin.swift b/Sources/JavaKitMacros/SwiftJNIMacrosPlugin.swift index f8841ef0..255e61f5 100644 --- a/Sources/JavaKitMacros/SwiftJNIMacrosPlugin.swift +++ b/Sources/JavaKitMacros/SwiftJNIMacrosPlugin.swift @@ -18,7 +18,7 @@ import SwiftSyntaxMacros @main struct JavaKitMacrosPlugin: CompilerPlugin { var providingMacros: [Macro.Type] = [ - ImplementsJavaMacro.self, + JavaImplementationMacro.self, JavaClassMacro.self, JavaFieldMacro.self, JavaMethodMacro.self, diff --git a/Sources/JavaKitReflection/Constructor+Utilities.swift b/Sources/JavaKitReflection/Constructor+Utilities.swift index 4979abbc..0eed3edd 100644 --- a/Sources/JavaKitReflection/Constructor+Utilities.swift +++ b/Sources/JavaKitReflection/Constructor+Utilities.swift @@ -13,6 +13,11 @@ //===----------------------------------------------------------------------===// extension Constructor { + /// Whether this is a 'native' method. + public var isNative: Bool { + return (getModifiers() & 256) != 0 + } + /// Whether this executable throws any checked exception. public var throwsCheckedException: Bool { return self.as(Executable.self)!.throwsCheckedException diff --git a/Sources/JavaKitReflection/JavaClass+Reflection.swift b/Sources/JavaKitReflection/JavaClass+Reflection.swift index fcaf80cc..65c93e15 100644 --- a/Sources/JavaKitReflection/JavaClass+Reflection.swift +++ b/Sources/JavaKitReflection/JavaClass+Reflection.swift @@ -17,6 +17,9 @@ import JavaKit // TODO: We should be able to autogenerate this as an extension based on // knowing that JavaClass was defined elsewhere. extension JavaClass { + @JavaMethod + public func equals(_ arg0: JavaObject?) -> Bool + @JavaMethod public func getName() -> String diff --git a/Sources/JavaKitReflection/Method+Utilities.swift b/Sources/JavaKitReflection/Method+Utilities.swift index 8f981369..28556c0f 100644 --- a/Sources/JavaKitReflection/Method+Utilities.swift +++ b/Sources/JavaKitReflection/Method+Utilities.swift @@ -18,6 +18,11 @@ extension Method { return (getModifiers() & 0x08) != 0 } + /// Whether this is a 'native' method. + public var isNative: Bool { + return (getModifiers() & 256) != 0 + } + /// Whether this executable throws any checked exception. public var throwsCheckedException: Bool { return self.as(Executable.self)!.throwsCheckedException diff --git a/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift b/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift index 1c1dceaa..2f3bccb1 100644 --- a/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift +++ b/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift @@ -102,8 +102,8 @@ final class FunctionDescriptorTests { } @Test - func FunctionDescriptor_class_counter_get() async throws { - try await variableAccessorDescriptorTest("counter", .get) { output in + func FunctionDescriptor_class_counter_get() throws { + try variableAccessorDescriptorTest("counter", .get) { output in assertOutput( output, expected: @@ -117,8 +117,8 @@ final class FunctionDescriptorTests { } } @Test - func FunctionDescriptor_class_counter_set() async throws { - try await variableAccessorDescriptorTest("counter", .set) { output in + func FunctionDescriptor_class_counter_set() throws { + try variableAccessorDescriptorTest("counter", .set) { output in assertOutput( output, expected: @@ -195,4 +195,4 @@ extension FunctionDescriptorTests { try body(getOutput) } -} \ No newline at end of file +} diff --git a/Tests/JExtractSwiftTests/VariableImportTests.swift b/Tests/JExtractSwiftTests/VariableImportTests.swift index f59b8ff4..d776b42a 100644 --- a/Tests/JExtractSwiftTests/VariableImportTests.swift +++ b/Tests/JExtractSwiftTests/VariableImportTests.swift @@ -34,14 +34,14 @@ final class VariableImportTests { """ @Test("Import: var counter: Int") - func variable_() async throws { + func variable_() throws { let st = Swift2JavaTranslator( javaPackage: "com.example.swift", swiftModuleName: "__FakeModule" ) st.log.logLevel = .error - try await st.analyze(swiftInterfacePath: "/fake/Fake.swiftinterface", text: class_interfaceFile) + try st.analyze(swiftInterfacePath: "/fake/Fake.swiftinterface", text: class_interfaceFile) let identifier = "counterInt" let varDecl: ImportedVariable? = @@ -168,4 +168,4 @@ final class VariableImportTests { """ ) } -} \ No newline at end of file +} diff --git a/Tests/Java2SwiftTests/Java2SwiftTests.swift b/Tests/Java2SwiftTests/Java2SwiftTests.swift index e4ded5ab..a2e3cb34 100644 --- a/Tests/Java2SwiftTests/Java2SwiftTests.swift +++ b/Tests/Java2SwiftTests/Java2SwiftTests.swift @@ -51,7 +51,7 @@ class Java2SwiftTests: XCTestCase { ) } - func testEnum() async throws { + func testEnum() throws { try assertTranslatedClass( JavaMonth.self, swiftTypeName: "Month", diff --git a/Tests/JavaKitTests/BasicRuntimeTests.swift b/Tests/JavaKitTests/BasicRuntimeTests.swift index ad379a92..0e5fed0b 100644 --- a/Tests/JavaKitTests/BasicRuntimeTests.swift +++ b/Tests/JavaKitTests/BasicRuntimeTests.swift @@ -24,11 +24,7 @@ var jvm: JavaVirtualMachine { } class BasicRuntimeTests: XCTestCase { - func testJavaObjectManagement() async throws { - if isLinux { - throw XCTSkip("Attempts to refcount a null pointer on Linux") - } - + func testJavaObjectManagement() throws { let environment = try jvm.environment() let sneakyJavaThis: jobject do { @@ -54,11 +50,7 @@ class BasicRuntimeTests: XCTestCase { XCTAssert(url.javaHolder === urlAgain.javaHolder) } - func testJavaExceptionsInSwift() async throws { - if isLinux { - throw XCTSkip("Attempts to refcount a null pointer on Linux") - } - + func testJavaExceptionsInSwift() throws { let environment = try jvm.environment() do { @@ -68,18 +60,14 @@ class BasicRuntimeTests: XCTestCase { } } - func testStaticMethods() async throws { - if isLinux { - throw XCTSkip("Attempts to refcount a null pointer on Linux") - } - + func testStaticMethods() throws { let environment = try jvm.environment() let urlConnectionClass = try JavaClass(in: environment) XCTAssert(urlConnectionClass.getDefaultAllowUserInteraction() == false) } - func testClassInstanceLookup() async throws { + func testClassInstanceLookup() throws { let environment = try jvm.environment() do { @@ -92,12 +80,3 @@ class BasicRuntimeTests: XCTestCase { @JavaClass("org.swift.javakit.Nonexistent") struct Nonexistent { } - -/// Whether we're running on Linux. -var isLinux: Bool { - #if os(Linux) - return true - #else - return false - #endif -} diff --git a/USER_GUIDE.md b/USER_GUIDE.md index 1e75b93d..dccdd27e 100644 --- a/USER_GUIDE.md +++ b/USER_GUIDE.md @@ -213,6 +213,69 @@ do { Note that we are passing the Jar file in the `classPath` argument when initializing the `JavaVirtualMachine` instance. Otherwise, the program will fail with an error because it cannot find the Java class `com.gazman.quadratic_sieve.primes.SieveOfEratosthenes`. +### Up and downcasting + +All Java classes available in Swift provide `is` and `as` methods to check whether an object dynamically matches another type. The `is` operation is the equivalent of Java's `instanceof` and Swift's `is` operator, and will checkin whether a given object is of the specified type, e.g., + +```swift +if myObject.is(URL.self) { + // myObject is a Java URL. +} +``` + +Often, one also wants to cast to that type. The `as` method returns an optional of the specified type, so it works well with `if let`: + +```swift +if let url = myObject.as(URL.self) { + // okay, url is a Java URL +} +``` + +> *Note*: The Swift `is`, `as?`, and `as!` operators do *not* work correctly with the Swift projections of Java types. Use the `is` and `as` methods consistently. + +### Implementing Java `native` methods in Swift + +JavaKit supports implementing Java `native` methods in Swift using JNI with the `@JavaImplementation` macro. In Java, the method must be declared as `native`, e.g., + +```java +package org.swift.javakit.example; + +public class HelloSwift { + static { + System.loadLibrary("HelloSwiftLib"); + } + + public native String reportStatistics(String meaning, double[] numbers); +} +``` + +On the Swift side, the Java class needs to be exposed to Swift through `Java2Swift.config`, e.g.,: + +```swift +{ + "classes" : { + "org.swift.javakit.example.HelloSwift" : "Hello", + } +} +``` + +Implementations of `native` methods are written in an extension of the Swift type that has been marked with `@JavaImplementation`. The methods themselves must be marked with `@JavaMethod`, indicating that they are available to Java as well. To help ensure that the Swift code implements all of the `native` methods with the right signatures, JavaKit produces a protocol with the Swift type name suffixed by `NativeMethods`. Declare conformance to that protocol and implement its requirements, for example: + +```swift +@JavaImplementation("org.swift.javakit.HelloSwift") +extension Hello: HelloNativeMethods { + @JavaMethod + func reportStatistics(_ meaning: String, _ numbers: [Double]) -> String { + let average = numbers.isEmpty ? 0.0 : numbers.reduce(0.0) { $0 + $1 } / Double(numbers.count) + return "Average of \(meaning) is \(average)" + } +} +``` + +Java native methods that throw any checked exception should be marked as `throws` in Swift. Swift will translate any thrown error into a Java exception. + +The Swift implementations of Java `native` constructors and static methods require an additional Swift parameter `environment: JNIEnvironment? = nil`, which will receive the JNI environment in which the function is being executed. In case of nil, the `JavaVirtualMachine.shared().environment()` value will be used. + ## Using Java libraries from Swift This section describes how Java libraries and mapped into Swift and their use from Swift. @@ -324,27 +387,7 @@ A number of JavaKit modules provide Swift projections of Java classes and interf | `java.lang.Throwable` | `Throwable` | `JavaKit` | | `java.net.URL` | `URL` | `JavaKitNetwork` | -The `Java2Swift` tool can translate any other Java classes into Swift projections. The easiest way to use `Java2Swift` is with the SwiftPM plugin described above. More information about using this tool directly are provided later in this document. - -### Up and downcasting - -All `AnyJavaObject` instances provide `is` and `as` methods to check whether an object dynamically matches another type. The `is` operation is the equivalent of Java's `instanceof` and Swift's `is` operator, and will checkin whether a given object is of the specified type, e.g., - -```swift -if myObject.is(URL.self) { - // myObject is a Java URL. -} -``` - -Often, one also wants to cast to that type. The `as` method returns an optional of the specified type, so it works well with `if let`: - -```swift -if let url = myObject.as(URL.self) { - // okay, url is a Java URL -} -``` - -> *Note*: The Swift `is`, `as?`, and `as!` operators do *not* work correctly with the Swift projections of Java types. Use the `is` and `as` methods consistently. +The `Java2Swift` tool can translate any other Java classes into Swift projections. The easiest way to use `Java2Swift` is with the SwiftPM plugin described above. More information about using this tool directly are provided later in this document ### Class objects and static methods @@ -362,57 +405,6 @@ extension JavaClass { Java interfaces are similar to classes, and are projected into Swift in much the same way, but with the macro `JavaInterface`. The `JavaInterface` macro takes the Java interface name as well as any Java interfaces that this interface extends. As an example, here is the Swift projection of the [`java.util.Enumeration`](https://docs.oracle.com/javase/8/docs/api/java/util/Enumeration.html) generic interface: -```swift -@JavaInterface("java.util.Enumeration") -public struct Enumeration { - @JavaMethod - public func hasMoreElements() -> Bool - - @JavaMethod - public func nextElement() -> JavaObject? -} -``` - -## Implementing Java `native` methods in Swift - -JavaKit supports implementing Java `native` methods in Swift using JNI. In Java, the method must be declared as `native`, e.g., - -```java -package org.swift.javakit; - -public class HelloSwift { - static { - System.loadLibrary("HelloSwiftLib"); - } - - public native String reportStatistics(String meaning, double[] numbers); -} -``` - -On the Swift side, the Java class needs to have been exposed to Swift: - -```swift -@JavaClass("org.swift.javakit.HelloSwift") -struct HelloSwift { ... } -``` - -Implementations of `native` methods can be written within the Swift type or an extension thereof, and should be marked with `@ImplementsJava`. For example: - -```swift -@JavaClass("org.swift.javakit.HelloSwift") -extension HelloSwift { - @ImplementsJava - func reportStatistics(_ meaning: String, _ numbers: [Double]) -> String { - let average = numbers.isEmpty ? 0.0 : numbers.reduce(0.0) { $0 + $1 } / Double(numbers.count) - return "Average of \(meaning) is \(average)" - } -} -``` - -Java native methods that throw any checked exception should be marked as `throws` in Swift. Swift will translate any thrown error into a Java exception. - -The Swift implementations of Java `native` constructors and static methods require an additional Swift parameter `environment: JNIEnvironment? = nil`, which will receive the JNI environment in which the function is being executed. In case of nil, the `JavaVirtualMachine.shared().environment()` value will be used. - ## Translating Java classes with `Java2Swift` The `Java2Swift` is a Swift program that uses Java's runtime reflection facilities to translate the requested Java classes into their Swift projections. The output is a number of Swift source files, each of which corresponds to a @@ -540,9 +532,9 @@ Now, in the `HelloSwift` Swift library, define a `struct` that provides the `mai ```swift import JavaKit -@JavaClass("org.swift.javakit.HelloSwiftMain") +@JavaImplementation("org.swift.javakit.HelloSwiftMain") struct HelloSwiftMain { - @ImplementsJava + @JavaStaticMethod static func main(arguments: [String], environment: JNIEnvironment? = nil) { print("Command line arguments are: \(arguments)") } @@ -574,7 +566,7 @@ struct HelloSwiftMain: ParsableCommand { @Option(name: .shortAndLong, help: "Enable verbose output") var verbose: Bool = false - @ImplementsJava + @JavaImplementation static func main(arguments: [String], environment: JNIEnvironment? = nil) { let command = Self.parseOrExit(arguments) command.run(environment: environment) From e16ef46e974d4b30cd5d003789af0f879d624f06 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Thu, 24 Oct 2024 16:44:19 +0900 Subject: [PATCH 123/426] javac plugin: keep parameter names (#108) --- Plugins/JavaCompilerPlugin/JavaCompilerPlugin.swift | 3 ++- USER_GUIDE.md | 13 +++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/Plugins/JavaCompilerPlugin/JavaCompilerPlugin.swift b/Plugins/JavaCompilerPlugin/JavaCompilerPlugin.swift index 3a6c4286..64e1d2a7 100644 --- a/Plugins/JavaCompilerPlugin/JavaCompilerPlugin.swift +++ b/Plugins/JavaCompilerPlugin/JavaCompilerPlugin.swift @@ -58,7 +58,8 @@ struct JavaCompilerBuildToolPlugin: BuildToolPlugin { .appending(path: "bin") .appending(path: "javac"), arguments: javaFiles.map { $0.path(percentEncoded: false) } + [ - "-d", javaClassFileURL.path() + "-d", javaClassFileURL.path(), + "-parameters", // keep parameter names, which allows us to emit them in generated Swift decls ], inputFiles: javaFiles, outputFiles: classFiles diff --git a/USER_GUIDE.md b/USER_GUIDE.md index dccdd27e..33e08423 100644 --- a/USER_GUIDE.md +++ b/USER_GUIDE.md @@ -389,6 +389,19 @@ A number of JavaKit modules provide Swift projections of Java classes and interf The `Java2Swift` tool can translate any other Java classes into Swift projections. The easiest way to use `Java2Swift` is with the SwiftPM plugin described above. More information about using this tool directly are provided later in this document +#### Improve parameter names of imported Java methods +When building Java libraries you can pass the `-parameters` option to javac +in your build system (Gradle, Maven, sbt, etc) in order to retain the parameter names in the resulting byte code. + +This way the imported methods will keep their original parameter names, and you'd get e.g.: +```swift +// public func hello(String name) +func hello(_ name: String) +``` +rather than just `arg0` parameters. + +When building Java sources using the JavaCompilerPlugin this option is passed by default. + ### Class objects and static methods Every `AnyJavaObject` has a property `javaClass` that provides an instance of `JavaClass` specialized to the type. For example, `url.javaClass` will produce an instance of `JavaClass`. The `JavaClass` instance is a wrapper around a Java class object (`java.lang.Class`) that has two roles in Swift. First, it provides access to all of the APIs on the Java class object. The `JavaKitReflection` library, for example, exposes these APIs and the types they depend on (`Method`, From 912d08da5815d5f1d0642672f054edadea270bcc Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Thu, 24 Oct 2024 22:08:07 -0700 Subject: [PATCH 124/426] Use getDeclaredMethods() so we can see non-public methods of classes (#110) When we are translating a class that was built as part of the Swift module, use getDeclaredMethods() so we also see non-public methods. Part of issue #106. --- .../com/example/swift/HelloSwift.java | 4 +- Sources/Java2SwiftLib/JavaTranslator.swift | 37 ++++++++++++++++--- .../JavaClass+Reflection.swift | 3 ++ 3 files changed, 36 insertions(+), 8 deletions(-) diff --git a/Samples/JavaKitSampleApp/Sources/JavaKitExample/com/example/swift/HelloSwift.java b/Samples/JavaKitSampleApp/Sources/JavaKitExample/com/example/swift/HelloSwift.java index f988bbb6..c59baf33 100644 --- a/Samples/JavaKitSampleApp/Sources/JavaKitExample/com/example/swift/HelloSwift.java +++ b/Samples/JavaKitSampleApp/Sources/JavaKitExample/com/example/swift/HelloSwift.java @@ -27,8 +27,8 @@ public HelloSwift() { this.value = initialValue; } - public native int sayHello(int x, int y); - public native String throwMessageFromSwift(String message) throws Exception; + native int sayHello(int x, int y); + native String throwMessageFromSwift(String message) throws Exception; // To be called back by the native code public double sayHelloBack(int i) { diff --git a/Sources/Java2SwiftLib/JavaTranslator.swift b/Sources/Java2SwiftLib/JavaTranslator.swift index a5af9baa..c48591b9 100644 --- a/Sources/Java2SwiftLib/JavaTranslator.swift +++ b/Sources/Java2SwiftLib/JavaTranslator.swift @@ -239,10 +239,6 @@ extension JavaTranslator { // Members var members: [DeclSyntax] = [] - // Members that are native and will instead go into a NativeMethods - // protocol. - var nativeMembers: [DeclSyntax] = [] - // Fields var staticFields: [Field] = [] var enumConstants: [Field] = [] @@ -290,7 +286,6 @@ extension JavaTranslator { ) if implementedInSwift { - nativeMembers.append(translated) return nil } @@ -327,7 +322,6 @@ extension JavaTranslator { ) if implementedInSwift { - nativeMembers.append(translated) return nil } @@ -441,6 +435,37 @@ extension JavaTranslator { ) } + // Members that are native and will instead go into a NativeMethods + // protocol. + var nativeMembers: [DeclSyntax] = [] + if swiftNativeImplementations.contains(javaClass.getCanonicalName()) { + nativeMembers.append( + contentsOf: javaClass.getDeclaredMethods().compactMap { + $0.flatMap { method in + // FIXME: For now, ignore static methods + if method.isStatic { + return nil + } + + if !method.isNative { + return nil + } + + // Translate the method if we can. + do { + return try translateMethod( + method, + implementedInSwift: true + ) + } catch { + logUntranslated("Unable to translate '\(fullName)' method '\(method.getName())': \(error)") + return nil + } + } + } + ) + } + if !nativeMembers.isEmpty { let protocolDecl: DeclSyntax = """ diff --git a/Sources/JavaKitReflection/JavaClass+Reflection.swift b/Sources/JavaKitReflection/JavaClass+Reflection.swift index 65c93e15..13e080ac 100644 --- a/Sources/JavaKitReflection/JavaClass+Reflection.swift +++ b/Sources/JavaKitReflection/JavaClass+Reflection.swift @@ -29,6 +29,9 @@ extension JavaClass { @JavaMethod public func getCanonicalName() -> String + @JavaMethod + public func getDeclaredMethods() -> [Method?] + @JavaMethod public func getMethods() -> [Method?] From c5a3d4de572fc03004d0b5f402a431abfc2a7005 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Thu, 24 Oct 2024 23:08:34 -0700 Subject: [PATCH 125/426] Minor cleanups to the JavaKit module and samples (#111) * Rename JavaClass.init(in:) to JavaClass.init(environment:). Every other API uses the argument label "environment" for the JNI environment, so be consistent. Additionally, make it an optional parameter and query the running JVM to get the environment if we don't already have one. * Remove the unnecessary ArrayList bits from the JavaKit sample app * Import the various java.lang.* class wrappers over primitive types * JavaKit: Autogenerate JavaClass rather than hand-rolling it * Clean up and fix samples --- .../Sources/JavaKitExample/Java2Swift.config | 1 - .../JavaKitExample/JavaKitExample.swift | 6 - Samples/JavaProbablyPrime/Package.swift | 1 + Samples/JavaProbablyPrime/README.md | 1 - .../Sources/JavaProbablyPrime/prime.swift | 5 +- .../Sources/JavaMath/Java2Swift.config | 3 +- .../JavaSieve/Sources/JavaSieve/main.swift | 3 +- Sources/Java2Swift/JavaToSwift.swift | 2 +- Sources/Java2SwiftLib/JavaTranslator.swift | 2 +- Sources/JavaKit/Java2Swift.config | 13 +- ...s.swift => JavaClass+Initialization.swift} | 10 +- Sources/JavaKit/generated/JavaBoolean.swift | 87 +++ Sources/JavaKit/generated/JavaByte.swift | 114 ++++ Sources/JavaKit/generated/JavaCharacter.swift | 510 ++++++++++++++++++ Sources/JavaKit/generated/JavaClass.swift | 162 ++++++ Sources/JavaKit/generated/JavaDouble.swift | 153 ++++++ Sources/JavaKit/generated/JavaFloat.swift | 162 ++++++ Sources/JavaKit/generated/JavaInteger.swift | 195 +++++++ Sources/JavaKit/generated/JavaLong.swift | 192 +++++++ Sources/JavaKit/generated/JavaNumber.swift | 53 ++ Sources/JavaKit/generated/JavaShort.swift | 117 ++++ Sources/JavaKit/generated/JavaVoid.swift | 36 ++ .../JavaClass+Reflection.swift | 18 - Tests/JavaKitTests/BasicRuntimeTests.swift | 4 +- USER_GUIDE.md | 42 +- 25 files changed, 1830 insertions(+), 62 deletions(-) rename Sources/JavaKit/{JavaClass.swift => JavaClass+Initialization.swift} (75%) create mode 100644 Sources/JavaKit/generated/JavaBoolean.swift create mode 100644 Sources/JavaKit/generated/JavaByte.swift create mode 100644 Sources/JavaKit/generated/JavaCharacter.swift create mode 100644 Sources/JavaKit/generated/JavaClass.swift create mode 100644 Sources/JavaKit/generated/JavaDouble.swift create mode 100644 Sources/JavaKit/generated/JavaFloat.swift create mode 100644 Sources/JavaKit/generated/JavaInteger.swift create mode 100644 Sources/JavaKit/generated/JavaLong.swift create mode 100644 Sources/JavaKit/generated/JavaNumber.swift create mode 100644 Sources/JavaKit/generated/JavaShort.swift create mode 100644 Sources/JavaKit/generated/JavaVoid.swift diff --git a/Samples/JavaKitSampleApp/Sources/JavaKitExample/Java2Swift.config b/Samples/JavaKitSampleApp/Sources/JavaKitExample/Java2Swift.config index 5ccb042b..b4e7368d 100644 --- a/Samples/JavaKitSampleApp/Sources/JavaKitExample/Java2Swift.config +++ b/Samples/JavaKitSampleApp/Sources/JavaKitExample/Java2Swift.config @@ -1,6 +1,5 @@ { "classes" : { - "java.util.ArrayList" : "ArrayList", "com.example.swift.HelloSwift" : "HelloSwift", "com.example.swift.HelloSubclass" : "HelloSubclass", "com.example.swift.JavaKitSampleMain" : "JavaKitSampleMain" diff --git a/Samples/JavaKitSampleApp/Sources/JavaKitExample/JavaKitExample.swift b/Samples/JavaKitSampleApp/Sources/JavaKitExample/JavaKitExample.swift index aaaff0bb..56a3cbb7 100644 --- a/Samples/JavaKitSampleApp/Sources/JavaKitExample/JavaKitExample.swift +++ b/Samples/JavaKitSampleApp/Sources/JavaKitExample/JavaKitExample.swift @@ -79,9 +79,3 @@ extension HelloSwift: HelloSwiftNativeMethods { throw SwiftWrappedError.message(message) } } - -func removeLast(arrayList: ArrayList>) { - if let lastObject = arrayList.getLast() { - _ = arrayList.remove(lastObject) - } -} diff --git a/Samples/JavaProbablyPrime/Package.swift b/Samples/JavaProbablyPrime/Package.swift index b35788f8..e837bfdb 100644 --- a/Samples/JavaProbablyPrime/Package.swift +++ b/Samples/JavaProbablyPrime/Package.swift @@ -26,6 +26,7 @@ let package = Package( .executableTarget( name: "JavaProbablyPrime", dependencies: [ + .product(name: "JavaKitCollection", package: "swift-java"), .product(name: "JavaKit", package: "swift-java"), .product(name: "ArgumentParser", package: "swift-argument-parser"), ], diff --git a/Samples/JavaProbablyPrime/README.md b/Samples/JavaProbablyPrime/README.md index f9fe318f..819ecf04 100644 --- a/Samples/JavaProbablyPrime/README.md +++ b/Samples/JavaProbablyPrime/README.md @@ -9,5 +9,4 @@ swift run JavaProbablyPrime The package itself demonstrates how to: * Use the Java2Swift build tool plugin to wrap the `java.math.BigInteger` type in Swift. -* Create a `JavaVirtualMachine` instance in a Swift command-line program. * Create an instance of `BigInteger` in Swift and use its `isProbablyPrime`. diff --git a/Samples/JavaProbablyPrime/Sources/JavaProbablyPrime/prime.swift b/Samples/JavaProbablyPrime/Sources/JavaProbablyPrime/prime.swift index ddebb518..07f701bd 100644 --- a/Samples/JavaProbablyPrime/Sources/JavaProbablyPrime/prime.swift +++ b/Samples/JavaProbablyPrime/Sources/JavaProbablyPrime/prime.swift @@ -24,10 +24,7 @@ struct ProbablyPrime: ParsableCommand { var certainty: Int32 = 10 func run() throws { - let javaVirtualMachine = try JavaVirtualMachine.shared() - let jniEnvironment = try javaVirtualMachine.environment() - - let bigInt = BigInteger(number, environment: jniEnvironment) + let bigInt = BigInteger(number) if bigInt.isProbablePrime(certainty) { print("\(number) is probably prime") } else { diff --git a/Samples/JavaSieve/Sources/JavaMath/Java2Swift.config b/Samples/JavaSieve/Sources/JavaMath/Java2Swift.config index 28e56a35..3c14b885 100644 --- a/Samples/JavaSieve/Sources/JavaMath/Java2Swift.config +++ b/Samples/JavaSieve/Sources/JavaMath/Java2Swift.config @@ -3,7 +3,6 @@ "java.math.BigDecimal" : "BigDecimal", "java.math.BigInteger" : "BigInteger", "java.math.MathContext" : "MathContext", - "java.math.RoundingMode" : "RoundingMode", - "java.lang.Integer" : "JavaInteger", + "java.math.RoundingMode" : "RoundingMode" } } diff --git a/Samples/JavaSieve/Sources/JavaSieve/main.swift b/Samples/JavaSieve/Sources/JavaSieve/main.swift index f2f24a53..c075a8a1 100644 --- a/Samples/JavaSieve/Sources/JavaSieve/main.swift +++ b/Samples/JavaSieve/Sources/JavaSieve/main.swift @@ -13,11 +13,10 @@ //===----------------------------------------------------------------------===// import JavaKit -import JavaKitVM let jvm = try JavaVirtualMachine.shared(classPath: ["QuadraticSieve-1.0.jar"]) do { - let sieveClass = try JavaClass(in: jvm.environment()) + let sieveClass = try JavaClass(environment: jvm.environment()) for prime in sieveClass.findPrimes(100)! { print("Found prime: \(prime.intValue())") } diff --git a/Sources/Java2Swift/JavaToSwift.swift b/Sources/Java2Swift/JavaToSwift.swift index 1cc094c2..80058ccd 100644 --- a/Sources/Java2Swift/JavaToSwift.swift +++ b/Sources/Java2Swift/JavaToSwift.swift @@ -210,7 +210,7 @@ struct JavaToSwift: ParsableCommand { environment: environment ) #else - let classLoader = try JavaClass(in: environment) + let classLoader = try JavaClass(environment: environment) .getSystemClassLoader()! #endif var javaClasses: [JavaClass] = [] diff --git a/Sources/Java2SwiftLib/JavaTranslator.swift b/Sources/Java2SwiftLib/JavaTranslator.swift index c48591b9..fa7e5789 100644 --- a/Sources/Java2SwiftLib/JavaTranslator.swift +++ b/Sources/Java2SwiftLib/JavaTranslator.swift @@ -581,7 +581,7 @@ extension JavaTranslator { } else { try! JavaVirtualMachine.shared().environment() } - let classObj = try! JavaClass(in: _environment) + let classObj = try! JavaClass(environment: _environment) switch enumValue { \(raw: enumFields.map { return """ diff --git a/Sources/JavaKit/Java2Swift.config b/Sources/JavaKit/Java2Swift.config index 7626a380..bace061f 100644 --- a/Sources/JavaKit/Java2Swift.config +++ b/Sources/JavaKit/Java2Swift.config @@ -1,9 +1,20 @@ { "classes" : { + "java.lang.Boolean" : "JavaBoolean", + "java.lang.Byte" : "JavaByte", + "java.lang.Character" : "JavaCharacter", + "java.lang.Class" : "JavaClass", + "java.lang.Double" : "JavaDouble", "java.lang.Error" : "JavaError", "java.lang.Exception" : "Exception", + "java.lang.Float" : "JavaFloat", + "java.lang.Integer" : "JavaInteger", + "java.lang.Long" : "JavaLong", + "java.lang.Number" : "JavaNumber", "java.lang.Object" : "JavaObject", "java.lang.RuntimeException" : "RuntimeException", - "java.lang.Throwable" : "Throwable" + "java.lang.Short" : "JavaShort", + "java.lang.Throwable" : "Throwable", + "java.lang.Void" : "JavaVoid" } } diff --git a/Sources/JavaKit/JavaClass.swift b/Sources/JavaKit/JavaClass+Initialization.swift similarity index 75% rename from Sources/JavaKit/JavaClass.swift rename to Sources/JavaKit/JavaClass+Initialization.swift index c9f0fdd2..a9302bd8 100644 --- a/Sources/JavaKit/JavaClass.swift +++ b/Sources/JavaKit/JavaClass+Initialization.swift @@ -14,12 +14,12 @@ import JavaRuntime -/// Wrapper around a Java class that provides access to the static members of -/// the class. -@JavaClass("java.lang.Class") -public struct JavaClass { +extension JavaClass { + public typealias ObjectType = T + /// Lookup this Java class within the given environment. - public init(in environment: JNIEnvironment) throws { + public init(environment: JNIEnvironment? = nil) throws { + let environment = try environment ?? JavaVirtualMachine.shared().environment() self.init( javaThis: try ObjectType.getJNIClass(in: environment), environment: environment diff --git a/Sources/JavaKit/generated/JavaBoolean.swift b/Sources/JavaKit/generated/JavaBoolean.swift new file mode 100644 index 00000000..c0cfbd04 --- /dev/null +++ b/Sources/JavaKit/generated/JavaBoolean.swift @@ -0,0 +1,87 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaRuntime + +@JavaClass("java.lang.Boolean") +public struct JavaBoolean { + @JavaMethod + public init(_ arg0: Bool, environment: JNIEnvironment? = nil) + + @JavaMethod + public init(_ arg0: String, environment: JNIEnvironment? = nil) + + @JavaMethod + public func equals(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func toString() -> String + + @JavaMethod + public func hashCode() -> Int32 + + @JavaMethod + public func compareTo(_ arg0: JavaBoolean?) -> Int32 + + @JavaMethod + public func compareTo(_ arg0: JavaObject?) -> Int32 + + @JavaMethod + public func booleanValue() -> Bool + + @JavaMethod + public func getClass() -> JavaClass? + + @JavaMethod + public func notify() + + @JavaMethod + public func notifyAll() + + @JavaMethod + public func wait(_ arg0: Int64) throws + + @JavaMethod + public func wait(_ arg0: Int64, _ arg1: Int32) throws + + @JavaMethod + public func wait() throws +} +extension JavaClass { + @JavaStaticField + public var TRUE: JavaBoolean? + + @JavaStaticField + public var FALSE: JavaBoolean? + + @JavaStaticField + public var TYPE: JavaClass? + + @JavaStaticMethod + public func toString(_ arg0: Bool) -> String + + @JavaStaticMethod + public func hashCode(_ arg0: Bool) -> Int32 + + @JavaStaticMethod + public func getBoolean(_ arg0: String) -> Bool + + @JavaStaticMethod + public func compare(_ arg0: Bool, _ arg1: Bool) -> Int32 + + @JavaStaticMethod + public func valueOf(_ arg0: String) -> JavaBoolean? + + @JavaStaticMethod + public func valueOf(_ arg0: Bool) -> JavaBoolean? + + @JavaStaticMethod + public func parseBoolean(_ arg0: String) -> Bool + + @JavaStaticMethod + public func logicalAnd(_ arg0: Bool, _ arg1: Bool) -> Bool + + @JavaStaticMethod + public func logicalOr(_ arg0: Bool, _ arg1: Bool) -> Bool + + @JavaStaticMethod + public func logicalXor(_ arg0: Bool, _ arg1: Bool) -> Bool +} diff --git a/Sources/JavaKit/generated/JavaByte.swift b/Sources/JavaKit/generated/JavaByte.swift new file mode 100644 index 00000000..c00cae95 --- /dev/null +++ b/Sources/JavaKit/generated/JavaByte.swift @@ -0,0 +1,114 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaRuntime + +@JavaClass("java.lang.Byte", extends: JavaNumber.self) +public struct JavaByte { + @JavaMethod + public init(_ arg0: Int8, environment: JNIEnvironment? = nil) + + @JavaMethod + public init(_ arg0: String, environment: JNIEnvironment? = nil) throws + + @JavaMethod + public func equals(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func toString() -> String + + @JavaMethod + public func hashCode() -> Int32 + + @JavaMethod + public func compareTo(_ arg0: JavaByte?) -> Int32 + + @JavaMethod + public func compareTo(_ arg0: JavaObject?) -> Int32 + + @JavaMethod + public func byteValue() -> Int8 + + @JavaMethod + public func shortValue() -> Int16 + + @JavaMethod + public func intValue() -> Int32 + + @JavaMethod + public func longValue() -> Int64 + + @JavaMethod + public func floatValue() -> Float + + @JavaMethod + public func doubleValue() -> Double + + @JavaMethod + public func getClass() -> JavaClass? + + @JavaMethod + public func notify() + + @JavaMethod + public func notifyAll() + + @JavaMethod + public func wait(_ arg0: Int64) throws + + @JavaMethod + public func wait(_ arg0: Int64, _ arg1: Int32) throws + + @JavaMethod + public func wait() throws +} +extension JavaClass { + @JavaStaticField + public var MIN_VALUE: Int8 + + @JavaStaticField + public var MAX_VALUE: Int8 + + @JavaStaticField + public var TYPE: JavaClass? + + @JavaStaticField + public var SIZE: Int32 + + @JavaStaticField + public var BYTES: Int32 + + @JavaStaticMethod + public func toString(_ arg0: Int8) -> String + + @JavaStaticMethod + public func hashCode(_ arg0: Int8) -> Int32 + + @JavaStaticMethod + public func compareUnsigned(_ arg0: Int8, _ arg1: Int8) -> Int32 + + @JavaStaticMethod + public func compare(_ arg0: Int8, _ arg1: Int8) -> Int32 + + @JavaStaticMethod + public func valueOf(_ arg0: String) throws -> JavaByte? + + @JavaStaticMethod + public func valueOf(_ arg0: String, _ arg1: Int32) throws -> JavaByte? + + @JavaStaticMethod + public func valueOf(_ arg0: Int8) -> JavaByte? + + @JavaStaticMethod + public func decode(_ arg0: String) throws -> JavaByte? + + @JavaStaticMethod + public func toUnsignedLong(_ arg0: Int8) -> Int64 + + @JavaStaticMethod + public func toUnsignedInt(_ arg0: Int8) -> Int32 + + @JavaStaticMethod + public func parseByte(_ arg0: String) throws -> Int8 + + @JavaStaticMethod + public func parseByte(_ arg0: String, _ arg1: Int32) throws -> Int8 +} diff --git a/Sources/JavaKit/generated/JavaCharacter.swift b/Sources/JavaKit/generated/JavaCharacter.swift new file mode 100644 index 00000000..c5d2e8b9 --- /dev/null +++ b/Sources/JavaKit/generated/JavaCharacter.swift @@ -0,0 +1,510 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaRuntime + +@JavaClass("java.lang.Character") +public struct JavaCharacter { + @JavaMethod + public init(_ arg0: UInt16, environment: JNIEnvironment? = nil) + + @JavaMethod + public func equals(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func toString() -> String + + @JavaMethod + public func hashCode() -> Int32 + + @JavaMethod + public func compareTo(_ arg0: JavaCharacter?) -> Int32 + + @JavaMethod + public func compareTo(_ arg0: JavaObject?) -> Int32 + + @JavaMethod + public func charValue() -> UInt16 + + @JavaMethod + public func getClass() -> JavaClass? + + @JavaMethod + public func notify() + + @JavaMethod + public func notifyAll() + + @JavaMethod + public func wait(_ arg0: Int64) throws + + @JavaMethod + public func wait(_ arg0: Int64, _ arg1: Int32) throws + + @JavaMethod + public func wait() throws +} +extension JavaClass { + @JavaStaticField + public var MIN_RADIX: Int32 + + @JavaStaticField + public var MAX_RADIX: Int32 + + @JavaStaticField + public var MIN_VALUE: UInt16 + + @JavaStaticField + public var MAX_VALUE: UInt16 + + @JavaStaticField + public var TYPE: JavaClass? + + @JavaStaticField + public var UNASSIGNED: Int8 + + @JavaStaticField + public var UPPERCASE_LETTER: Int8 + + @JavaStaticField + public var LOWERCASE_LETTER: Int8 + + @JavaStaticField + public var TITLECASE_LETTER: Int8 + + @JavaStaticField + public var MODIFIER_LETTER: Int8 + + @JavaStaticField + public var OTHER_LETTER: Int8 + + @JavaStaticField + public var NON_SPACING_MARK: Int8 + + @JavaStaticField + public var ENCLOSING_MARK: Int8 + + @JavaStaticField + public var COMBINING_SPACING_MARK: Int8 + + @JavaStaticField + public var DECIMAL_DIGIT_NUMBER: Int8 + + @JavaStaticField + public var LETTER_NUMBER: Int8 + + @JavaStaticField + public var OTHER_NUMBER: Int8 + + @JavaStaticField + public var SPACE_SEPARATOR: Int8 + + @JavaStaticField + public var LINE_SEPARATOR: Int8 + + @JavaStaticField + public var PARAGRAPH_SEPARATOR: Int8 + + @JavaStaticField + public var CONTROL: Int8 + + @JavaStaticField + public var FORMAT: Int8 + + @JavaStaticField + public var PRIVATE_USE: Int8 + + @JavaStaticField + public var SURROGATE: Int8 + + @JavaStaticField + public var DASH_PUNCTUATION: Int8 + + @JavaStaticField + public var START_PUNCTUATION: Int8 + + @JavaStaticField + public var END_PUNCTUATION: Int8 + + @JavaStaticField + public var CONNECTOR_PUNCTUATION: Int8 + + @JavaStaticField + public var OTHER_PUNCTUATION: Int8 + + @JavaStaticField + public var MATH_SYMBOL: Int8 + + @JavaStaticField + public var CURRENCY_SYMBOL: Int8 + + @JavaStaticField + public var MODIFIER_SYMBOL: Int8 + + @JavaStaticField + public var OTHER_SYMBOL: Int8 + + @JavaStaticField + public var INITIAL_QUOTE_PUNCTUATION: Int8 + + @JavaStaticField + public var FINAL_QUOTE_PUNCTUATION: Int8 + + @JavaStaticField + public var DIRECTIONALITY_UNDEFINED: Int8 + + @JavaStaticField + public var DIRECTIONALITY_LEFT_TO_RIGHT: Int8 + + @JavaStaticField + public var DIRECTIONALITY_RIGHT_TO_LEFT: Int8 + + @JavaStaticField + public var DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC: Int8 + + @JavaStaticField + public var DIRECTIONALITY_EUROPEAN_NUMBER: Int8 + + @JavaStaticField + public var DIRECTIONALITY_EUROPEAN_NUMBER_SEPARATOR: Int8 + + @JavaStaticField + public var DIRECTIONALITY_EUROPEAN_NUMBER_TERMINATOR: Int8 + + @JavaStaticField + public var DIRECTIONALITY_ARABIC_NUMBER: Int8 + + @JavaStaticField + public var DIRECTIONALITY_COMMON_NUMBER_SEPARATOR: Int8 + + @JavaStaticField + public var DIRECTIONALITY_NONSPACING_MARK: Int8 + + @JavaStaticField + public var DIRECTIONALITY_BOUNDARY_NEUTRAL: Int8 + + @JavaStaticField + public var DIRECTIONALITY_PARAGRAPH_SEPARATOR: Int8 + + @JavaStaticField + public var DIRECTIONALITY_SEGMENT_SEPARATOR: Int8 + + @JavaStaticField + public var DIRECTIONALITY_WHITESPACE: Int8 + + @JavaStaticField + public var DIRECTIONALITY_OTHER_NEUTRALS: Int8 + + @JavaStaticField + public var DIRECTIONALITY_LEFT_TO_RIGHT_EMBEDDING: Int8 + + @JavaStaticField + public var DIRECTIONALITY_LEFT_TO_RIGHT_OVERRIDE: Int8 + + @JavaStaticField + public var DIRECTIONALITY_RIGHT_TO_LEFT_EMBEDDING: Int8 + + @JavaStaticField + public var DIRECTIONALITY_RIGHT_TO_LEFT_OVERRIDE: Int8 + + @JavaStaticField + public var DIRECTIONALITY_POP_DIRECTIONAL_FORMAT: Int8 + + @JavaStaticField + public var DIRECTIONALITY_LEFT_TO_RIGHT_ISOLATE: Int8 + + @JavaStaticField + public var DIRECTIONALITY_RIGHT_TO_LEFT_ISOLATE: Int8 + + @JavaStaticField + public var DIRECTIONALITY_FIRST_STRONG_ISOLATE: Int8 + + @JavaStaticField + public var DIRECTIONALITY_POP_DIRECTIONAL_ISOLATE: Int8 + + @JavaStaticField + public var MIN_HIGH_SURROGATE: UInt16 + + @JavaStaticField + public var MAX_HIGH_SURROGATE: UInt16 + + @JavaStaticField + public var MIN_LOW_SURROGATE: UInt16 + + @JavaStaticField + public var MAX_LOW_SURROGATE: UInt16 + + @JavaStaticField + public var MIN_SURROGATE: UInt16 + + @JavaStaticField + public var MAX_SURROGATE: UInt16 + + @JavaStaticField + public var MIN_SUPPLEMENTARY_CODE_POINT: Int32 + + @JavaStaticField + public var MIN_CODE_POINT: Int32 + + @JavaStaticField + public var MAX_CODE_POINT: Int32 + + @JavaStaticField + public var SIZE: Int32 + + @JavaStaticField + public var BYTES: Int32 + + @JavaStaticMethod + public func getName(_ arg0: Int32) -> String + + @JavaStaticMethod + public func isJavaIdentifierStart(_ arg0: UInt16) -> Bool + + @JavaStaticMethod + public func isJavaIdentifierStart(_ arg0: Int32) -> Bool + + @JavaStaticMethod + public func isJavaIdentifierPart(_ arg0: UInt16) -> Bool + + @JavaStaticMethod + public func isJavaIdentifierPart(_ arg0: Int32) -> Bool + + @JavaStaticMethod + public func toString(_ arg0: Int32) -> String + + @JavaStaticMethod + public func toString(_ arg0: UInt16) -> String + + @JavaStaticMethod + public func hashCode(_ arg0: UInt16) -> Int32 + + @JavaStaticMethod + public func reverseBytes(_ arg0: UInt16) -> UInt16 + + @JavaStaticMethod + public func isDigit(_ arg0: UInt16) -> Bool + + @JavaStaticMethod + public func isDigit(_ arg0: Int32) -> Bool + + @JavaStaticMethod + public func isLowerCase(_ arg0: UInt16) -> Bool + + @JavaStaticMethod + public func isLowerCase(_ arg0: Int32) -> Bool + + @JavaStaticMethod + public func isUpperCase(_ arg0: Int32) -> Bool + + @JavaStaticMethod + public func isUpperCase(_ arg0: UInt16) -> Bool + + @JavaStaticMethod + public func isWhitespace(_ arg0: UInt16) -> Bool + + @JavaStaticMethod + public func isWhitespace(_ arg0: Int32) -> Bool + + @JavaStaticMethod + public func compare(_ arg0: UInt16, _ arg1: UInt16) -> Int32 + + @JavaStaticMethod + public func valueOf(_ arg0: UInt16) -> JavaCharacter? + + @JavaStaticMethod + public func toChars(_ arg0: Int32) -> [UInt16] + + @JavaStaticMethod + public func toChars(_ arg0: Int32, _ arg1: [UInt16], _ arg2: Int32) -> Int32 + + @JavaStaticMethod + public func isHighSurrogate(_ arg0: UInt16) -> Bool + + @JavaStaticMethod + public func isLowSurrogate(_ arg0: UInt16) -> Bool + + @JavaStaticMethod + public func isSurrogate(_ arg0: UInt16) -> Bool + + @JavaStaticMethod + public func isSupplementaryCodePoint(_ arg0: Int32) -> Bool + + @JavaStaticMethod + public func highSurrogate(_ arg0: Int32) -> UInt16 + + @JavaStaticMethod + public func lowSurrogate(_ arg0: Int32) -> UInt16 + + @JavaStaticMethod + public func toCodePoint(_ arg0: UInt16, _ arg1: UInt16) -> Int32 + + @JavaStaticMethod + public func codePointAt(_ arg0: [UInt16], _ arg1: Int32, _ arg2: Int32) -> Int32 + + @JavaStaticMethod + public func codePointAt(_ arg0: [UInt16], _ arg1: Int32) -> Int32 + + @JavaStaticMethod + public func codePointBefore(_ arg0: [UInt16], _ arg1: Int32) -> Int32 + + @JavaStaticMethod + public func codePointBefore(_ arg0: [UInt16], _ arg1: Int32, _ arg2: Int32) -> Int32 + + @JavaStaticMethod + public func codePointCount(_ arg0: [UInt16], _ arg1: Int32, _ arg2: Int32) -> Int32 + + @JavaStaticMethod + public func offsetByCodePoints(_ arg0: [UInt16], _ arg1: Int32, _ arg2: Int32, _ arg3: Int32, _ arg4: Int32) -> Int32 + + @JavaStaticMethod + public func toLowerCase(_ arg0: UInt16) -> UInt16 + + @JavaStaticMethod + public func toLowerCase(_ arg0: Int32) -> Int32 + + @JavaStaticMethod + public func toUpperCase(_ arg0: Int32) -> Int32 + + @JavaStaticMethod + public func toUpperCase(_ arg0: UInt16) -> UInt16 + + @JavaStaticMethod + public func isBmpCodePoint(_ arg0: Int32) -> Bool + + @JavaStaticMethod + public func getType(_ arg0: UInt16) -> Int32 + + @JavaStaticMethod + public func getType(_ arg0: Int32) -> Int32 + + @JavaStaticMethod + public func isLetter(_ arg0: UInt16) -> Bool + + @JavaStaticMethod + public func isLetter(_ arg0: Int32) -> Bool + + @JavaStaticMethod + public func isLetterOrDigit(_ arg0: Int32) -> Bool + + @JavaStaticMethod + public func isLetterOrDigit(_ arg0: UInt16) -> Bool + + @JavaStaticMethod + public func isValidCodePoint(_ arg0: Int32) -> Bool + + @JavaStaticMethod + public func isTitleCase(_ arg0: Int32) -> Bool + + @JavaStaticMethod + public func isTitleCase(_ arg0: UInt16) -> Bool + + @JavaStaticMethod + public func isDefined(_ arg0: UInt16) -> Bool + + @JavaStaticMethod + public func isDefined(_ arg0: Int32) -> Bool + + @JavaStaticMethod + public func isIdeographic(_ arg0: Int32) -> Bool + + @JavaStaticMethod + public func isUnicodeIdentifierStart(_ arg0: Int32) -> Bool + + @JavaStaticMethod + public func isUnicodeIdentifierStart(_ arg0: UInt16) -> Bool + + @JavaStaticMethod + public func isUnicodeIdentifierPart(_ arg0: Int32) -> Bool + + @JavaStaticMethod + public func isUnicodeIdentifierPart(_ arg0: UInt16) -> Bool + + @JavaStaticMethod + public func isIdentifierIgnorable(_ arg0: Int32) -> Bool + + @JavaStaticMethod + public func isIdentifierIgnorable(_ arg0: UInt16) -> Bool + + @JavaStaticMethod + public func isEmoji(_ arg0: Int32) -> Bool + + @JavaStaticMethod + public func isEmojiPresentation(_ arg0: Int32) -> Bool + + @JavaStaticMethod + public func isEmojiModifier(_ arg0: Int32) -> Bool + + @JavaStaticMethod + public func isEmojiModifierBase(_ arg0: Int32) -> Bool + + @JavaStaticMethod + public func isEmojiComponent(_ arg0: Int32) -> Bool + + @JavaStaticMethod + public func isExtendedPictographic(_ arg0: Int32) -> Bool + + @JavaStaticMethod + public func toTitleCase(_ arg0: UInt16) -> UInt16 + + @JavaStaticMethod + public func toTitleCase(_ arg0: Int32) -> Int32 + + @JavaStaticMethod + public func digit(_ arg0: UInt16, _ arg1: Int32) -> Int32 + + @JavaStaticMethod + public func digit(_ arg0: Int32, _ arg1: Int32) -> Int32 + + @JavaStaticMethod + public func getNumericValue(_ arg0: Int32) -> Int32 + + @JavaStaticMethod + public func getNumericValue(_ arg0: UInt16) -> Int32 + + @JavaStaticMethod + public func isSpaceChar(_ arg0: UInt16) -> Bool + + @JavaStaticMethod + public func isSpaceChar(_ arg0: Int32) -> Bool + + @JavaStaticMethod + public func isISOControl(_ arg0: Int32) -> Bool + + @JavaStaticMethod + public func isISOControl(_ arg0: UInt16) -> Bool + + @JavaStaticMethod + public func getDirectionality(_ arg0: UInt16) -> Int8 + + @JavaStaticMethod + public func getDirectionality(_ arg0: Int32) -> Int8 + + @JavaStaticMethod + public func isMirrored(_ arg0: UInt16) -> Bool + + @JavaStaticMethod + public func isMirrored(_ arg0: Int32) -> Bool + + @JavaStaticMethod + public func isSurrogatePair(_ arg0: UInt16, _ arg1: UInt16) -> Bool + + @JavaStaticMethod + public func charCount(_ arg0: Int32) -> Int32 + + @JavaStaticMethod + public func isJavaLetter(_ arg0: UInt16) -> Bool + + @JavaStaticMethod + public func isJavaLetterOrDigit(_ arg0: UInt16) -> Bool + + @JavaStaticMethod + public func isAlphabetic(_ arg0: Int32) -> Bool + + @JavaStaticMethod + public func isSpace(_ arg0: UInt16) -> Bool + + @JavaStaticMethod + public func forDigit(_ arg0: Int32, _ arg1: Int32) -> UInt16 + + @JavaStaticMethod + public func codePointOf(_ arg0: String) -> Int32 +} diff --git a/Sources/JavaKit/generated/JavaClass.swift b/Sources/JavaKit/generated/JavaClass.swift new file mode 100644 index 00000000..1696db8a --- /dev/null +++ b/Sources/JavaKit/generated/JavaClass.swift @@ -0,0 +1,162 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaRuntime + +@JavaClass("java.lang.Class") +public struct JavaClass { + @JavaMethod + public func getName() -> String + + @JavaMethod + public func toString() -> String + + @JavaMethod + public func isAssignableFrom(_ arg0: JavaClass?) -> Bool + + @JavaMethod + public func isInstance(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func getModifiers() -> Int32 + + @JavaMethod + public func isInterface() -> Bool + + @JavaMethod + public func isArray() -> Bool + + @JavaMethod + public func isPrimitive() -> Bool + + @JavaMethod + public func isHidden() -> Bool + + @JavaMethod + public func getSuperclass() -> JavaClass? + + @JavaMethod + public func cast(_ arg0: JavaObject?) -> JavaObject? + + @JavaMethod + public func componentType() -> JavaClass? + + @JavaMethod + public func getComponentType() -> JavaClass? + + @JavaMethod + public func isAnnotation() -> Bool + + @JavaMethod + public func isEnum() -> Bool + + @JavaMethod + public func isRecord() -> Bool + + @JavaMethod + public func newInstance() throws -> JavaObject? + + @JavaMethod + public func getInterfaces() -> [JavaClass?] + + @JavaMethod + public func isMemberClass() -> Bool + + @JavaMethod + public func isLocalClass() -> Bool + + @JavaMethod + public func isAnonymousClass() -> Bool + + @JavaMethod + public func getEnclosingClass() throws -> JavaClass? + + @JavaMethod + public func arrayType() -> JavaClass? + + @JavaMethod + public func getSimpleName() -> String + + @JavaMethod + public func getCanonicalName() -> String + + @JavaMethod + public func getPackageName() -> String + + @JavaMethod + public func desiredAssertionStatus() -> Bool + + @JavaMethod + public func getNestHost() -> JavaClass? + + @JavaMethod + public func descriptorString() -> String + + @JavaMethod + public func getPermittedSubclasses() -> [JavaClass?] + + @JavaMethod + public func toGenericString() -> String + + @JavaMethod + public func isSynthetic() -> Bool + + @JavaMethod + public func getSigners() -> [JavaObject?] + + @JavaMethod + public func getDeclaringClass() throws -> JavaClass? + + @JavaMethod + public func getTypeName() -> String + + @JavaMethod + public func getClasses() -> [JavaClass?] + + @JavaMethod + public func getDeclaredClasses() throws -> [JavaClass?] + + @JavaMethod + public func getEnumConstants() -> [JavaObject?] + + @JavaMethod + public func asSubclass(_ arg0: JavaClass?) -> JavaClass? + + @JavaMethod + public func isNestmateOf(_ arg0: JavaClass?) -> Bool + + @JavaMethod + public func getNestMembers() -> [JavaClass?] + + @JavaMethod + public func isSealed() -> Bool + + @JavaMethod + public func equals(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func hashCode() -> Int32 + + @JavaMethod + public func getClass() -> JavaClass? + + @JavaMethod + public func notify() + + @JavaMethod + public func notifyAll() + + @JavaMethod + public func wait(_ arg0: Int64) throws + + @JavaMethod + public func wait(_ arg0: Int64, _ arg1: Int32) throws + + @JavaMethod + public func wait() throws +} +extension JavaClass { + @JavaStaticMethod + public func forName(_ arg0: String) throws -> JavaClass? where ObjectType == JavaClass + + @JavaStaticMethod + public func forPrimitiveName(_ arg0: String) -> JavaClass? where ObjectType == JavaClass +} diff --git a/Sources/JavaKit/generated/JavaDouble.swift b/Sources/JavaKit/generated/JavaDouble.swift new file mode 100644 index 00000000..8d7a9abc --- /dev/null +++ b/Sources/JavaKit/generated/JavaDouble.swift @@ -0,0 +1,153 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaRuntime + +@JavaClass("java.lang.Double", extends: JavaNumber.self) +public struct JavaDouble { + @JavaMethod + public init(_ arg0: Double, environment: JNIEnvironment? = nil) + + @JavaMethod + public init(_ arg0: String, environment: JNIEnvironment? = nil) throws + + @JavaMethod + public func equals(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func toString() -> String + + @JavaMethod + public func hashCode() -> Int32 + + @JavaMethod + public func isInfinite() -> Bool + + @JavaMethod + public func compareTo(_ arg0: JavaDouble?) -> Int32 + + @JavaMethod + public func compareTo(_ arg0: JavaObject?) -> Int32 + + @JavaMethod + public func byteValue() -> Int8 + + @JavaMethod + public func shortValue() -> Int16 + + @JavaMethod + public func intValue() -> Int32 + + @JavaMethod + public func longValue() -> Int64 + + @JavaMethod + public func floatValue() -> Float + + @JavaMethod + public func doubleValue() -> Double + + @JavaMethod + public func isNaN() -> Bool + + @JavaMethod + public func getClass() -> JavaClass? + + @JavaMethod + public func notify() + + @JavaMethod + public func notifyAll() + + @JavaMethod + public func wait(_ arg0: Int64) throws + + @JavaMethod + public func wait(_ arg0: Int64, _ arg1: Int32) throws + + @JavaMethod + public func wait() throws +} +extension JavaClass { + @JavaStaticField + public var POSITIVE_INFINITY: Double + + @JavaStaticField + public var NEGATIVE_INFINITY: Double + + @JavaStaticField + public var NaN: Double + + @JavaStaticField + public var MAX_VALUE: Double + + @JavaStaticField + public var MIN_NORMAL: Double + + @JavaStaticField + public var MIN_VALUE: Double + + @JavaStaticField + public var SIZE: Int32 + + @JavaStaticField + public var PRECISION: Int32 + + @JavaStaticField + public var MAX_EXPONENT: Int32 + + @JavaStaticField + public var MIN_EXPONENT: Int32 + + @JavaStaticField + public var BYTES: Int32 + + @JavaStaticField + public var TYPE: JavaClass? + + @JavaStaticMethod + public func toString(_ arg0: Double) -> String + + @JavaStaticMethod + public func hashCode(_ arg0: Double) -> Int32 + + @JavaStaticMethod + public func min(_ arg0: Double, _ arg1: Double) -> Double + + @JavaStaticMethod + public func max(_ arg0: Double, _ arg1: Double) -> Double + + @JavaStaticMethod + public func isInfinite(_ arg0: Double) -> Bool + + @JavaStaticMethod + public func isFinite(_ arg0: Double) -> Bool + + @JavaStaticMethod + public func doubleToRawLongBits(_ arg0: Double) -> Int64 + + @JavaStaticMethod + public func doubleToLongBits(_ arg0: Double) -> Int64 + + @JavaStaticMethod + public func longBitsToDouble(_ arg0: Int64) -> Double + + @JavaStaticMethod + public func compare(_ arg0: Double, _ arg1: Double) -> Int32 + + @JavaStaticMethod + public func valueOf(_ arg0: String) throws -> JavaDouble? + + @JavaStaticMethod + public func valueOf(_ arg0: Double) -> JavaDouble? + + @JavaStaticMethod + public func toHexString(_ arg0: Double) -> String + + @JavaStaticMethod + public func isNaN(_ arg0: Double) -> Bool + + @JavaStaticMethod + public func sum(_ arg0: Double, _ arg1: Double) -> Double + + @JavaStaticMethod + public func parseDouble(_ arg0: String) throws -> Double +} diff --git a/Sources/JavaKit/generated/JavaFloat.swift b/Sources/JavaKit/generated/JavaFloat.swift new file mode 100644 index 00000000..83672479 --- /dev/null +++ b/Sources/JavaKit/generated/JavaFloat.swift @@ -0,0 +1,162 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaRuntime + +@JavaClass("java.lang.Float", extends: JavaNumber.self) +public struct JavaFloat { + @JavaMethod + public init(_ arg0: String, environment: JNIEnvironment? = nil) throws + + @JavaMethod + public init(_ arg0: Double, environment: JNIEnvironment? = nil) + + @JavaMethod + public init(_ arg0: Float, environment: JNIEnvironment? = nil) + + @JavaMethod + public func equals(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func toString() -> String + + @JavaMethod + public func hashCode() -> Int32 + + @JavaMethod + public func isInfinite() -> Bool + + @JavaMethod + public func compareTo(_ arg0: JavaObject?) -> Int32 + + @JavaMethod + public func compareTo(_ arg0: JavaFloat?) -> Int32 + + @JavaMethod + public func byteValue() -> Int8 + + @JavaMethod + public func shortValue() -> Int16 + + @JavaMethod + public func intValue() -> Int32 + + @JavaMethod + public func longValue() -> Int64 + + @JavaMethod + public func floatValue() -> Float + + @JavaMethod + public func doubleValue() -> Double + + @JavaMethod + public func isNaN() -> Bool + + @JavaMethod + public func getClass() -> JavaClass? + + @JavaMethod + public func notify() + + @JavaMethod + public func notifyAll() + + @JavaMethod + public func wait(_ arg0: Int64) throws + + @JavaMethod + public func wait(_ arg0: Int64, _ arg1: Int32) throws + + @JavaMethod + public func wait() throws +} +extension JavaClass { + @JavaStaticField + public var POSITIVE_INFINITY: Float + + @JavaStaticField + public var NEGATIVE_INFINITY: Float + + @JavaStaticField + public var NaN: Float + + @JavaStaticField + public var MAX_VALUE: Float + + @JavaStaticField + public var MIN_NORMAL: Float + + @JavaStaticField + public var MIN_VALUE: Float + + @JavaStaticField + public var SIZE: Int32 + + @JavaStaticField + public var PRECISION: Int32 + + @JavaStaticField + public var MAX_EXPONENT: Int32 + + @JavaStaticField + public var MIN_EXPONENT: Int32 + + @JavaStaticField + public var BYTES: Int32 + + @JavaStaticField + public var TYPE: JavaClass? + + @JavaStaticMethod + public func toString(_ arg0: Float) -> String + + @JavaStaticMethod + public func hashCode(_ arg0: Float) -> Int32 + + @JavaStaticMethod + public func min(_ arg0: Float, _ arg1: Float) -> Float + + @JavaStaticMethod + public func max(_ arg0: Float, _ arg1: Float) -> Float + + @JavaStaticMethod + public func isInfinite(_ arg0: Float) -> Bool + + @JavaStaticMethod + public func isFinite(_ arg0: Float) -> Bool + + @JavaStaticMethod + public func floatToRawIntBits(_ arg0: Float) -> Int32 + + @JavaStaticMethod + public func floatToIntBits(_ arg0: Float) -> Int32 + + @JavaStaticMethod + public func intBitsToFloat(_ arg0: Int32) -> Float + + @JavaStaticMethod + public func float16ToFloat(_ arg0: Int16) -> Float + + @JavaStaticMethod + public func floatToFloat16(_ arg0: Float) -> Int16 + + @JavaStaticMethod + public func compare(_ arg0: Float, _ arg1: Float) -> Int32 + + @JavaStaticMethod + public func valueOf(_ arg0: Float) -> JavaFloat? + + @JavaStaticMethod + public func valueOf(_ arg0: String) throws -> JavaFloat? + + @JavaStaticMethod + public func toHexString(_ arg0: Float) -> String + + @JavaStaticMethod + public func isNaN(_ arg0: Float) -> Bool + + @JavaStaticMethod + public func sum(_ arg0: Float, _ arg1: Float) -> Float + + @JavaStaticMethod + public func parseFloat(_ arg0: String) throws -> Float +} diff --git a/Sources/JavaKit/generated/JavaInteger.swift b/Sources/JavaKit/generated/JavaInteger.swift new file mode 100644 index 00000000..09d27eed --- /dev/null +++ b/Sources/JavaKit/generated/JavaInteger.swift @@ -0,0 +1,195 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaRuntime + +@JavaClass("java.lang.Integer", extends: JavaNumber.self) +public struct JavaInteger { + @JavaMethod + public init(_ arg0: Int32, environment: JNIEnvironment? = nil) + + @JavaMethod + public init(_ arg0: String, environment: JNIEnvironment? = nil) throws + + @JavaMethod + public func equals(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func toString() -> String + + @JavaMethod + public func hashCode() -> Int32 + + @JavaMethod + public func compareTo(_ arg0: JavaObject?) -> Int32 + + @JavaMethod + public func compareTo(_ arg0: JavaInteger?) -> Int32 + + @JavaMethod + public func byteValue() -> Int8 + + @JavaMethod + public func shortValue() -> Int16 + + @JavaMethod + public func intValue() -> Int32 + + @JavaMethod + public func longValue() -> Int64 + + @JavaMethod + public func floatValue() -> Float + + @JavaMethod + public func doubleValue() -> Double + + @JavaMethod + public func getClass() -> JavaClass? + + @JavaMethod + public func notify() + + @JavaMethod + public func notifyAll() + + @JavaMethod + public func wait(_ arg0: Int64) throws + + @JavaMethod + public func wait(_ arg0: Int64, _ arg1: Int32) throws + + @JavaMethod + public func wait() throws +} +extension JavaClass { + @JavaStaticField + public var MIN_VALUE: Int32 + + @JavaStaticField + public var MAX_VALUE: Int32 + + @JavaStaticField + public var TYPE: JavaClass? + + @JavaStaticField + public var SIZE: Int32 + + @JavaStaticField + public var BYTES: Int32 + + @JavaStaticMethod + public func numberOfLeadingZeros(_ arg0: Int32) -> Int32 + + @JavaStaticMethod + public func numberOfTrailingZeros(_ arg0: Int32) -> Int32 + + @JavaStaticMethod + public func bitCount(_ arg0: Int32) -> Int32 + + @JavaStaticMethod + public func toString(_ arg0: Int32) -> String + + @JavaStaticMethod + public func toString(_ arg0: Int32, _ arg1: Int32) -> String + + @JavaStaticMethod + public func hashCode(_ arg0: Int32) -> Int32 + + @JavaStaticMethod + public func min(_ arg0: Int32, _ arg1: Int32) -> Int32 + + @JavaStaticMethod + public func max(_ arg0: Int32, _ arg1: Int32) -> Int32 + + @JavaStaticMethod + public func signum(_ arg0: Int32) -> Int32 + + @JavaStaticMethod + public func expand(_ arg0: Int32, _ arg1: Int32) -> Int32 + + @JavaStaticMethod + public func compareUnsigned(_ arg0: Int32, _ arg1: Int32) -> Int32 + + @JavaStaticMethod + public func divideUnsigned(_ arg0: Int32, _ arg1: Int32) -> Int32 + + @JavaStaticMethod + public func remainderUnsigned(_ arg0: Int32, _ arg1: Int32) -> Int32 + + @JavaStaticMethod + public func reverse(_ arg0: Int32) -> Int32 + + @JavaStaticMethod + public func reverseBytes(_ arg0: Int32) -> Int32 + + @JavaStaticMethod + public func compress(_ arg0: Int32, _ arg1: Int32) -> Int32 + + @JavaStaticMethod + public func compare(_ arg0: Int32, _ arg1: Int32) -> Int32 + + @JavaStaticMethod + public func valueOf(_ arg0: String) throws -> JavaInteger? + + @JavaStaticMethod + public func valueOf(_ arg0: String, _ arg1: Int32) throws -> JavaInteger? + + @JavaStaticMethod + public func valueOf(_ arg0: Int32) -> JavaInteger? + + @JavaStaticMethod + public func toHexString(_ arg0: Int32) -> String + + @JavaStaticMethod + public func decode(_ arg0: String) throws -> JavaInteger? + + @JavaStaticMethod + public func parseInt(_ arg0: String) throws -> Int32 + + @JavaStaticMethod + public func parseInt(_ arg0: String, _ arg1: Int32) throws -> Int32 + + @JavaStaticMethod + public func toUnsignedLong(_ arg0: Int32) -> Int64 + + @JavaStaticMethod + public func sum(_ arg0: Int32, _ arg1: Int32) -> Int32 + + @JavaStaticMethod + public func toUnsignedString(_ arg0: Int32, _ arg1: Int32) -> String + + @JavaStaticMethod + public func toUnsignedString(_ arg0: Int32) -> String + + @JavaStaticMethod + public func parseUnsignedInt(_ arg0: String) throws -> Int32 + + @JavaStaticMethod + public func parseUnsignedInt(_ arg0: String, _ arg1: Int32) throws -> Int32 + + @JavaStaticMethod + public func getInteger(_ arg0: String, _ arg1: JavaInteger?) -> JavaInteger? + + @JavaStaticMethod + public func getInteger(_ arg0: String, _ arg1: Int32) -> JavaInteger? + + @JavaStaticMethod + public func getInteger(_ arg0: String) -> JavaInteger? + + @JavaStaticMethod + public func toOctalString(_ arg0: Int32) -> String + + @JavaStaticMethod + public func toBinaryString(_ arg0: Int32) -> String + + @JavaStaticMethod + public func highestOneBit(_ arg0: Int32) -> Int32 + + @JavaStaticMethod + public func lowestOneBit(_ arg0: Int32) -> Int32 + + @JavaStaticMethod + public func rotateLeft(_ arg0: Int32, _ arg1: Int32) -> Int32 + + @JavaStaticMethod + public func rotateRight(_ arg0: Int32, _ arg1: Int32) -> Int32 +} diff --git a/Sources/JavaKit/generated/JavaLong.swift b/Sources/JavaKit/generated/JavaLong.swift new file mode 100644 index 00000000..f2aa72bd --- /dev/null +++ b/Sources/JavaKit/generated/JavaLong.swift @@ -0,0 +1,192 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaRuntime + +@JavaClass("java.lang.Long", extends: JavaNumber.self) +public struct JavaLong { + @JavaMethod + public init(_ arg0: String, environment: JNIEnvironment? = nil) throws + + @JavaMethod + public init(_ arg0: Int64, environment: JNIEnvironment? = nil) + + @JavaMethod + public func equals(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func toString() -> String + + @JavaMethod + public func hashCode() -> Int32 + + @JavaMethod + public func compareTo(_ arg0: JavaObject?) -> Int32 + + @JavaMethod + public func compareTo(_ arg0: JavaLong?) -> Int32 + + @JavaMethod + public func byteValue() -> Int8 + + @JavaMethod + public func shortValue() -> Int16 + + @JavaMethod + public func intValue() -> Int32 + + @JavaMethod + public func longValue() -> Int64 + + @JavaMethod + public func floatValue() -> Float + + @JavaMethod + public func doubleValue() -> Double + + @JavaMethod + public func getClass() -> JavaClass? + + @JavaMethod + public func notify() + + @JavaMethod + public func notifyAll() + + @JavaMethod + public func wait(_ arg0: Int64) throws + + @JavaMethod + public func wait(_ arg0: Int64, _ arg1: Int32) throws + + @JavaMethod + public func wait() throws +} +extension JavaClass { + @JavaStaticField + public var MIN_VALUE: Int64 + + @JavaStaticField + public var MAX_VALUE: Int64 + + @JavaStaticField + public var TYPE: JavaClass? + + @JavaStaticField + public var SIZE: Int32 + + @JavaStaticField + public var BYTES: Int32 + + @JavaStaticMethod + public func numberOfLeadingZeros(_ arg0: Int64) -> Int32 + + @JavaStaticMethod + public func numberOfTrailingZeros(_ arg0: Int64) -> Int32 + + @JavaStaticMethod + public func bitCount(_ arg0: Int64) -> Int32 + + @JavaStaticMethod + public func toString(_ arg0: Int64) -> String + + @JavaStaticMethod + public func toString(_ arg0: Int64, _ arg1: Int32) -> String + + @JavaStaticMethod + public func hashCode(_ arg0: Int64) -> Int32 + + @JavaStaticMethod + public func min(_ arg0: Int64, _ arg1: Int64) -> Int64 + + @JavaStaticMethod + public func max(_ arg0: Int64, _ arg1: Int64) -> Int64 + + @JavaStaticMethod + public func signum(_ arg0: Int64) -> Int32 + + @JavaStaticMethod + public func expand(_ arg0: Int64, _ arg1: Int64) -> Int64 + + @JavaStaticMethod + public func compareUnsigned(_ arg0: Int64, _ arg1: Int64) -> Int32 + + @JavaStaticMethod + public func divideUnsigned(_ arg0: Int64, _ arg1: Int64) -> Int64 + + @JavaStaticMethod + public func remainderUnsigned(_ arg0: Int64, _ arg1: Int64) -> Int64 + + @JavaStaticMethod + public func reverse(_ arg0: Int64) -> Int64 + + @JavaStaticMethod + public func reverseBytes(_ arg0: Int64) -> Int64 + + @JavaStaticMethod + public func compress(_ arg0: Int64, _ arg1: Int64) -> Int64 + + @JavaStaticMethod + public func getLong(_ arg0: String, _ arg1: JavaLong?) -> JavaLong? + + @JavaStaticMethod + public func getLong(_ arg0: String) -> JavaLong? + + @JavaStaticMethod + public func getLong(_ arg0: String, _ arg1: Int64) -> JavaLong? + + @JavaStaticMethod + public func compare(_ arg0: Int64, _ arg1: Int64) -> Int32 + + @JavaStaticMethod + public func valueOf(_ arg0: String) throws -> JavaLong? + + @JavaStaticMethod + public func valueOf(_ arg0: Int64) -> JavaLong? + + @JavaStaticMethod + public func valueOf(_ arg0: String, _ arg1: Int32) throws -> JavaLong? + + @JavaStaticMethod + public func toHexString(_ arg0: Int64) -> String + + @JavaStaticMethod + public func decode(_ arg0: String) throws -> JavaLong? + + @JavaStaticMethod + public func sum(_ arg0: Int64, _ arg1: Int64) -> Int64 + + @JavaStaticMethod + public func toUnsignedString(_ arg0: Int64) -> String + + @JavaStaticMethod + public func toUnsignedString(_ arg0: Int64, _ arg1: Int32) -> String + + @JavaStaticMethod + public func toOctalString(_ arg0: Int64) -> String + + @JavaStaticMethod + public func toBinaryString(_ arg0: Int64) -> String + + @JavaStaticMethod + public func highestOneBit(_ arg0: Int64) -> Int64 + + @JavaStaticMethod + public func lowestOneBit(_ arg0: Int64) -> Int64 + + @JavaStaticMethod + public func rotateLeft(_ arg0: Int64, _ arg1: Int32) -> Int64 + + @JavaStaticMethod + public func rotateRight(_ arg0: Int64, _ arg1: Int32) -> Int64 + + @JavaStaticMethod + public func parseLong(_ arg0: String, _ arg1: Int32) throws -> Int64 + + @JavaStaticMethod + public func parseLong(_ arg0: String) throws -> Int64 + + @JavaStaticMethod + public func parseUnsignedLong(_ arg0: String, _ arg1: Int32) throws -> Int64 + + @JavaStaticMethod + public func parseUnsignedLong(_ arg0: String) throws -> Int64 +} diff --git a/Sources/JavaKit/generated/JavaNumber.swift b/Sources/JavaKit/generated/JavaNumber.swift new file mode 100644 index 00000000..42864a37 --- /dev/null +++ b/Sources/JavaKit/generated/JavaNumber.swift @@ -0,0 +1,53 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaRuntime + +@JavaClass("java.lang.Number") +public struct JavaNumber { + @JavaMethod + public init(environment: JNIEnvironment? = nil) + + @JavaMethod + public func byteValue() -> Int8 + + @JavaMethod + public func shortValue() -> Int16 + + @JavaMethod + public func intValue() -> Int32 + + @JavaMethod + public func longValue() -> Int64 + + @JavaMethod + public func floatValue() -> Float + + @JavaMethod + public func doubleValue() -> Double + + @JavaMethod + public func equals(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func toString() -> String + + @JavaMethod + public func hashCode() -> Int32 + + @JavaMethod + public func getClass() -> JavaClass? + + @JavaMethod + public func notify() + + @JavaMethod + public func notifyAll() + + @JavaMethod + public func wait(_ arg0: Int64) throws + + @JavaMethod + public func wait(_ arg0: Int64, _ arg1: Int32) throws + + @JavaMethod + public func wait() throws +} diff --git a/Sources/JavaKit/generated/JavaShort.swift b/Sources/JavaKit/generated/JavaShort.swift new file mode 100644 index 00000000..b7c5de3f --- /dev/null +++ b/Sources/JavaKit/generated/JavaShort.swift @@ -0,0 +1,117 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaRuntime + +@JavaClass("java.lang.Short", extends: JavaNumber.self) +public struct JavaShort { + @JavaMethod + public init(_ arg0: Int16, environment: JNIEnvironment? = nil) + + @JavaMethod + public init(_ arg0: String, environment: JNIEnvironment? = nil) throws + + @JavaMethod + public func equals(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func toString() -> String + + @JavaMethod + public func hashCode() -> Int32 + + @JavaMethod + public func compareTo(_ arg0: JavaShort?) -> Int32 + + @JavaMethod + public func compareTo(_ arg0: JavaObject?) -> Int32 + + @JavaMethod + public func byteValue() -> Int8 + + @JavaMethod + public func shortValue() -> Int16 + + @JavaMethod + public func intValue() -> Int32 + + @JavaMethod + public func longValue() -> Int64 + + @JavaMethod + public func floatValue() -> Float + + @JavaMethod + public func doubleValue() -> Double + + @JavaMethod + public func getClass() -> JavaClass? + + @JavaMethod + public func notify() + + @JavaMethod + public func notifyAll() + + @JavaMethod + public func wait(_ arg0: Int64) throws + + @JavaMethod + public func wait(_ arg0: Int64, _ arg1: Int32) throws + + @JavaMethod + public func wait() throws +} +extension JavaClass { + @JavaStaticField + public var MIN_VALUE: Int16 + + @JavaStaticField + public var MAX_VALUE: Int16 + + @JavaStaticField + public var TYPE: JavaClass? + + @JavaStaticField + public var SIZE: Int32 + + @JavaStaticField + public var BYTES: Int32 + + @JavaStaticMethod + public func toString(_ arg0: Int16) -> String + + @JavaStaticMethod + public func hashCode(_ arg0: Int16) -> Int32 + + @JavaStaticMethod + public func compareUnsigned(_ arg0: Int16, _ arg1: Int16) -> Int32 + + @JavaStaticMethod + public func reverseBytes(_ arg0: Int16) -> Int16 + + @JavaStaticMethod + public func compare(_ arg0: Int16, _ arg1: Int16) -> Int32 + + @JavaStaticMethod + public func valueOf(_ arg0: String, _ arg1: Int32) throws -> JavaShort? + + @JavaStaticMethod + public func valueOf(_ arg0: String) throws -> JavaShort? + + @JavaStaticMethod + public func valueOf(_ arg0: Int16) -> JavaShort? + + @JavaStaticMethod + public func decode(_ arg0: String) throws -> JavaShort? + + @JavaStaticMethod + public func toUnsignedLong(_ arg0: Int16) -> Int64 + + @JavaStaticMethod + public func toUnsignedInt(_ arg0: Int16) -> Int32 + + @JavaStaticMethod + public func parseShort(_ arg0: String) throws -> Int16 + + @JavaStaticMethod + public func parseShort(_ arg0: String, _ arg1: Int32) throws -> Int16 +} diff --git a/Sources/JavaKit/generated/JavaVoid.swift b/Sources/JavaKit/generated/JavaVoid.swift new file mode 100644 index 00000000..f6e0f4a6 --- /dev/null +++ b/Sources/JavaKit/generated/JavaVoid.swift @@ -0,0 +1,36 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaRuntime + +@JavaClass("java.lang.Void") +public struct JavaVoid { + @JavaMethod + public func equals(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func toString() -> String + + @JavaMethod + public func hashCode() -> Int32 + + @JavaMethod + public func getClass() -> JavaClass? + + @JavaMethod + public func notify() + + @JavaMethod + public func notifyAll() + + @JavaMethod + public func wait(_ arg0: Int64) throws + + @JavaMethod + public func wait(_ arg0: Int64, _ arg1: Int32) throws + + @JavaMethod + public func wait() throws +} +extension JavaClass { + @JavaStaticField + public var TYPE: JavaClass? +} diff --git a/Sources/JavaKitReflection/JavaClass+Reflection.swift b/Sources/JavaKitReflection/JavaClass+Reflection.swift index 13e080ac..569b72e8 100644 --- a/Sources/JavaKitReflection/JavaClass+Reflection.swift +++ b/Sources/JavaKitReflection/JavaClass+Reflection.swift @@ -17,18 +17,6 @@ import JavaKit // TODO: We should be able to autogenerate this as an extension based on // knowing that JavaClass was defined elsewhere. extension JavaClass { - @JavaMethod - public func equals(_ arg0: JavaObject?) -> Bool - - @JavaMethod - public func getName() -> String - - @JavaMethod - public func getSimpleName() -> String - - @JavaMethod - public func getCanonicalName() -> String - @JavaMethod public func getDeclaredMethods() -> [Method?] @@ -44,15 +32,9 @@ extension JavaClass { @JavaMethod public func getParameters() -> [Parameter?] - @JavaMethod - public func getSuperclass() -> JavaClass? - @JavaMethod public func getTypeParameters() -> [TypeVariable>?] @JavaMethod public func getGenericInterfaces() -> [Type?] - - @JavaMethod - public func isInterface() -> Bool } diff --git a/Tests/JavaKitTests/BasicRuntimeTests.swift b/Tests/JavaKitTests/BasicRuntimeTests.swift index 0e5fed0b..5185294e 100644 --- a/Tests/JavaKitTests/BasicRuntimeTests.swift +++ b/Tests/JavaKitTests/BasicRuntimeTests.swift @@ -63,7 +63,7 @@ class BasicRuntimeTests: XCTestCase { func testStaticMethods() throws { let environment = try jvm.environment() - let urlConnectionClass = try JavaClass(in: environment) + let urlConnectionClass = try JavaClass(environment: environment) XCTAssert(urlConnectionClass.getDefaultAllowUserInteraction() == false) } @@ -71,7 +71,7 @@ class BasicRuntimeTests: XCTestCase { let environment = try jvm.environment() do { - _ = try JavaClass(in: environment) + _ = try JavaClass(environment: environment) } catch { XCTAssertEqual(String(describing: error), "org/swift/javakit/Nonexistent") } diff --git a/USER_GUIDE.md b/USER_GUIDE.md index 33e08423..a85fa94e 100644 --- a/USER_GUIDE.md +++ b/USER_GUIDE.md @@ -61,35 +61,43 @@ public struct BigInteger { This Swift type wraps `java.math.BigInteger`, exposing its constructors, methods, and fields for use directly to Swift. Let's try using it! -### Creating a Java Virtual Machine instance from Swift +### Creating a `BigInteger` and determine whether it is probably prime -The `JavaVirtualMachine` class, which is part of the `JavaKitVM` module, provides the ability to create and query the Java Virtual Machine. One can create a shared instance of `JavaVirtualMachine` by calling `JavaVirtualMachine.shared()`, optionally passing along extra options to the JVM (such as the class path): +Now, we can go ahead and create a `BigInteger` instance from a Swift string like this: ```swift -let javaVirtualMachine = try JavaVirtualMachine.shared() +let bigInt = BigInteger(veryBigNumber) ``` -If the JVM is already running, a `JavaVirtualMachine` instance will be created to reference that existing JVM. Given a `JavaVirtualMachine` instance, one can query the JNI environment for the currently-active thread by calling `environment()`, e.g., +And then call methods on it. For example, check whether the big integer is a probable prime with some certainty: ```swift -let jniEnvironment = try javaVirtualMachine.environment() +if bigInt.isProbablePrime(10) { + print("\(bigInt.toString()) is probably prime") +} ``` -This JNI environment can be used to create instances of Java objects. For example, we can create a `BigInteger` instance from a Swift string like this: +Swift ensures that the Java garbage collector will keep the object alive until `bigInt` (and any copies of it) are been destroyed. + +### Creating a Java Virtual Machine instance from Swift + +When JavaKit requires a running Java Virtual Machine to use an operation (for example, to create an instance of `BigInteger`), it will query to determine if one is running and, if not, create one. To exercise more control over the creation and configuration of the Java virtual machine, use the `JavaVirtualMachine` class, which provides creation and query operations. One can create a shared instance by calling `JavaVirtualMachine.shared()`, optionally passing along extra options to the JVM (such as the class path): ```swift -let bigInt = BigInteger(veryBigNumber, environment: jniEnvironment) +let javaVirtualMachine = try JavaVirtualMachine.shared() ``` -And then call methods on it. For example, check whether the big integer is a probable prime with some certainty: +If the JVM is already running, a `JavaVirtualMachine` instance will be created to reference that existing JVM. Given a `JavaVirtualMachine` instance, one can query the JNI environment for the currently-active thread by calling `environment()`, e.g., ```swift -if bigInt.isProbablePrime(10) { - print("\(bigInt.toString()) is probably prime") -} +let jniEnvironment = try javaVirtualMachine.environment() ``` -Swift ensures that the Java garbage collector will keep the object alive until `bigInt` (and any copies of it) are been destroyed. +This JNI environment can be used to create instances of Java objects in a specific JNI environment. For example, we can pass this environment along when we create the `BigInteger` instance from a Swift string, like this: + +```swift +let bigInt = BigInteger(veryBigNumber, environment: jniEnvironment) +``` ### Importing a Jar file into Swift @@ -134,7 +142,7 @@ The resulting configuration file will look something like this: } ``` -As with the previous `JavaProbablyPrime` sample, the `JavaSieve` target in `Package.swift` should depend on the `swift-java` package modules (`JavaKit`, `JavaKitVM`) and apply the `Java2Swift` plugin. This makes all of the Java classes found in the Jar file available to Swift within the `JavaSieve` target. +As with the previous `JavaProbablyPrime` sample, the `JavaSieve` target in `Package.swift` should depend on the `swift-java` package modules (`JavaKit`) and apply the `Java2Swift` plugin. This makes all of the Java classes found in the Jar file available to Swift within the `JavaSieve` target. If you inspect the build output, there are a number of warnings that look like this: @@ -164,8 +172,7 @@ Then define a a Java2Swift configuration file in `Sources/JavaMath/Java2Swift.co "java.math.BigDecimal" : "BigDecimal", "java.math.BigInteger" : "BigInteger", "java.math.MathContext" : "MathContext", - "java.math.RoundingMode" : "RoundingMode", - "java.lang.Integer" : "JavaInteger", + "java.math.RoundingMode" : "RoundingMode" } } ``` @@ -185,7 +192,7 @@ public class SieveOfEratosthenes { In Java, static methods are called as members of the class itself. For Swift to call a Java static method, it needs a representation of the Java class. This is expressed as an instance of the generic type `JavaClass`, which can be created in a particular JNI environment like this: ```swift -let sieveClass = try JavaClass(in: jvm.environment()) +let sieveClass = try JavaClass(environment: jvm.environment()) ``` Now we can call Java's static methods on that class as instance methods on the `JavaClass` instance, e.g., @@ -198,11 +205,10 @@ Putting it all together, we can define a main program in `Sources/JavaSieve/main ```swift import JavaKit -import JavaKitVM let jvm = try JavaVirtualMachine.shared(classPath: ["QuadraticSieve-1.0.jar"]) do { - let sieveClass = try JavaClass(in: jvm.environment()) + let sieveClass = try JavaClass(environment: jvm.environment()) for prime in sieveClass.findPrimes(100)! { print("Found prime: \(prime.intValue())") } From 07b0c54b9649b97f85f043d22e77ef84cb2d4ac0 Mon Sep 17 00:00:00 2001 From: Jack Rosen Date: Sat, 26 Oct 2024 02:37:07 -0400 Subject: [PATCH 126/426] Add Support for Final Fields (#117) * Add Support for Final Fields * Generate Classes --- Sources/Java2SwiftLib/JavaTranslator.swift | 2 +- Sources/JavaKit/Macros.swift | 4 +- Sources/JavaKit/generated/JavaBoolean.swift | 6 +- Sources/JavaKit/generated/JavaByte.swift | 10 +- Sources/JavaKit/generated/JavaCharacter.swift | 140 +++++++++--------- Sources/JavaKit/generated/JavaDouble.swift | 24 +-- Sources/JavaKit/generated/JavaFloat.swift | 24 +-- Sources/JavaKit/generated/JavaInteger.swift | 10 +- Sources/JavaKit/generated/JavaLong.swift | 10 +- Sources/JavaKit/generated/JavaShort.swift | 10 +- Sources/JavaKit/generated/JavaVoid.swift | 2 +- Sources/JavaKitJar/generated/JarEntry.swift | 84 +++++------ Sources/JavaKitJar/generated/JarFile.swift | 86 +++++------ .../JavaKitJar/generated/JarInputStream.swift | 80 +++++----- .../generated/JarOutputStream.swift | 84 +++++------ Sources/JavaKitMacros/JavaFieldMacro.swift | 25 +++- .../JavaKitReflection/Field+Utilities.swift | 5 + .../generated/Constructor.swift | 4 +- .../generated/Executable.swift | 4 +- .../JavaKitReflection/generated/Field.swift | 4 +- .../JavaKitReflection/generated/Method.swift | 4 +- Tests/Java2SwiftTests/Java2SwiftTests.swift | 2 +- .../JavaClassMacroTests.swift | 8 + 23 files changed, 331 insertions(+), 301 deletions(-) diff --git a/Sources/Java2SwiftLib/JavaTranslator.swift b/Sources/Java2SwiftLib/JavaTranslator.swift index fa7e5789..fc0d0733 100644 --- a/Sources/Java2SwiftLib/JavaTranslator.swift +++ b/Sources/Java2SwiftLib/JavaTranslator.swift @@ -546,7 +546,7 @@ extension JavaTranslator { let fieldAttribute: AttributeSyntax = javaField.isStatic ? "@JavaStaticField" : "@JavaField"; let swiftFieldName = javaField.getName().escapedSwiftName return """ - \(fieldAttribute) + \(fieldAttribute)(isFinal: \(raw: javaField.isFinal)) public var \(raw: swiftFieldName): \(raw: typeName) """ } diff --git a/Sources/JavaKit/Macros.swift b/Sources/JavaKit/Macros.swift index 12ae0c26..4caef659 100644 --- a/Sources/JavaKit/Macros.swift +++ b/Sources/JavaKit/Macros.swift @@ -92,7 +92,7 @@ public macro JavaInterface(_ fullClassName: String, extends: (any AnyJavaObject. /// } /// ``` @attached(accessor) -public macro JavaField(_ javaFieldName: String? = nil) = #externalMacro(module: "JavaKitMacros", type: "JavaFieldMacro") +public macro JavaField(_ javaFieldName: String? = nil, isFinal: Bool = false) = #externalMacro(module: "JavaKitMacros", type: "JavaFieldMacro") /// Attached macro that turns a Swift property into one that accesses a Java static field on the underlying Java object. @@ -106,7 +106,7 @@ public macro JavaField(_ javaFieldName: String? = nil) = #externalMacro(module: /// } /// ``` @attached(accessor) -public macro JavaStaticField(_ javaFieldName: String? = nil) = #externalMacro(module: "JavaKitMacros", type: "JavaFieldMacro") +public macro JavaStaticField(_ javaFieldName: String? = nil, isFinal: Bool = false) = #externalMacro(module: "JavaKitMacros", type: "JavaFieldMacro") /// Attached macro that turns a Swift method into one that wraps a Java method on the underlying Java object. /// diff --git a/Sources/JavaKit/generated/JavaBoolean.swift b/Sources/JavaKit/generated/JavaBoolean.swift index c0cfbd04..310f46e4 100644 --- a/Sources/JavaKit/generated/JavaBoolean.swift +++ b/Sources/JavaKit/generated/JavaBoolean.swift @@ -46,13 +46,13 @@ public struct JavaBoolean { public func wait() throws } extension JavaClass { - @JavaStaticField + @JavaStaticField(isFinal: true) public var TRUE: JavaBoolean? - @JavaStaticField + @JavaStaticField(isFinal: true) public var FALSE: JavaBoolean? - @JavaStaticField + @JavaStaticField(isFinal: true) public var TYPE: JavaClass? @JavaStaticMethod diff --git a/Sources/JavaKit/generated/JavaByte.swift b/Sources/JavaKit/generated/JavaByte.swift index c00cae95..79b6b5f2 100644 --- a/Sources/JavaKit/generated/JavaByte.swift +++ b/Sources/JavaKit/generated/JavaByte.swift @@ -61,19 +61,19 @@ public struct JavaByte { public func wait() throws } extension JavaClass { - @JavaStaticField + @JavaStaticField(isFinal: true) public var MIN_VALUE: Int8 - @JavaStaticField + @JavaStaticField(isFinal: true) public var MAX_VALUE: Int8 - @JavaStaticField + @JavaStaticField(isFinal: true) public var TYPE: JavaClass? - @JavaStaticField + @JavaStaticField(isFinal: true) public var SIZE: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var BYTES: Int32 @JavaStaticMethod diff --git a/Sources/JavaKit/generated/JavaCharacter.swift b/Sources/JavaKit/generated/JavaCharacter.swift index c5d2e8b9..68412f22 100644 --- a/Sources/JavaKit/generated/JavaCharacter.swift +++ b/Sources/JavaKit/generated/JavaCharacter.swift @@ -43,214 +43,214 @@ public struct JavaCharacter { public func wait() throws } extension JavaClass { - @JavaStaticField + @JavaStaticField(isFinal: true) public var MIN_RADIX: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var MAX_RADIX: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var MIN_VALUE: UInt16 - @JavaStaticField + @JavaStaticField(isFinal: true) public var MAX_VALUE: UInt16 - @JavaStaticField + @JavaStaticField(isFinal: true) public var TYPE: JavaClass? - @JavaStaticField + @JavaStaticField(isFinal: true) public var UNASSIGNED: Int8 - @JavaStaticField + @JavaStaticField(isFinal: true) public var UPPERCASE_LETTER: Int8 - @JavaStaticField + @JavaStaticField(isFinal: true) public var LOWERCASE_LETTER: Int8 - @JavaStaticField + @JavaStaticField(isFinal: true) public var TITLECASE_LETTER: Int8 - @JavaStaticField + @JavaStaticField(isFinal: true) public var MODIFIER_LETTER: Int8 - @JavaStaticField + @JavaStaticField(isFinal: true) public var OTHER_LETTER: Int8 - @JavaStaticField + @JavaStaticField(isFinal: true) public var NON_SPACING_MARK: Int8 - @JavaStaticField + @JavaStaticField(isFinal: true) public var ENCLOSING_MARK: Int8 - @JavaStaticField + @JavaStaticField(isFinal: true) public var COMBINING_SPACING_MARK: Int8 - @JavaStaticField + @JavaStaticField(isFinal: true) public var DECIMAL_DIGIT_NUMBER: Int8 - @JavaStaticField + @JavaStaticField(isFinal: true) public var LETTER_NUMBER: Int8 - @JavaStaticField + @JavaStaticField(isFinal: true) public var OTHER_NUMBER: Int8 - @JavaStaticField + @JavaStaticField(isFinal: true) public var SPACE_SEPARATOR: Int8 - @JavaStaticField + @JavaStaticField(isFinal: true) public var LINE_SEPARATOR: Int8 - @JavaStaticField + @JavaStaticField(isFinal: true) public var PARAGRAPH_SEPARATOR: Int8 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CONTROL: Int8 - @JavaStaticField + @JavaStaticField(isFinal: true) public var FORMAT: Int8 - @JavaStaticField + @JavaStaticField(isFinal: true) public var PRIVATE_USE: Int8 - @JavaStaticField + @JavaStaticField(isFinal: true) public var SURROGATE: Int8 - @JavaStaticField + @JavaStaticField(isFinal: true) public var DASH_PUNCTUATION: Int8 - @JavaStaticField + @JavaStaticField(isFinal: true) public var START_PUNCTUATION: Int8 - @JavaStaticField + @JavaStaticField(isFinal: true) public var END_PUNCTUATION: Int8 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CONNECTOR_PUNCTUATION: Int8 - @JavaStaticField + @JavaStaticField(isFinal: true) public var OTHER_PUNCTUATION: Int8 - @JavaStaticField + @JavaStaticField(isFinal: true) public var MATH_SYMBOL: Int8 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CURRENCY_SYMBOL: Int8 - @JavaStaticField + @JavaStaticField(isFinal: true) public var MODIFIER_SYMBOL: Int8 - @JavaStaticField + @JavaStaticField(isFinal: true) public var OTHER_SYMBOL: Int8 - @JavaStaticField + @JavaStaticField(isFinal: true) public var INITIAL_QUOTE_PUNCTUATION: Int8 - @JavaStaticField + @JavaStaticField(isFinal: true) public var FINAL_QUOTE_PUNCTUATION: Int8 - @JavaStaticField + @JavaStaticField(isFinal: true) public var DIRECTIONALITY_UNDEFINED: Int8 - @JavaStaticField + @JavaStaticField(isFinal: true) public var DIRECTIONALITY_LEFT_TO_RIGHT: Int8 - @JavaStaticField + @JavaStaticField(isFinal: true) public var DIRECTIONALITY_RIGHT_TO_LEFT: Int8 - @JavaStaticField + @JavaStaticField(isFinal: true) public var DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC: Int8 - @JavaStaticField + @JavaStaticField(isFinal: true) public var DIRECTIONALITY_EUROPEAN_NUMBER: Int8 - @JavaStaticField + @JavaStaticField(isFinal: true) public var DIRECTIONALITY_EUROPEAN_NUMBER_SEPARATOR: Int8 - @JavaStaticField + @JavaStaticField(isFinal: true) public var DIRECTIONALITY_EUROPEAN_NUMBER_TERMINATOR: Int8 - @JavaStaticField + @JavaStaticField(isFinal: true) public var DIRECTIONALITY_ARABIC_NUMBER: Int8 - @JavaStaticField + @JavaStaticField(isFinal: true) public var DIRECTIONALITY_COMMON_NUMBER_SEPARATOR: Int8 - @JavaStaticField + @JavaStaticField(isFinal: true) public var DIRECTIONALITY_NONSPACING_MARK: Int8 - @JavaStaticField + @JavaStaticField(isFinal: true) public var DIRECTIONALITY_BOUNDARY_NEUTRAL: Int8 - @JavaStaticField + @JavaStaticField(isFinal: true) public var DIRECTIONALITY_PARAGRAPH_SEPARATOR: Int8 - @JavaStaticField + @JavaStaticField(isFinal: true) public var DIRECTIONALITY_SEGMENT_SEPARATOR: Int8 - @JavaStaticField + @JavaStaticField(isFinal: true) public var DIRECTIONALITY_WHITESPACE: Int8 - @JavaStaticField + @JavaStaticField(isFinal: true) public var DIRECTIONALITY_OTHER_NEUTRALS: Int8 - @JavaStaticField + @JavaStaticField(isFinal: true) public var DIRECTIONALITY_LEFT_TO_RIGHT_EMBEDDING: Int8 - @JavaStaticField + @JavaStaticField(isFinal: true) public var DIRECTIONALITY_LEFT_TO_RIGHT_OVERRIDE: Int8 - @JavaStaticField + @JavaStaticField(isFinal: true) public var DIRECTIONALITY_RIGHT_TO_LEFT_EMBEDDING: Int8 - @JavaStaticField + @JavaStaticField(isFinal: true) public var DIRECTIONALITY_RIGHT_TO_LEFT_OVERRIDE: Int8 - @JavaStaticField + @JavaStaticField(isFinal: true) public var DIRECTIONALITY_POP_DIRECTIONAL_FORMAT: Int8 - @JavaStaticField + @JavaStaticField(isFinal: true) public var DIRECTIONALITY_LEFT_TO_RIGHT_ISOLATE: Int8 - @JavaStaticField + @JavaStaticField(isFinal: true) public var DIRECTIONALITY_RIGHT_TO_LEFT_ISOLATE: Int8 - @JavaStaticField + @JavaStaticField(isFinal: true) public var DIRECTIONALITY_FIRST_STRONG_ISOLATE: Int8 - @JavaStaticField + @JavaStaticField(isFinal: true) public var DIRECTIONALITY_POP_DIRECTIONAL_ISOLATE: Int8 - @JavaStaticField + @JavaStaticField(isFinal: true) public var MIN_HIGH_SURROGATE: UInt16 - @JavaStaticField + @JavaStaticField(isFinal: true) public var MAX_HIGH_SURROGATE: UInt16 - @JavaStaticField + @JavaStaticField(isFinal: true) public var MIN_LOW_SURROGATE: UInt16 - @JavaStaticField + @JavaStaticField(isFinal: true) public var MAX_LOW_SURROGATE: UInt16 - @JavaStaticField + @JavaStaticField(isFinal: true) public var MIN_SURROGATE: UInt16 - @JavaStaticField + @JavaStaticField(isFinal: true) public var MAX_SURROGATE: UInt16 - @JavaStaticField + @JavaStaticField(isFinal: true) public var MIN_SUPPLEMENTARY_CODE_POINT: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var MIN_CODE_POINT: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var MAX_CODE_POINT: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var SIZE: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var BYTES: Int32 @JavaStaticMethod diff --git a/Sources/JavaKit/generated/JavaDouble.swift b/Sources/JavaKit/generated/JavaDouble.swift index 8d7a9abc..d5279a31 100644 --- a/Sources/JavaKit/generated/JavaDouble.swift +++ b/Sources/JavaKit/generated/JavaDouble.swift @@ -67,40 +67,40 @@ public struct JavaDouble { public func wait() throws } extension JavaClass { - @JavaStaticField + @JavaStaticField(isFinal: true) public var POSITIVE_INFINITY: Double - @JavaStaticField + @JavaStaticField(isFinal: true) public var NEGATIVE_INFINITY: Double - @JavaStaticField + @JavaStaticField(isFinal: true) public var NaN: Double - @JavaStaticField + @JavaStaticField(isFinal: true) public var MAX_VALUE: Double - @JavaStaticField + @JavaStaticField(isFinal: true) public var MIN_NORMAL: Double - @JavaStaticField + @JavaStaticField(isFinal: true) public var MIN_VALUE: Double - @JavaStaticField + @JavaStaticField(isFinal: true) public var SIZE: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var PRECISION: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var MAX_EXPONENT: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var MIN_EXPONENT: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var BYTES: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var TYPE: JavaClass? @JavaStaticMethod diff --git a/Sources/JavaKit/generated/JavaFloat.swift b/Sources/JavaKit/generated/JavaFloat.swift index 83672479..5ff972c2 100644 --- a/Sources/JavaKit/generated/JavaFloat.swift +++ b/Sources/JavaKit/generated/JavaFloat.swift @@ -70,40 +70,40 @@ public struct JavaFloat { public func wait() throws } extension JavaClass { - @JavaStaticField + @JavaStaticField(isFinal: true) public var POSITIVE_INFINITY: Float - @JavaStaticField + @JavaStaticField(isFinal: true) public var NEGATIVE_INFINITY: Float - @JavaStaticField + @JavaStaticField(isFinal: true) public var NaN: Float - @JavaStaticField + @JavaStaticField(isFinal: true) public var MAX_VALUE: Float - @JavaStaticField + @JavaStaticField(isFinal: true) public var MIN_NORMAL: Float - @JavaStaticField + @JavaStaticField(isFinal: true) public var MIN_VALUE: Float - @JavaStaticField + @JavaStaticField(isFinal: true) public var SIZE: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var PRECISION: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var MAX_EXPONENT: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var MIN_EXPONENT: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var BYTES: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var TYPE: JavaClass? @JavaStaticMethod diff --git a/Sources/JavaKit/generated/JavaInteger.swift b/Sources/JavaKit/generated/JavaInteger.swift index 09d27eed..f923016a 100644 --- a/Sources/JavaKit/generated/JavaInteger.swift +++ b/Sources/JavaKit/generated/JavaInteger.swift @@ -61,19 +61,19 @@ public struct JavaInteger { public func wait() throws } extension JavaClass { - @JavaStaticField + @JavaStaticField(isFinal: true) public var MIN_VALUE: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var MAX_VALUE: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var TYPE: JavaClass? - @JavaStaticField + @JavaStaticField(isFinal: true) public var SIZE: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var BYTES: Int32 @JavaStaticMethod diff --git a/Sources/JavaKit/generated/JavaLong.swift b/Sources/JavaKit/generated/JavaLong.swift index f2aa72bd..64aeed13 100644 --- a/Sources/JavaKit/generated/JavaLong.swift +++ b/Sources/JavaKit/generated/JavaLong.swift @@ -61,19 +61,19 @@ public struct JavaLong { public func wait() throws } extension JavaClass { - @JavaStaticField + @JavaStaticField(isFinal: true) public var MIN_VALUE: Int64 - @JavaStaticField + @JavaStaticField(isFinal: true) public var MAX_VALUE: Int64 - @JavaStaticField + @JavaStaticField(isFinal: true) public var TYPE: JavaClass? - @JavaStaticField + @JavaStaticField(isFinal: true) public var SIZE: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var BYTES: Int32 @JavaStaticMethod diff --git a/Sources/JavaKit/generated/JavaShort.swift b/Sources/JavaKit/generated/JavaShort.swift index b7c5de3f..6d5da70c 100644 --- a/Sources/JavaKit/generated/JavaShort.swift +++ b/Sources/JavaKit/generated/JavaShort.swift @@ -61,19 +61,19 @@ public struct JavaShort { public func wait() throws } extension JavaClass { - @JavaStaticField + @JavaStaticField(isFinal: true) public var MIN_VALUE: Int16 - @JavaStaticField + @JavaStaticField(isFinal: true) public var MAX_VALUE: Int16 - @JavaStaticField + @JavaStaticField(isFinal: true) public var TYPE: JavaClass? - @JavaStaticField + @JavaStaticField(isFinal: true) public var SIZE: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var BYTES: Int32 @JavaStaticMethod diff --git a/Sources/JavaKit/generated/JavaVoid.swift b/Sources/JavaKit/generated/JavaVoid.swift index f6e0f4a6..4baedada 100644 --- a/Sources/JavaKit/generated/JavaVoid.swift +++ b/Sources/JavaKit/generated/JavaVoid.swift @@ -31,6 +31,6 @@ public struct JavaVoid { public func wait() throws } extension JavaClass { - @JavaStaticField + @JavaStaticField(isFinal: true) public var TYPE: JavaClass? } diff --git a/Sources/JavaKitJar/generated/JarEntry.swift b/Sources/JavaKitJar/generated/JarEntry.swift index 5fae3e56..fa688559 100644 --- a/Sources/JavaKitJar/generated/JarEntry.swift +++ b/Sources/JavaKitJar/generated/JarEntry.swift @@ -95,129 +95,129 @@ public struct JarEntry { public func wait() throws } extension JavaClass { - @JavaStaticField + @JavaStaticField(isFinal: true) public var STORED: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var DEFLATED: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var LOCSIG: Int64 - @JavaStaticField + @JavaStaticField(isFinal: true) public var EXTSIG: Int64 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CENSIG: Int64 - @JavaStaticField + @JavaStaticField(isFinal: true) public var ENDSIG: Int64 - @JavaStaticField + @JavaStaticField(isFinal: true) public var LOCHDR: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var EXTHDR: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CENHDR: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var ENDHDR: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var LOCVER: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var LOCFLG: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var LOCHOW: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var LOCTIM: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var LOCCRC: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var LOCSIZ: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var LOCLEN: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var LOCNAM: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var LOCEXT: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var EXTCRC: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var EXTSIZ: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var EXTLEN: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CENVEM: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CENVER: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CENFLG: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CENHOW: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CENTIM: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CENCRC: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CENSIZ: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CENLEN: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CENNAM: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CENEXT: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CENCOM: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CENDSK: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CENATT: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CENATX: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CENOFF: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var ENDSUB: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var ENDTOT: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var ENDSIZ: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var ENDOFF: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var ENDCOM: Int32 } diff --git a/Sources/JavaKitJar/generated/JarFile.swift b/Sources/JavaKitJar/generated/JarFile.swift index 5dbfdcad..60f51883 100644 --- a/Sources/JavaKitJar/generated/JarFile.swift +++ b/Sources/JavaKitJar/generated/JarFile.swift @@ -63,132 +63,132 @@ public struct JarFile { public func wait() throws } extension JavaClass { - @JavaStaticField + @JavaStaticField(isFinal: true) public var MANIFEST_NAME: String - @JavaStaticField + @JavaStaticField(isFinal: true) public var OPEN_READ: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var OPEN_DELETE: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var LOCSIG: Int64 - @JavaStaticField + @JavaStaticField(isFinal: true) public var EXTSIG: Int64 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CENSIG: Int64 - @JavaStaticField + @JavaStaticField(isFinal: true) public var ENDSIG: Int64 - @JavaStaticField + @JavaStaticField(isFinal: true) public var LOCHDR: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var EXTHDR: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CENHDR: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var ENDHDR: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var LOCVER: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var LOCFLG: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var LOCHOW: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var LOCTIM: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var LOCCRC: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var LOCSIZ: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var LOCLEN: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var LOCNAM: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var LOCEXT: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var EXTCRC: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var EXTSIZ: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var EXTLEN: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CENVEM: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CENVER: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CENFLG: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CENHOW: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CENTIM: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CENCRC: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CENSIZ: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CENLEN: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CENNAM: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CENEXT: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CENCOM: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CENDSK: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CENATT: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CENATX: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CENOFF: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var ENDSUB: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var ENDTOT: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var ENDSIZ: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var ENDOFF: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var ENDCOM: Int32 } diff --git a/Sources/JavaKitJar/generated/JarInputStream.swift b/Sources/JavaKitJar/generated/JarInputStream.swift index 467bb8f6..185636cd 100644 --- a/Sources/JavaKitJar/generated/JarInputStream.swift +++ b/Sources/JavaKitJar/generated/JarInputStream.swift @@ -80,123 +80,123 @@ public struct JarInputStream { public func wait() throws } extension JavaClass { - @JavaStaticField + @JavaStaticField(isFinal: true) public var LOCSIG: Int64 - @JavaStaticField + @JavaStaticField(isFinal: true) public var EXTSIG: Int64 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CENSIG: Int64 - @JavaStaticField + @JavaStaticField(isFinal: true) public var ENDSIG: Int64 - @JavaStaticField + @JavaStaticField(isFinal: true) public var LOCHDR: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var EXTHDR: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CENHDR: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var ENDHDR: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var LOCVER: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var LOCFLG: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var LOCHOW: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var LOCTIM: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var LOCCRC: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var LOCSIZ: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var LOCLEN: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var LOCNAM: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var LOCEXT: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var EXTCRC: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var EXTSIZ: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var EXTLEN: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CENVEM: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CENVER: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CENFLG: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CENHOW: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CENTIM: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CENCRC: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CENSIZ: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CENLEN: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CENNAM: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CENEXT: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CENCOM: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CENDSK: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CENATT: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CENATX: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CENOFF: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var ENDSUB: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var ENDTOT: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var ENDSIZ: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var ENDOFF: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var ENDCOM: Int32 } diff --git a/Sources/JavaKitJar/generated/JarOutputStream.swift b/Sources/JavaKitJar/generated/JarOutputStream.swift index fdfbbbaa..cc915fe6 100644 --- a/Sources/JavaKitJar/generated/JarOutputStream.swift +++ b/Sources/JavaKitJar/generated/JarOutputStream.swift @@ -62,129 +62,129 @@ public struct JarOutputStream { public func wait() throws } extension JavaClass { - @JavaStaticField + @JavaStaticField(isFinal: true) public var STORED: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var DEFLATED: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var LOCSIG: Int64 - @JavaStaticField + @JavaStaticField(isFinal: true) public var EXTSIG: Int64 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CENSIG: Int64 - @JavaStaticField + @JavaStaticField(isFinal: true) public var ENDSIG: Int64 - @JavaStaticField + @JavaStaticField(isFinal: true) public var LOCHDR: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var EXTHDR: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CENHDR: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var ENDHDR: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var LOCVER: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var LOCFLG: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var LOCHOW: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var LOCTIM: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var LOCCRC: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var LOCSIZ: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var LOCLEN: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var LOCNAM: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var LOCEXT: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var EXTCRC: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var EXTSIZ: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var EXTLEN: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CENVEM: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CENVER: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CENFLG: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CENHOW: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CENTIM: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CENCRC: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CENSIZ: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CENLEN: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CENNAM: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CENEXT: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CENCOM: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CENDSK: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CENATT: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CENATX: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var CENOFF: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var ENDSUB: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var ENDTOT: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var ENDSIZ: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var ENDOFF: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var ENDCOM: Int32 } diff --git a/Sources/JavaKitMacros/JavaFieldMacro.swift b/Sources/JavaKitMacros/JavaFieldMacro.swift index d9c7929f..cb85d352 100644 --- a/Sources/JavaKitMacros/JavaFieldMacro.swift +++ b/Sources/JavaKitMacros/JavaFieldMacro.swift @@ -46,14 +46,31 @@ extension JavaFieldMacro: AccessorMacro { fieldNameAsWritten } + let createSetter = + if case .argumentList(let arguments) = node.arguments, + let wrapperIsBoolean = arguments.first(where: { $0.label?.text == "isFinal" })?.expression, + let booleanLiteral = wrapperIsBoolean.as(BooleanLiteralExprSyntax.self) + { + booleanLiteral.literal.text == "false" // Create the setter if we are not final + } else { + true + } + let getter: AccessorDeclSyntax = """ get { self[javaFieldName: \(literal: fieldName), fieldType: \(fieldType).self] } """ - let setter: AccessorDeclSyntax = """ - nonmutating set { self[javaFieldName: \(literal: fieldName), fieldType: \(fieldType).self] = newValue } - """ + var accessors: [AccessorDeclSyntax] = [ + getter + ] + + if createSetter { + let setter: AccessorDeclSyntax = """ + nonmutating set { self[javaFieldName: \(literal: fieldName), fieldType: \(fieldType).self] = newValue } + """ + accessors.append(setter) + } - return [getter, setter] + return accessors } } diff --git a/Sources/JavaKitReflection/Field+Utilities.swift b/Sources/JavaKitReflection/Field+Utilities.swift index 1f803bac..0fc1b2be 100644 --- a/Sources/JavaKitReflection/Field+Utilities.swift +++ b/Sources/JavaKitReflection/Field+Utilities.swift @@ -17,4 +17,9 @@ extension Field { public var isStatic: Bool { return (getModifiers() & 0x08) != 0 } + + /// Whether this is a 'final' field. + public var isFinal: Bool { + return (getModifiers() & 16) != 0 + } } diff --git a/Sources/JavaKitReflection/generated/Constructor.swift b/Sources/JavaKitReflection/generated/Constructor.swift index f3d1bb55..58ac5690 100644 --- a/Sources/JavaKitReflection/generated/Constructor.swift +++ b/Sources/JavaKitReflection/generated/Constructor.swift @@ -123,10 +123,10 @@ public struct Constructor { public func wait() throws } extension JavaClass { - @JavaStaticField + @JavaStaticField(isFinal: true) public var PUBLIC: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var DECLARED: Int32 @JavaStaticMethod diff --git a/Sources/JavaKitReflection/generated/Executable.swift b/Sources/JavaKitReflection/generated/Executable.swift index 4c337cbe..6f1fa6d8 100644 --- a/Sources/JavaKitReflection/generated/Executable.swift +++ b/Sources/JavaKitReflection/generated/Executable.swift @@ -120,10 +120,10 @@ public struct Executable { public func wait() throws } extension JavaClass { - @JavaStaticField + @JavaStaticField(isFinal: true) public var PUBLIC: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var DECLARED: Int32 @JavaStaticMethod diff --git a/Sources/JavaKitReflection/generated/Field.swift b/Sources/JavaKitReflection/generated/Field.swift index 72ab10a9..d68700b3 100644 --- a/Sources/JavaKitReflection/generated/Field.swift +++ b/Sources/JavaKitReflection/generated/Field.swift @@ -147,10 +147,10 @@ public struct Field { public func wait() throws } extension JavaClass { - @JavaStaticField + @JavaStaticField(isFinal: true) public var PUBLIC: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var DECLARED: Int32 @JavaStaticMethod diff --git a/Sources/JavaKitReflection/generated/Method.swift b/Sources/JavaKitReflection/generated/Method.swift index 2c6e1a46..74e74e10 100644 --- a/Sources/JavaKitReflection/generated/Method.swift +++ b/Sources/JavaKitReflection/generated/Method.swift @@ -138,10 +138,10 @@ public struct Method { public func wait() throws } extension JavaClass { - @JavaStaticField + @JavaStaticField(isFinal: true) public var PUBLIC: Int32 - @JavaStaticField + @JavaStaticField(isFinal: true) public var DECLARED: Int32 @JavaStaticMethod diff --git a/Tests/Java2SwiftTests/Java2SwiftTests.swift b/Tests/Java2SwiftTests/Java2SwiftTests.swift index a2e3cb34..0217bd7d 100644 --- a/Tests/Java2SwiftTests/Java2SwiftTests.swift +++ b/Tests/Java2SwiftTests/Java2SwiftTests.swift @@ -75,7 +75,7 @@ class Java2SwiftTests: XCTestCase { } """, """ - @JavaStaticField + @JavaStaticField(isFinal: true) public var APRIL: Month? """ ]) diff --git a/Tests/JavaKitMacroTests/JavaClassMacroTests.swift b/Tests/JavaKitMacroTests/JavaClassMacroTests.swift index 82792df6..e033bc0f 100644 --- a/Tests/JavaKitMacroTests/JavaClassMacroTests.swift +++ b/Tests/JavaKitMacroTests/JavaClassMacroTests.swift @@ -41,6 +41,9 @@ class JavaKitMacroTests: XCTestCase { @JavaField public var myField: Int64 + + @JavaField(isFinal: true) + public var myFinalField: Int64 } """, expandedSource: """ @@ -73,6 +76,11 @@ class JavaKitMacroTests: XCTestCase { self[javaFieldName: "myField", fieldType: Int64.self] = newValue } } + public var myFinalField: Int64 { + get { + self[javaFieldName: "myFinalField", fieldType: Int64.self] + } + } /// The full Java class name for this Swift type. public static var fullJavaClassName: String { From ec760841096d33ae933cbfb6d1ca874754bae513 Mon Sep 17 00:00:00 2001 From: Jack Rosen Date: Sat, 26 Oct 2024 10:46:50 -0400 Subject: [PATCH 127/426] Add Support for Nested Classes (#115) * First pass * Keep going * Add Tests for Subclasses * Fix issues with nested classes * Remove $ checks * Correctly support $ * remove tick * Add Subclass Generated * Update enums and tests * Fix incorrect comment * Some pr feedback --- Sources/Java2Swift/JavaToSwift.swift | 45 +++++++-- Sources/Java2SwiftLib/JavaTranslator.swift | 40 ++++++-- Sources/JavaKitJar/generated/Attributes.swift | 92 +++++++++++++++++++ Tests/Java2SwiftTests/Java2SwiftTests.swift | 41 ++++++++- 4 files changed, 197 insertions(+), 21 deletions(-) diff --git a/Sources/Java2Swift/JavaToSwift.swift b/Sources/Java2Swift/JavaToSwift.swift index 80058ccd..86d3cf8d 100644 --- a/Sources/Java2Swift/JavaToSwift.swift +++ b/Sources/Java2Swift/JavaToSwift.swift @@ -228,12 +228,27 @@ struct JavaToSwift: ParsableCommand { // Note that we will be translating this Java class, so it is a known class. translator.translatedClasses[javaClassName] = (translatedSwiftName, nil, true) + + var classes: [JavaClass?] = javaClass.getClasses() + + // Go through all subclasses to find all of the classes to translate + while let internalClass = classes.popLast() { + if let internalClass { + let (javaName, swiftName) = names(from: internalClass.getName()) + // If we have already been through this class, don't go through it again + guard translator.translatedClasses[javaName] == nil else { continue } + let currentClassName = swiftName + let currentSanitizedClassName = currentClassName.replacing("$", with: ".") + classes.append(contentsOf: internalClass.getClasses()) + translator.translatedClasses[javaName] = (currentSanitizedClassName, nil, true) + } + } } // Translate all of the Java classes into Swift classes. for javaClass in javaClasses { translator.startNewFile() - let swiftClassDecls = translator.translateClass(javaClass) + let swiftClassDecls = try translator.translateClass(javaClass) let importDecls = translator.getImportDecls() let swiftFileText = """ @@ -247,11 +262,32 @@ struct JavaToSwift: ParsableCommand { try writeContents( swiftFileText, to: swiftFileName, - description: "Java class '\(javaClass.getCanonicalName())' translation" + description: "Java class '\(javaClass.getName())' translation" ) } } + private func names(from javaClassNameOpt: String) -> (javaClassName: String, swiftName: String) { + let javaClassName: String + let swiftName: String + if let equalLoc = javaClassNameOpt.firstIndex(of: "=") { + let afterEqual = javaClassNameOpt.index(after: equalLoc) + javaClassName = String(javaClassNameOpt[..) -> [DeclSyntax] { - let fullName = javaClass.getCanonicalName() - let swiftTypeName = try! getSwiftTypeNameFromJavaClassName(fullName) + package func translateClass(_ javaClass: JavaClass) throws -> [DeclSyntax] { + let fullName = javaClass.getName() + let swiftTypeName = try getSwiftTypeNameFromJavaClassName(fullName) + let (swiftParentType, swiftInnermostTypeName) = swiftTypeName.splitSwiftTypeName() + + // If the swift parent type has not been translated, don't try to translate this one + if let swiftParentType, + !translatedClasses.contains(where: { _, value in value.swiftType == swiftParentType }) + { + logUntranslated("Unable to translate '\(fullName)' parent class: \(swiftParentType) not found") + return [] + } // Superclass. let extends: String if !javaClass.isInterface(), let superclass = javaClass.getSuperclass(), - superclass.getCanonicalName() != "java.lang.Object" + superclass.getName() != "java.lang.Object" { do { extends = ", extends: \(try getSwiftTypeName(superclass).swiftName).self" @@ -265,7 +274,7 @@ extension JavaTranslator { ) if !enumConstants.isEmpty { - let enumName = "\(swiftTypeName)Cases" + let enumName = "\(swiftInnermostTypeName)Cases" members.append( contentsOf: translateToEnumValue(name: enumName, enumFields: enumConstants) ) @@ -278,7 +287,7 @@ extension JavaTranslator { do { let implementedInSwift = constructor.isNative && constructor.getDeclaringClass()!.equals(javaClass.as(JavaObject.self)!) && - swiftNativeImplementations.contains(javaClass.getCanonicalName()) + swiftNativeImplementations.contains(javaClass.getName()) let translated = try translateConstructor( constructor, @@ -312,7 +321,7 @@ extension JavaTranslator { let implementedInSwift = method.isNative && method.getDeclaringClass()!.equals(javaClass.as(JavaObject.self)!) && - swiftNativeImplementations.contains(javaClass.getCanonicalName()) + swiftNativeImplementations.contains(javaClass.getName()) // Translate the method if we can. do { @@ -357,7 +366,6 @@ extension JavaTranslator { } // Emit the struct declaration describing the java class. - let (swiftParentType, swiftInnermostTypeName) = swiftTypeName.splitSwiftTypeName() let classOrInterface: String = javaClass.isInterface() ? "JavaInterface" : "JavaClass"; var classDecl = """ @@ -383,6 +391,20 @@ extension JavaTranslator { topLevelDecls.append(classDecl) + let subClassDecls = javaClass.getClasses().compactMap { + $0.flatMap { clazz in + do { + return try translateClass(clazz) + } catch { + logUntranslated("Unable to translate '\(fullName)' subclass '\(clazz.getName())': \(error)") + return nil + } + } + }.flatMap(\.self) + + topLevelDecls.append( + contentsOf: subClassDecls + ) // Translate static members. var staticMembers: [DeclSyntax] = [] @@ -438,7 +460,7 @@ extension JavaTranslator { // Members that are native and will instead go into a NativeMethods // protocol. var nativeMembers: [DeclSyntax] = [] - if swiftNativeImplementations.contains(javaClass.getCanonicalName()) { + if swiftNativeImplementations.contains(javaClass.getName()) { nativeMembers.append( contentsOf: javaClass.getDeclaredMethods().compactMap { $0.flatMap { method in diff --git a/Sources/JavaKitJar/generated/Attributes.swift b/Sources/JavaKitJar/generated/Attributes.swift index 22aa68a4..74a1352c 100644 --- a/Sources/JavaKitJar/generated/Attributes.swift +++ b/Sources/JavaKitJar/generated/Attributes.swift @@ -44,6 +44,9 @@ public struct Attributes { @JavaMethod public func getValue(_ arg0: String) -> String + @JavaMethod + public func getValue(_ arg0: Attributes.Name?) -> String + @JavaMethod public func isEmpty() -> Bool @@ -95,3 +98,92 @@ public struct Attributes { @JavaMethod public func getOrDefault(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject? } +extension Attributes { + @JavaClass("java.util.jar.Attributes$Name") + public struct Name { + @JavaMethod + public init(_ arg0: String, environment: JNIEnvironment? = nil) + + @JavaMethod + public func equals(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func toString() -> String + + @JavaMethod + public func hashCode() -> Int32 + + @JavaMethod + public func getClass() -> JavaClass? + + @JavaMethod + public func notify() + + @JavaMethod + public func notifyAll() + + @JavaMethod + public func wait(_ arg0: Int64) throws + + @JavaMethod + public func wait(_ arg0: Int64, _ arg1: Int32) throws + + @JavaMethod + public func wait() throws + } +} +extension JavaClass { + @JavaStaticField + public var MANIFEST_VERSION: Attributes.Name? + + @JavaStaticField + public var SIGNATURE_VERSION: Attributes.Name? + + @JavaStaticField + public var CONTENT_TYPE: Attributes.Name? + + @JavaStaticField + public var CLASS_PATH: Attributes.Name? + + @JavaStaticField + public var MAIN_CLASS: Attributes.Name? + + @JavaStaticField + public var SEALED: Attributes.Name? + + @JavaStaticField + public var EXTENSION_LIST: Attributes.Name? + + @JavaStaticField + public var EXTENSION_NAME: Attributes.Name? + + @JavaStaticField + public var EXTENSION_INSTALLATION: Attributes.Name? + + @JavaStaticField + public var IMPLEMENTATION_TITLE: Attributes.Name? + + @JavaStaticField + public var IMPLEMENTATION_VERSION: Attributes.Name? + + @JavaStaticField + public var IMPLEMENTATION_VENDOR: Attributes.Name? + + @JavaStaticField + public var IMPLEMENTATION_VENDOR_ID: Attributes.Name? + + @JavaStaticField + public var IMPLEMENTATION_URL: Attributes.Name? + + @JavaStaticField + public var SPECIFICATION_TITLE: Attributes.Name? + + @JavaStaticField + public var SPECIFICATION_VERSION: Attributes.Name? + + @JavaStaticField + public var SPECIFICATION_VENDOR: Attributes.Name? + + @JavaStaticField + public var MULTI_RELEASE: Attributes.Name? +} diff --git a/Tests/Java2SwiftTests/Java2SwiftTests.swift b/Tests/Java2SwiftTests/Java2SwiftTests.swift index 0217bd7d..5a4e8e33 100644 --- a/Tests/Java2SwiftTests/Java2SwiftTests.swift +++ b/Tests/Java2SwiftTests/Java2SwiftTests.swift @@ -24,9 +24,9 @@ var jvm: JavaVirtualMachine { } @JavaClass("java.time.Month") -public struct JavaMonth { - -} +public struct JavaMonth {} +@JavaClass("java.lang.ProcessBuilder") +struct ProcessBuilder {} class Java2SwiftTests: XCTestCase { func testJavaLangObjectMapping() throws { @@ -114,6 +114,36 @@ class Java2SwiftTests: XCTestCase { ] ) } + + func testNestedSubclasses() throws { + try assertTranslatedClass( + ProcessBuilder.self, + swiftTypeName: "ProcessBuilder", + translatedClasses: [ + "java.lang.ProcessBuilder": ("ProcessBuilder", nil, true), + "java.lang.ProcessBuilder$Redirect": ("ProcessBuilder.Redirect", nil, true), + "java.lang.ProcessBuilder$Redirect$Type": ("ProcessBuilder.Redirect.Type", nil, true), + ], + expectedChunks: [ + "import JavaKit", + """ + @JavaMethod + public func redirectInput() -> ProcessBuilder.Redirect? + """, + """ + extension ProcessBuilder { + @JavaClass("java.lang.ProcessBuilder$Redirect") + public struct Redirect { + """, + """ + extension ProcessBuilder.Redirect { + @JavaClass("java.lang.ProcessBuilder$Redirect$Type") + public struct Type { + """ + ] + ) + } + } @JavaClass("java.util.ArrayList") @@ -145,9 +175,10 @@ func assertTranslatedClass( translator.translatedClasses = translatedClasses translator.translatedClasses[javaType.fullJavaClassName] = (swiftTypeName, nil, true) + translator.startNewFile() - let translatedDecls = translator.translateClass( - try JavaClass( + let translatedDecls = try translator.translateClass( + JavaClass( javaThis: javaType.getJNIClass(in: environment), environment: environment) ) From 97473d9a5e443d302512adc23f79810848645ada Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Sat, 26 Oct 2024 18:18:35 -0700 Subject: [PATCH 128/426] Make nested classes explicitly-specifiable and work through some integration issues (#118) * Java2Swift: Add a test for a generic static method * Drop the "canonicalClassName" from JavaTypes because it is now incorrect We're using the "normal" name now that uses $ for nested classes. * Remove dead code behind a `#if false` * Teach the Java2Swift plugin to match the nested type naming scheme for Java2Swift * Regenerate java.util.jar.Attributes with the "isFinal" change * Java2Swift: Drive recursion into nested subclasses from the outside Rather than having the Java-to-Swift translator walking all nested classes itself, provide it with the set of nested classes that should be translated along with the enclosing class. This allows us to be explicit about the naming of nested classes in the config file (where we want to), while still getting the convenience of translating the nested classes automatically for you by default. * Update JavaSieve example now that we're handling nested classes * Java2Swift: Use the parent's Swift type name to form nested type names * Escape member types named "Type" * Work around issues with Java classes named "Type" by renaming them "JavaType" This is deeply unfortunate, but we need compile-side fixes for nested types named "Type" to work. --- .../Java2SwiftPlugin/Java2SwiftPlugin.swift | 3 +- .../Sources/JavaSieve/Java2Swift.config | 1 + Sources/Java2Swift/JavaToSwift.swift | 121 ++++++++++++------ Sources/Java2SwiftLib/JavaTranslator.swift | 63 +++++++-- Sources/JavaKit/Optional+JavaObject.swift | 2 +- Sources/JavaKitJar/generated/Attributes.swift | 36 +++--- Sources/JavaTypes/JavaType+JavaSource.swift | 2 +- Sources/JavaTypes/JavaType.swift | 4 +- Sources/JavaTypes/Mangling.swift | 2 +- Tests/Java2SwiftTests/Java2SwiftTests.swift | 85 +++++++++++- 10 files changed, 242 insertions(+), 77 deletions(-) diff --git a/Plugins/Java2SwiftPlugin/Java2SwiftPlugin.swift b/Plugins/Java2SwiftPlugin/Java2SwiftPlugin.swift index 37ee1b3a..452ec8b3 100644 --- a/Plugins/Java2SwiftPlugin/Java2SwiftPlugin.swift +++ b/Plugins/Java2SwiftPlugin/Java2SwiftPlugin.swift @@ -90,7 +90,8 @@ struct Java2SwiftBuildToolPlugin: BuildToolPlugin { /// Determine the set of Swift files that will be emitted by the Java2Swift /// tool. let outputSwiftFiles = config.classes.map { (javaClassName, swiftName) in - outputDirectory.appending(path: "\(swiftName).swift") + let swiftNestedName = swiftName.replacingOccurrences(of: ".", with: "+") + return outputDirectory.appending(path: "\(swiftNestedName).swift") } // Find the Java .class files generated from prior plugins. diff --git a/Samples/JavaSieve/Sources/JavaSieve/Java2Swift.config b/Samples/JavaSieve/Sources/JavaSieve/Java2Swift.config index aa88865f..61d5cb31 100644 --- a/Samples/JavaSieve/Sources/JavaSieve/Java2Swift.config +++ b/Samples/JavaSieve/Sources/JavaSieve/Java2Swift.config @@ -20,6 +20,7 @@ "com.gazman.quadratic_sieve.data.VectorWorkData" : "VectorWorkData", "com.gazman.quadratic_sieve.debug.Analytics" : "Analytics", "com.gazman.quadratic_sieve.debug.AssertUtils" : "AssertUtils", + "com.gazman.quadratic_sieve.debug.AssertUtils$Tester" : "AssertUtils.Tester", "com.gazman.quadratic_sieve.debug.Logger" : "Logger", "com.gazman.quadratic_sieve.fact.TrivialDivision" : "TrivialDivision", "com.gazman.quadratic_sieve.primes.BigPrimes" : "BigPrimes", diff --git a/Sources/Java2Swift/JavaToSwift.swift b/Sources/Java2Swift/JavaToSwift.swift index 86d3cf8d..205c6a43 100644 --- a/Sources/Java2Swift/JavaToSwift.swift +++ b/Sources/Java2Swift/JavaToSwift.swift @@ -201,18 +201,9 @@ struct JavaToSwift: ParsableCommand { // Add the configuration for this module. translator.addConfiguration(config, forSwiftModule: moduleName) - // Load all of the requested classes. - #if false - let classLoader = URLClassLoader( - [ - try URL("file://\(classPath)", environment: environment) - ], - environment: environment - ) - #else + // Load all of the explicitly-requested classes. let classLoader = try JavaClass(environment: environment) .getSystemClassLoader()! - #endif var javaClasses: [JavaClass] = [] for (javaClassName, swiftName) in config.classes { guard let javaClass = try classLoader.loadClass(javaClassName) else { @@ -220,29 +211,59 @@ struct JavaToSwift: ParsableCommand { continue } + // Add this class to the list of classes we'll translate. javaClasses.append(javaClass) + } + + // Find all of the nested classes for each class, adding them to the list + // of classes to be translated if they were already specified. + var allClassesToVisit = javaClasses + var currentClassIndex: Int = 0 + while currentClassIndex < allClassesToVisit.count { + defer { + currentClassIndex += 1 + } + + // The current class we're in. + let currentClass = allClassesToVisit[currentClassIndex] + guard let currentSwiftName = translator.translatedClasses[currentClass.getName()]?.swiftType else { + continue + } + + // Find all of the nested classes that weren't explicitly translated + // already. + let nestedClasses: [JavaClass] = currentClass.getClasses().compactMap { nestedClass in + guard let nestedClass else { return nil } - // Replace any $'s within the Java class name (which separate nested - // classes) with .'s (which represent nesting in Swift). - let translatedSwiftName = swiftName.replacing("$", with: ".") - - // Note that we will be translating this Java class, so it is a known class. - translator.translatedClasses[javaClassName] = (translatedSwiftName, nil, true) - - var classes: [JavaClass?] = javaClass.getClasses() - - // Go through all subclasses to find all of the classes to translate - while let internalClass = classes.popLast() { - if let internalClass { - let (javaName, swiftName) = names(from: internalClass.getName()) - // If we have already been through this class, don't go through it again - guard translator.translatedClasses[javaName] == nil else { continue } - let currentClassName = swiftName - let currentSanitizedClassName = currentClassName.replacing("$", with: ".") - classes.append(contentsOf: internalClass.getClasses()) - translator.translatedClasses[javaName] = (currentSanitizedClassName, nil, true) + // If this is a local class, we're done. + let javaClassName = nestedClass.getName() + if javaClassName.isLocalJavaClass { + return nil } + + // If this class has been explicitly mentioned, we're done. + if translator.translatedClasses[javaClassName] != nil { + return nil + } + + // Record this as a translated class. + let swiftUnqualifiedName = javaClassName.javaClassNameToCanonicalName + .defaultSwiftNameForJavaClass + + + let swiftName = "\(currentSwiftName).\(swiftUnqualifiedName)" + translator.translatedClasses[javaClassName] = (swiftName, nil, true) + return nestedClass + } + + // If there were no new nested classes, there's nothing to do. + if nestedClasses.isEmpty { + continue } + + // Record all of the nested classes that we will visit. + translator.nestedClasses[currentClass.getName()] = nestedClasses + allClassesToVisit.append(contentsOf: nestedClasses) } // Translate all of the Java classes into Swift classes. @@ -285,7 +306,7 @@ struct JavaToSwift: ParsableCommand { javaClassName = javaClassNameOpt } - return (javaClassName, swiftName) + return (javaClassName, swiftName.javaClassNameToCanonicalName) } mutating func writeContents(_ contents: String, to filename: String, description: String) throws { @@ -326,12 +347,9 @@ struct JavaToSwift: ParsableCommand { continue } - // If any of the segments of the Java name start with a number, it's a - // local class that cannot be mapped into Swift. - for segment in entry.getName().split(separator: "$") { - if let firstChar = segment.first, firstChar.isNumber { - continue - } + // If this is a local class, it cannot be mapped into Swift. + if entry.getName().isLocalJavaClass { + continue } let javaCanonicalName = String(entry.getName().replacing("/", with: ".") @@ -374,10 +392,10 @@ extension String { fileprivate var defaultSwiftNameForJavaClass: String { if let dotLoc = lastIndex(of: ".") { let afterDot = index(after: dotLoc) - return String(self[afterDot...]) + return String(self[afterDot...]).javaClassNameToCanonicalName.adjustedSwiftTypeName } - return self + return javaClassNameToCanonicalName.adjustedSwiftTypeName } } @@ -391,3 +409,30 @@ extension JavaClass { @JavaStaticMethod public func getSystemClassLoader() -> ClassLoader? } + +extension String { + /// Replace all of the $'s for nested names with "." to turn a Java class + /// name into a Java canonical class name, + fileprivate var javaClassNameToCanonicalName: String { + return replacing("$", with: ".") + } + + /// Whether this is the name of an anonymous class. + fileprivate var isLocalJavaClass: Bool { + for segment in split(separator: "$") { + if let firstChar = segment.first, firstChar.isNumber { + return true + } + } + + return false + } + + /// Adjust type name for "bad" type names that don't work well in Swift. + fileprivate var adjustedSwiftTypeName: String { + switch self { + case "Type": return "JavaType" + default: return self + } + } +} diff --git a/Sources/Java2SwiftLib/JavaTranslator.swift b/Sources/Java2SwiftLib/JavaTranslator.swift index e5890e2a..9a9a5b4d 100644 --- a/Sources/Java2SwiftLib/JavaTranslator.swift +++ b/Sources/Java2SwiftLib/JavaTranslator.swift @@ -43,6 +43,12 @@ package class JavaTranslator { /// methods will be implemented in Swift. package var swiftNativeImplementations: Set = [] + /// The set of nested classes that we should traverse from the given class, + /// indexed by the name of the class. + /// + /// TODO: Make JavaClass Hashable so we can index by the object? + package var nestedClasses: [String: [JavaClass]] = [:] + package init( swiftModuleName: String, environment: JNIEnvironment, @@ -79,7 +85,6 @@ extension JavaTranslator { /// itself. This should only be used to refer to types that are built-in to /// JavaKit and therefore aren't captured in any configuration file. package static let defaultTranslatedClasses: [String: (swiftType: String, swiftModule: String?, isOptional: Bool)] = [ - "java.lang.Class": ("JavaClass", "JavaKit", true), "java.lang.String": ("String", "JavaKit", false), ] } @@ -165,19 +170,28 @@ extension JavaTranslator { let javaType = try JavaType(javaTypeName: javaClass.getName()) let isSwiftOptional = javaType.isSwiftOptional return ( - try javaType.swiftTypeName(resolver: self.getSwiftTypeNameFromJavaClassName(_:)), + try javaType.swiftTypeName { javaClassName in + try self.getSwiftTypeNameFromJavaClassName(javaClassName) + }, isSwiftOptional ) } /// Map a Java class name to its corresponding Swift type. - private func getSwiftTypeNameFromJavaClassName(_ name: String) throws -> String { + private func getSwiftTypeNameFromJavaClassName( + _ name: String, + escapeMemberNames: Bool = true + ) throws -> String { if let translated = translatedClasses[name] { // Note that we need to import this Swift module. if let swiftModule = translated.swiftModule, swiftModule != swiftModuleName { importedSwiftModules.insert(swiftModule) } + if escapeMemberNames { + return translated.swiftType.escapingSwiftMemberNames + } + return translated.swiftType } @@ -192,7 +206,7 @@ extension JavaTranslator { /// JavaClass to house static methods. package func translateClass(_ javaClass: JavaClass) throws -> [DeclSyntax] { let fullName = javaClass.getName() - let swiftTypeName = try getSwiftTypeNameFromJavaClassName(fullName) + let swiftTypeName = try getSwiftTypeNameFromJavaClassName(fullName, escapeMemberNames: false) let (swiftParentType, swiftInnermostTypeName) = swiftTypeName.splitSwiftTypeName() // If the swift parent type has not been translated, don't try to translate this one @@ -391,14 +405,12 @@ extension JavaTranslator { topLevelDecls.append(classDecl) - let subClassDecls = javaClass.getClasses().compactMap { - $0.flatMap { clazz in - do { - return try translateClass(clazz) - } catch { - logUntranslated("Unable to translate '\(fullName)' subclass '\(clazz.getName())': \(error)") - return nil - } + let subClassDecls = (nestedClasses[fullName] ?? []).compactMap { clazz in + do { + return try translateClass(clazz) + } catch { + logUntranslated("Unable to translate '\(fullName)' subclass '\(clazz.getName())': \(error)") + return nil } }.flatMap(\.self) @@ -633,3 +645,30 @@ extension JavaTranslator { } } } + +extension String { + /// Escape Swift types that involve member name references like '.Type' + fileprivate var escapingSwiftMemberNames: String { + var count = 0 + return split(separator: ".").map { component in + defer { + count += 1 + } + + if count > 0 && component.memberRequiresBackticks { + return "`\(component)`" + } + + return String(component) + }.joined(separator: ".") + } +} + +extension Substring { + fileprivate var memberRequiresBackticks: Bool { + switch self { + case "Type": return true + default: return false + } + } +} diff --git a/Sources/JavaKit/Optional+JavaObject.swift b/Sources/JavaKit/Optional+JavaObject.swift index 55ad366e..b2f115db 100644 --- a/Sources/JavaKit/Optional+JavaObject.swift +++ b/Sources/JavaKit/Optional+JavaObject.swift @@ -37,7 +37,7 @@ extension Optional: JavaValue where Wrapped: AnyJavaObject { } public static var javaType: JavaType { - JavaType(canonicalClassName: Wrapped.fullJavaClassName) + JavaType(className: Wrapped.fullJavaClassName) } public static func jniMethodCall( diff --git a/Sources/JavaKitJar/generated/Attributes.swift b/Sources/JavaKitJar/generated/Attributes.swift index 74a1352c..8e3d0ca9 100644 --- a/Sources/JavaKitJar/generated/Attributes.swift +++ b/Sources/JavaKitJar/generated/Attributes.swift @@ -133,57 +133,57 @@ extension Attributes { } } extension JavaClass { - @JavaStaticField + @JavaStaticField(isFinal: true) public var MANIFEST_VERSION: Attributes.Name? - @JavaStaticField + @JavaStaticField(isFinal: true) public var SIGNATURE_VERSION: Attributes.Name? - @JavaStaticField + @JavaStaticField(isFinal: true) public var CONTENT_TYPE: Attributes.Name? - @JavaStaticField + @JavaStaticField(isFinal: true) public var CLASS_PATH: Attributes.Name? - @JavaStaticField + @JavaStaticField(isFinal: true) public var MAIN_CLASS: Attributes.Name? - @JavaStaticField + @JavaStaticField(isFinal: true) public var SEALED: Attributes.Name? - @JavaStaticField + @JavaStaticField(isFinal: true) public var EXTENSION_LIST: Attributes.Name? - @JavaStaticField + @JavaStaticField(isFinal: true) public var EXTENSION_NAME: Attributes.Name? - @JavaStaticField + @JavaStaticField(isFinal: true) public var EXTENSION_INSTALLATION: Attributes.Name? - @JavaStaticField + @JavaStaticField(isFinal: true) public var IMPLEMENTATION_TITLE: Attributes.Name? - @JavaStaticField + @JavaStaticField(isFinal: true) public var IMPLEMENTATION_VERSION: Attributes.Name? - @JavaStaticField + @JavaStaticField(isFinal: true) public var IMPLEMENTATION_VENDOR: Attributes.Name? - @JavaStaticField + @JavaStaticField(isFinal: true) public var IMPLEMENTATION_VENDOR_ID: Attributes.Name? - @JavaStaticField + @JavaStaticField(isFinal: true) public var IMPLEMENTATION_URL: Attributes.Name? - @JavaStaticField + @JavaStaticField(isFinal: true) public var SPECIFICATION_TITLE: Attributes.Name? - @JavaStaticField + @JavaStaticField(isFinal: true) public var SPECIFICATION_VERSION: Attributes.Name? - @JavaStaticField + @JavaStaticField(isFinal: true) public var SPECIFICATION_VENDOR: Attributes.Name? - @JavaStaticField + @JavaStaticField(isFinal: true) public var MULTI_RELEASE: Attributes.Name? } diff --git a/Sources/JavaTypes/JavaType+JavaSource.swift b/Sources/JavaTypes/JavaType+JavaSource.swift index e1fa8129..ccb4e96b 100644 --- a/Sources/JavaTypes/JavaType+JavaSource.swift +++ b/Sources/JavaTypes/JavaType+JavaSource.swift @@ -32,7 +32,7 @@ extension JavaType { self = try JavaType(mangledName: name) case let className: - self = JavaType(canonicalClassName: className) + self = JavaType(className: className) } } } diff --git a/Sources/JavaTypes/JavaType.swift b/Sources/JavaTypes/JavaType.swift index 80364b5b..6c5f5357 100644 --- a/Sources/JavaTypes/JavaType.swift +++ b/Sources/JavaTypes/JavaType.swift @@ -31,9 +31,9 @@ public enum JavaType: Equatable, Hashable { /// A Java array. indirect case array(JavaType) - /// Given a canonical class name such as "java.lang.Object", split it into + /// Given a class name such as "java.lang.Object", split it into /// its package and class name to form a class instance. - public init(canonicalClassName name: some StringProtocol) { + public init(className name: some StringProtocol) { if let lastDot = name.lastIndex(of: ".") { self = .class( package: String(name[...self, + swiftTypeName: "MyJavaClass", + translatedClasses: [ + "java.lang.Object": ("JavaObject", nil, true), + "java.lang.String": ("JavaString", nil, true), + ], + expectedChunks: [ + "import JavaKit", + """ + @JavaClass("java.lang.Class") + public struct MyJavaClass { + """, + """ + @JavaStaticMethod + public func forName(_ arg0: JavaString) throws -> MyJavaClass? where ObjectType == MyJavaClass + """, + ] + ) + } + func testEnum() throws { try assertTranslatedClass( JavaMonth.self, @@ -124,6 +153,10 @@ class Java2SwiftTests: XCTestCase { "java.lang.ProcessBuilder$Redirect": ("ProcessBuilder.Redirect", nil, true), "java.lang.ProcessBuilder$Redirect$Type": ("ProcessBuilder.Redirect.Type", nil, true), ], + nestedClasses: [ + "java.lang.ProcessBuilder": [JavaClass().as(JavaClass.self)!], + "java.lang.ProcessBuilder$Redirect": [JavaClass().as(JavaClass.self)!], + ], expectedChunks: [ "import JavaKit", """ @@ -136,14 +169,60 @@ class Java2SwiftTests: XCTestCase { public struct Redirect { """, """ + public func redirectError() -> ProcessBuilder.Redirect? + """, + """ extension ProcessBuilder.Redirect { @JavaClass("java.lang.ProcessBuilder$Redirect$Type") public struct Type { + """, """ + @JavaMethod + public func type() -> ProcessBuilder.Redirect.`Type`? + """, ] ) } + func testNestedRenamedSubclasses() throws { + try assertTranslatedClass( + ProcessBuilder.self, + swiftTypeName: "ProcessBuilder", + translatedClasses: [ + "java.lang.ProcessBuilder": ("ProcessBuilder", nil, true), + "java.lang.ProcessBuilder$Redirect": ("ProcessBuilder.PBRedirect", nil, true), + "java.lang.ProcessBuilder$Redirect$Type": ("ProcessBuilder.PBRedirect.JavaType", nil, true), + ], + nestedClasses: [ + "java.lang.ProcessBuilder": [JavaClass().as(JavaClass.self)!], + "java.lang.ProcessBuilder$Redirect": [JavaClass().as(JavaClass.self)!], + ], + expectedChunks: [ + "import JavaKit", + """ + @JavaMethod + public func redirectInput() -> ProcessBuilder.PBRedirect? + """, + """ + extension ProcessBuilder { + @JavaClass("java.lang.ProcessBuilder$Redirect") + public struct PBRedirect { + """, + """ + public func redirectError() -> ProcessBuilder.PBRedirect? + """, + """ + extension ProcessBuilder.PBRedirect { + @JavaClass("java.lang.ProcessBuilder$Redirect$Type") + public struct JavaType { + """, + """ + @JavaMethod + public func type() -> ProcessBuilder.PBRedirect.JavaType? + """ + ] + ) + } } @JavaClass("java.util.ArrayList") @@ -162,6 +241,7 @@ func assertTranslatedClass( translatedClasses: [ String: (swiftType: String, swiftModule: String?, isOptional: Bool) ] = JavaTranslator.defaultTranslatedClasses, + nestedClasses: [String: [JavaClass]] = [:], expectedChunks: [String], file: StaticString = #filePath, line: UInt = #line @@ -174,8 +254,7 @@ func assertTranslatedClass( translator.translatedClasses = translatedClasses translator.translatedClasses[javaType.fullJavaClassName] = (swiftTypeName, nil, true) - - + translator.nestedClasses = nestedClasses translator.startNewFile() let translatedDecls = try translator.translateClass( JavaClass( From 7baa992298f423b06145562f4bbf72a381a63ca1 Mon Sep 17 00:00:00 2001 From: Iain Smith Date: Sun, 27 Oct 2024 09:08:24 +0000 Subject: [PATCH 129/426] Generate JavaKitFunction module --- Makefile | 4 ++ Package.swift | 14 +++++ Sources/JavaKitFunction/Java2Swift.config | 51 +++++++++++++++++++ .../generated/JavaBiConsumer.swift | 14 +++++ .../generated/JavaBiFunction.swift | 14 +++++ .../generated/JavaBiPredicate.swift | 22 ++++++++ .../generated/JavaBinaryOperator.swift | 16 ++++++ .../generated/JavaBooleanSupplier.swift | 9 ++++ .../generated/JavaConsumer.swift | 12 +++++ .../generated/JavaDoubleBinaryOperator.swift | 9 ++++ .../generated/JavaDoubleConsumer.swift | 12 +++++ .../generated/JavaDoubleFunction.swift | 9 ++++ .../generated/JavaDoublePredicate.swift | 18 +++++++ .../generated/JavaDoubleSupplier.swift | 9 ++++ .../generated/JavaDoubleToIntFunction.swift | 9 ++++ .../generated/JavaDoubleToLongFunction.swift | 9 ++++ .../generated/JavaDoubleUnaryOperator.swift | 19 +++++++ .../generated/JavaFunction.swift | 25 +++++++++ .../generated/JavaIntBinaryOperator.swift | 9 ++++ .../generated/JavaIntConsumer.swift | 12 +++++ .../generated/JavaIntFunction.swift | 9 ++++ .../generated/JavaIntPredicate.swift | 18 +++++++ .../generated/JavaIntSupplier.swift | 9 ++++ .../generated/JavaIntToDoubleFunction.swift | 9 ++++ .../generated/JavaIntToLongFunction.swift | 9 ++++ .../generated/JavaIntUnaryOperator.swift | 19 +++++++ .../generated/JavaLongBinaryOperator.swift | 9 ++++ .../generated/JavaLongConsumer.swift | 12 +++++ .../generated/JavaLongFunction.swift | 9 ++++ .../generated/JavaLongPredicate.swift | 18 +++++++ .../generated/JavaLongSupplier.swift | 9 ++++ .../generated/JavaLongToDoubleFunction.swift | 9 ++++ .../generated/JavaLongToIntFunction.swift | 9 ++++ .../generated/JavaLongUnaryOperator.swift | 19 +++++++ .../generated/JavaObjDoubleConsumer.swift | 9 ++++ .../generated/JavaObjIntConsumer.swift | 9 ++++ .../generated/JavaObjLongConsumer.swift | 9 ++++ .../generated/JavaPredicate.swift | 28 ++++++++++ .../generated/JavaSupplier.swift | 9 ++++ .../generated/JavaToDoubleBiFunction.swift | 9 ++++ .../generated/JavaToDoubleFunction.swift | 9 ++++ .../generated/JavaToIntBiFunction.swift | 9 ++++ .../generated/JavaToIntFunction.swift | 9 ++++ .../generated/JavaToLongBiFunction.swift | 9 ++++ .../generated/JavaToLongFunction.swift | 9 ++++ .../generated/JavaUnaryOperator.swift | 25 +++++++++ 46 files changed, 606 insertions(+) create mode 100644 Sources/JavaKitFunction/Java2Swift.config create mode 100644 Sources/JavaKitFunction/generated/JavaBiConsumer.swift create mode 100644 Sources/JavaKitFunction/generated/JavaBiFunction.swift create mode 100644 Sources/JavaKitFunction/generated/JavaBiPredicate.swift create mode 100644 Sources/JavaKitFunction/generated/JavaBinaryOperator.swift create mode 100644 Sources/JavaKitFunction/generated/JavaBooleanSupplier.swift create mode 100644 Sources/JavaKitFunction/generated/JavaConsumer.swift create mode 100644 Sources/JavaKitFunction/generated/JavaDoubleBinaryOperator.swift create mode 100644 Sources/JavaKitFunction/generated/JavaDoubleConsumer.swift create mode 100644 Sources/JavaKitFunction/generated/JavaDoubleFunction.swift create mode 100644 Sources/JavaKitFunction/generated/JavaDoublePredicate.swift create mode 100644 Sources/JavaKitFunction/generated/JavaDoubleSupplier.swift create mode 100644 Sources/JavaKitFunction/generated/JavaDoubleToIntFunction.swift create mode 100644 Sources/JavaKitFunction/generated/JavaDoubleToLongFunction.swift create mode 100644 Sources/JavaKitFunction/generated/JavaDoubleUnaryOperator.swift create mode 100644 Sources/JavaKitFunction/generated/JavaFunction.swift create mode 100644 Sources/JavaKitFunction/generated/JavaIntBinaryOperator.swift create mode 100644 Sources/JavaKitFunction/generated/JavaIntConsumer.swift create mode 100644 Sources/JavaKitFunction/generated/JavaIntFunction.swift create mode 100644 Sources/JavaKitFunction/generated/JavaIntPredicate.swift create mode 100644 Sources/JavaKitFunction/generated/JavaIntSupplier.swift create mode 100644 Sources/JavaKitFunction/generated/JavaIntToDoubleFunction.swift create mode 100644 Sources/JavaKitFunction/generated/JavaIntToLongFunction.swift create mode 100644 Sources/JavaKitFunction/generated/JavaIntUnaryOperator.swift create mode 100644 Sources/JavaKitFunction/generated/JavaLongBinaryOperator.swift create mode 100644 Sources/JavaKitFunction/generated/JavaLongConsumer.swift create mode 100644 Sources/JavaKitFunction/generated/JavaLongFunction.swift create mode 100644 Sources/JavaKitFunction/generated/JavaLongPredicate.swift create mode 100644 Sources/JavaKitFunction/generated/JavaLongSupplier.swift create mode 100644 Sources/JavaKitFunction/generated/JavaLongToDoubleFunction.swift create mode 100644 Sources/JavaKitFunction/generated/JavaLongToIntFunction.swift create mode 100644 Sources/JavaKitFunction/generated/JavaLongUnaryOperator.swift create mode 100644 Sources/JavaKitFunction/generated/JavaObjDoubleConsumer.swift create mode 100644 Sources/JavaKitFunction/generated/JavaObjIntConsumer.swift create mode 100644 Sources/JavaKitFunction/generated/JavaObjLongConsumer.swift create mode 100644 Sources/JavaKitFunction/generated/JavaPredicate.swift create mode 100644 Sources/JavaKitFunction/generated/JavaSupplier.swift create mode 100644 Sources/JavaKitFunction/generated/JavaToDoubleBiFunction.swift create mode 100644 Sources/JavaKitFunction/generated/JavaToDoubleFunction.swift create mode 100644 Sources/JavaKitFunction/generated/JavaToIntBiFunction.swift create mode 100644 Sources/JavaKitFunction/generated/JavaToIntFunction.swift create mode 100644 Sources/JavaKitFunction/generated/JavaToLongBiFunction.swift create mode 100644 Sources/JavaKitFunction/generated/JavaToLongFunction.swift create mode 100644 Sources/JavaKitFunction/generated/JavaUnaryOperator.swift diff --git a/Makefile b/Makefile index ab0a89b6..4aee0561 100644 --- a/Makefile +++ b/Makefile @@ -76,6 +76,10 @@ generate-JavaKitCollection: Java2Swift mkdir -p Sources/JavaKitCollection/generated $(BUILD_DIR)/debug/Java2Swift --module-name JavaKitCollection --depends-on JavaKit=Sources/JavaKit/Java2Swift.config -o Sources/JavaKitCollection/generated Sources/JavaKitCollection/Java2Swift.config +generate-JavaKitFunction: Java2Swift + mkdir -p Sources/JavaKitFunction/generated + $(BUILD_DIR)/debug/Java2Swift --module-name JavaKitFunction --depends-on JavaKit=Sources/JavaKit/Java2Swift.config -o Sources/JavaKitFunction/generated Sources/JavaKitFunction/Java2Swift.config + generate-JavaKitReflection: Java2Swift generate-JavaKit generate-JavaKitCollection mkdir -p Sources/JavaKitReflection/generated $(BUILD_DIR)/debug/Java2Swift --module-name JavaKitReflection --depends-on JavaKit=Sources/JavaKit/Java2Swift.config --depends-on JavaKitCollection=Sources/JavaKitCollection/Java2Swift.config -o Sources/JavaKitReflection/generated Sources/JavaKitReflection/Java2Swift.config diff --git a/Package.swift b/Package.swift index e7f6353f..f2d9ff89 100644 --- a/Package.swift +++ b/Package.swift @@ -62,6 +62,11 @@ let package = Package( targets: ["JavaKitCollection"] ), + .library( + name: "JavaKitFunction", + targets: ["JavaKitFunction"] + ), + .library( name: "JavaKitJar", targets: ["JavaKitReflection"] @@ -183,6 +188,15 @@ let package = Package( .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) ] ), + .target( + name: "JavaKitFunction", + dependencies: ["JavaKit"], + exclude: ["Java2Swift.config"], + swiftSettings: [ + .swiftLanguageMode(.v5), + .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) + ] + ), .target( name: "JavaKitJar", dependencies: ["JavaKit", "JavaKitCollection"], diff --git a/Sources/JavaKitFunction/Java2Swift.config b/Sources/JavaKitFunction/Java2Swift.config new file mode 100644 index 00000000..93debe57 --- /dev/null +++ b/Sources/JavaKitFunction/Java2Swift.config @@ -0,0 +1,51 @@ +{ + "classes" : { + "java.util.function.BiConsumer" : "JavaBiConsumer", + "java.util.function.BiFunction" : "JavaBiFunction", + "java.util.function.BinaryOperator" : "JavaBinaryOperator", + "java.util.function.BiPredicate" : "JavaBiPredicate", + "java.util.function.BinaryOperator" : "JavaBinaryOperator", + "java.util.function.BooleanSupplier" : "JavaBooleanSupplier", + "java.util.function.Consumer" : "JavaConsumer", + "java.util.function.DoubleBinaryOperator" : "JavaDoubleBinaryOperator", + "java.util.function.DoubleConsumer" : "JavaDoubleConsumer", + "java.util.function.DoubleFunction" : "JavaDoubleFunction", + "java.util.function.DoublePredicate" : "JavaDoublePredicate", + "java.util.function.DoubleSupplier" : "JavaDoubleSupplier", + "java.util.function.DoubleToIntFunction" : "JavaDoubleToIntFunction", + "java.util.function.DoubleToLongFunction" : "JavaDoubleToLongFunction", + "java.util.function.DoubleUnaryOperator" : "JavaDoubleUnaryOperator", + "java.util.function.Function" : "JavaFunction", + "java.util.function.IntBinaryOperator" : "JavaIntBinaryOperator", + "java.util.function.IntConsumer" : "JavaIntConsumer", + "java.util.function.IntConsumer" : "JavaIntConsumer", + "java.util.function.IntFunction" : "JavaIntFunction", + "java.util.function.IntPredicate" : "JavaIntPredicate", + "java.util.function.IntSupplier" : "JavaIntSupplier", + "java.util.function.IntToDoubleFunction" : "JavaIntToDoubleFunction", + "java.util.function.IntToLongFunction" : "JavaIntToLongFunction", + "java.util.function.IntUnaryOperator" : "JavaIntUnaryOperator", + "java.util.function.LongBinaryOperator" : "JavaLongBinaryOperator", + "java.util.function.LongConsumer" : "JavaLongConsumer", + "java.util.function.LongFunction" : "JavaLongFunction", + "java.util.function.LongPredicate" : "JavaLongPredicate", + "java.util.function.LongSupplier" : "JavaLongSupplier", + "java.util.function.LongToDoubleFunction" : "JavaLongToDoubleFunction", + "java.util.function.LongToIntFunction" : "JavaLongToIntFunction", + "java.util.function.LongUnaryOperator" : "JavaLongUnaryOperator", + "java.util.function.ObjDoubleConsumer" : "JavaObjDoubleConsumer", + "java.util.function.ObjIntConsumer" : "JavaObjIntConsumer", + "java.util.function.ObjLongConsumer" : "JavaObjLongConsumer", + "java.util.function.Predicate" : "JavaPredicate", + "java.util.function.Supplier" : "JavaSupplier", + "java.util.function.ToDoubleBiFunction" : "JavaToDoubleBiFunction", + "java.util.function.ToDoubleFunction" : "JavaToDoubleFunction", + "java.util.function.ToIntBiFunction" : "JavaToIntBiFunction", + "java.util.function.ToIntFunction" : "JavaToIntFunction", + "java.util.function.ToLongBiFunction" : "JavaToLongBiFunction", + "java.util.function.ToLongFunction" : "JavaToLongFunction", + "java.util.function.UnaryOperator" : "JavaUnaryOperator" + } +} + + diff --git a/Sources/JavaKitFunction/generated/JavaBiConsumer.swift b/Sources/JavaKitFunction/generated/JavaBiConsumer.swift new file mode 100644 index 00000000..c5f5b7bf --- /dev/null +++ b/Sources/JavaKitFunction/generated/JavaBiConsumer.swift @@ -0,0 +1,14 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaInterface("java.util.function.BiConsumer") +public struct JavaBiConsumer { + @JavaMethod + public func accept(_ arg0: JavaObject?, _ arg1: JavaObject?) + + @JavaMethod + public func andThen(_ arg0: JavaBiConsumer?) -> JavaBiConsumer< + JavaObject, JavaObject + >? +} diff --git a/Sources/JavaKitFunction/generated/JavaBiFunction.swift b/Sources/JavaKitFunction/generated/JavaBiFunction.swift new file mode 100644 index 00000000..edecbff5 --- /dev/null +++ b/Sources/JavaKitFunction/generated/JavaBiFunction.swift @@ -0,0 +1,14 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaInterface("java.util.function.BiFunction") +public struct JavaBiFunction { + @JavaMethod + public func apply(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject? + + @JavaMethod + public func andThen(_ arg0: JavaFunction?) -> JavaBiFunction< + JavaObject, JavaObject, JavaObject + >? +} diff --git a/Sources/JavaKitFunction/generated/JavaBiPredicate.swift b/Sources/JavaKitFunction/generated/JavaBiPredicate.swift new file mode 100644 index 00000000..5fbc145e --- /dev/null +++ b/Sources/JavaKitFunction/generated/JavaBiPredicate.swift @@ -0,0 +1,22 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaInterface("java.util.function.BiPredicate") +public struct JavaBiPredicate { + @JavaMethod + public func test(_ arg0: JavaObject?, _ arg1: JavaObject?) -> Bool + + @JavaMethod + public func or(_ arg0: JavaBiPredicate?) -> JavaBiPredicate< + JavaObject, JavaObject + >? + + @JavaMethod + public func and(_ arg0: JavaBiPredicate?) -> JavaBiPredicate< + JavaObject, JavaObject + >? + + @JavaMethod + public func negate() -> JavaBiPredicate? +} diff --git a/Sources/JavaKitFunction/generated/JavaBinaryOperator.swift b/Sources/JavaKitFunction/generated/JavaBinaryOperator.swift new file mode 100644 index 00000000..3d0b0cd5 --- /dev/null +++ b/Sources/JavaKitFunction/generated/JavaBinaryOperator.swift @@ -0,0 +1,16 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaInterface( + "java.util.function.BinaryOperator", + extends: JavaBiFunction.self) +public struct JavaBinaryOperator { + @JavaMethod + public func apply(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject? + + @JavaMethod + public func andThen(_ arg0: JavaFunction?) -> JavaBiFunction< + JavaObject, JavaObject, JavaObject + >? +} diff --git a/Sources/JavaKitFunction/generated/JavaBooleanSupplier.swift b/Sources/JavaKitFunction/generated/JavaBooleanSupplier.swift new file mode 100644 index 00000000..eef96025 --- /dev/null +++ b/Sources/JavaKitFunction/generated/JavaBooleanSupplier.swift @@ -0,0 +1,9 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaInterface("java.util.function.BooleanSupplier") +public struct JavaBooleanSupplier { + @JavaMethod + public func getAsBoolean() -> Bool +} diff --git a/Sources/JavaKitFunction/generated/JavaConsumer.swift b/Sources/JavaKitFunction/generated/JavaConsumer.swift new file mode 100644 index 00000000..91eac106 --- /dev/null +++ b/Sources/JavaKitFunction/generated/JavaConsumer.swift @@ -0,0 +1,12 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaInterface("java.util.function.Consumer") +public struct JavaConsumer { + @JavaMethod + public func accept(_ arg0: JavaObject?) + + @JavaMethod + public func andThen(_ arg0: JavaConsumer?) -> JavaConsumer? +} diff --git a/Sources/JavaKitFunction/generated/JavaDoubleBinaryOperator.swift b/Sources/JavaKitFunction/generated/JavaDoubleBinaryOperator.swift new file mode 100644 index 00000000..0415ed90 --- /dev/null +++ b/Sources/JavaKitFunction/generated/JavaDoubleBinaryOperator.swift @@ -0,0 +1,9 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaInterface("java.util.function.DoubleBinaryOperator") +public struct JavaDoubleBinaryOperator { + @JavaMethod + public func applyAsDouble(_ arg0: Double, _ arg1: Double) -> Double +} diff --git a/Sources/JavaKitFunction/generated/JavaDoubleConsumer.swift b/Sources/JavaKitFunction/generated/JavaDoubleConsumer.swift new file mode 100644 index 00000000..9c322584 --- /dev/null +++ b/Sources/JavaKitFunction/generated/JavaDoubleConsumer.swift @@ -0,0 +1,12 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaInterface("java.util.function.DoubleConsumer") +public struct JavaDoubleConsumer { + @JavaMethod + public func accept(_ arg0: Double) + + @JavaMethod + public func andThen(_ arg0: JavaDoubleConsumer?) -> JavaDoubleConsumer? +} diff --git a/Sources/JavaKitFunction/generated/JavaDoubleFunction.swift b/Sources/JavaKitFunction/generated/JavaDoubleFunction.swift new file mode 100644 index 00000000..4ff4f3ef --- /dev/null +++ b/Sources/JavaKitFunction/generated/JavaDoubleFunction.swift @@ -0,0 +1,9 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaInterface("java.util.function.DoubleFunction") +public struct JavaDoubleFunction { + @JavaMethod + public func apply(_ arg0: Double) -> JavaObject? +} diff --git a/Sources/JavaKitFunction/generated/JavaDoublePredicate.swift b/Sources/JavaKitFunction/generated/JavaDoublePredicate.swift new file mode 100644 index 00000000..b2add42f --- /dev/null +++ b/Sources/JavaKitFunction/generated/JavaDoublePredicate.swift @@ -0,0 +1,18 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaInterface("java.util.function.DoublePredicate") +public struct JavaDoublePredicate { + @JavaMethod + public func test(_ arg0: Double) -> Bool + + @JavaMethod + public func or(_ arg0: JavaDoublePredicate?) -> JavaDoublePredicate? + + @JavaMethod + public func and(_ arg0: JavaDoublePredicate?) -> JavaDoublePredicate? + + @JavaMethod + public func negate() -> JavaDoublePredicate? +} diff --git a/Sources/JavaKitFunction/generated/JavaDoubleSupplier.swift b/Sources/JavaKitFunction/generated/JavaDoubleSupplier.swift new file mode 100644 index 00000000..184a4353 --- /dev/null +++ b/Sources/JavaKitFunction/generated/JavaDoubleSupplier.swift @@ -0,0 +1,9 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaInterface("java.util.function.DoubleSupplier") +public struct JavaDoubleSupplier { + @JavaMethod + public func getAsDouble() -> Double +} diff --git a/Sources/JavaKitFunction/generated/JavaDoubleToIntFunction.swift b/Sources/JavaKitFunction/generated/JavaDoubleToIntFunction.swift new file mode 100644 index 00000000..ae4ab0b3 --- /dev/null +++ b/Sources/JavaKitFunction/generated/JavaDoubleToIntFunction.swift @@ -0,0 +1,9 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaInterface("java.util.function.DoubleToIntFunction") +public struct JavaDoubleToIntFunction { + @JavaMethod + public func applyAsInt(_ arg0: Double) -> Int32 +} diff --git a/Sources/JavaKitFunction/generated/JavaDoubleToLongFunction.swift b/Sources/JavaKitFunction/generated/JavaDoubleToLongFunction.swift new file mode 100644 index 00000000..b0c9f9d6 --- /dev/null +++ b/Sources/JavaKitFunction/generated/JavaDoubleToLongFunction.swift @@ -0,0 +1,9 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaInterface("java.util.function.DoubleToLongFunction") +public struct JavaDoubleToLongFunction { + @JavaMethod + public func applyAsLong(_ arg0: Double) -> Int64 +} diff --git a/Sources/JavaKitFunction/generated/JavaDoubleUnaryOperator.swift b/Sources/JavaKitFunction/generated/JavaDoubleUnaryOperator.swift new file mode 100644 index 00000000..eb29139a --- /dev/null +++ b/Sources/JavaKitFunction/generated/JavaDoubleUnaryOperator.swift @@ -0,0 +1,19 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaInterface("java.util.function.DoubleUnaryOperator") +public struct JavaDoubleUnaryOperator { + @JavaMethod + public func applyAsDouble(_ arg0: Double) -> Double + + @JavaMethod + public func compose(_ arg0: JavaDoubleUnaryOperator?) -> JavaDoubleUnaryOperator? + + @JavaMethod + public func andThen(_ arg0: JavaDoubleUnaryOperator?) -> JavaDoubleUnaryOperator? +} +extension JavaClass { + @JavaStaticMethod + public func identity() -> JavaDoubleUnaryOperator? +} diff --git a/Sources/JavaKitFunction/generated/JavaFunction.swift b/Sources/JavaKitFunction/generated/JavaFunction.swift new file mode 100644 index 00000000..744461a9 --- /dev/null +++ b/Sources/JavaKitFunction/generated/JavaFunction.swift @@ -0,0 +1,25 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaInterface("java.util.function.Function") +public struct JavaFunction { + @JavaMethod + public func apply(_ arg0: JavaObject?) -> JavaObject? + + @JavaMethod + public func compose(_ arg0: JavaFunction?) -> JavaFunction< + JavaObject, JavaObject + >? + + @JavaMethod + public func andThen(_ arg0: JavaFunction?) -> JavaFunction< + JavaObject, JavaObject + >? +} +extension JavaClass { + @JavaStaticMethod + public func identity() -> JavaFunction< + JavaObject, JavaObject + >? where ObjectType == JavaFunction +} diff --git a/Sources/JavaKitFunction/generated/JavaIntBinaryOperator.swift b/Sources/JavaKitFunction/generated/JavaIntBinaryOperator.swift new file mode 100644 index 00000000..458885fe --- /dev/null +++ b/Sources/JavaKitFunction/generated/JavaIntBinaryOperator.swift @@ -0,0 +1,9 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaInterface("java.util.function.IntBinaryOperator") +public struct JavaIntBinaryOperator { + @JavaMethod + public func applyAsInt(_ arg0: Int32, _ arg1: Int32) -> Int32 +} diff --git a/Sources/JavaKitFunction/generated/JavaIntConsumer.swift b/Sources/JavaKitFunction/generated/JavaIntConsumer.swift new file mode 100644 index 00000000..704a4513 --- /dev/null +++ b/Sources/JavaKitFunction/generated/JavaIntConsumer.swift @@ -0,0 +1,12 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaInterface("java.util.function.IntConsumer") +public struct JavaIntConsumer { + @JavaMethod + public func accept(_ arg0: Int32) + + @JavaMethod + public func andThen(_ arg0: JavaIntConsumer?) -> JavaIntConsumer? +} diff --git a/Sources/JavaKitFunction/generated/JavaIntFunction.swift b/Sources/JavaKitFunction/generated/JavaIntFunction.swift new file mode 100644 index 00000000..cd7e7219 --- /dev/null +++ b/Sources/JavaKitFunction/generated/JavaIntFunction.swift @@ -0,0 +1,9 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaInterface("java.util.function.IntFunction") +public struct JavaIntFunction { + @JavaMethod + public func apply(_ arg0: Int32) -> JavaObject? +} diff --git a/Sources/JavaKitFunction/generated/JavaIntPredicate.swift b/Sources/JavaKitFunction/generated/JavaIntPredicate.swift new file mode 100644 index 00000000..9580ef87 --- /dev/null +++ b/Sources/JavaKitFunction/generated/JavaIntPredicate.swift @@ -0,0 +1,18 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaInterface("java.util.function.IntPredicate") +public struct JavaIntPredicate { + @JavaMethod + public func test(_ arg0: Int32) -> Bool + + @JavaMethod + public func or(_ arg0: JavaIntPredicate?) -> JavaIntPredicate? + + @JavaMethod + public func and(_ arg0: JavaIntPredicate?) -> JavaIntPredicate? + + @JavaMethod + public func negate() -> JavaIntPredicate? +} diff --git a/Sources/JavaKitFunction/generated/JavaIntSupplier.swift b/Sources/JavaKitFunction/generated/JavaIntSupplier.swift new file mode 100644 index 00000000..f0fae86a --- /dev/null +++ b/Sources/JavaKitFunction/generated/JavaIntSupplier.swift @@ -0,0 +1,9 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaInterface("java.util.function.IntSupplier") +public struct JavaIntSupplier { + @JavaMethod + public func getAsInt() -> Int32 +} diff --git a/Sources/JavaKitFunction/generated/JavaIntToDoubleFunction.swift b/Sources/JavaKitFunction/generated/JavaIntToDoubleFunction.swift new file mode 100644 index 00000000..0a52e5b7 --- /dev/null +++ b/Sources/JavaKitFunction/generated/JavaIntToDoubleFunction.swift @@ -0,0 +1,9 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaInterface("java.util.function.IntToDoubleFunction") +public struct JavaIntToDoubleFunction { + @JavaMethod + public func applyAsDouble(_ arg0: Int32) -> Double +} diff --git a/Sources/JavaKitFunction/generated/JavaIntToLongFunction.swift b/Sources/JavaKitFunction/generated/JavaIntToLongFunction.swift new file mode 100644 index 00000000..395dc876 --- /dev/null +++ b/Sources/JavaKitFunction/generated/JavaIntToLongFunction.swift @@ -0,0 +1,9 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaInterface("java.util.function.IntToLongFunction") +public struct JavaIntToLongFunction { + @JavaMethod + public func applyAsLong(_ arg0: Int32) -> Int64 +} diff --git a/Sources/JavaKitFunction/generated/JavaIntUnaryOperator.swift b/Sources/JavaKitFunction/generated/JavaIntUnaryOperator.swift new file mode 100644 index 00000000..221b3a97 --- /dev/null +++ b/Sources/JavaKitFunction/generated/JavaIntUnaryOperator.swift @@ -0,0 +1,19 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaInterface("java.util.function.IntUnaryOperator") +public struct JavaIntUnaryOperator { + @JavaMethod + public func applyAsInt(_ arg0: Int32) -> Int32 + + @JavaMethod + public func compose(_ arg0: JavaIntUnaryOperator?) -> JavaIntUnaryOperator? + + @JavaMethod + public func andThen(_ arg0: JavaIntUnaryOperator?) -> JavaIntUnaryOperator? +} +extension JavaClass { + @JavaStaticMethod + public func identity() -> JavaIntUnaryOperator? +} diff --git a/Sources/JavaKitFunction/generated/JavaLongBinaryOperator.swift b/Sources/JavaKitFunction/generated/JavaLongBinaryOperator.swift new file mode 100644 index 00000000..88035edc --- /dev/null +++ b/Sources/JavaKitFunction/generated/JavaLongBinaryOperator.swift @@ -0,0 +1,9 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaInterface("java.util.function.LongBinaryOperator") +public struct JavaLongBinaryOperator { + @JavaMethod + public func applyAsLong(_ arg0: Int64, _ arg1: Int64) -> Int64 +} diff --git a/Sources/JavaKitFunction/generated/JavaLongConsumer.swift b/Sources/JavaKitFunction/generated/JavaLongConsumer.swift new file mode 100644 index 00000000..b0ef6013 --- /dev/null +++ b/Sources/JavaKitFunction/generated/JavaLongConsumer.swift @@ -0,0 +1,12 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaInterface("java.util.function.LongConsumer") +public struct JavaLongConsumer { + @JavaMethod + public func accept(_ arg0: Int64) + + @JavaMethod + public func andThen(_ arg0: JavaLongConsumer?) -> JavaLongConsumer? +} diff --git a/Sources/JavaKitFunction/generated/JavaLongFunction.swift b/Sources/JavaKitFunction/generated/JavaLongFunction.swift new file mode 100644 index 00000000..2d9a7559 --- /dev/null +++ b/Sources/JavaKitFunction/generated/JavaLongFunction.swift @@ -0,0 +1,9 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaInterface("java.util.function.LongFunction") +public struct JavaLongFunction { + @JavaMethod + public func apply(_ arg0: Int64) -> JavaObject? +} diff --git a/Sources/JavaKitFunction/generated/JavaLongPredicate.swift b/Sources/JavaKitFunction/generated/JavaLongPredicate.swift new file mode 100644 index 00000000..3ed020eb --- /dev/null +++ b/Sources/JavaKitFunction/generated/JavaLongPredicate.swift @@ -0,0 +1,18 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaInterface("java.util.function.LongPredicate") +public struct JavaLongPredicate { + @JavaMethod + public func test(_ arg0: Int64) -> Bool + + @JavaMethod + public func or(_ arg0: JavaLongPredicate?) -> JavaLongPredicate? + + @JavaMethod + public func and(_ arg0: JavaLongPredicate?) -> JavaLongPredicate? + + @JavaMethod + public func negate() -> JavaLongPredicate? +} diff --git a/Sources/JavaKitFunction/generated/JavaLongSupplier.swift b/Sources/JavaKitFunction/generated/JavaLongSupplier.swift new file mode 100644 index 00000000..03ad6303 --- /dev/null +++ b/Sources/JavaKitFunction/generated/JavaLongSupplier.swift @@ -0,0 +1,9 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaInterface("java.util.function.LongSupplier") +public struct JavaLongSupplier { + @JavaMethod + public func getAsLong() -> Int64 +} diff --git a/Sources/JavaKitFunction/generated/JavaLongToDoubleFunction.swift b/Sources/JavaKitFunction/generated/JavaLongToDoubleFunction.swift new file mode 100644 index 00000000..99b56ba3 --- /dev/null +++ b/Sources/JavaKitFunction/generated/JavaLongToDoubleFunction.swift @@ -0,0 +1,9 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaInterface("java.util.function.LongToDoubleFunction") +public struct JavaLongToDoubleFunction { + @JavaMethod + public func applyAsDouble(_ arg0: Int64) -> Double +} diff --git a/Sources/JavaKitFunction/generated/JavaLongToIntFunction.swift b/Sources/JavaKitFunction/generated/JavaLongToIntFunction.swift new file mode 100644 index 00000000..2c952a17 --- /dev/null +++ b/Sources/JavaKitFunction/generated/JavaLongToIntFunction.swift @@ -0,0 +1,9 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaInterface("java.util.function.LongToIntFunction") +public struct JavaLongToIntFunction { + @JavaMethod + public func applyAsInt(_ arg0: Int64) -> Int32 +} diff --git a/Sources/JavaKitFunction/generated/JavaLongUnaryOperator.swift b/Sources/JavaKitFunction/generated/JavaLongUnaryOperator.swift new file mode 100644 index 00000000..fe99e338 --- /dev/null +++ b/Sources/JavaKitFunction/generated/JavaLongUnaryOperator.swift @@ -0,0 +1,19 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaInterface("java.util.function.LongUnaryOperator") +public struct JavaLongUnaryOperator { + @JavaMethod + public func applyAsLong(_ arg0: Int64) -> Int64 + + @JavaMethod + public func compose(_ arg0: JavaLongUnaryOperator?) -> JavaLongUnaryOperator? + + @JavaMethod + public func andThen(_ arg0: JavaLongUnaryOperator?) -> JavaLongUnaryOperator? +} +extension JavaClass { + @JavaStaticMethod + public func identity() -> JavaLongUnaryOperator? +} diff --git a/Sources/JavaKitFunction/generated/JavaObjDoubleConsumer.swift b/Sources/JavaKitFunction/generated/JavaObjDoubleConsumer.swift new file mode 100644 index 00000000..cf1ac236 --- /dev/null +++ b/Sources/JavaKitFunction/generated/JavaObjDoubleConsumer.swift @@ -0,0 +1,9 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaInterface("java.util.function.ObjDoubleConsumer") +public struct JavaObjDoubleConsumer { + @JavaMethod + public func accept(_ arg0: JavaObject?, _ arg1: Double) +} diff --git a/Sources/JavaKitFunction/generated/JavaObjIntConsumer.swift b/Sources/JavaKitFunction/generated/JavaObjIntConsumer.swift new file mode 100644 index 00000000..6c1e3b1e --- /dev/null +++ b/Sources/JavaKitFunction/generated/JavaObjIntConsumer.swift @@ -0,0 +1,9 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaInterface("java.util.function.ObjIntConsumer") +public struct JavaObjIntConsumer { + @JavaMethod + public func accept(_ arg0: JavaObject?, _ arg1: Int32) +} diff --git a/Sources/JavaKitFunction/generated/JavaObjLongConsumer.swift b/Sources/JavaKitFunction/generated/JavaObjLongConsumer.swift new file mode 100644 index 00000000..5486e910 --- /dev/null +++ b/Sources/JavaKitFunction/generated/JavaObjLongConsumer.swift @@ -0,0 +1,9 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaInterface("java.util.function.ObjLongConsumer") +public struct JavaObjLongConsumer { + @JavaMethod + public func accept(_ arg0: JavaObject?, _ arg1: Int64) +} diff --git a/Sources/JavaKitFunction/generated/JavaPredicate.swift b/Sources/JavaKitFunction/generated/JavaPredicate.swift new file mode 100644 index 00000000..9c953e3f --- /dev/null +++ b/Sources/JavaKitFunction/generated/JavaPredicate.swift @@ -0,0 +1,28 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaInterface("java.util.function.Predicate") +public struct JavaPredicate { + @JavaMethod + public func test(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func or(_ arg0: JavaPredicate?) -> JavaPredicate? + + @JavaMethod + public func and(_ arg0: JavaPredicate?) -> JavaPredicate? + + @JavaMethod + public func negate() -> JavaPredicate? +} +extension JavaClass { + @JavaStaticMethod + public func not(_ arg0: JavaPredicate?) -> JavaPredicate< + JavaObject + >? where ObjectType == JavaPredicate + + @JavaStaticMethod + public func isEqual(_ arg0: JavaObject?) -> JavaPredicate? + where ObjectType == JavaPredicate +} diff --git a/Sources/JavaKitFunction/generated/JavaSupplier.swift b/Sources/JavaKitFunction/generated/JavaSupplier.swift new file mode 100644 index 00000000..b44740dd --- /dev/null +++ b/Sources/JavaKitFunction/generated/JavaSupplier.swift @@ -0,0 +1,9 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaInterface("java.util.function.Supplier") +public struct JavaSupplier { + @JavaMethod + public func get() -> JavaObject? +} diff --git a/Sources/JavaKitFunction/generated/JavaToDoubleBiFunction.swift b/Sources/JavaKitFunction/generated/JavaToDoubleBiFunction.swift new file mode 100644 index 00000000..22ccf62c --- /dev/null +++ b/Sources/JavaKitFunction/generated/JavaToDoubleBiFunction.swift @@ -0,0 +1,9 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaInterface("java.util.function.ToDoubleBiFunction") +public struct JavaToDoubleBiFunction { + @JavaMethod + public func applyAsDouble(_ arg0: JavaObject?, _ arg1: JavaObject?) -> Double +} diff --git a/Sources/JavaKitFunction/generated/JavaToDoubleFunction.swift b/Sources/JavaKitFunction/generated/JavaToDoubleFunction.swift new file mode 100644 index 00000000..bf1c1d37 --- /dev/null +++ b/Sources/JavaKitFunction/generated/JavaToDoubleFunction.swift @@ -0,0 +1,9 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaInterface("java.util.function.ToDoubleFunction") +public struct JavaToDoubleFunction { + @JavaMethod + public func applyAsDouble(_ arg0: JavaObject?) -> Double +} diff --git a/Sources/JavaKitFunction/generated/JavaToIntBiFunction.swift b/Sources/JavaKitFunction/generated/JavaToIntBiFunction.swift new file mode 100644 index 00000000..6ebc0ff1 --- /dev/null +++ b/Sources/JavaKitFunction/generated/JavaToIntBiFunction.swift @@ -0,0 +1,9 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaInterface("java.util.function.ToIntBiFunction") +public struct JavaToIntBiFunction { + @JavaMethod + public func applyAsInt(_ arg0: JavaObject?, _ arg1: JavaObject?) -> Int32 +} diff --git a/Sources/JavaKitFunction/generated/JavaToIntFunction.swift b/Sources/JavaKitFunction/generated/JavaToIntFunction.swift new file mode 100644 index 00000000..c960913d --- /dev/null +++ b/Sources/JavaKitFunction/generated/JavaToIntFunction.swift @@ -0,0 +1,9 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaInterface("java.util.function.ToIntFunction") +public struct JavaToIntFunction { + @JavaMethod + public func applyAsInt(_ arg0: JavaObject?) -> Int32 +} diff --git a/Sources/JavaKitFunction/generated/JavaToLongBiFunction.swift b/Sources/JavaKitFunction/generated/JavaToLongBiFunction.swift new file mode 100644 index 00000000..93d0fc47 --- /dev/null +++ b/Sources/JavaKitFunction/generated/JavaToLongBiFunction.swift @@ -0,0 +1,9 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaInterface("java.util.function.ToLongBiFunction") +public struct JavaToLongBiFunction { + @JavaMethod + public func applyAsLong(_ arg0: JavaObject?, _ arg1: JavaObject?) -> Int64 +} diff --git a/Sources/JavaKitFunction/generated/JavaToLongFunction.swift b/Sources/JavaKitFunction/generated/JavaToLongFunction.swift new file mode 100644 index 00000000..f4fd5767 --- /dev/null +++ b/Sources/JavaKitFunction/generated/JavaToLongFunction.swift @@ -0,0 +1,9 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaInterface("java.util.function.ToLongFunction") +public struct JavaToLongFunction { + @JavaMethod + public func applyAsLong(_ arg0: JavaObject?) -> Int64 +} diff --git a/Sources/JavaKitFunction/generated/JavaUnaryOperator.swift b/Sources/JavaKitFunction/generated/JavaUnaryOperator.swift new file mode 100644 index 00000000..232283ba --- /dev/null +++ b/Sources/JavaKitFunction/generated/JavaUnaryOperator.swift @@ -0,0 +1,25 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaInterface( + "java.util.function.UnaryOperator", extends: JavaFunction.self) +public struct JavaUnaryOperator { + @JavaMethod + public func apply(_ arg0: JavaObject?) -> JavaObject? + + @JavaMethod + public func compose(_ arg0: JavaFunction?) -> JavaFunction< + JavaObject, JavaObject + >? + + @JavaMethod + public func andThen(_ arg0: JavaFunction?) -> JavaFunction< + JavaObject, JavaObject + >? +} +extension JavaClass { + @JavaStaticMethod + public func identity() -> JavaUnaryOperator? + where ObjectType == JavaUnaryOperator +} From e268bd34227b102690194b222bdff64087eb075c Mon Sep 17 00:00:00 2001 From: Iain Smith Date: Sun, 27 Oct 2024 09:08:56 +0000 Subject: [PATCH 130/426] Use JavaKitFunction in example --- Samples/JavaKitSampleApp/Package.swift | 1 + .../Sources/JavaKitExample/JavaKitExample.swift | 5 +++++ .../JavaKitExample/com/example/swift/HelloSwift.java | 7 +++++++ 3 files changed, 13 insertions(+) diff --git a/Samples/JavaKitSampleApp/Package.swift b/Samples/JavaKitSampleApp/Package.swift index 1da05c29..8976bd41 100644 --- a/Samples/JavaKitSampleApp/Package.swift +++ b/Samples/JavaKitSampleApp/Package.swift @@ -67,6 +67,7 @@ let package = Package( name: "JavaKitExample", dependencies: [ .product(name: "JavaKit", package: "swift-java"), + .product(name: "JavaKitFunction", package: "swift-java"), .product(name: "JavaKitJar", package: "swift-java"), ], swiftSettings: [ diff --git a/Samples/JavaKitSampleApp/Sources/JavaKitExample/JavaKitExample.swift b/Samples/JavaKitSampleApp/Sources/JavaKitExample/JavaKitExample.swift index 56a3cbb7..140c0604 100644 --- a/Samples/JavaKitSampleApp/Sources/JavaKitExample/JavaKitExample.swift +++ b/Samples/JavaKitSampleApp/Sources/JavaKitExample/JavaKitExample.swift @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// import JavaKit +import JavaKitFunction enum SwiftWrappedError: Error { case message(String) @@ -44,6 +45,10 @@ extension HelloSwift: HelloSwiftNativeMethods { self.name = "a 🗑️-collected language" _ = self.sayHelloBack(42) + let predicate: JavaPredicate = self.lessThanTen()! + let value = predicate.test(JavaInteger(3).as(JavaObject.self)) + print("Running a JavaPredicate from swift 3 < 10 = \(value)") + let strings = doublesToStrings([3.14159, 2.71828]) print("Converting doubles to strings: \(strings)") diff --git a/Samples/JavaKitSampleApp/Sources/JavaKitExample/com/example/swift/HelloSwift.java b/Samples/JavaKitSampleApp/Sources/JavaKitExample/com/example/swift/HelloSwift.java index c59baf33..d7ea7f22 100644 --- a/Samples/JavaKitSampleApp/Sources/JavaKitExample/com/example/swift/HelloSwift.java +++ b/Samples/JavaKitSampleApp/Sources/JavaKitExample/com/example/swift/HelloSwift.java @@ -14,6 +14,8 @@ package com.example.swift; +import java.util.function.Predicate; + public class HelloSwift { public double value; public static double initialValue = 3.14159; @@ -40,6 +42,11 @@ public void greet(String name) { System.out.println("Salutations, " + name); } + public Predicate lessThanTen() { + Predicate predicate = i -> (i < 10); + return predicate; + } + public String[] doublesToStrings(double[] doubles) { int size = doubles.length; String[] strings = new String[size]; From 8a48e979f0939502bfd439828b3c7232cbf7a38c Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Sun, 27 Oct 2024 22:04:16 -0700 Subject: [PATCH 131/426] Java2Swift: Factor Java class translation into its own type & file The main function for translating a Java class into a sequence of Swift declarations was very large and very tangled. Refactor it into a separate class that more deliberately separates the analysis of the Java class (picking out what needs to be translated) from the actual rendering of the Swift declarations, then breaks that rendering down into more digestible pieces. No (intended) functionality change here: this is cleanup to make it easier to implement some upcoming improvements. --- .../Java2SwiftLib/JavaClassTranslator.swift | 555 ++++++++++++++++++ Sources/Java2SwiftLib/JavaTranslator.swift | 441 +------------- .../Constructor+Utilities.swift | 7 +- .../JavaKitReflection/Method+Utilities.swift | 5 + 4 files changed, 568 insertions(+), 440 deletions(-) create mode 100644 Sources/Java2SwiftLib/JavaClassTranslator.swift diff --git a/Sources/Java2SwiftLib/JavaClassTranslator.swift b/Sources/Java2SwiftLib/JavaClassTranslator.swift new file mode 100644 index 00000000..906f17a4 --- /dev/null +++ b/Sources/Java2SwiftLib/JavaClassTranslator.swift @@ -0,0 +1,555 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import JavaKit +import JavaKitReflection +import SwiftSyntax + +/// Utility type that translates a single Java class into its corresponding +/// Swift type and any additional helper types or functions. +struct JavaClassTranslator { + /// The translator we are working with, which provides global knowledge + /// needed for translation. + let translator: JavaTranslator + + /// The Java class (or interface) being translated. + let javaClass: JavaClass + + /// The type parameters to the Java class or interface. + let javaTypeParameters: [TypeVariable>] + + /// The set of nested classes of this class that will be rendered along + /// with it. + let nestedClasses: [JavaClass] + + /// The full name of the Swift type that will be generated for this Java + /// class. + let swiftTypeName: String + + /// The Swift name of the superclass. + let swiftSuperclass: String? + + /// The Swift names of the interfaces that this class implements. + let swiftInterfaces: [String] + + /// The (instance) fields of the Java class. + var fields: [Field] = [] + + /// The static fields of the Java class. + var staticFields: [Field] = [] + + /// Enum constants of the Java class, which are also static fields and are + /// reflected additionally as enum cases. + var enumConstants: [Field] = [] + + /// Constructors of the Java class. + var constructors: [Constructor] = [] + + /// The (instance) methods of the Java class. + var methods: [Method] = [] + + /// The static methods of the Java class. + var staticMethods: [Method] = [] + + /// The native instance methods of the Java class, which are also reflected + /// in a `*NativeMethods` protocol so they can be implemented in Swift. + var nativeMethods: [Method] = [] + + /// The native static methods of the Java class. + /// TODO: These are currently unimplemented. + var nativeStaticMethods: [Method] = [] + + /// Whether the Java class we're translating is actually an interface. + var isInterface: Bool { + return javaClass.isInterface() + } + + /// The name of the enclosing Swift type, if there is one. + var swiftParentType: String? { + swiftTypeName.splitSwiftTypeName().parentType + } + + /// The name of the innermost Swift type, without the enclosing type. + var swiftInnermostTypeName: String { + swiftTypeName.splitSwiftTypeName().name + } + + /// The generic parameter clause for the Swift version of the Java class. + var genericParameterClause: String { + if javaTypeParameters.isEmpty { + return "" + } + + let genericParameters = javaTypeParameters.map { param in + "\(param.getName()): AnyJavaObject" + } + + return "<\(genericParameters.joined(separator: ", "))>" + } + + /// Prepare translation for the given Java class (or interface). + init(javaClass: JavaClass, translator: JavaTranslator) throws { + let fullName = javaClass.getName() + self.javaClass = javaClass + self.translator = translator + self.swiftTypeName = try translator.getSwiftTypeNameFromJavaClassName(fullName, escapeMemberNames: false) + + // Type parameters. + self.javaTypeParameters = javaClass.getTypeParameters().compactMap { $0 } + self.nestedClasses = translator.nestedClasses[fullName] ?? [] + + // Superclass. + if !javaClass.isInterface(), + let javaSuperclass = javaClass.getSuperclass(), + javaSuperclass.getName() != "java.lang.Object" + { + do { + self.swiftSuperclass = try translator.getSwiftTypeName(javaSuperclass).swiftName + } catch { + translator.logUntranslated("Unable to translate '\(fullName)' superclass: \(error)") + self.swiftSuperclass = nil + } + } else { + self.swiftSuperclass = nil + } + + // Interfaces. + self.swiftInterfaces = javaClass.getGenericInterfaces().compactMap { (javaType) -> String? in + guard let javaType else { + return nil + } + + do { + let typeName = try translator.getSwiftTypeNameAsString(javaType, outerOptional: false) + return "\(typeName)" + } catch { + translator.logUntranslated("Unable to translate '\(fullName)' interface '\(javaType.getTypeName())': \(error)") + return nil + } + } + + // Collect all of the class members that we will need to translate. + // TODO: Switch over to "declared" versions of these whenever we don't need + // to see inherited members. + + // Gather fields. + for field in javaClass.getFields() { + guard let field else { continue } + addField(field) + } + + // Gather constructors. + for constructor in javaClass.getConstructors() { + guard let constructor else { continue } + addConstructor(constructor) + } + + // Gather methods. + for method in javaClass.getMethods() { + guard let method else { continue } + + // Skip any methods that are expected to be implemented in Swift. We will + // visit them in the second pass, over the *declared* methods, because + // we want to see non-public methods as well. + let implementedInSwift = method.isNative && + method.getDeclaringClass()!.equals(javaClass.as(JavaObject.self)!) && + translator.swiftNativeImplementations.contains(javaClass.getName()) + if implementedInSwift { + continue + } + + addMethod(method, isNative: false) + } + + if translator.swiftNativeImplementations.contains(javaClass.getName()) { + for method in javaClass.getDeclaredMethods() { + guard let method else { continue } + + // Only visit native methods in this second pass. + if !method.isNative { + continue + } + + addMethod(method, isNative: true) + } + } + } +} + +/// MARK: Collection of Java class members. +extension JavaClassTranslator { + /// Add a field to the appropriate lists(s) for later translation. + private mutating func addField(_ field: Field) { + // Static fields go into a separate list. + if field.isStatic { + staticFields.append(field) + + // Enum constants will be used to produce a Swift enum projecting the + // Java enum. + if field.isEnumConstant() { + enumConstants.append(field) + } + + return + } + + fields.append(field) + } + + /// Add a constructor to the list of constructors for later translation. + private mutating func addConstructor(_ constructor: Constructor) { + constructors.append(constructor) + } + + /// Add a method to the appropriate list for later translation. + private mutating func addMethod(_ method: Method, isNative: Bool) { + switch (method.isStatic, isNative) { + case (false, false): methods.append(method) + case (true, false): staticMethods.append(method) + case (false, true): nativeMethods.append(method) + case (true, true): nativeStaticMethods.append(method) + } + } +} + +/// MARK: Rendering of Java class members as Swift declarations. +extension JavaClassTranslator { + /// Render the Swift declarations that will express this Java class in Swift. + package func render() -> [DeclSyntax] { + var allDecls: [DeclSyntax] = [] + allDecls.append(renderPrimaryType()) + allDecls.append(contentsOf: renderNestedClasses()) + if let staticMemberExtension = renderStaticMemberExtension() { + allDecls.append(staticMemberExtension) + } + if let nativeMethodsProtocol = renderNativeMethodsProtocol() { + allDecls.append(nativeMethodsProtocol) + } + return allDecls + } + + /// Render the declaration for the main part of the Java class, which + /// includes the constructors, non-static fields, and non-static methods. + private func renderPrimaryType() -> DeclSyntax { + // Render all of the instance fields as Swift properties. + let properties = fields.compactMap { field in + do { + return try renderField(field) + } catch { + translator.logUntranslated("Unable to translate '\(javaClass.getName())' static field '\(field.getName())': \(error)") + return nil + } + } + + // Declarations used to capture Java enums. + let enumDecls: [DeclSyntax] = renderEnum(name: "\(swiftInnermostTypeName)Cases") + + // Render all of the constructors as Swift initializers. + let initializers = constructors.compactMap { constructor in + do { + return try renderConstructor(constructor) + } catch { + translator.logUntranslated("Unable to translate '\(javaClass.getName())' constructor: \(error)") + return nil + } + } + + // Render all of the instance methods in Swift. + let instanceMethods = methods.compactMap { method in + do { + return try renderMethod(method, implementedInSwift: false) + } catch { + translator.logUntranslated("Unable to translate '\(javaClass.getName())' method '\(method.getName())': \(error)") + return nil + } + } + + // Collect all of the members of this type. + let members = properties + enumDecls + initializers + instanceMethods + + // Compute the "extends" clause for the superclass. + let extends = swiftSuperclass.map { ", extends: \($0).self" } ?? "" + + // Compute the string to capture all of the interfaces. + let interfacesStr: String + if swiftInterfaces.isEmpty { + interfacesStr = "" + } else { + let prefix = javaClass.isInterface() ? "extends" : "implements" + interfacesStr = ", \(prefix): \(swiftInterfaces.map { "\($0).self" }.joined(separator: ", "))" + } + + // Emit the struct declaration describing the java class. + let classOrInterface: String = isInterface ? "JavaInterface" : "JavaClass"; + var classDecl: DeclSyntax = + """ + @\(raw: classOrInterface)(\(literal: javaClass.getName())\(raw: extends)\(raw: interfacesStr)) + public struct \(raw: swiftInnermostTypeName)\(raw: genericParameterClause) { + \(raw: members.map { $0.description }.joined(separator: "\n\n")) + } + """ + + // If there is a parent type, wrap this type up in an extension of that + // parent type. + if let swiftParentType { + classDecl = + """ + extension \(raw: swiftParentType) { + \(classDecl) + } + """ + } + + // Format the class declaration. + return classDecl.formatted(using: translator.format).cast(DeclSyntax.self) + } + + /// Render any nested classes that will not be rendered separately. + func renderNestedClasses() -> [DeclSyntax] { + return nestedClasses.compactMap { clazz in + do { + return try translator.translateClass(clazz) + } catch { + translator.logUntranslated("Unable to translate '\(javaClass.getName())' nested class '\(clazz.getName())': \(error)") + return nil + } + }.flatMap(\.self) + } + + /// Render the extension of JavaClass that collects all of the static + /// fields and methods. + package func renderStaticMemberExtension() -> DeclSyntax? { + // Determine the where clause we need for static methods. + let staticMemberWhereClause: String + if !javaTypeParameters.isEmpty { + let genericParameterNames = javaTypeParameters.compactMap { typeVar in + typeVar.getName() + } + + let genericArgumentClause = "<\(genericParameterNames.joined(separator: ", "))>" + staticMemberWhereClause = " where ObjectType == \(swiftTypeName)\(genericArgumentClause)" + } else { + staticMemberWhereClause = "" + } + + // Render static fields. + let properties = staticFields.compactMap { field in + // Translate each static field. + do { + return try renderField(field) + } catch { + translator.logUntranslated("Unable to translate '\(javaClass.getName())' field '\(field.getName())': \(error)") + return nil + } + } + + // Render static methods. + let methods = staticMethods.compactMap { method in + // Translate each static method. + do { + return try renderMethod( + method, implementedInSwift: /*FIXME:*/false, + genericParameterClause: genericParameterClause, + whereClause: staticMemberWhereClause + ) + } catch { + translator.logUntranslated("Unable to translate '\(javaClass.getName())' static method '\(method.getName())': \(error)") + return nil + } + } + + // Gather all of the members. + let members = properties + methods + if members.isEmpty { + return nil + } + + // Specify the specialization arguments when needed. + let extSpecialization: String + if genericParameterClause.isEmpty { + extSpecialization = "<\(swiftTypeName)>" + } else { + extSpecialization = "" + } + + let extDecl: DeclSyntax = + """ + extension JavaClass\(raw: extSpecialization) { + \(raw: members.map { $0.description }.joined(separator: "\n\n")) + } + """ + + return extDecl.formatted(using: translator.format).cast(DeclSyntax.self) + } + + /// Render the protocol used for native methods. + func renderNativeMethodsProtocol() -> DeclSyntax? { + guard translator.swiftNativeImplementations.contains(javaClass.getName()) else { + return nil + } + + let nativeMembers = nativeMethods.compactMap { method in + do { + return try renderMethod( + method, + implementedInSwift: true + ) + } catch { + translator.logUntranslated("Unable to translate '\(javaClass.getName())' method '\(method.getName())': \(error)") + return nil + } + } + + if nativeMembers.isEmpty { + return nil + } + + let protocolDecl: DeclSyntax = + """ + /// Describes the Java `native` methods for ``\(raw: swiftTypeName)``. + /// + /// To implement all of the `native` methods for \(raw: swiftTypeName) in Swift, + /// extend \(raw: swiftTypeName) to conform to this protocol and mark + /// each implementation of the protocol requirement with + /// `@JavaMethod`. + protocol \(raw: swiftTypeName)NativeMethods { + \(raw: nativeMembers.map { $0.description }.joined(separator: "\n\n")) + } + """ + + return protocolDecl.formatted(using: translator.format).cast(DeclSyntax.self) + } + + /// Render the given Java constructor as a Swift initializer. + package func renderConstructor( + _ javaConstructor: Constructor + ) throws -> DeclSyntax { + let parameters = try translateParameters(javaConstructor.getParameters()) + ["environment: JNIEnvironment? = nil"] + let parametersStr = parameters.map { $0.description }.joined(separator: ", ") + let throwsStr = javaConstructor.throwsCheckedException ? "throws" : "" + let accessModifier = javaConstructor.isPublic ? "public " : "" + return """ + @JavaMethod + \(raw: accessModifier)init(\(raw: parametersStr))\(raw: throwsStr) + """ + } + + /// Translates the given Java method into a Swift declaration. + package func renderMethod( + _ javaMethod: Method, + implementedInSwift: Bool, + genericParameterClause: String = "", + whereClause: String = "" + ) throws -> DeclSyntax { + // Map the parameters. + let parameters = try translateParameters(javaMethod.getParameters()) + + let parametersStr = parameters.map { $0.description }.joined(separator: ", ") + + // Map the result type. + let resultTypeStr: String + let resultType = try translator.getSwiftTypeNameAsString(javaMethod.getGenericReturnType()!, outerOptional: true) + if resultType != "Void" { + resultTypeStr = " -> \(resultType)" + } else { + resultTypeStr = "" + } + + let throwsStr = javaMethod.throwsCheckedException ? "throws" : "" + let swiftMethodName = javaMethod.getName().escapedSwiftName + let methodAttribute: AttributeSyntax = implementedInSwift + ? "" + : javaMethod.isStatic ? "@JavaStaticMethod\n" : "@JavaMethod\n"; + let accessModifier = implementedInSwift ? "" : "public " + return """ + \(methodAttribute)\(raw: accessModifier)func \(raw: swiftMethodName)\(raw: genericParameterClause)(\(raw: parametersStr))\(raw: throwsStr)\(raw: resultTypeStr)\(raw: whereClause) + """ + } + + /// Render a single Java field into the corresponding Swift property, or + /// throw an error if that is not possible for any reason. + package func renderField(_ javaField: Field) throws -> DeclSyntax { + let typeName = try translator.getSwiftTypeNameAsString(javaField.getGenericType()!, outerOptional: true) + let fieldAttribute: AttributeSyntax = javaField.isStatic ? "@JavaStaticField" : "@JavaField"; + let swiftFieldName = javaField.getName().escapedSwiftName + return """ + \(fieldAttribute)(isFinal: \(raw: javaField.isFinal)) + public var \(raw: swiftFieldName): \(raw: typeName) + """ + } + + package func renderEnum(name: String) -> [DeclSyntax] { + if enumConstants.isEmpty { + return [] + } + + let extensionSyntax: DeclSyntax = """ + public enum \(raw: name): Equatable { + \(raw: enumConstants.map { "case \($0.getName())" }.joined(separator: "\n")) + } + """ + + let mappingSyntax: DeclSyntax = """ + public var enumValue: \(raw: name)? { + let classObj = self.javaClass + \(raw: enumConstants.map { + // The equals method takes a java object, so we need to cast it here + """ + if self.equals(classObj.\($0.getName())?.as(JavaObject.self)) { + return \(name).\($0.getName()) + } + """ + }.joined(separator: " else ")) else { + return nil + } + } + """ + + let initSyntax: DeclSyntax = """ + public init(_ enumValue: \(raw: name), environment: JNIEnvironment? = nil) { + let _environment = if let environment { + environment + } else { + try! JavaVirtualMachine.shared().environment() + } + let classObj = try! JavaClass(environment: _environment) + switch enumValue { + \(raw: enumConstants.map { + return """ + case .\($0.getName()): + if let \($0.getName()) = classObj.\($0.getName()) { + self = \($0.getName()) + } else { + fatalError("Enum value \($0.getName()) was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + """ + }.joined(separator: "\n")) + } + } + """ + + return [extensionSyntax, mappingSyntax, initSyntax] + } + + // Translate a Java parameter list into Swift parameters. + private func translateParameters(_ parameters: [Parameter?]) throws -> [FunctionParameterSyntax] { + return try parameters.compactMap { javaParameter in + guard let javaParameter else { return nil } + + let typeName = try translator.getSwiftTypeNameAsString(javaParameter.getParameterizedType()!, outerOptional: true) + let paramName = javaParameter.getName() + return "_ \(raw: paramName): \(raw: typeName)" + } + } +} diff --git a/Sources/Java2SwiftLib/JavaTranslator.swift b/Sources/Java2SwiftLib/JavaTranslator.swift index 9a9a5b4d..89e417e6 100644 --- a/Sources/Java2SwiftLib/JavaTranslator.swift +++ b/Sources/Java2SwiftLib/JavaTranslator.swift @@ -178,7 +178,7 @@ extension JavaTranslator { } /// Map a Java class name to its corresponding Swift type. - private func getSwiftTypeNameFromJavaClassName( + func getSwiftTypeNameFromJavaClassName( _ name: String, escapeMemberNames: Bool = true ) throws -> String { @@ -205,444 +205,7 @@ extension JavaTranslator { /// can produce multiple declarations, such as a separate extension of /// JavaClass to house static methods. package func translateClass(_ javaClass: JavaClass) throws -> [DeclSyntax] { - let fullName = javaClass.getName() - let swiftTypeName = try getSwiftTypeNameFromJavaClassName(fullName, escapeMemberNames: false) - let (swiftParentType, swiftInnermostTypeName) = swiftTypeName.splitSwiftTypeName() - - // If the swift parent type has not been translated, don't try to translate this one - if let swiftParentType, - !translatedClasses.contains(where: { _, value in value.swiftType == swiftParentType }) - { - logUntranslated("Unable to translate '\(fullName)' parent class: \(swiftParentType) not found") - return [] - } - - // Superclass. - let extends: String - if !javaClass.isInterface(), - let superclass = javaClass.getSuperclass(), - superclass.getName() != "java.lang.Object" - { - do { - extends = ", extends: \(try getSwiftTypeName(superclass).swiftName).self" - } catch { - logUntranslated("Unable to translate '\(fullName)' superclass: \(error)") - extends = "" - } - } else { - extends = "" - } - - // The set of generic interfaces implemented by a class or - // extended by an interface. - let interfaces: [String] = javaClass.getGenericInterfaces().compactMap { javaType in - guard let javaType else { - return nil - } - - do { - let typeName = try getSwiftTypeNameAsString(javaType, outerOptional: false) - return "\(typeName).self" - } catch { - logUntranslated("Unable to translate '\(fullName)' interface '\(javaType.getTypeName())': \(error)") - return nil - } - } - let interfacesStr: String - if interfaces.isEmpty { - interfacesStr = "" - } else { - let prefix = javaClass.isInterface() ? "extends" : "implements" - interfacesStr = ", \(prefix): \(interfaces.joined(separator: ", "))" - } - - // The top-level declarations we will be returning. - var topLevelDecls: [DeclSyntax] = [] - - // Members - var members: [DeclSyntax] = [] - - // Fields - var staticFields: [Field] = [] - var enumConstants: [Field] = [] - members.append( - contentsOf: javaClass.getFields().compactMap { - $0.flatMap { field in - if field.isStatic { - staticFields.append(field) - - if field.isEnumConstant() { - enumConstants.append(field) - } - return nil - } - - do { - return try translateField(field) - } catch { - logUntranslated("Unable to translate '\(fullName)' static field '\(field.getName())': \(error)") - return nil - } - } - } - ) - - if !enumConstants.isEmpty { - let enumName = "\(swiftInnermostTypeName)Cases" - members.append( - contentsOf: translateToEnumValue(name: enumName, enumFields: enumConstants) - ) - } - - // Constructors - members.append( - contentsOf: javaClass.getConstructors().compactMap { - $0.flatMap { constructor in - do { - let implementedInSwift = constructor.isNative && - constructor.getDeclaringClass()!.equals(javaClass.as(JavaObject.self)!) && - swiftNativeImplementations.contains(javaClass.getName()) - - let translated = try translateConstructor( - constructor, - implementedInSwift: implementedInSwift - ) - - if implementedInSwift { - return nil - } - - return translated - } catch { - logUntranslated("Unable to translate '\(fullName)' constructor: \(error)") - return nil - } - } - } - ) - - // Methods - var staticMethods: [Method] = [] - members.append( - contentsOf: javaClass.getMethods().compactMap { - $0.flatMap { (method) -> DeclSyntax? in - // Save the static methods; they need to go on an extension of - // JavaClass. - if method.isStatic { - staticMethods.append(method) - return nil - } - - let implementedInSwift = method.isNative && - method.getDeclaringClass()!.equals(javaClass.as(JavaObject.self)!) && - swiftNativeImplementations.contains(javaClass.getName()) - - // Translate the method if we can. - do { - let translated = try translateMethod( - method, - implementedInSwift: implementedInSwift - ) - - if implementedInSwift { - return nil - } - - return translated - } catch { - logUntranslated("Unable to translate '\(fullName)' method '\(method.getName())': \(error)") - return nil - } - } - } - ) - - // Map the generic parameters. - let genericParameterClause: String - let staticMemberWhereClause: String - let javaTypeParameters = javaClass.getTypeParameters() - if !javaTypeParameters.isEmpty { - let genericParameterNames = javaTypeParameters.compactMap { typeVar in - typeVar?.getName() - } - - let genericParameters = genericParameterNames.map { name in - "\(name): AnyJavaObject" - } - - genericParameterClause = "<\(genericParameters.joined(separator: ", "))>" - let genericArgumentClause = "<\(genericParameterNames.joined(separator: ", "))>" - - staticMemberWhereClause = " where ObjectType == \(swiftTypeName)\(genericArgumentClause)" - } else { - genericParameterClause = "" - staticMemberWhereClause = "" - } - - // Emit the struct declaration describing the java class. - let classOrInterface: String = javaClass.isInterface() ? "JavaInterface" : "JavaClass"; - var classDecl = - """ - @\(raw:classOrInterface)(\(literal: fullName)\(raw: extends)\(raw: interfacesStr)) - public struct \(raw: swiftInnermostTypeName)\(raw: genericParameterClause) { - \(raw: members.map { $0.description }.joined(separator: "\n\n")) - } - """ as DeclSyntax - - // If there is a parent type, wrap this type up in an extension of that - // parent type. - if let swiftParentType { - classDecl = - """ - extension \(raw: swiftParentType) { - \(classDecl) - } - """ - } - - // Format the class declaration. - classDecl = classDecl.formatted(using: format).cast(DeclSyntax.self) - - topLevelDecls.append(classDecl) - - let subClassDecls = (nestedClasses[fullName] ?? []).compactMap { clazz in - do { - return try translateClass(clazz) - } catch { - logUntranslated("Unable to translate '\(fullName)' subclass '\(clazz.getName())': \(error)") - return nil - } - }.flatMap(\.self) - - topLevelDecls.append( - contentsOf: subClassDecls - ) - // Translate static members. - var staticMembers: [DeclSyntax] = [] - - staticMembers.append( - contentsOf: staticFields.compactMap { field in - // Translate each static field. - do { - return try translateField(field) - } catch { - logUntranslated("Unable to translate '\(fullName)' field '\(field.getName())': \(error)") - return nil - } - } - ) - - staticMembers.append( - contentsOf: staticMethods.compactMap { method in - // Translate each static method. - do { - return try translateMethod( - method, implementedInSwift: /*FIXME:*/false, - genericParameterClause: genericParameterClause, - whereClause: staticMemberWhereClause - ) - } catch { - logUntranslated("Unable to translate '\(fullName)' static method '\(method.getName())': \(error)") - return nil - } - } - ) - - if !staticMembers.isEmpty { - // Specify the specialization arguments when needed. - let extSpecialization: String - if genericParameterClause.isEmpty { - extSpecialization = "<\(swiftTypeName)>" - } else { - extSpecialization = "" - } - - let extDecl: DeclSyntax = - """ - extension JavaClass\(raw: extSpecialization) { - \(raw: staticMembers.map { $0.description }.joined(separator: "\n\n")) - } - """ - - topLevelDecls.append( - extDecl.formatted(using: format).cast(DeclSyntax.self) - ) - } - - // Members that are native and will instead go into a NativeMethods - // protocol. - var nativeMembers: [DeclSyntax] = [] - if swiftNativeImplementations.contains(javaClass.getName()) { - nativeMembers.append( - contentsOf: javaClass.getDeclaredMethods().compactMap { - $0.flatMap { method in - // FIXME: For now, ignore static methods - if method.isStatic { - return nil - } - - if !method.isNative { - return nil - } - - // Translate the method if we can. - do { - return try translateMethod( - method, - implementedInSwift: true - ) - } catch { - logUntranslated("Unable to translate '\(fullName)' method '\(method.getName())': \(error)") - return nil - } - } - } - ) - } - - if !nativeMembers.isEmpty { - let protocolDecl: DeclSyntax = - """ - /// Describes the Java `native` methods for ``\(raw: swiftTypeName)``. - /// - /// To implement all of the `native` methods for \(raw: swiftTypeName) in Swift, - /// extend \(raw: swiftTypeName) to conform to this protocol and mark - /// each implementation of the protocol requirement with - /// `@JavaMethod`. - protocol \(raw: swiftTypeName)NativeMethods { - \(raw: nativeMembers.map { $0.description }.joined(separator: "\n\n")) - } - """ - - topLevelDecls.append( - protocolDecl.formatted(using: format).cast(DeclSyntax.self) - ) - } - - return topLevelDecls - } -} - -// MARK: Method and constructor translation -extension JavaTranslator { - /// Translates the given Java constructor into a Swift declaration. - package func translateConstructor( - _ javaConstructor: Constructor, - implementedInSwift: Bool - ) throws -> DeclSyntax { - let parameters = try translateParameters(javaConstructor.getParameters()) + ["environment: JNIEnvironment? = nil"] - let parametersStr = parameters.map { $0.description }.joined(separator: ", ") - let throwsStr = javaConstructor.throwsCheckedException ? "throws" : "" - - let javaMethodAttribute = implementedInSwift - ? "" - : "@JavaMethod\n" - let accessModifier = implementedInSwift ? "" : "public " - return """ - \(raw: javaMethodAttribute)\(raw: accessModifier)init(\(raw: parametersStr))\(raw: throwsStr) - """ - } - - /// Translates the given Java method into a Swift declaration. - package func translateMethod( - _ javaMethod: Method, - implementedInSwift: Bool, - genericParameterClause: String = "", - whereClause: String = "" - ) throws -> DeclSyntax { - // Map the parameters. - let parameters = try translateParameters(javaMethod.getParameters()) - - let parametersStr = parameters.map { $0.description }.joined(separator: ", ") - - // Map the result type. - let resultTypeStr: String - let resultType = try getSwiftTypeNameAsString(javaMethod.getGenericReturnType()!, outerOptional: true) - if resultType != "Void" { - resultTypeStr = " -> \(resultType)" - } else { - resultTypeStr = "" - } - - let throwsStr = javaMethod.throwsCheckedException ? "throws" : "" - let swiftMethodName = javaMethod.getName().escapedSwiftName - let methodAttribute: AttributeSyntax = implementedInSwift - ? "" - : javaMethod.isStatic ? "@JavaStaticMethod\n" : "@JavaMethod\n"; - let accessModifier = implementedInSwift ? "" : "public " - return """ - \(methodAttribute)\(raw: accessModifier)func \(raw: swiftMethodName)\(raw: genericParameterClause)(\(raw: parametersStr))\(raw: throwsStr)\(raw: resultTypeStr)\(raw: whereClause) - """ - } - - package func translateField(_ javaField: Field) throws -> DeclSyntax { - let typeName = try getSwiftTypeNameAsString(javaField.getGenericType()!, outerOptional: true) - let fieldAttribute: AttributeSyntax = javaField.isStatic ? "@JavaStaticField" : "@JavaField"; - let swiftFieldName = javaField.getName().escapedSwiftName - return """ - \(fieldAttribute)(isFinal: \(raw: javaField.isFinal)) - public var \(raw: swiftFieldName): \(raw: typeName) - """ - } - - package func translateToEnumValue(name: String, enumFields: [Field]) -> [DeclSyntax] { - let extensionSyntax: DeclSyntax = """ - public enum \(raw: name): Equatable { - \(raw: enumFields.map { "case \($0.getName())" }.joined(separator: "\n")) - } - """ - - let mappingSyntax: DeclSyntax = """ - public var enumValue: \(raw: name)? { - let classObj = self.javaClass - \(raw: enumFields.map { - // The equals method takes a java object, so we need to cast it here - """ - if self.equals(classObj.\($0.getName())?.as(JavaObject.self)) { - return \(name).\($0.getName()) - } - """ - }.joined(separator: " else ")) else { - return nil - } - } - """ - - let initSyntax: DeclSyntax = """ - public init(_ enumValue: \(raw: name), environment: JNIEnvironment? = nil) { - let _environment = if let environment { - environment - } else { - try! JavaVirtualMachine.shared().environment() - } - let classObj = try! JavaClass(environment: _environment) - switch enumValue { - \(raw: enumFields.map { - return """ - case .\($0.getName()): - if let \($0.getName()) = classObj.\($0.getName()) { - self = \($0.getName()) - } else { - fatalError("Enum value \($0.getName()) was unexpectedly nil, please re-run Java2Swift on the most updated Java class") - } - """ - }.joined(separator: "\n")) - } - } - """ - - return [extensionSyntax, mappingSyntax, initSyntax] - } - - // Translate a Java parameter list into Swift parameters. - private func translateParameters(_ parameters: [Parameter?]) throws -> [FunctionParameterSyntax] { - return try parameters.compactMap { javaParameter in - guard let javaParameter else { return nil } - - let typeName = try getSwiftTypeNameAsString(javaParameter.getParameterizedType()!, outerOptional: true) - let paramName = javaParameter.getName() - return "_ \(raw: paramName): \(raw: typeName)" - } + return try JavaClassTranslator(javaClass: javaClass, translator: self).render() } } diff --git a/Sources/JavaKitReflection/Constructor+Utilities.swift b/Sources/JavaKitReflection/Constructor+Utilities.swift index 0eed3edd..676a6283 100644 --- a/Sources/JavaKitReflection/Constructor+Utilities.swift +++ b/Sources/JavaKitReflection/Constructor+Utilities.swift @@ -13,7 +13,12 @@ //===----------------------------------------------------------------------===// extension Constructor { - /// Whether this is a 'native' method. + /// Whether this is a 'public' constructor. + public var isPublic: Bool { + return (getModifiers() & 1) != 0 + } + + /// Whether this is a 'native' constructor. public var isNative: Bool { return (getModifiers() & 256) != 0 } diff --git a/Sources/JavaKitReflection/Method+Utilities.swift b/Sources/JavaKitReflection/Method+Utilities.swift index 28556c0f..1b632337 100644 --- a/Sources/JavaKitReflection/Method+Utilities.swift +++ b/Sources/JavaKitReflection/Method+Utilities.swift @@ -13,6 +13,11 @@ //===----------------------------------------------------------------------===// extension Method { + /// Whether this is a 'public' method. + public var isPublic: Bool { + return (getModifiers() & 1) != 0 + } + /// Whether this is a 'static' method. public var isStatic: Bool { return (getModifiers() & 0x08) != 0 From bce97333ca7d2e9d1920a5b598c58013a3b23255 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Sun, 27 Oct 2024 23:13:13 -0700 Subject: [PATCH 132/426] Java2Swift: Account for covariant overrides so we don't have duplicates When we see methods with the same name and parameter types but different result types, check whether the result types are related and only keep the more specialized method. --- .../Java2SwiftLib/JavaClassTranslator.swift | 50 +++++++-- Sources/Java2SwiftLib/MethodVariance.swift | 102 ++++++++++++++++++ 2 files changed, 146 insertions(+), 6 deletions(-) create mode 100644 Sources/Java2SwiftLib/MethodVariance.swift diff --git a/Sources/Java2SwiftLib/JavaClassTranslator.swift b/Sources/Java2SwiftLib/JavaClassTranslator.swift index 906f17a4..f8aecec7 100644 --- a/Sources/Java2SwiftLib/JavaClassTranslator.swift +++ b/Sources/Java2SwiftLib/JavaClassTranslator.swift @@ -57,10 +57,10 @@ struct JavaClassTranslator { var constructors: [Constructor] = [] /// The (instance) methods of the Java class. - var methods: [Method] = [] + var methods: MethodCollector = MethodCollector() /// The static methods of the Java class. - var staticMethods: [Method] = [] + var staticMethods: MethodCollector = MethodCollector() /// The native instance methods of the Java class, which are also reflected /// in a `*NativeMethods` protocol so they can be implemented in Swift. @@ -215,8 +215,8 @@ extension JavaClassTranslator { /// Add a method to the appropriate list for later translation. private mutating func addMethod(_ method: Method, isNative: Bool) { switch (method.isStatic, isNative) { - case (false, false): methods.append(method) - case (true, false): staticMethods.append(method) + case (false, false): methods.add(method) + case (true, false): staticMethods.add(method) case (false, true): nativeMethods.append(method) case (true, true): nativeStaticMethods.append(method) } @@ -266,7 +266,7 @@ extension JavaClassTranslator { } // Render all of the instance methods in Swift. - let instanceMethods = methods.compactMap { method in + let instanceMethods = methods.methods.compactMap { method in do { return try renderMethod(method, implementedInSwift: false) } catch { @@ -355,7 +355,7 @@ extension JavaClassTranslator { } // Render static methods. - let methods = staticMethods.compactMap { method in + let methods = staticMethods.methods.compactMap { method in // Translate each static method. do { return try renderMethod( @@ -553,3 +553,41 @@ extension JavaClassTranslator { } } } + +/// Helper struct that collects methods, removing any that have been overridden +/// by a covariant method. +struct MethodCollector { + var methods: [Method] = [] + + /// Mapping from method names to the indices of each method within the + /// list of methods. + var methodsByName: [String: [Int]] = [:] + + /// Add this method to the collector. + mutating func add(_ method: Method) { + // Compare against existing methods with this same name. + for existingMethodIndex in methodsByName[method.getName()] ?? [] { + let existingMethod = methods[existingMethodIndex] + switch MethodVariance(method, existingMethod) { + case .equivalent, .unrelated: + // Nothing to do. + continue + + case .contravariantResult: + // This method is worse than what we have; there is nothing to do. + return + + case .covariantResult: + // This method is better than the one we have; replace the one we + // have with it. + methods[existingMethodIndex] = method + return + } + } + + // If we get here, there is no related method in the list. Add this + // new method. + methodsByName[method.getName(), default: []].append(methods.count) + methods.append(method) + } +} diff --git a/Sources/Java2SwiftLib/MethodVariance.swift b/Sources/Java2SwiftLib/MethodVariance.swift new file mode 100644 index 00000000..09bd6444 --- /dev/null +++ b/Sources/Java2SwiftLib/MethodVariance.swift @@ -0,0 +1,102 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// +import JavaKit +import JavaKitReflection + +/// Captures the relationship between two methods by comparing their parameter +/// and result types. +enum MethodVariance { + /// The methods are equivalent. + case equivalent + + /// The methods are unrelated, e.g., some parameter types are different or + /// the return types cannot be compared. + case unrelated + + /// The second method is covariant with the first, meaning that its result + /// type is a subclass of the result type of the first method. + case covariantResult + + /// The second method is contravariant with the first, meaning that its result + /// type is a superclass of the result type of the first method. + /// + /// This is the same as getting a covariant result when flipping the order + /// of the methods. + case contravariantResult + + init(_ first: Method, _ second: Method) { + // If there are obvious differences, note that these are unrelated. + if first.getName() != second.getName() || + first.isStatic != second.isStatic || + first.getParameterCount() != second.getParameterCount() { + self = .unrelated + return + } + + // Check the parameter types. + for (firstParamType, secondParamType) in zip(first.getParameterTypes(), second.getParameterTypes()) { + guard let firstParamType, let secondParamType else { continue } + + // If the parameter types don't match, these methods are unrelated. + guard firstParamType.equals(secondParamType.as(JavaObject.self)) else { + self = .unrelated + return + } + } + + // Check the result type. + let firstResultType = first.getReturnType()! + let secondResultType = second.getReturnType()! + + // If the result types are equivalent, the methods are equivalent. + if firstResultType.equals(secondResultType.as(JavaObject.self)) { + self = .equivalent + return + } + + // If first result type is a subclass of the second result type, it's + // covariant. + if firstResultType.isSubclass(of: secondResultType.as(JavaClass.self)!) { + self = .covariantResult + return + } + + // If second result type is a subclass of the first result type, it's + // contravariant. + if secondResultType.isSubclass(of: firstResultType.as(JavaClass.self)!) { + self = .contravariantResult + return + } + + // Treat the methods as unrelated, because we cannot compare their result + // types. + self = .unrelated + } +} + +extension JavaClass { + /// Whether this Java class is a subclass of the other Java class. + func isSubclass(of other: JavaClass) -> Bool { + var current = self.as(JavaClass.self) + while let currentClass = current { + if currentClass.equals(other.as(JavaObject.self)) { + return true + } + + current = currentClass.getSuperclass() + } + + return false + } +} From 3ea7c334562d047bfeb43239bd06aac7b5531823 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Sun, 27 Oct 2024 23:20:53 -0700 Subject: [PATCH 133/426] Regenerate JavaKit sources --- Sources/JavaKit/generated/JavaCharacter.swift | 3135 +++++++++++++++++ .../generated/ArrayDeque.swift | 3 - .../JavaKitCollection/generated/TreeMap.swift | 86 + 3 files changed, 3221 insertions(+), 3 deletions(-) diff --git a/Sources/JavaKit/generated/JavaCharacter.swift b/Sources/JavaKit/generated/JavaCharacter.swift index 68412f22..ccf11323 100644 --- a/Sources/JavaKit/generated/JavaCharacter.swift +++ b/Sources/JavaKit/generated/JavaCharacter.swift @@ -42,6 +42,3141 @@ public struct JavaCharacter { @JavaMethod public func wait() throws } +extension JavaCharacter { + @JavaClass("java.lang.Character$UnicodeBlock", extends: JavaCharacter.Subset.self) + public struct UnicodeBlock { + @JavaMethod + public func equals(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func toString() -> String + + @JavaMethod + public func hashCode() -> Int32 + + @JavaMethod + public func getClass() -> JavaClass? + + @JavaMethod + public func notify() + + @JavaMethod + public func notifyAll() + + @JavaMethod + public func wait(_ arg0: Int64) throws + + @JavaMethod + public func wait(_ arg0: Int64, _ arg1: Int32) throws + + @JavaMethod + public func wait() throws + } +} +extension JavaClass { + @JavaStaticField(isFinal: true) + public var BASIC_LATIN: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var LATIN_1_SUPPLEMENT: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var LATIN_EXTENDED_A: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var LATIN_EXTENDED_B: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var IPA_EXTENSIONS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var SPACING_MODIFIER_LETTERS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var COMBINING_DIACRITICAL_MARKS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var GREEK: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var CYRILLIC: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var ARMENIAN: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var HEBREW: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var ARABIC: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var DEVANAGARI: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var BENGALI: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var GURMUKHI: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var GUJARATI: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var ORIYA: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var TAMIL: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var TELUGU: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var KANNADA: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var MALAYALAM: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var THAI: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var LAO: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var TIBETAN: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var GEORGIAN: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var HANGUL_JAMO: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var LATIN_EXTENDED_ADDITIONAL: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var GREEK_EXTENDED: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var GENERAL_PUNCTUATION: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var SUPERSCRIPTS_AND_SUBSCRIPTS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var CURRENCY_SYMBOLS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var COMBINING_MARKS_FOR_SYMBOLS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var LETTERLIKE_SYMBOLS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var NUMBER_FORMS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var ARROWS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var MATHEMATICAL_OPERATORS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var MISCELLANEOUS_TECHNICAL: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var CONTROL_PICTURES: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var OPTICAL_CHARACTER_RECOGNITION: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var ENCLOSED_ALPHANUMERICS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var BOX_DRAWING: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var BLOCK_ELEMENTS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var GEOMETRIC_SHAPES: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var MISCELLANEOUS_SYMBOLS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var DINGBATS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var CJK_SYMBOLS_AND_PUNCTUATION: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var HIRAGANA: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var KATAKANA: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var BOPOMOFO: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var HANGUL_COMPATIBILITY_JAMO: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var KANBUN: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var ENCLOSED_CJK_LETTERS_AND_MONTHS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var CJK_COMPATIBILITY: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var CJK_UNIFIED_IDEOGRAPHS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var HANGUL_SYLLABLES: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var PRIVATE_USE_AREA: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var CJK_COMPATIBILITY_IDEOGRAPHS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var ALPHABETIC_PRESENTATION_FORMS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var ARABIC_PRESENTATION_FORMS_A: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var COMBINING_HALF_MARKS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var CJK_COMPATIBILITY_FORMS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var SMALL_FORM_VARIANTS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var ARABIC_PRESENTATION_FORMS_B: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var HALFWIDTH_AND_FULLWIDTH_FORMS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var SPECIALS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var SURROGATES_AREA: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var SYRIAC: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var THAANA: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var SINHALA: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var MYANMAR: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var ETHIOPIC: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var CHEROKEE: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var OGHAM: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var RUNIC: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var KHMER: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var MONGOLIAN: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var BRAILLE_PATTERNS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var CJK_RADICALS_SUPPLEMENT: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var KANGXI_RADICALS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var IDEOGRAPHIC_DESCRIPTION_CHARACTERS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var BOPOMOFO_EXTENDED: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var YI_SYLLABLES: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var YI_RADICALS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var CYRILLIC_SUPPLEMENTARY: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var TAGALOG: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var HANUNOO: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var BUHID: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var TAGBANWA: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var LIMBU: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var TAI_LE: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var KHMER_SYMBOLS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var PHONETIC_EXTENSIONS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var MISCELLANEOUS_MATHEMATICAL_SYMBOLS_A: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var SUPPLEMENTAL_ARROWS_A: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var SUPPLEMENTAL_ARROWS_B: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var MISCELLANEOUS_MATHEMATICAL_SYMBOLS_B: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var SUPPLEMENTAL_MATHEMATICAL_OPERATORS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var MISCELLANEOUS_SYMBOLS_AND_ARROWS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var KATAKANA_PHONETIC_EXTENSIONS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var YIJING_HEXAGRAM_SYMBOLS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var VARIATION_SELECTORS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var LINEAR_B_SYLLABARY: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var LINEAR_B_IDEOGRAMS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var AEGEAN_NUMBERS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var OLD_ITALIC: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var GOTHIC: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var UGARITIC: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var DESERET: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var SHAVIAN: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var OSMANYA: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var CYPRIOT_SYLLABARY: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var BYZANTINE_MUSICAL_SYMBOLS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var MUSICAL_SYMBOLS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var TAI_XUAN_JING_SYMBOLS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var MATHEMATICAL_ALPHANUMERIC_SYMBOLS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var TAGS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var VARIATION_SELECTORS_SUPPLEMENT: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var SUPPLEMENTARY_PRIVATE_USE_AREA_A: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var SUPPLEMENTARY_PRIVATE_USE_AREA_B: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var HIGH_SURROGATES: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var HIGH_PRIVATE_USE_SURROGATES: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var LOW_SURROGATES: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var ARABIC_SUPPLEMENT: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var NKO: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var SAMARITAN: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var MANDAIC: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var ETHIOPIC_SUPPLEMENT: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS_EXTENDED: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var NEW_TAI_LUE: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var BUGINESE: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var TAI_THAM: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var BALINESE: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var SUNDANESE: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var BATAK: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var LEPCHA: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var OL_CHIKI: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var VEDIC_EXTENSIONS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var PHONETIC_EXTENSIONS_SUPPLEMENT: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var COMBINING_DIACRITICAL_MARKS_SUPPLEMENT: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var GLAGOLITIC: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var LATIN_EXTENDED_C: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var COPTIC: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var GEORGIAN_SUPPLEMENT: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var TIFINAGH: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var ETHIOPIC_EXTENDED: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var CYRILLIC_EXTENDED_A: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var SUPPLEMENTAL_PUNCTUATION: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var CJK_STROKES: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var LISU: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var VAI: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var CYRILLIC_EXTENDED_B: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var BAMUM: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var MODIFIER_TONE_LETTERS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var LATIN_EXTENDED_D: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var SYLOTI_NAGRI: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var COMMON_INDIC_NUMBER_FORMS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var PHAGS_PA: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var SAURASHTRA: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var DEVANAGARI_EXTENDED: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var KAYAH_LI: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var REJANG: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var HANGUL_JAMO_EXTENDED_A: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var JAVANESE: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var CHAM: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var MYANMAR_EXTENDED_A: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var TAI_VIET: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var ETHIOPIC_EXTENDED_A: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var MEETEI_MAYEK: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var HANGUL_JAMO_EXTENDED_B: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var VERTICAL_FORMS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var ANCIENT_GREEK_NUMBERS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var ANCIENT_SYMBOLS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var PHAISTOS_DISC: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var LYCIAN: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var CARIAN: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var OLD_PERSIAN: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var IMPERIAL_ARAMAIC: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var PHOENICIAN: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var LYDIAN: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var KHAROSHTHI: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var OLD_SOUTH_ARABIAN: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var AVESTAN: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var INSCRIPTIONAL_PARTHIAN: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var INSCRIPTIONAL_PAHLAVI: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var OLD_TURKIC: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var RUMI_NUMERAL_SYMBOLS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var BRAHMI: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var KAITHI: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var CUNEIFORM: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var CUNEIFORM_NUMBERS_AND_PUNCTUATION: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var EGYPTIAN_HIEROGLYPHS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var BAMUM_SUPPLEMENT: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var KANA_SUPPLEMENT: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var ANCIENT_GREEK_MUSICAL_NOTATION: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var COUNTING_ROD_NUMERALS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var MAHJONG_TILES: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var DOMINO_TILES: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var PLAYING_CARDS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var ENCLOSED_ALPHANUMERIC_SUPPLEMENT: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var ENCLOSED_IDEOGRAPHIC_SUPPLEMENT: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var MISCELLANEOUS_SYMBOLS_AND_PICTOGRAPHS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var EMOTICONS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var TRANSPORT_AND_MAP_SYMBOLS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var ALCHEMICAL_SYMBOLS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var CJK_UNIFIED_IDEOGRAPHS_EXTENSION_C: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var CJK_UNIFIED_IDEOGRAPHS_EXTENSION_D: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var ARABIC_EXTENDED_A: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var SUNDANESE_SUPPLEMENT: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var MEETEI_MAYEK_EXTENSIONS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var MEROITIC_HIEROGLYPHS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var MEROITIC_CURSIVE: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var SORA_SOMPENG: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var CHAKMA: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var SHARADA: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var TAKRI: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var MIAO: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var ARABIC_MATHEMATICAL_ALPHABETIC_SYMBOLS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var COMBINING_DIACRITICAL_MARKS_EXTENDED: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var MYANMAR_EXTENDED_B: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var LATIN_EXTENDED_E: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var COPTIC_EPACT_NUMBERS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var OLD_PERMIC: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var ELBASAN: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var CAUCASIAN_ALBANIAN: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var LINEAR_A: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var PALMYRENE: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var NABATAEAN: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var OLD_NORTH_ARABIAN: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var MANICHAEAN: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var PSALTER_PAHLAVI: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var MAHAJANI: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var SINHALA_ARCHAIC_NUMBERS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var KHOJKI: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var KHUDAWADI: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var GRANTHA: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var TIRHUTA: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var SIDDHAM: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var MODI: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var WARANG_CITI: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var PAU_CIN_HAU: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var MRO: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var BASSA_VAH: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var PAHAWH_HMONG: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var DUPLOYAN: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var SHORTHAND_FORMAT_CONTROLS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var MENDE_KIKAKUI: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var ORNAMENTAL_DINGBATS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var GEOMETRIC_SHAPES_EXTENDED: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var SUPPLEMENTAL_ARROWS_C: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var CHEROKEE_SUPPLEMENT: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var HATRAN: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var OLD_HUNGARIAN: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var MULTANI: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var AHOM: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var EARLY_DYNASTIC_CUNEIFORM: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var ANATOLIAN_HIEROGLYPHS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var SUTTON_SIGNWRITING: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var SUPPLEMENTAL_SYMBOLS_AND_PICTOGRAPHS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var CJK_UNIFIED_IDEOGRAPHS_EXTENSION_E: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var SYRIAC_SUPPLEMENT: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var CYRILLIC_EXTENDED_C: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var OSAGE: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var NEWA: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var MONGOLIAN_SUPPLEMENT: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var MARCHEN: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var IDEOGRAPHIC_SYMBOLS_AND_PUNCTUATION: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var TANGUT: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var TANGUT_COMPONENTS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var KANA_EXTENDED_A: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var GLAGOLITIC_SUPPLEMENT: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var ADLAM: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var MASARAM_GONDI: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var ZANABAZAR_SQUARE: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var NUSHU: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var SOYOMBO: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var BHAIKSUKI: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var CJK_UNIFIED_IDEOGRAPHS_EXTENSION_F: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var GEORGIAN_EXTENDED: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var HANIFI_ROHINGYA: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var OLD_SOGDIAN: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var SOGDIAN: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var DOGRA: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var GUNJALA_GONDI: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var MAKASAR: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var MEDEFAIDRIN: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var MAYAN_NUMERALS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var INDIC_SIYAQ_NUMBERS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var CHESS_SYMBOLS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var ELYMAIC: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var NANDINAGARI: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var TAMIL_SUPPLEMENT: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var EGYPTIAN_HIEROGLYPH_FORMAT_CONTROLS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var SMALL_KANA_EXTENSION: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var NYIAKENG_PUACHUE_HMONG: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var WANCHO: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var OTTOMAN_SIYAQ_NUMBERS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var SYMBOLS_AND_PICTOGRAPHS_EXTENDED_A: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var YEZIDI: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var CHORASMIAN: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var DIVES_AKURU: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var LISU_SUPPLEMENT: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var KHITAN_SMALL_SCRIPT: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var TANGUT_SUPPLEMENT: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var SYMBOLS_FOR_LEGACY_COMPUTING: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var CJK_UNIFIED_IDEOGRAPHS_EXTENSION_G: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var ARABIC_EXTENDED_B: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var VITHKUQI: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var LATIN_EXTENDED_F: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var OLD_UYGHUR: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS_EXTENDED_A: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var CYPRO_MINOAN: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var TANGSA: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var KANA_EXTENDED_B: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var ZNAMENNY_MUSICAL_NOTATION: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var LATIN_EXTENDED_G: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var TOTO: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var ETHIOPIC_EXTENDED_B: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var ARABIC_EXTENDED_C: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var DEVANAGARI_EXTENDED_A: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var KAWI: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var KAKTOVIK_NUMERALS: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var CYRILLIC_EXTENDED_D: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var NAG_MUNDARI: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var CJK_UNIFIED_IDEOGRAPHS_EXTENSION_H: JavaCharacter.UnicodeBlock? + + @JavaStaticField(isFinal: true) + public var CJK_UNIFIED_IDEOGRAPHS_EXTENSION_I: JavaCharacter.UnicodeBlock? + + @JavaStaticMethod + public func forName(_ arg0: String) -> JavaCharacter.UnicodeBlock? + + @JavaStaticMethod + public func of(_ arg0: Int32) -> JavaCharacter.UnicodeBlock? + + @JavaStaticMethod + public func of(_ arg0: UInt16) -> JavaCharacter.UnicodeBlock? +} +extension JavaCharacter { + @JavaClass("java.lang.Character$UnicodeScript") + public struct UnicodeScript { + public enum UnicodeScriptCases: Equatable { + case COMMON + case LATIN + case GREEK + case CYRILLIC + case ARMENIAN + case HEBREW + case ARABIC + case SYRIAC + case THAANA + case DEVANAGARI + case BENGALI + case GURMUKHI + case GUJARATI + case ORIYA + case TAMIL + case TELUGU + case KANNADA + case MALAYALAM + case SINHALA + case THAI + case LAO + case TIBETAN + case MYANMAR + case GEORGIAN + case HANGUL + case ETHIOPIC + case CHEROKEE + case CANADIAN_ABORIGINAL + case OGHAM + case RUNIC + case KHMER + case MONGOLIAN + case HIRAGANA + case KATAKANA + case BOPOMOFO + case HAN + case YI + case OLD_ITALIC + case GOTHIC + case DESERET + case INHERITED + case TAGALOG + case HANUNOO + case BUHID + case TAGBANWA + case LIMBU + case TAI_LE + case LINEAR_B + case UGARITIC + case SHAVIAN + case OSMANYA + case CYPRIOT + case BRAILLE + case BUGINESE + case COPTIC + case NEW_TAI_LUE + case GLAGOLITIC + case TIFINAGH + case SYLOTI_NAGRI + case OLD_PERSIAN + case KHAROSHTHI + case BALINESE + case CUNEIFORM + case PHOENICIAN + case PHAGS_PA + case NKO + case SUNDANESE + case BATAK + case LEPCHA + case OL_CHIKI + case VAI + case SAURASHTRA + case KAYAH_LI + case REJANG + case LYCIAN + case CARIAN + case LYDIAN + case CHAM + case TAI_THAM + case TAI_VIET + case AVESTAN + case EGYPTIAN_HIEROGLYPHS + case SAMARITAN + case MANDAIC + case LISU + case BAMUM + case JAVANESE + case MEETEI_MAYEK + case IMPERIAL_ARAMAIC + case OLD_SOUTH_ARABIAN + case INSCRIPTIONAL_PARTHIAN + case INSCRIPTIONAL_PAHLAVI + case OLD_TURKIC + case BRAHMI + case KAITHI + case MEROITIC_HIEROGLYPHS + case MEROITIC_CURSIVE + case SORA_SOMPENG + case CHAKMA + case SHARADA + case TAKRI + case MIAO + case CAUCASIAN_ALBANIAN + case BASSA_VAH + case DUPLOYAN + case ELBASAN + case GRANTHA + case PAHAWH_HMONG + case KHOJKI + case LINEAR_A + case MAHAJANI + case MANICHAEAN + case MENDE_KIKAKUI + case MODI + case MRO + case OLD_NORTH_ARABIAN + case NABATAEAN + case PALMYRENE + case PAU_CIN_HAU + case OLD_PERMIC + case PSALTER_PAHLAVI + case SIDDHAM + case KHUDAWADI + case TIRHUTA + case WARANG_CITI + case AHOM + case ANATOLIAN_HIEROGLYPHS + case HATRAN + case MULTANI + case OLD_HUNGARIAN + case SIGNWRITING + case ADLAM + case BHAIKSUKI + case MARCHEN + case NEWA + case OSAGE + case TANGUT + case MASARAM_GONDI + case NUSHU + case SOYOMBO + case ZANABAZAR_SQUARE + case HANIFI_ROHINGYA + case OLD_SOGDIAN + case SOGDIAN + case DOGRA + case GUNJALA_GONDI + case MAKASAR + case MEDEFAIDRIN + case ELYMAIC + case NANDINAGARI + case NYIAKENG_PUACHUE_HMONG + case WANCHO + case YEZIDI + case CHORASMIAN + case DIVES_AKURU + case KHITAN_SMALL_SCRIPT + case VITHKUQI + case OLD_UYGHUR + case CYPRO_MINOAN + case TANGSA + case TOTO + case KAWI + case NAG_MUNDARI + case UNKNOWN + } + + public var enumValue: UnicodeScriptCases? { + let classObj = self.javaClass + if self.equals(classObj.COMMON?.as(JavaObject.self)) { + return UnicodeScriptCases.COMMON + } else if self.equals(classObj.LATIN?.as(JavaObject.self)) { + return UnicodeScriptCases.LATIN + } else if self.equals(classObj.GREEK?.as(JavaObject.self)) { + return UnicodeScriptCases.GREEK + } else if self.equals(classObj.CYRILLIC?.as(JavaObject.self)) { + return UnicodeScriptCases.CYRILLIC + } else if self.equals(classObj.ARMENIAN?.as(JavaObject.self)) { + return UnicodeScriptCases.ARMENIAN + } else if self.equals(classObj.HEBREW?.as(JavaObject.self)) { + return UnicodeScriptCases.HEBREW + } else if self.equals(classObj.ARABIC?.as(JavaObject.self)) { + return UnicodeScriptCases.ARABIC + } else if self.equals(classObj.SYRIAC?.as(JavaObject.self)) { + return UnicodeScriptCases.SYRIAC + } else if self.equals(classObj.THAANA?.as(JavaObject.self)) { + return UnicodeScriptCases.THAANA + } else if self.equals(classObj.DEVANAGARI?.as(JavaObject.self)) { + return UnicodeScriptCases.DEVANAGARI + } else if self.equals(classObj.BENGALI?.as(JavaObject.self)) { + return UnicodeScriptCases.BENGALI + } else if self.equals(classObj.GURMUKHI?.as(JavaObject.self)) { + return UnicodeScriptCases.GURMUKHI + } else if self.equals(classObj.GUJARATI?.as(JavaObject.self)) { + return UnicodeScriptCases.GUJARATI + } else if self.equals(classObj.ORIYA?.as(JavaObject.self)) { + return UnicodeScriptCases.ORIYA + } else if self.equals(classObj.TAMIL?.as(JavaObject.self)) { + return UnicodeScriptCases.TAMIL + } else if self.equals(classObj.TELUGU?.as(JavaObject.self)) { + return UnicodeScriptCases.TELUGU + } else if self.equals(classObj.KANNADA?.as(JavaObject.self)) { + return UnicodeScriptCases.KANNADA + } else if self.equals(classObj.MALAYALAM?.as(JavaObject.self)) { + return UnicodeScriptCases.MALAYALAM + } else if self.equals(classObj.SINHALA?.as(JavaObject.self)) { + return UnicodeScriptCases.SINHALA + } else if self.equals(classObj.THAI?.as(JavaObject.self)) { + return UnicodeScriptCases.THAI + } else if self.equals(classObj.LAO?.as(JavaObject.self)) { + return UnicodeScriptCases.LAO + } else if self.equals(classObj.TIBETAN?.as(JavaObject.self)) { + return UnicodeScriptCases.TIBETAN + } else if self.equals(classObj.MYANMAR?.as(JavaObject.self)) { + return UnicodeScriptCases.MYANMAR + } else if self.equals(classObj.GEORGIAN?.as(JavaObject.self)) { + return UnicodeScriptCases.GEORGIAN + } else if self.equals(classObj.HANGUL?.as(JavaObject.self)) { + return UnicodeScriptCases.HANGUL + } else if self.equals(classObj.ETHIOPIC?.as(JavaObject.self)) { + return UnicodeScriptCases.ETHIOPIC + } else if self.equals(classObj.CHEROKEE?.as(JavaObject.self)) { + return UnicodeScriptCases.CHEROKEE + } else if self.equals(classObj.CANADIAN_ABORIGINAL?.as(JavaObject.self)) { + return UnicodeScriptCases.CANADIAN_ABORIGINAL + } else if self.equals(classObj.OGHAM?.as(JavaObject.self)) { + return UnicodeScriptCases.OGHAM + } else if self.equals(classObj.RUNIC?.as(JavaObject.self)) { + return UnicodeScriptCases.RUNIC + } else if self.equals(classObj.KHMER?.as(JavaObject.self)) { + return UnicodeScriptCases.KHMER + } else if self.equals(classObj.MONGOLIAN?.as(JavaObject.self)) { + return UnicodeScriptCases.MONGOLIAN + } else if self.equals(classObj.HIRAGANA?.as(JavaObject.self)) { + return UnicodeScriptCases.HIRAGANA + } else if self.equals(classObj.KATAKANA?.as(JavaObject.self)) { + return UnicodeScriptCases.KATAKANA + } else if self.equals(classObj.BOPOMOFO?.as(JavaObject.self)) { + return UnicodeScriptCases.BOPOMOFO + } else if self.equals(classObj.HAN?.as(JavaObject.self)) { + return UnicodeScriptCases.HAN + } else if self.equals(classObj.YI?.as(JavaObject.self)) { + return UnicodeScriptCases.YI + } else if self.equals(classObj.OLD_ITALIC?.as(JavaObject.self)) { + return UnicodeScriptCases.OLD_ITALIC + } else if self.equals(classObj.GOTHIC?.as(JavaObject.self)) { + return UnicodeScriptCases.GOTHIC + } else if self.equals(classObj.DESERET?.as(JavaObject.self)) { + return UnicodeScriptCases.DESERET + } else if self.equals(classObj.INHERITED?.as(JavaObject.self)) { + return UnicodeScriptCases.INHERITED + } else if self.equals(classObj.TAGALOG?.as(JavaObject.self)) { + return UnicodeScriptCases.TAGALOG + } else if self.equals(classObj.HANUNOO?.as(JavaObject.self)) { + return UnicodeScriptCases.HANUNOO + } else if self.equals(classObj.BUHID?.as(JavaObject.self)) { + return UnicodeScriptCases.BUHID + } else if self.equals(classObj.TAGBANWA?.as(JavaObject.self)) { + return UnicodeScriptCases.TAGBANWA + } else if self.equals(classObj.LIMBU?.as(JavaObject.self)) { + return UnicodeScriptCases.LIMBU + } else if self.equals(classObj.TAI_LE?.as(JavaObject.self)) { + return UnicodeScriptCases.TAI_LE + } else if self.equals(classObj.LINEAR_B?.as(JavaObject.self)) { + return UnicodeScriptCases.LINEAR_B + } else if self.equals(classObj.UGARITIC?.as(JavaObject.self)) { + return UnicodeScriptCases.UGARITIC + } else if self.equals(classObj.SHAVIAN?.as(JavaObject.self)) { + return UnicodeScriptCases.SHAVIAN + } else if self.equals(classObj.OSMANYA?.as(JavaObject.self)) { + return UnicodeScriptCases.OSMANYA + } else if self.equals(classObj.CYPRIOT?.as(JavaObject.self)) { + return UnicodeScriptCases.CYPRIOT + } else if self.equals(classObj.BRAILLE?.as(JavaObject.self)) { + return UnicodeScriptCases.BRAILLE + } else if self.equals(classObj.BUGINESE?.as(JavaObject.self)) { + return UnicodeScriptCases.BUGINESE + } else if self.equals(classObj.COPTIC?.as(JavaObject.self)) { + return UnicodeScriptCases.COPTIC + } else if self.equals(classObj.NEW_TAI_LUE?.as(JavaObject.self)) { + return UnicodeScriptCases.NEW_TAI_LUE + } else if self.equals(classObj.GLAGOLITIC?.as(JavaObject.self)) { + return UnicodeScriptCases.GLAGOLITIC + } else if self.equals(classObj.TIFINAGH?.as(JavaObject.self)) { + return UnicodeScriptCases.TIFINAGH + } else if self.equals(classObj.SYLOTI_NAGRI?.as(JavaObject.self)) { + return UnicodeScriptCases.SYLOTI_NAGRI + } else if self.equals(classObj.OLD_PERSIAN?.as(JavaObject.self)) { + return UnicodeScriptCases.OLD_PERSIAN + } else if self.equals(classObj.KHAROSHTHI?.as(JavaObject.self)) { + return UnicodeScriptCases.KHAROSHTHI + } else if self.equals(classObj.BALINESE?.as(JavaObject.self)) { + return UnicodeScriptCases.BALINESE + } else if self.equals(classObj.CUNEIFORM?.as(JavaObject.self)) { + return UnicodeScriptCases.CUNEIFORM + } else if self.equals(classObj.PHOENICIAN?.as(JavaObject.self)) { + return UnicodeScriptCases.PHOENICIAN + } else if self.equals(classObj.PHAGS_PA?.as(JavaObject.self)) { + return UnicodeScriptCases.PHAGS_PA + } else if self.equals(classObj.NKO?.as(JavaObject.self)) { + return UnicodeScriptCases.NKO + } else if self.equals(classObj.SUNDANESE?.as(JavaObject.self)) { + return UnicodeScriptCases.SUNDANESE + } else if self.equals(classObj.BATAK?.as(JavaObject.self)) { + return UnicodeScriptCases.BATAK + } else if self.equals(classObj.LEPCHA?.as(JavaObject.self)) { + return UnicodeScriptCases.LEPCHA + } else if self.equals(classObj.OL_CHIKI?.as(JavaObject.self)) { + return UnicodeScriptCases.OL_CHIKI + } else if self.equals(classObj.VAI?.as(JavaObject.self)) { + return UnicodeScriptCases.VAI + } else if self.equals(classObj.SAURASHTRA?.as(JavaObject.self)) { + return UnicodeScriptCases.SAURASHTRA + } else if self.equals(classObj.KAYAH_LI?.as(JavaObject.self)) { + return UnicodeScriptCases.KAYAH_LI + } else if self.equals(classObj.REJANG?.as(JavaObject.self)) { + return UnicodeScriptCases.REJANG + } else if self.equals(classObj.LYCIAN?.as(JavaObject.self)) { + return UnicodeScriptCases.LYCIAN + } else if self.equals(classObj.CARIAN?.as(JavaObject.self)) { + return UnicodeScriptCases.CARIAN + } else if self.equals(classObj.LYDIAN?.as(JavaObject.self)) { + return UnicodeScriptCases.LYDIAN + } else if self.equals(classObj.CHAM?.as(JavaObject.self)) { + return UnicodeScriptCases.CHAM + } else if self.equals(classObj.TAI_THAM?.as(JavaObject.self)) { + return UnicodeScriptCases.TAI_THAM + } else if self.equals(classObj.TAI_VIET?.as(JavaObject.self)) { + return UnicodeScriptCases.TAI_VIET + } else if self.equals(classObj.AVESTAN?.as(JavaObject.self)) { + return UnicodeScriptCases.AVESTAN + } else if self.equals(classObj.EGYPTIAN_HIEROGLYPHS?.as(JavaObject.self)) { + return UnicodeScriptCases.EGYPTIAN_HIEROGLYPHS + } else if self.equals(classObj.SAMARITAN?.as(JavaObject.self)) { + return UnicodeScriptCases.SAMARITAN + } else if self.equals(classObj.MANDAIC?.as(JavaObject.self)) { + return UnicodeScriptCases.MANDAIC + } else if self.equals(classObj.LISU?.as(JavaObject.self)) { + return UnicodeScriptCases.LISU + } else if self.equals(classObj.BAMUM?.as(JavaObject.self)) { + return UnicodeScriptCases.BAMUM + } else if self.equals(classObj.JAVANESE?.as(JavaObject.self)) { + return UnicodeScriptCases.JAVANESE + } else if self.equals(classObj.MEETEI_MAYEK?.as(JavaObject.self)) { + return UnicodeScriptCases.MEETEI_MAYEK + } else if self.equals(classObj.IMPERIAL_ARAMAIC?.as(JavaObject.self)) { + return UnicodeScriptCases.IMPERIAL_ARAMAIC + } else if self.equals(classObj.OLD_SOUTH_ARABIAN?.as(JavaObject.self)) { + return UnicodeScriptCases.OLD_SOUTH_ARABIAN + } else if self.equals(classObj.INSCRIPTIONAL_PARTHIAN?.as(JavaObject.self)) { + return UnicodeScriptCases.INSCRIPTIONAL_PARTHIAN + } else if self.equals(classObj.INSCRIPTIONAL_PAHLAVI?.as(JavaObject.self)) { + return UnicodeScriptCases.INSCRIPTIONAL_PAHLAVI + } else if self.equals(classObj.OLD_TURKIC?.as(JavaObject.self)) { + return UnicodeScriptCases.OLD_TURKIC + } else if self.equals(classObj.BRAHMI?.as(JavaObject.self)) { + return UnicodeScriptCases.BRAHMI + } else if self.equals(classObj.KAITHI?.as(JavaObject.self)) { + return UnicodeScriptCases.KAITHI + } else if self.equals(classObj.MEROITIC_HIEROGLYPHS?.as(JavaObject.self)) { + return UnicodeScriptCases.MEROITIC_HIEROGLYPHS + } else if self.equals(classObj.MEROITIC_CURSIVE?.as(JavaObject.self)) { + return UnicodeScriptCases.MEROITIC_CURSIVE + } else if self.equals(classObj.SORA_SOMPENG?.as(JavaObject.self)) { + return UnicodeScriptCases.SORA_SOMPENG + } else if self.equals(classObj.CHAKMA?.as(JavaObject.self)) { + return UnicodeScriptCases.CHAKMA + } else if self.equals(classObj.SHARADA?.as(JavaObject.self)) { + return UnicodeScriptCases.SHARADA + } else if self.equals(classObj.TAKRI?.as(JavaObject.self)) { + return UnicodeScriptCases.TAKRI + } else if self.equals(classObj.MIAO?.as(JavaObject.self)) { + return UnicodeScriptCases.MIAO + } else if self.equals(classObj.CAUCASIAN_ALBANIAN?.as(JavaObject.self)) { + return UnicodeScriptCases.CAUCASIAN_ALBANIAN + } else if self.equals(classObj.BASSA_VAH?.as(JavaObject.self)) { + return UnicodeScriptCases.BASSA_VAH + } else if self.equals(classObj.DUPLOYAN?.as(JavaObject.self)) { + return UnicodeScriptCases.DUPLOYAN + } else if self.equals(classObj.ELBASAN?.as(JavaObject.self)) { + return UnicodeScriptCases.ELBASAN + } else if self.equals(classObj.GRANTHA?.as(JavaObject.self)) { + return UnicodeScriptCases.GRANTHA + } else if self.equals(classObj.PAHAWH_HMONG?.as(JavaObject.self)) { + return UnicodeScriptCases.PAHAWH_HMONG + } else if self.equals(classObj.KHOJKI?.as(JavaObject.self)) { + return UnicodeScriptCases.KHOJKI + } else if self.equals(classObj.LINEAR_A?.as(JavaObject.self)) { + return UnicodeScriptCases.LINEAR_A + } else if self.equals(classObj.MAHAJANI?.as(JavaObject.self)) { + return UnicodeScriptCases.MAHAJANI + } else if self.equals(classObj.MANICHAEAN?.as(JavaObject.self)) { + return UnicodeScriptCases.MANICHAEAN + } else if self.equals(classObj.MENDE_KIKAKUI?.as(JavaObject.self)) { + return UnicodeScriptCases.MENDE_KIKAKUI + } else if self.equals(classObj.MODI?.as(JavaObject.self)) { + return UnicodeScriptCases.MODI + } else if self.equals(classObj.MRO?.as(JavaObject.self)) { + return UnicodeScriptCases.MRO + } else if self.equals(classObj.OLD_NORTH_ARABIAN?.as(JavaObject.self)) { + return UnicodeScriptCases.OLD_NORTH_ARABIAN + } else if self.equals(classObj.NABATAEAN?.as(JavaObject.self)) { + return UnicodeScriptCases.NABATAEAN + } else if self.equals(classObj.PALMYRENE?.as(JavaObject.self)) { + return UnicodeScriptCases.PALMYRENE + } else if self.equals(classObj.PAU_CIN_HAU?.as(JavaObject.self)) { + return UnicodeScriptCases.PAU_CIN_HAU + } else if self.equals(classObj.OLD_PERMIC?.as(JavaObject.self)) { + return UnicodeScriptCases.OLD_PERMIC + } else if self.equals(classObj.PSALTER_PAHLAVI?.as(JavaObject.self)) { + return UnicodeScriptCases.PSALTER_PAHLAVI + } else if self.equals(classObj.SIDDHAM?.as(JavaObject.self)) { + return UnicodeScriptCases.SIDDHAM + } else if self.equals(classObj.KHUDAWADI?.as(JavaObject.self)) { + return UnicodeScriptCases.KHUDAWADI + } else if self.equals(classObj.TIRHUTA?.as(JavaObject.self)) { + return UnicodeScriptCases.TIRHUTA + } else if self.equals(classObj.WARANG_CITI?.as(JavaObject.self)) { + return UnicodeScriptCases.WARANG_CITI + } else if self.equals(classObj.AHOM?.as(JavaObject.self)) { + return UnicodeScriptCases.AHOM + } else if self.equals(classObj.ANATOLIAN_HIEROGLYPHS?.as(JavaObject.self)) { + return UnicodeScriptCases.ANATOLIAN_HIEROGLYPHS + } else if self.equals(classObj.HATRAN?.as(JavaObject.self)) { + return UnicodeScriptCases.HATRAN + } else if self.equals(classObj.MULTANI?.as(JavaObject.self)) { + return UnicodeScriptCases.MULTANI + } else if self.equals(classObj.OLD_HUNGARIAN?.as(JavaObject.self)) { + return UnicodeScriptCases.OLD_HUNGARIAN + } else if self.equals(classObj.SIGNWRITING?.as(JavaObject.self)) { + return UnicodeScriptCases.SIGNWRITING + } else if self.equals(classObj.ADLAM?.as(JavaObject.self)) { + return UnicodeScriptCases.ADLAM + } else if self.equals(classObj.BHAIKSUKI?.as(JavaObject.self)) { + return UnicodeScriptCases.BHAIKSUKI + } else if self.equals(classObj.MARCHEN?.as(JavaObject.self)) { + return UnicodeScriptCases.MARCHEN + } else if self.equals(classObj.NEWA?.as(JavaObject.self)) { + return UnicodeScriptCases.NEWA + } else if self.equals(classObj.OSAGE?.as(JavaObject.self)) { + return UnicodeScriptCases.OSAGE + } else if self.equals(classObj.TANGUT?.as(JavaObject.self)) { + return UnicodeScriptCases.TANGUT + } else if self.equals(classObj.MASARAM_GONDI?.as(JavaObject.self)) { + return UnicodeScriptCases.MASARAM_GONDI + } else if self.equals(classObj.NUSHU?.as(JavaObject.self)) { + return UnicodeScriptCases.NUSHU + } else if self.equals(classObj.SOYOMBO?.as(JavaObject.self)) { + return UnicodeScriptCases.SOYOMBO + } else if self.equals(classObj.ZANABAZAR_SQUARE?.as(JavaObject.self)) { + return UnicodeScriptCases.ZANABAZAR_SQUARE + } else if self.equals(classObj.HANIFI_ROHINGYA?.as(JavaObject.self)) { + return UnicodeScriptCases.HANIFI_ROHINGYA + } else if self.equals(classObj.OLD_SOGDIAN?.as(JavaObject.self)) { + return UnicodeScriptCases.OLD_SOGDIAN + } else if self.equals(classObj.SOGDIAN?.as(JavaObject.self)) { + return UnicodeScriptCases.SOGDIAN + } else if self.equals(classObj.DOGRA?.as(JavaObject.self)) { + return UnicodeScriptCases.DOGRA + } else if self.equals(classObj.GUNJALA_GONDI?.as(JavaObject.self)) { + return UnicodeScriptCases.GUNJALA_GONDI + } else if self.equals(classObj.MAKASAR?.as(JavaObject.self)) { + return UnicodeScriptCases.MAKASAR + } else if self.equals(classObj.MEDEFAIDRIN?.as(JavaObject.self)) { + return UnicodeScriptCases.MEDEFAIDRIN + } else if self.equals(classObj.ELYMAIC?.as(JavaObject.self)) { + return UnicodeScriptCases.ELYMAIC + } else if self.equals(classObj.NANDINAGARI?.as(JavaObject.self)) { + return UnicodeScriptCases.NANDINAGARI + } else if self.equals(classObj.NYIAKENG_PUACHUE_HMONG?.as(JavaObject.self)) { + return UnicodeScriptCases.NYIAKENG_PUACHUE_HMONG + } else if self.equals(classObj.WANCHO?.as(JavaObject.self)) { + return UnicodeScriptCases.WANCHO + } else if self.equals(classObj.YEZIDI?.as(JavaObject.self)) { + return UnicodeScriptCases.YEZIDI + } else if self.equals(classObj.CHORASMIAN?.as(JavaObject.self)) { + return UnicodeScriptCases.CHORASMIAN + } else if self.equals(classObj.DIVES_AKURU?.as(JavaObject.self)) { + return UnicodeScriptCases.DIVES_AKURU + } else if self.equals(classObj.KHITAN_SMALL_SCRIPT?.as(JavaObject.self)) { + return UnicodeScriptCases.KHITAN_SMALL_SCRIPT + } else if self.equals(classObj.VITHKUQI?.as(JavaObject.self)) { + return UnicodeScriptCases.VITHKUQI + } else if self.equals(classObj.OLD_UYGHUR?.as(JavaObject.self)) { + return UnicodeScriptCases.OLD_UYGHUR + } else if self.equals(classObj.CYPRO_MINOAN?.as(JavaObject.self)) { + return UnicodeScriptCases.CYPRO_MINOAN + } else if self.equals(classObj.TANGSA?.as(JavaObject.self)) { + return UnicodeScriptCases.TANGSA + } else if self.equals(classObj.TOTO?.as(JavaObject.self)) { + return UnicodeScriptCases.TOTO + } else if self.equals(classObj.KAWI?.as(JavaObject.self)) { + return UnicodeScriptCases.KAWI + } else if self.equals(classObj.NAG_MUNDARI?.as(JavaObject.self)) { + return UnicodeScriptCases.NAG_MUNDARI + } else if self.equals(classObj.UNKNOWN?.as(JavaObject.self)) { + return UnicodeScriptCases.UNKNOWN + } else { + return nil + } + } + + public init(_ enumValue: UnicodeScriptCases, environment: JNIEnvironment? = nil) { + let _environment = if let environment { + environment + } else { + try! JavaVirtualMachine.shared().environment() + } + let classObj = try! JavaClass(environment: _environment) + switch enumValue { + case .COMMON: + if let COMMON = classObj.COMMON { + self = COMMON + } else { + fatalError("Enum value COMMON was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .LATIN: + if let LATIN = classObj.LATIN { + self = LATIN + } else { + fatalError("Enum value LATIN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .GREEK: + if let GREEK = classObj.GREEK { + self = GREEK + } else { + fatalError("Enum value GREEK was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .CYRILLIC: + if let CYRILLIC = classObj.CYRILLIC { + self = CYRILLIC + } else { + fatalError("Enum value CYRILLIC was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .ARMENIAN: + if let ARMENIAN = classObj.ARMENIAN { + self = ARMENIAN + } else { + fatalError("Enum value ARMENIAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .HEBREW: + if let HEBREW = classObj.HEBREW { + self = HEBREW + } else { + fatalError("Enum value HEBREW was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .ARABIC: + if let ARABIC = classObj.ARABIC { + self = ARABIC + } else { + fatalError("Enum value ARABIC was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .SYRIAC: + if let SYRIAC = classObj.SYRIAC { + self = SYRIAC + } else { + fatalError("Enum value SYRIAC was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .THAANA: + if let THAANA = classObj.THAANA { + self = THAANA + } else { + fatalError("Enum value THAANA was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .DEVANAGARI: + if let DEVANAGARI = classObj.DEVANAGARI { + self = DEVANAGARI + } else { + fatalError("Enum value DEVANAGARI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .BENGALI: + if let BENGALI = classObj.BENGALI { + self = BENGALI + } else { + fatalError("Enum value BENGALI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .GURMUKHI: + if let GURMUKHI = classObj.GURMUKHI { + self = GURMUKHI + } else { + fatalError("Enum value GURMUKHI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .GUJARATI: + if let GUJARATI = classObj.GUJARATI { + self = GUJARATI + } else { + fatalError("Enum value GUJARATI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .ORIYA: + if let ORIYA = classObj.ORIYA { + self = ORIYA + } else { + fatalError("Enum value ORIYA was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .TAMIL: + if let TAMIL = classObj.TAMIL { + self = TAMIL + } else { + fatalError("Enum value TAMIL was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .TELUGU: + if let TELUGU = classObj.TELUGU { + self = TELUGU + } else { + fatalError("Enum value TELUGU was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .KANNADA: + if let KANNADA = classObj.KANNADA { + self = KANNADA + } else { + fatalError("Enum value KANNADA was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .MALAYALAM: + if let MALAYALAM = classObj.MALAYALAM { + self = MALAYALAM + } else { + fatalError("Enum value MALAYALAM was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .SINHALA: + if let SINHALA = classObj.SINHALA { + self = SINHALA + } else { + fatalError("Enum value SINHALA was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .THAI: + if let THAI = classObj.THAI { + self = THAI + } else { + fatalError("Enum value THAI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .LAO: + if let LAO = classObj.LAO { + self = LAO + } else { + fatalError("Enum value LAO was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .TIBETAN: + if let TIBETAN = classObj.TIBETAN { + self = TIBETAN + } else { + fatalError("Enum value TIBETAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .MYANMAR: + if let MYANMAR = classObj.MYANMAR { + self = MYANMAR + } else { + fatalError("Enum value MYANMAR was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .GEORGIAN: + if let GEORGIAN = classObj.GEORGIAN { + self = GEORGIAN + } else { + fatalError("Enum value GEORGIAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .HANGUL: + if let HANGUL = classObj.HANGUL { + self = HANGUL + } else { + fatalError("Enum value HANGUL was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .ETHIOPIC: + if let ETHIOPIC = classObj.ETHIOPIC { + self = ETHIOPIC + } else { + fatalError("Enum value ETHIOPIC was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .CHEROKEE: + if let CHEROKEE = classObj.CHEROKEE { + self = CHEROKEE + } else { + fatalError("Enum value CHEROKEE was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .CANADIAN_ABORIGINAL: + if let CANADIAN_ABORIGINAL = classObj.CANADIAN_ABORIGINAL { + self = CANADIAN_ABORIGINAL + } else { + fatalError("Enum value CANADIAN_ABORIGINAL was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .OGHAM: + if let OGHAM = classObj.OGHAM { + self = OGHAM + } else { + fatalError("Enum value OGHAM was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .RUNIC: + if let RUNIC = classObj.RUNIC { + self = RUNIC + } else { + fatalError("Enum value RUNIC was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .KHMER: + if let KHMER = classObj.KHMER { + self = KHMER + } else { + fatalError("Enum value KHMER was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .MONGOLIAN: + if let MONGOLIAN = classObj.MONGOLIAN { + self = MONGOLIAN + } else { + fatalError("Enum value MONGOLIAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .HIRAGANA: + if let HIRAGANA = classObj.HIRAGANA { + self = HIRAGANA + } else { + fatalError("Enum value HIRAGANA was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .KATAKANA: + if let KATAKANA = classObj.KATAKANA { + self = KATAKANA + } else { + fatalError("Enum value KATAKANA was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .BOPOMOFO: + if let BOPOMOFO = classObj.BOPOMOFO { + self = BOPOMOFO + } else { + fatalError("Enum value BOPOMOFO was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .HAN: + if let HAN = classObj.HAN { + self = HAN + } else { + fatalError("Enum value HAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .YI: + if let YI = classObj.YI { + self = YI + } else { + fatalError("Enum value YI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .OLD_ITALIC: + if let OLD_ITALIC = classObj.OLD_ITALIC { + self = OLD_ITALIC + } else { + fatalError("Enum value OLD_ITALIC was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .GOTHIC: + if let GOTHIC = classObj.GOTHIC { + self = GOTHIC + } else { + fatalError("Enum value GOTHIC was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .DESERET: + if let DESERET = classObj.DESERET { + self = DESERET + } else { + fatalError("Enum value DESERET was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .INHERITED: + if let INHERITED = classObj.INHERITED { + self = INHERITED + } else { + fatalError("Enum value INHERITED was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .TAGALOG: + if let TAGALOG = classObj.TAGALOG { + self = TAGALOG + } else { + fatalError("Enum value TAGALOG was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .HANUNOO: + if let HANUNOO = classObj.HANUNOO { + self = HANUNOO + } else { + fatalError("Enum value HANUNOO was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .BUHID: + if let BUHID = classObj.BUHID { + self = BUHID + } else { + fatalError("Enum value BUHID was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .TAGBANWA: + if let TAGBANWA = classObj.TAGBANWA { + self = TAGBANWA + } else { + fatalError("Enum value TAGBANWA was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .LIMBU: + if let LIMBU = classObj.LIMBU { + self = LIMBU + } else { + fatalError("Enum value LIMBU was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .TAI_LE: + if let TAI_LE = classObj.TAI_LE { + self = TAI_LE + } else { + fatalError("Enum value TAI_LE was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .LINEAR_B: + if let LINEAR_B = classObj.LINEAR_B { + self = LINEAR_B + } else { + fatalError("Enum value LINEAR_B was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .UGARITIC: + if let UGARITIC = classObj.UGARITIC { + self = UGARITIC + } else { + fatalError("Enum value UGARITIC was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .SHAVIAN: + if let SHAVIAN = classObj.SHAVIAN { + self = SHAVIAN + } else { + fatalError("Enum value SHAVIAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .OSMANYA: + if let OSMANYA = classObj.OSMANYA { + self = OSMANYA + } else { + fatalError("Enum value OSMANYA was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .CYPRIOT: + if let CYPRIOT = classObj.CYPRIOT { + self = CYPRIOT + } else { + fatalError("Enum value CYPRIOT was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .BRAILLE: + if let BRAILLE = classObj.BRAILLE { + self = BRAILLE + } else { + fatalError("Enum value BRAILLE was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .BUGINESE: + if let BUGINESE = classObj.BUGINESE { + self = BUGINESE + } else { + fatalError("Enum value BUGINESE was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .COPTIC: + if let COPTIC = classObj.COPTIC { + self = COPTIC + } else { + fatalError("Enum value COPTIC was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .NEW_TAI_LUE: + if let NEW_TAI_LUE = classObj.NEW_TAI_LUE { + self = NEW_TAI_LUE + } else { + fatalError("Enum value NEW_TAI_LUE was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .GLAGOLITIC: + if let GLAGOLITIC = classObj.GLAGOLITIC { + self = GLAGOLITIC + } else { + fatalError("Enum value GLAGOLITIC was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .TIFINAGH: + if let TIFINAGH = classObj.TIFINAGH { + self = TIFINAGH + } else { + fatalError("Enum value TIFINAGH was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .SYLOTI_NAGRI: + if let SYLOTI_NAGRI = classObj.SYLOTI_NAGRI { + self = SYLOTI_NAGRI + } else { + fatalError("Enum value SYLOTI_NAGRI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .OLD_PERSIAN: + if let OLD_PERSIAN = classObj.OLD_PERSIAN { + self = OLD_PERSIAN + } else { + fatalError("Enum value OLD_PERSIAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .KHAROSHTHI: + if let KHAROSHTHI = classObj.KHAROSHTHI { + self = KHAROSHTHI + } else { + fatalError("Enum value KHAROSHTHI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .BALINESE: + if let BALINESE = classObj.BALINESE { + self = BALINESE + } else { + fatalError("Enum value BALINESE was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .CUNEIFORM: + if let CUNEIFORM = classObj.CUNEIFORM { + self = CUNEIFORM + } else { + fatalError("Enum value CUNEIFORM was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .PHOENICIAN: + if let PHOENICIAN = classObj.PHOENICIAN { + self = PHOENICIAN + } else { + fatalError("Enum value PHOENICIAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .PHAGS_PA: + if let PHAGS_PA = classObj.PHAGS_PA { + self = PHAGS_PA + } else { + fatalError("Enum value PHAGS_PA was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .NKO: + if let NKO = classObj.NKO { + self = NKO + } else { + fatalError("Enum value NKO was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .SUNDANESE: + if let SUNDANESE = classObj.SUNDANESE { + self = SUNDANESE + } else { + fatalError("Enum value SUNDANESE was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .BATAK: + if let BATAK = classObj.BATAK { + self = BATAK + } else { + fatalError("Enum value BATAK was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .LEPCHA: + if let LEPCHA = classObj.LEPCHA { + self = LEPCHA + } else { + fatalError("Enum value LEPCHA was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .OL_CHIKI: + if let OL_CHIKI = classObj.OL_CHIKI { + self = OL_CHIKI + } else { + fatalError("Enum value OL_CHIKI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .VAI: + if let VAI = classObj.VAI { + self = VAI + } else { + fatalError("Enum value VAI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .SAURASHTRA: + if let SAURASHTRA = classObj.SAURASHTRA { + self = SAURASHTRA + } else { + fatalError("Enum value SAURASHTRA was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .KAYAH_LI: + if let KAYAH_LI = classObj.KAYAH_LI { + self = KAYAH_LI + } else { + fatalError("Enum value KAYAH_LI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .REJANG: + if let REJANG = classObj.REJANG { + self = REJANG + } else { + fatalError("Enum value REJANG was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .LYCIAN: + if let LYCIAN = classObj.LYCIAN { + self = LYCIAN + } else { + fatalError("Enum value LYCIAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .CARIAN: + if let CARIAN = classObj.CARIAN { + self = CARIAN + } else { + fatalError("Enum value CARIAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .LYDIAN: + if let LYDIAN = classObj.LYDIAN { + self = LYDIAN + } else { + fatalError("Enum value LYDIAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .CHAM: + if let CHAM = classObj.CHAM { + self = CHAM + } else { + fatalError("Enum value CHAM was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .TAI_THAM: + if let TAI_THAM = classObj.TAI_THAM { + self = TAI_THAM + } else { + fatalError("Enum value TAI_THAM was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .TAI_VIET: + if let TAI_VIET = classObj.TAI_VIET { + self = TAI_VIET + } else { + fatalError("Enum value TAI_VIET was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .AVESTAN: + if let AVESTAN = classObj.AVESTAN { + self = AVESTAN + } else { + fatalError("Enum value AVESTAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .EGYPTIAN_HIEROGLYPHS: + if let EGYPTIAN_HIEROGLYPHS = classObj.EGYPTIAN_HIEROGLYPHS { + self = EGYPTIAN_HIEROGLYPHS + } else { + fatalError("Enum value EGYPTIAN_HIEROGLYPHS was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .SAMARITAN: + if let SAMARITAN = classObj.SAMARITAN { + self = SAMARITAN + } else { + fatalError("Enum value SAMARITAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .MANDAIC: + if let MANDAIC = classObj.MANDAIC { + self = MANDAIC + } else { + fatalError("Enum value MANDAIC was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .LISU: + if let LISU = classObj.LISU { + self = LISU + } else { + fatalError("Enum value LISU was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .BAMUM: + if let BAMUM = classObj.BAMUM { + self = BAMUM + } else { + fatalError("Enum value BAMUM was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .JAVANESE: + if let JAVANESE = classObj.JAVANESE { + self = JAVANESE + } else { + fatalError("Enum value JAVANESE was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .MEETEI_MAYEK: + if let MEETEI_MAYEK = classObj.MEETEI_MAYEK { + self = MEETEI_MAYEK + } else { + fatalError("Enum value MEETEI_MAYEK was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .IMPERIAL_ARAMAIC: + if let IMPERIAL_ARAMAIC = classObj.IMPERIAL_ARAMAIC { + self = IMPERIAL_ARAMAIC + } else { + fatalError("Enum value IMPERIAL_ARAMAIC was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .OLD_SOUTH_ARABIAN: + if let OLD_SOUTH_ARABIAN = classObj.OLD_SOUTH_ARABIAN { + self = OLD_SOUTH_ARABIAN + } else { + fatalError("Enum value OLD_SOUTH_ARABIAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .INSCRIPTIONAL_PARTHIAN: + if let INSCRIPTIONAL_PARTHIAN = classObj.INSCRIPTIONAL_PARTHIAN { + self = INSCRIPTIONAL_PARTHIAN + } else { + fatalError("Enum value INSCRIPTIONAL_PARTHIAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .INSCRIPTIONAL_PAHLAVI: + if let INSCRIPTIONAL_PAHLAVI = classObj.INSCRIPTIONAL_PAHLAVI { + self = INSCRIPTIONAL_PAHLAVI + } else { + fatalError("Enum value INSCRIPTIONAL_PAHLAVI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .OLD_TURKIC: + if let OLD_TURKIC = classObj.OLD_TURKIC { + self = OLD_TURKIC + } else { + fatalError("Enum value OLD_TURKIC was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .BRAHMI: + if let BRAHMI = classObj.BRAHMI { + self = BRAHMI + } else { + fatalError("Enum value BRAHMI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .KAITHI: + if let KAITHI = classObj.KAITHI { + self = KAITHI + } else { + fatalError("Enum value KAITHI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .MEROITIC_HIEROGLYPHS: + if let MEROITIC_HIEROGLYPHS = classObj.MEROITIC_HIEROGLYPHS { + self = MEROITIC_HIEROGLYPHS + } else { + fatalError("Enum value MEROITIC_HIEROGLYPHS was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .MEROITIC_CURSIVE: + if let MEROITIC_CURSIVE = classObj.MEROITIC_CURSIVE { + self = MEROITIC_CURSIVE + } else { + fatalError("Enum value MEROITIC_CURSIVE was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .SORA_SOMPENG: + if let SORA_SOMPENG = classObj.SORA_SOMPENG { + self = SORA_SOMPENG + } else { + fatalError("Enum value SORA_SOMPENG was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .CHAKMA: + if let CHAKMA = classObj.CHAKMA { + self = CHAKMA + } else { + fatalError("Enum value CHAKMA was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .SHARADA: + if let SHARADA = classObj.SHARADA { + self = SHARADA + } else { + fatalError("Enum value SHARADA was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .TAKRI: + if let TAKRI = classObj.TAKRI { + self = TAKRI + } else { + fatalError("Enum value TAKRI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .MIAO: + if let MIAO = classObj.MIAO { + self = MIAO + } else { + fatalError("Enum value MIAO was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .CAUCASIAN_ALBANIAN: + if let CAUCASIAN_ALBANIAN = classObj.CAUCASIAN_ALBANIAN { + self = CAUCASIAN_ALBANIAN + } else { + fatalError("Enum value CAUCASIAN_ALBANIAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .BASSA_VAH: + if let BASSA_VAH = classObj.BASSA_VAH { + self = BASSA_VAH + } else { + fatalError("Enum value BASSA_VAH was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .DUPLOYAN: + if let DUPLOYAN = classObj.DUPLOYAN { + self = DUPLOYAN + } else { + fatalError("Enum value DUPLOYAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .ELBASAN: + if let ELBASAN = classObj.ELBASAN { + self = ELBASAN + } else { + fatalError("Enum value ELBASAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .GRANTHA: + if let GRANTHA = classObj.GRANTHA { + self = GRANTHA + } else { + fatalError("Enum value GRANTHA was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .PAHAWH_HMONG: + if let PAHAWH_HMONG = classObj.PAHAWH_HMONG { + self = PAHAWH_HMONG + } else { + fatalError("Enum value PAHAWH_HMONG was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .KHOJKI: + if let KHOJKI = classObj.KHOJKI { + self = KHOJKI + } else { + fatalError("Enum value KHOJKI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .LINEAR_A: + if let LINEAR_A = classObj.LINEAR_A { + self = LINEAR_A + } else { + fatalError("Enum value LINEAR_A was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .MAHAJANI: + if let MAHAJANI = classObj.MAHAJANI { + self = MAHAJANI + } else { + fatalError("Enum value MAHAJANI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .MANICHAEAN: + if let MANICHAEAN = classObj.MANICHAEAN { + self = MANICHAEAN + } else { + fatalError("Enum value MANICHAEAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .MENDE_KIKAKUI: + if let MENDE_KIKAKUI = classObj.MENDE_KIKAKUI { + self = MENDE_KIKAKUI + } else { + fatalError("Enum value MENDE_KIKAKUI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .MODI: + if let MODI = classObj.MODI { + self = MODI + } else { + fatalError("Enum value MODI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .MRO: + if let MRO = classObj.MRO { + self = MRO + } else { + fatalError("Enum value MRO was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .OLD_NORTH_ARABIAN: + if let OLD_NORTH_ARABIAN = classObj.OLD_NORTH_ARABIAN { + self = OLD_NORTH_ARABIAN + } else { + fatalError("Enum value OLD_NORTH_ARABIAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .NABATAEAN: + if let NABATAEAN = classObj.NABATAEAN { + self = NABATAEAN + } else { + fatalError("Enum value NABATAEAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .PALMYRENE: + if let PALMYRENE = classObj.PALMYRENE { + self = PALMYRENE + } else { + fatalError("Enum value PALMYRENE was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .PAU_CIN_HAU: + if let PAU_CIN_HAU = classObj.PAU_CIN_HAU { + self = PAU_CIN_HAU + } else { + fatalError("Enum value PAU_CIN_HAU was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .OLD_PERMIC: + if let OLD_PERMIC = classObj.OLD_PERMIC { + self = OLD_PERMIC + } else { + fatalError("Enum value OLD_PERMIC was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .PSALTER_PAHLAVI: + if let PSALTER_PAHLAVI = classObj.PSALTER_PAHLAVI { + self = PSALTER_PAHLAVI + } else { + fatalError("Enum value PSALTER_PAHLAVI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .SIDDHAM: + if let SIDDHAM = classObj.SIDDHAM { + self = SIDDHAM + } else { + fatalError("Enum value SIDDHAM was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .KHUDAWADI: + if let KHUDAWADI = classObj.KHUDAWADI { + self = KHUDAWADI + } else { + fatalError("Enum value KHUDAWADI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .TIRHUTA: + if let TIRHUTA = classObj.TIRHUTA { + self = TIRHUTA + } else { + fatalError("Enum value TIRHUTA was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .WARANG_CITI: + if let WARANG_CITI = classObj.WARANG_CITI { + self = WARANG_CITI + } else { + fatalError("Enum value WARANG_CITI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .AHOM: + if let AHOM = classObj.AHOM { + self = AHOM + } else { + fatalError("Enum value AHOM was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .ANATOLIAN_HIEROGLYPHS: + if let ANATOLIAN_HIEROGLYPHS = classObj.ANATOLIAN_HIEROGLYPHS { + self = ANATOLIAN_HIEROGLYPHS + } else { + fatalError("Enum value ANATOLIAN_HIEROGLYPHS was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .HATRAN: + if let HATRAN = classObj.HATRAN { + self = HATRAN + } else { + fatalError("Enum value HATRAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .MULTANI: + if let MULTANI = classObj.MULTANI { + self = MULTANI + } else { + fatalError("Enum value MULTANI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .OLD_HUNGARIAN: + if let OLD_HUNGARIAN = classObj.OLD_HUNGARIAN { + self = OLD_HUNGARIAN + } else { + fatalError("Enum value OLD_HUNGARIAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .SIGNWRITING: + if let SIGNWRITING = classObj.SIGNWRITING { + self = SIGNWRITING + } else { + fatalError("Enum value SIGNWRITING was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .ADLAM: + if let ADLAM = classObj.ADLAM { + self = ADLAM + } else { + fatalError("Enum value ADLAM was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .BHAIKSUKI: + if let BHAIKSUKI = classObj.BHAIKSUKI { + self = BHAIKSUKI + } else { + fatalError("Enum value BHAIKSUKI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .MARCHEN: + if let MARCHEN = classObj.MARCHEN { + self = MARCHEN + } else { + fatalError("Enum value MARCHEN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .NEWA: + if let NEWA = classObj.NEWA { + self = NEWA + } else { + fatalError("Enum value NEWA was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .OSAGE: + if let OSAGE = classObj.OSAGE { + self = OSAGE + } else { + fatalError("Enum value OSAGE was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .TANGUT: + if let TANGUT = classObj.TANGUT { + self = TANGUT + } else { + fatalError("Enum value TANGUT was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .MASARAM_GONDI: + if let MASARAM_GONDI = classObj.MASARAM_GONDI { + self = MASARAM_GONDI + } else { + fatalError("Enum value MASARAM_GONDI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .NUSHU: + if let NUSHU = classObj.NUSHU { + self = NUSHU + } else { + fatalError("Enum value NUSHU was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .SOYOMBO: + if let SOYOMBO = classObj.SOYOMBO { + self = SOYOMBO + } else { + fatalError("Enum value SOYOMBO was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .ZANABAZAR_SQUARE: + if let ZANABAZAR_SQUARE = classObj.ZANABAZAR_SQUARE { + self = ZANABAZAR_SQUARE + } else { + fatalError("Enum value ZANABAZAR_SQUARE was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .HANIFI_ROHINGYA: + if let HANIFI_ROHINGYA = classObj.HANIFI_ROHINGYA { + self = HANIFI_ROHINGYA + } else { + fatalError("Enum value HANIFI_ROHINGYA was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .OLD_SOGDIAN: + if let OLD_SOGDIAN = classObj.OLD_SOGDIAN { + self = OLD_SOGDIAN + } else { + fatalError("Enum value OLD_SOGDIAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .SOGDIAN: + if let SOGDIAN = classObj.SOGDIAN { + self = SOGDIAN + } else { + fatalError("Enum value SOGDIAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .DOGRA: + if let DOGRA = classObj.DOGRA { + self = DOGRA + } else { + fatalError("Enum value DOGRA was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .GUNJALA_GONDI: + if let GUNJALA_GONDI = classObj.GUNJALA_GONDI { + self = GUNJALA_GONDI + } else { + fatalError("Enum value GUNJALA_GONDI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .MAKASAR: + if let MAKASAR = classObj.MAKASAR { + self = MAKASAR + } else { + fatalError("Enum value MAKASAR was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .MEDEFAIDRIN: + if let MEDEFAIDRIN = classObj.MEDEFAIDRIN { + self = MEDEFAIDRIN + } else { + fatalError("Enum value MEDEFAIDRIN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .ELYMAIC: + if let ELYMAIC = classObj.ELYMAIC { + self = ELYMAIC + } else { + fatalError("Enum value ELYMAIC was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .NANDINAGARI: + if let NANDINAGARI = classObj.NANDINAGARI { + self = NANDINAGARI + } else { + fatalError("Enum value NANDINAGARI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .NYIAKENG_PUACHUE_HMONG: + if let NYIAKENG_PUACHUE_HMONG = classObj.NYIAKENG_PUACHUE_HMONG { + self = NYIAKENG_PUACHUE_HMONG + } else { + fatalError("Enum value NYIAKENG_PUACHUE_HMONG was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .WANCHO: + if let WANCHO = classObj.WANCHO { + self = WANCHO + } else { + fatalError("Enum value WANCHO was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .YEZIDI: + if let YEZIDI = classObj.YEZIDI { + self = YEZIDI + } else { + fatalError("Enum value YEZIDI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .CHORASMIAN: + if let CHORASMIAN = classObj.CHORASMIAN { + self = CHORASMIAN + } else { + fatalError("Enum value CHORASMIAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .DIVES_AKURU: + if let DIVES_AKURU = classObj.DIVES_AKURU { + self = DIVES_AKURU + } else { + fatalError("Enum value DIVES_AKURU was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .KHITAN_SMALL_SCRIPT: + if let KHITAN_SMALL_SCRIPT = classObj.KHITAN_SMALL_SCRIPT { + self = KHITAN_SMALL_SCRIPT + } else { + fatalError("Enum value KHITAN_SMALL_SCRIPT was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .VITHKUQI: + if let VITHKUQI = classObj.VITHKUQI { + self = VITHKUQI + } else { + fatalError("Enum value VITHKUQI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .OLD_UYGHUR: + if let OLD_UYGHUR = classObj.OLD_UYGHUR { + self = OLD_UYGHUR + } else { + fatalError("Enum value OLD_UYGHUR was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .CYPRO_MINOAN: + if let CYPRO_MINOAN = classObj.CYPRO_MINOAN { + self = CYPRO_MINOAN + } else { + fatalError("Enum value CYPRO_MINOAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .TANGSA: + if let TANGSA = classObj.TANGSA { + self = TANGSA + } else { + fatalError("Enum value TANGSA was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .TOTO: + if let TOTO = classObj.TOTO { + self = TOTO + } else { + fatalError("Enum value TOTO was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .KAWI: + if let KAWI = classObj.KAWI { + self = KAWI + } else { + fatalError("Enum value KAWI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .NAG_MUNDARI: + if let NAG_MUNDARI = classObj.NAG_MUNDARI { + self = NAG_MUNDARI + } else { + fatalError("Enum value NAG_MUNDARI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + case .UNKNOWN: + if let UNKNOWN = classObj.UNKNOWN { + self = UNKNOWN + } else { + fatalError("Enum value UNKNOWN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + } + } + + @JavaMethod + public func name() -> String + + @JavaMethod + public func equals(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func toString() -> String + + @JavaMethod + public func hashCode() -> Int32 + + @JavaMethod + public func compareTo(_ arg0: JavaObject?) -> Int32 + + @JavaMethod + public func ordinal() -> Int32 + + @JavaMethod + public func getClass() -> JavaClass? + + @JavaMethod + public func notify() + + @JavaMethod + public func notifyAll() + + @JavaMethod + public func wait(_ arg0: Int64) throws + + @JavaMethod + public func wait(_ arg0: Int64, _ arg1: Int32) throws + + @JavaMethod + public func wait() throws + } +} +extension JavaCharacter.UnicodeScript { + @JavaClass("java.lang.Enum$EnumDesc") + public struct EnumDesc { + @JavaMethod + public func toString() -> String + + @JavaMethod + public func constantName() -> String + + @JavaMethod + public func equals(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func hashCode() -> Int32 + + @JavaMethod + public func getClass() -> JavaClass? + + @JavaMethod + public func notify() + + @JavaMethod + public func notifyAll() + + @JavaMethod + public func wait(_ arg0: Int64) throws + + @JavaMethod + public func wait(_ arg0: Int64, _ arg1: Int32) throws + + @JavaMethod + public func wait() throws + } +} +extension JavaClass { + @JavaStaticField(isFinal: true) + public var COMMON: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var LATIN: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var GREEK: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var CYRILLIC: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var ARMENIAN: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var HEBREW: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var ARABIC: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var SYRIAC: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var THAANA: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var DEVANAGARI: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var BENGALI: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var GURMUKHI: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var GUJARATI: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var ORIYA: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var TAMIL: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var TELUGU: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var KANNADA: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var MALAYALAM: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var SINHALA: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var THAI: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var LAO: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var TIBETAN: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var MYANMAR: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var GEORGIAN: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var HANGUL: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var ETHIOPIC: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var CHEROKEE: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var CANADIAN_ABORIGINAL: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var OGHAM: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var RUNIC: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var KHMER: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var MONGOLIAN: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var HIRAGANA: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var KATAKANA: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var BOPOMOFO: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var HAN: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var YI: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var OLD_ITALIC: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var GOTHIC: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var DESERET: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var INHERITED: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var TAGALOG: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var HANUNOO: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var BUHID: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var TAGBANWA: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var LIMBU: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var TAI_LE: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var LINEAR_B: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var UGARITIC: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var SHAVIAN: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var OSMANYA: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var CYPRIOT: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var BRAILLE: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var BUGINESE: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var COPTIC: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var NEW_TAI_LUE: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var GLAGOLITIC: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var TIFINAGH: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var SYLOTI_NAGRI: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var OLD_PERSIAN: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var KHAROSHTHI: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var BALINESE: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var CUNEIFORM: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var PHOENICIAN: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var PHAGS_PA: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var NKO: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var SUNDANESE: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var BATAK: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var LEPCHA: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var OL_CHIKI: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var VAI: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var SAURASHTRA: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var KAYAH_LI: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var REJANG: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var LYCIAN: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var CARIAN: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var LYDIAN: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var CHAM: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var TAI_THAM: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var TAI_VIET: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var AVESTAN: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var EGYPTIAN_HIEROGLYPHS: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var SAMARITAN: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var MANDAIC: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var LISU: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var BAMUM: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var JAVANESE: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var MEETEI_MAYEK: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var IMPERIAL_ARAMAIC: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var OLD_SOUTH_ARABIAN: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var INSCRIPTIONAL_PARTHIAN: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var INSCRIPTIONAL_PAHLAVI: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var OLD_TURKIC: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var BRAHMI: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var KAITHI: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var MEROITIC_HIEROGLYPHS: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var MEROITIC_CURSIVE: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var SORA_SOMPENG: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var CHAKMA: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var SHARADA: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var TAKRI: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var MIAO: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var CAUCASIAN_ALBANIAN: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var BASSA_VAH: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var DUPLOYAN: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var ELBASAN: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var GRANTHA: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var PAHAWH_HMONG: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var KHOJKI: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var LINEAR_A: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var MAHAJANI: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var MANICHAEAN: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var MENDE_KIKAKUI: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var MODI: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var MRO: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var OLD_NORTH_ARABIAN: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var NABATAEAN: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var PALMYRENE: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var PAU_CIN_HAU: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var OLD_PERMIC: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var PSALTER_PAHLAVI: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var SIDDHAM: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var KHUDAWADI: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var TIRHUTA: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var WARANG_CITI: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var AHOM: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var ANATOLIAN_HIEROGLYPHS: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var HATRAN: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var MULTANI: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var OLD_HUNGARIAN: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var SIGNWRITING: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var ADLAM: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var BHAIKSUKI: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var MARCHEN: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var NEWA: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var OSAGE: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var TANGUT: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var MASARAM_GONDI: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var NUSHU: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var SOYOMBO: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var ZANABAZAR_SQUARE: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var HANIFI_ROHINGYA: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var OLD_SOGDIAN: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var SOGDIAN: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var DOGRA: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var GUNJALA_GONDI: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var MAKASAR: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var MEDEFAIDRIN: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var ELYMAIC: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var NANDINAGARI: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var NYIAKENG_PUACHUE_HMONG: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var WANCHO: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var YEZIDI: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var CHORASMIAN: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var DIVES_AKURU: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var KHITAN_SMALL_SCRIPT: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var VITHKUQI: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var OLD_UYGHUR: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var CYPRO_MINOAN: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var TANGSA: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var TOTO: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var KAWI: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var NAG_MUNDARI: JavaCharacter.UnicodeScript? + + @JavaStaticField(isFinal: true) + public var UNKNOWN: JavaCharacter.UnicodeScript? + + @JavaStaticMethod + public func forName(_ arg0: String) -> JavaCharacter.UnicodeScript? + + @JavaStaticMethod + public func values() -> [JavaCharacter.UnicodeScript?] + + @JavaStaticMethod + public func valueOf(_ arg0: String) -> JavaCharacter.UnicodeScript? + + @JavaStaticMethod + public func of(_ arg0: Int32) -> JavaCharacter.UnicodeScript? +} +extension JavaCharacter { + @JavaClass("java.lang.Character$Subset") + public struct Subset { + @JavaMethod + public func equals(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func toString() -> String + + @JavaMethod + public func hashCode() -> Int32 + + @JavaMethod + public func getClass() -> JavaClass? + + @JavaMethod + public func notify() + + @JavaMethod + public func notifyAll() + + @JavaMethod + public func wait(_ arg0: Int64) throws + + @JavaMethod + public func wait(_ arg0: Int64, _ arg1: Int32) throws + + @JavaMethod + public func wait() throws + } +} extension JavaClass { @JavaStaticField(isFinal: true) public var MIN_RADIX: Int32 diff --git a/Sources/JavaKitCollection/generated/ArrayDeque.swift b/Sources/JavaKitCollection/generated/ArrayDeque.swift index 85040ac7..6d84d201 100644 --- a/Sources/JavaKitCollection/generated/ArrayDeque.swift +++ b/Sources/JavaKitCollection/generated/ArrayDeque.swift @@ -25,9 +25,6 @@ public struct ArrayDeque { @JavaMethod public func clone() -> ArrayDeque? - @JavaMethod - public func clone() throws -> JavaObject? - @JavaMethod public func clear() diff --git a/Sources/JavaKitCollection/generated/TreeMap.swift b/Sources/JavaKitCollection/generated/TreeMap.swift index 49055dce..75eb36c1 100644 --- a/Sources/JavaKitCollection/generated/TreeMap.swift +++ b/Sources/JavaKitCollection/generated/TreeMap.swift @@ -106,3 +106,89 @@ public struct TreeMap { @JavaMethod public func getOrDefault(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject? } +extension TreeMap { + @JavaClass("java.util.AbstractMap$SimpleImmutableEntry") + public struct SimpleImmutableEntry { + @JavaMethod + public init(_ arg0: JavaObject?, _ arg1: JavaObject?, environment: JNIEnvironment? = nil) + + @JavaMethod + public func equals(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func toString() -> String + + @JavaMethod + public func hashCode() -> Int32 + + @JavaMethod + public func getValue() -> JavaObject? + + @JavaMethod + public func getKey() -> JavaObject? + + @JavaMethod + public func setValue(_ arg0: JavaObject?) -> JavaObject? + + @JavaMethod + public func getClass() -> JavaClass? + + @JavaMethod + public func notify() + + @JavaMethod + public func notifyAll() + + @JavaMethod + public func wait(_ arg0: Int64) throws + + @JavaMethod + public func wait(_ arg0: Int64, _ arg1: Int32) throws + + @JavaMethod + public func wait() throws + } +} +extension TreeMap { + @JavaClass("java.util.AbstractMap$SimpleEntry") + public struct SimpleEntry { + @JavaMethod + public init(_ arg0: JavaObject?, _ arg1: JavaObject?, environment: JNIEnvironment? = nil) + + @JavaMethod + public func equals(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func toString() -> String + + @JavaMethod + public func hashCode() -> Int32 + + @JavaMethod + public func getValue() -> JavaObject? + + @JavaMethod + public func getKey() -> JavaObject? + + @JavaMethod + public func setValue(_ arg0: JavaObject?) -> JavaObject? + + @JavaMethod + public func getClass() -> JavaClass? + + @JavaMethod + public func notify() + + @JavaMethod + public func notifyAll() + + @JavaMethod + public func wait(_ arg0: Int64) throws + + @JavaMethod + public func wait(_ arg0: Int64, _ arg1: Int32) throws + + @JavaMethod + public func wait() throws + } +} From 1d774d60c94adc17e9db9b9dfd285bb443985de4 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Mon, 28 Oct 2024 09:23:44 -0700 Subject: [PATCH 134/426] Fix incorrect specific of targets associated with a few products --- Package.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Package.swift b/Package.swift index f2d9ff89..006562b2 100644 --- a/Package.swift +++ b/Package.swift @@ -69,12 +69,12 @@ let package = Package( .library( name: "JavaKitJar", - targets: ["JavaKitReflection"] + targets: ["JavaKitJar"] ), .library( name: "JavaKitNetwork", - targets: ["JavaKitReflection"] + targets: ["JavaKitNetwork"] ), .library( From e71cfb1479f58072a097e6bf640b8e24dbcd2de4 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Mon, 28 Oct 2024 10:16:19 -0700 Subject: [PATCH 135/426] Java2Swift: Use implicitly-unwrapped optionals for field types and method results All Java references are nullable, so modeling them as optional in Swift is both correct and extremely annoying. Use implicitly-unwrapped optionals instead. Fixes issue #122. --- .../Java2SwiftLib/JavaClassTranslator.swift | 10 +++---- Sources/Java2SwiftLib/JavaTranslator.swift | 27 ++++++++++++------- Sources/Java2SwiftLib/OptionalKind.swift | 25 +++++++++++++++++ Sources/JavaKitMacros/JavaFieldMacro.swift | 2 +- Sources/JavaKitMacros/JavaMethodMacro.swift | 24 ++++++++++++++++- Tests/Java2SwiftTests/Java2SwiftTests.swift | 22 +++++++-------- .../JavaClassMacroTests.swift | 11 ++++++++ 7 files changed, 93 insertions(+), 28 deletions(-) create mode 100644 Sources/Java2SwiftLib/OptionalKind.swift diff --git a/Sources/Java2SwiftLib/JavaClassTranslator.swift b/Sources/Java2SwiftLib/JavaClassTranslator.swift index f8aecec7..59477f3f 100644 --- a/Sources/Java2SwiftLib/JavaClassTranslator.swift +++ b/Sources/Java2SwiftLib/JavaClassTranslator.swift @@ -131,7 +131,7 @@ struct JavaClassTranslator { } do { - let typeName = try translator.getSwiftTypeNameAsString(javaType, outerOptional: false) + let typeName = try translator.getSwiftTypeNameAsString(javaType, outerOptional: .nonoptional) return "\(typeName)" } catch { translator.logUntranslated("Unable to translate '\(fullName)' interface '\(javaType.getTypeName())': \(error)") @@ -459,7 +459,7 @@ extension JavaClassTranslator { // Map the result type. let resultTypeStr: String - let resultType = try translator.getSwiftTypeNameAsString(javaMethod.getGenericReturnType()!, outerOptional: true) + let resultType = try translator.getSwiftTypeNameAsString(javaMethod.getGenericReturnType()!, outerOptional: .implicitlyUnwrappedOptional) if resultType != "Void" { resultTypeStr = " -> \(resultType)" } else { @@ -480,7 +480,7 @@ extension JavaClassTranslator { /// Render a single Java field into the corresponding Swift property, or /// throw an error if that is not possible for any reason. package func renderField(_ javaField: Field) throws -> DeclSyntax { - let typeName = try translator.getSwiftTypeNameAsString(javaField.getGenericType()!, outerOptional: true) + let typeName = try translator.getSwiftTypeNameAsString(javaField.getGenericType()!, outerOptional: .implicitlyUnwrappedOptional) let fieldAttribute: AttributeSyntax = javaField.isStatic ? "@JavaStaticField" : "@JavaField"; let swiftFieldName = javaField.getName().escapedSwiftName return """ @@ -501,7 +501,7 @@ extension JavaClassTranslator { """ let mappingSyntax: DeclSyntax = """ - public var enumValue: \(raw: name)? { + public var enumValue: \(raw: name)! { let classObj = self.javaClass \(raw: enumConstants.map { // The equals method takes a java object, so we need to cast it here @@ -547,7 +547,7 @@ extension JavaClassTranslator { return try parameters.compactMap { javaParameter in guard let javaParameter else { return nil } - let typeName = try translator.getSwiftTypeNameAsString(javaParameter.getParameterizedType()!, outerOptional: true) + let typeName = try translator.getSwiftTypeNameAsString(javaParameter.getParameterizedType()!, outerOptional: .optional) let paramName = javaParameter.getName() return "_ \(raw: paramName): \(raw: typeName)" } diff --git a/Sources/Java2SwiftLib/JavaTranslator.swift b/Sources/Java2SwiftLib/JavaTranslator.swift index 89e417e6..9f5fa292 100644 --- a/Sources/Java2SwiftLib/JavaTranslator.swift +++ b/Sources/Java2SwiftLib/JavaTranslator.swift @@ -104,7 +104,7 @@ extension JavaTranslator { // MARK: Type translation extension JavaTranslator { /// Turn a Java type into a string. - func getSwiftTypeNameAsString(_ javaType: Type, outerOptional: Bool) throws -> String { + func getSwiftTypeNameAsString(_ javaType: Type, outerOptional: OptionalKind) throws -> String { // Replace type variables with their bounds. if let typeVariable = javaType.as(TypeVariable.self), typeVariable.getBounds().count == 1, @@ -124,7 +124,7 @@ extension JavaTranslator { // Handle array types by recursing into the component type. if let arrayType = javaType.as(GenericArrayType.self) { - let elementType = try getSwiftTypeNameAsString(arrayType.getGenericComponentType()!, outerOptional: true) + let elementType = try getSwiftTypeNameAsString(arrayType.getGenericComponentType()!, outerOptional: .optional) return "[\(elementType)]" } @@ -135,21 +135,21 @@ extension JavaTranslator { { var rawSwiftType = try getSwiftTypeNameAsString(rawJavaType, outerOptional: outerOptional) - let makeOptional: Bool - if rawSwiftType.last == "?" { - makeOptional = true + let optionalSuffix: String + if let lastChar = rawSwiftType.last, lastChar == "?" || lastChar == "!" { + optionalSuffix = "\(lastChar)" rawSwiftType.removeLast() } else { - makeOptional = false + optionalSuffix = "" } let typeArguments = try parameterizedType.getActualTypeArguments().compactMap { typeArg in try typeArg.map { typeArg in - try getSwiftTypeNameAsString(typeArg, outerOptional: false) + try getSwiftTypeNameAsString(typeArg, outerOptional: .nonoptional) } } - return "\(rawSwiftType)<\(typeArguments.joined(separator: ", "))>\(makeOptional ? "?" : "")" + return "\(rawSwiftType)<\(typeArguments.joined(separator: ", "))>\(optionalSuffix)" } // Handle direct references to Java classes. @@ -159,8 +159,15 @@ extension JavaTranslator { let (swiftName, isOptional) = try getSwiftTypeName(javaClass) var resultString = swiftName - if isOptional && outerOptional { - resultString += "?" + if isOptional { + switch outerOptional { + case .implicitlyUnwrappedOptional: + resultString += "!" + case .optional: + resultString += "?" + case .nonoptional: + break + } } return resultString } diff --git a/Sources/Java2SwiftLib/OptionalKind.swift b/Sources/Java2SwiftLib/OptionalKind.swift new file mode 100644 index 00000000..57951fa4 --- /dev/null +++ b/Sources/Java2SwiftLib/OptionalKind.swift @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +/// Describes the kind of optional type to use. +enum OptionalKind { + /// The value is nonoptional. + case nonoptional + + /// The value is optional. + case optional + + /// The value uses an implicitly-unwrapped optional. + case implicitlyUnwrappedOptional +} diff --git a/Sources/JavaKitMacros/JavaFieldMacro.swift b/Sources/JavaKitMacros/JavaFieldMacro.swift index cb85d352..02280570 100644 --- a/Sources/JavaKitMacros/JavaFieldMacro.swift +++ b/Sources/JavaKitMacros/JavaFieldMacro.swift @@ -27,7 +27,7 @@ extension JavaFieldMacro: AccessorMacro { guard let varDecl = declaration.as(VariableDeclSyntax.self), let binding = varDecl.bindings.first, let fieldNameAsWritten = binding.pattern.as(IdentifierPatternSyntax.self)?.identifier.trimmed.text, - let fieldType = binding.typeAnnotation?.type.trimmed, + let fieldType = binding.typeAnnotation?.type.typeReference, binding.accessorBlock == nil else { return [] diff --git a/Sources/JavaKitMacros/JavaMethodMacro.swift b/Sources/JavaKitMacros/JavaMethodMacro.swift index f525c985..0a4be1f0 100644 --- a/Sources/JavaKitMacros/JavaMethodMacro.swift +++ b/Sources/JavaKitMacros/JavaMethodMacro.swift @@ -55,7 +55,7 @@ extension JavaMethodMacro: BodyMacro { let params = funcDecl.signature.parameterClause.parameters let resultType: String = funcDecl.signature.returnClause.map { result in - ", resultType: \(result.type.trimmedDescription).self" + ", resultType: \(result.type.typeReferenceString).self" } ?? "" let paramNames = params.map { param in param.parameterName?.text ?? "" }.joined(separator: ", ") @@ -126,3 +126,25 @@ extension FunctionParameterListSyntax { return firstIndex { $0.parameterName?.text == name } } } + +extension TypeSyntaxProtocol { + /// Produce a reference to the given type syntax node with any adjustments + /// needed to pretty-print it back into source. + var typeReference: TypeSyntax { + if let iuoType = self.as(ImplicitlyUnwrappedOptionalTypeSyntax.self) { + return TypeSyntax( + OptionalTypeSyntax( + wrappedType: iuoType.wrappedType.trimmed + ) + ) + } + + return TypeSyntax(trimmed) + } + + /// Produce a reference to the given type syntax node with any adjustments + /// needed to pretty-print it back into source, as a string. + var typeReferenceString: String { + typeReference.description + } +} diff --git a/Tests/Java2SwiftTests/Java2SwiftTests.swift b/Tests/Java2SwiftTests/Java2SwiftTests.swift index e1224746..d1e19551 100644 --- a/Tests/Java2SwiftTests/Java2SwiftTests.swift +++ b/Tests/Java2SwiftTests/Java2SwiftTests.swift @@ -74,7 +74,7 @@ class Java2SwiftTests: XCTestCase { """, """ @JavaStaticMethod - public func forName(_ arg0: JavaString) throws -> MyJavaClass? where ObjectType == MyJavaClass + public func forName(_ arg0: JavaString) throws -> MyJavaClass! where ObjectType == MyJavaClass """, ] ) @@ -88,7 +88,7 @@ class Java2SwiftTests: XCTestCase { "import JavaKit", "enum MonthCases: Equatable", "case APRIL", - "public var enumValue: MonthCases?", + "public var enumValue: MonthCases!", """ } else if self.equals(classObj.APRIL?.as(JavaObject.self)) { return MonthCases.APRIL @@ -105,7 +105,7 @@ class Java2SwiftTests: XCTestCase { """, """ @JavaStaticField(isFinal: true) - public var APRIL: Month? + public var APRIL: Month! """ ]) } @@ -121,7 +121,7 @@ class Java2SwiftTests: XCTestCase { expectedChunks: [ """ @JavaMethod - public func subList(_ arg0: Int32, _ arg1: Int32) -> JavaList? + public func subList(_ arg0: Int32, _ arg1: Int32) -> JavaList! """ ] ) @@ -138,7 +138,7 @@ class Java2SwiftTests: XCTestCase { expectedChunks: [ """ @JavaMethod - public func subList(_ arg0: Int32, _ arg1: Int32) -> JavaList? + public func subList(_ arg0: Int32, _ arg1: Int32) -> JavaList! """ ] ) @@ -161,7 +161,7 @@ class Java2SwiftTests: XCTestCase { "import JavaKit", """ @JavaMethod - public func redirectInput() -> ProcessBuilder.Redirect? + public func redirectInput() -> ProcessBuilder.Redirect! """, """ extension ProcessBuilder { @@ -169,7 +169,7 @@ class Java2SwiftTests: XCTestCase { public struct Redirect { """, """ - public func redirectError() -> ProcessBuilder.Redirect? + public func redirectError() -> ProcessBuilder.Redirect! """, """ extension ProcessBuilder.Redirect { @@ -178,7 +178,7 @@ class Java2SwiftTests: XCTestCase { """, """ @JavaMethod - public func type() -> ProcessBuilder.Redirect.`Type`? + public func type() -> ProcessBuilder.Redirect.`Type`! """, ] ) @@ -201,7 +201,7 @@ class Java2SwiftTests: XCTestCase { "import JavaKit", """ @JavaMethod - public func redirectInput() -> ProcessBuilder.PBRedirect? + public func redirectInput() -> ProcessBuilder.PBRedirect! """, """ extension ProcessBuilder { @@ -209,7 +209,7 @@ class Java2SwiftTests: XCTestCase { public struct PBRedirect { """, """ - public func redirectError() -> ProcessBuilder.PBRedirect? + public func redirectError() -> ProcessBuilder.PBRedirect! """, """ extension ProcessBuilder.PBRedirect { @@ -218,7 +218,7 @@ class Java2SwiftTests: XCTestCase { """, """ @JavaMethod - public func type() -> ProcessBuilder.PBRedirect.JavaType? + public func type() -> ProcessBuilder.PBRedirect.JavaType! """ ] ) diff --git a/Tests/JavaKitMacroTests/JavaClassMacroTests.swift b/Tests/JavaKitMacroTests/JavaClassMacroTests.swift index e033bc0f..42ce532f 100644 --- a/Tests/JavaKitMacroTests/JavaClassMacroTests.swift +++ b/Tests/JavaKitMacroTests/JavaClassMacroTests.swift @@ -42,6 +42,9 @@ class JavaKitMacroTests: XCTestCase { @JavaField public var myField: Int64 + @JavaField + public var objectField: JavaObject! + @JavaField(isFinal: true) public var myFinalField: Int64 } @@ -76,6 +79,14 @@ class JavaKitMacroTests: XCTestCase { self[javaFieldName: "myField", fieldType: Int64.self] = newValue } } + public var objectField: JavaObject! { + get { + self[javaFieldName: "objectField", fieldType: JavaObject?.self] + } + nonmutating set { + self[javaFieldName: "objectField", fieldType: JavaObject?.self] = newValue + } + } public var myFinalField: Int64 { get { self[javaFieldName: "myFinalField", fieldType: Int64.self] From 6ca4ec32d9fbeab6d325ff001000b1d441515afe Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Mon, 28 Oct 2024 11:08:47 -0700 Subject: [PATCH 136/426] Regenerate JavaKit code with implicitly-unwrapped optionals --- Sources/JavaKit/generated/Exception.swift | 8 +- Sources/JavaKit/generated/JavaBoolean.swift | 12 +- Sources/JavaKit/generated/JavaByte.swift | 12 +- Sources/JavaKit/generated/JavaCharacter.swift | 1014 ++++++++--------- Sources/JavaKit/generated/JavaClass.swift | 26 +- Sources/JavaKit/generated/JavaDouble.swift | 8 +- Sources/JavaKit/generated/JavaError.swift | 8 +- Sources/JavaKit/generated/JavaFloat.swift | 8 +- Sources/JavaKit/generated/JavaInteger.swift | 18 +- Sources/JavaKit/generated/JavaLong.swift | 18 +- Sources/JavaKit/generated/JavaNumber.swift | 2 +- Sources/JavaKit/generated/JavaObject.swift | 2 +- Sources/JavaKit/generated/JavaShort.swift | 12 +- Sources/JavaKit/generated/JavaVoid.swift | 4 +- .../JavaKit/generated/RuntimeException.swift | 8 +- Sources/JavaKit/generated/Throwable.swift | 8 +- .../generated/ArrayDeque.swift | 34 +- .../generated/ArrayList.swift | 28 +- .../JavaKitCollection/generated/BitSet.swift | 10 +- .../generated/Enumeration.swift | 4 +- .../JavaKitCollection/generated/HashMap.swift | 22 +- .../JavaKitCollection/generated/HashSet.swift | 8 +- .../generated/JavaCollection.swift | 2 +- .../generated/JavaDictionary.swift | 12 +- .../generated/JavaIterator.swift | 2 +- .../JavaKitCollection/generated/JavaSet.swift | 28 +- .../JavaKitCollection/generated/List.swift | 50 +- .../generated/ListIterator.swift | 4 +- .../generated/PriorityQueue.swift | 12 +- .../JavaKitCollection/generated/Queue.swift | 10 +- .../JavaKitCollection/generated/Stack.swift | 42 +- .../JavaKitCollection/generated/TreeMap.swift | 52 +- .../JavaKitCollection/generated/TreeSet.swift | 32 +- Sources/JavaKitJar/generated/Attributes.swift | 58 +- Sources/JavaKitJar/generated/JarEntry.swift | 6 +- Sources/JavaKitJar/generated/JarFile.swift | 8 +- .../JavaKitJar/generated/JarInputStream.swift | 6 +- .../generated/JarOutputStream.swift | 2 +- Sources/JavaKitJar/generated/Manifest.swift | 8 +- Sources/JavaKitNetwork/generated/URI.swift | 16 +- Sources/JavaKitNetwork/generated/URL.swift | 8 +- .../generated/URLClassLoader.swift | 18 +- .../generated/AccessibleObject.swift | 6 +- .../generated/AnnotatedType.swift | 8 +- .../generated/Annotation.swift | 2 +- .../generated/Constructor.swift | 14 +- .../generated/Executable.swift | 12 +- .../JavaKitReflection/generated/Field.swift | 16 +- .../generated/GenericArrayType.swift | 2 +- .../generated/GenericDeclaration.swift | 4 +- .../JavaKitReflection/generated/Method.swift | 20 +- .../generated/Parameter.swift | 14 +- .../generated/ParameterizedType.swift | 4 +- .../generated/TypeVariable.swift | 6 +- 54 files changed, 879 insertions(+), 879 deletions(-) diff --git a/Sources/JavaKit/generated/Exception.swift b/Sources/JavaKit/generated/Exception.swift index 59a1f246..694dc112 100644 --- a/Sources/JavaKit/generated/Exception.swift +++ b/Sources/JavaKit/generated/Exception.swift @@ -19,13 +19,13 @@ public struct Exception { public func printStackTrace() @JavaMethod - public func fillInStackTrace() -> Throwable? + public func fillInStackTrace() -> Throwable! @JavaMethod - public func getCause() -> Throwable? + public func getCause() -> Throwable! @JavaMethod - public func initCause(_ arg0: Throwable?) -> Throwable? + public func initCause(_ arg0: Throwable?) -> Throwable! @JavaMethod public func toString() -> String @@ -49,7 +49,7 @@ public struct Exception { public func hashCode() -> Int32 @JavaMethod - public func getClass() -> JavaClass? + public func getClass() -> JavaClass! @JavaMethod public func notify() diff --git a/Sources/JavaKit/generated/JavaBoolean.swift b/Sources/JavaKit/generated/JavaBoolean.swift index 310f46e4..b5fc9067 100644 --- a/Sources/JavaKit/generated/JavaBoolean.swift +++ b/Sources/JavaKit/generated/JavaBoolean.swift @@ -28,7 +28,7 @@ public struct JavaBoolean { public func booleanValue() -> Bool @JavaMethod - public func getClass() -> JavaClass? + public func getClass() -> JavaClass! @JavaMethod public func notify() @@ -47,13 +47,13 @@ public struct JavaBoolean { } extension JavaClass { @JavaStaticField(isFinal: true) - public var TRUE: JavaBoolean? + public var TRUE: JavaBoolean! @JavaStaticField(isFinal: true) - public var FALSE: JavaBoolean? + public var FALSE: JavaBoolean! @JavaStaticField(isFinal: true) - public var TYPE: JavaClass? + public var TYPE: JavaClass! @JavaStaticMethod public func toString(_ arg0: Bool) -> String @@ -68,10 +68,10 @@ extension JavaClass { public func compare(_ arg0: Bool, _ arg1: Bool) -> Int32 @JavaStaticMethod - public func valueOf(_ arg0: String) -> JavaBoolean? + public func valueOf(_ arg0: String) -> JavaBoolean! @JavaStaticMethod - public func valueOf(_ arg0: Bool) -> JavaBoolean? + public func valueOf(_ arg0: Bool) -> JavaBoolean! @JavaStaticMethod public func parseBoolean(_ arg0: String) -> Bool diff --git a/Sources/JavaKit/generated/JavaByte.swift b/Sources/JavaKit/generated/JavaByte.swift index 79b6b5f2..7b832217 100644 --- a/Sources/JavaKit/generated/JavaByte.swift +++ b/Sources/JavaKit/generated/JavaByte.swift @@ -43,7 +43,7 @@ public struct JavaByte { public func doubleValue() -> Double @JavaMethod - public func getClass() -> JavaClass? + public func getClass() -> JavaClass! @JavaMethod public func notify() @@ -68,7 +68,7 @@ extension JavaClass { public var MAX_VALUE: Int8 @JavaStaticField(isFinal: true) - public var TYPE: JavaClass? + public var TYPE: JavaClass! @JavaStaticField(isFinal: true) public var SIZE: Int32 @@ -89,16 +89,16 @@ extension JavaClass { public func compare(_ arg0: Int8, _ arg1: Int8) -> Int32 @JavaStaticMethod - public func valueOf(_ arg0: String) throws -> JavaByte? + public func valueOf(_ arg0: String) throws -> JavaByte! @JavaStaticMethod - public func valueOf(_ arg0: String, _ arg1: Int32) throws -> JavaByte? + public func valueOf(_ arg0: String, _ arg1: Int32) throws -> JavaByte! @JavaStaticMethod - public func valueOf(_ arg0: Int8) -> JavaByte? + public func valueOf(_ arg0: Int8) -> JavaByte! @JavaStaticMethod - public func decode(_ arg0: String) throws -> JavaByte? + public func decode(_ arg0: String) throws -> JavaByte! @JavaStaticMethod public func toUnsignedLong(_ arg0: Int8) -> Int64 diff --git a/Sources/JavaKit/generated/JavaCharacter.swift b/Sources/JavaKit/generated/JavaCharacter.swift index ccf11323..4e9ee4b5 100644 --- a/Sources/JavaKit/generated/JavaCharacter.swift +++ b/Sources/JavaKit/generated/JavaCharacter.swift @@ -25,7 +25,7 @@ public struct JavaCharacter { public func charValue() -> UInt16 @JavaMethod - public func getClass() -> JavaClass? + public func getClass() -> JavaClass! @JavaMethod public func notify() @@ -55,7 +55,7 @@ extension JavaCharacter { public func hashCode() -> Int32 @JavaMethod - public func getClass() -> JavaClass? + public func getClass() -> JavaClass! @JavaMethod public func notify() @@ -75,1000 +75,1000 @@ extension JavaCharacter { } extension JavaClass { @JavaStaticField(isFinal: true) - public var BASIC_LATIN: JavaCharacter.UnicodeBlock? + public var BASIC_LATIN: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var LATIN_1_SUPPLEMENT: JavaCharacter.UnicodeBlock? + public var LATIN_1_SUPPLEMENT: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var LATIN_EXTENDED_A: JavaCharacter.UnicodeBlock? + public var LATIN_EXTENDED_A: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var LATIN_EXTENDED_B: JavaCharacter.UnicodeBlock? + public var LATIN_EXTENDED_B: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var IPA_EXTENSIONS: JavaCharacter.UnicodeBlock? + public var IPA_EXTENSIONS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var SPACING_MODIFIER_LETTERS: JavaCharacter.UnicodeBlock? + public var SPACING_MODIFIER_LETTERS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var COMBINING_DIACRITICAL_MARKS: JavaCharacter.UnicodeBlock? + public var COMBINING_DIACRITICAL_MARKS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var GREEK: JavaCharacter.UnicodeBlock? + public var GREEK: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var CYRILLIC: JavaCharacter.UnicodeBlock? + public var CYRILLIC: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var ARMENIAN: JavaCharacter.UnicodeBlock? + public var ARMENIAN: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var HEBREW: JavaCharacter.UnicodeBlock? + public var HEBREW: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var ARABIC: JavaCharacter.UnicodeBlock? + public var ARABIC: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var DEVANAGARI: JavaCharacter.UnicodeBlock? + public var DEVANAGARI: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var BENGALI: JavaCharacter.UnicodeBlock? + public var BENGALI: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var GURMUKHI: JavaCharacter.UnicodeBlock? + public var GURMUKHI: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var GUJARATI: JavaCharacter.UnicodeBlock? + public var GUJARATI: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var ORIYA: JavaCharacter.UnicodeBlock? + public var ORIYA: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var TAMIL: JavaCharacter.UnicodeBlock? + public var TAMIL: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var TELUGU: JavaCharacter.UnicodeBlock? + public var TELUGU: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var KANNADA: JavaCharacter.UnicodeBlock? + public var KANNADA: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var MALAYALAM: JavaCharacter.UnicodeBlock? + public var MALAYALAM: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var THAI: JavaCharacter.UnicodeBlock? + public var THAI: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var LAO: JavaCharacter.UnicodeBlock? + public var LAO: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var TIBETAN: JavaCharacter.UnicodeBlock? + public var TIBETAN: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var GEORGIAN: JavaCharacter.UnicodeBlock? + public var GEORGIAN: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var HANGUL_JAMO: JavaCharacter.UnicodeBlock? + public var HANGUL_JAMO: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var LATIN_EXTENDED_ADDITIONAL: JavaCharacter.UnicodeBlock? + public var LATIN_EXTENDED_ADDITIONAL: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var GREEK_EXTENDED: JavaCharacter.UnicodeBlock? + public var GREEK_EXTENDED: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var GENERAL_PUNCTUATION: JavaCharacter.UnicodeBlock? + public var GENERAL_PUNCTUATION: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var SUPERSCRIPTS_AND_SUBSCRIPTS: JavaCharacter.UnicodeBlock? + public var SUPERSCRIPTS_AND_SUBSCRIPTS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var CURRENCY_SYMBOLS: JavaCharacter.UnicodeBlock? + public var CURRENCY_SYMBOLS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var COMBINING_MARKS_FOR_SYMBOLS: JavaCharacter.UnicodeBlock? + public var COMBINING_MARKS_FOR_SYMBOLS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var LETTERLIKE_SYMBOLS: JavaCharacter.UnicodeBlock? + public var LETTERLIKE_SYMBOLS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var NUMBER_FORMS: JavaCharacter.UnicodeBlock? + public var NUMBER_FORMS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var ARROWS: JavaCharacter.UnicodeBlock? + public var ARROWS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var MATHEMATICAL_OPERATORS: JavaCharacter.UnicodeBlock? + public var MATHEMATICAL_OPERATORS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var MISCELLANEOUS_TECHNICAL: JavaCharacter.UnicodeBlock? + public var MISCELLANEOUS_TECHNICAL: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var CONTROL_PICTURES: JavaCharacter.UnicodeBlock? + public var CONTROL_PICTURES: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var OPTICAL_CHARACTER_RECOGNITION: JavaCharacter.UnicodeBlock? + public var OPTICAL_CHARACTER_RECOGNITION: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var ENCLOSED_ALPHANUMERICS: JavaCharacter.UnicodeBlock? + public var ENCLOSED_ALPHANUMERICS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var BOX_DRAWING: JavaCharacter.UnicodeBlock? + public var BOX_DRAWING: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var BLOCK_ELEMENTS: JavaCharacter.UnicodeBlock? + public var BLOCK_ELEMENTS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var GEOMETRIC_SHAPES: JavaCharacter.UnicodeBlock? + public var GEOMETRIC_SHAPES: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var MISCELLANEOUS_SYMBOLS: JavaCharacter.UnicodeBlock? + public var MISCELLANEOUS_SYMBOLS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var DINGBATS: JavaCharacter.UnicodeBlock? + public var DINGBATS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var CJK_SYMBOLS_AND_PUNCTUATION: JavaCharacter.UnicodeBlock? + public var CJK_SYMBOLS_AND_PUNCTUATION: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var HIRAGANA: JavaCharacter.UnicodeBlock? + public var HIRAGANA: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var KATAKANA: JavaCharacter.UnicodeBlock? + public var KATAKANA: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var BOPOMOFO: JavaCharacter.UnicodeBlock? + public var BOPOMOFO: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var HANGUL_COMPATIBILITY_JAMO: JavaCharacter.UnicodeBlock? + public var HANGUL_COMPATIBILITY_JAMO: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var KANBUN: JavaCharacter.UnicodeBlock? + public var KANBUN: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var ENCLOSED_CJK_LETTERS_AND_MONTHS: JavaCharacter.UnicodeBlock? + public var ENCLOSED_CJK_LETTERS_AND_MONTHS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var CJK_COMPATIBILITY: JavaCharacter.UnicodeBlock? + public var CJK_COMPATIBILITY: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var CJK_UNIFIED_IDEOGRAPHS: JavaCharacter.UnicodeBlock? + public var CJK_UNIFIED_IDEOGRAPHS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var HANGUL_SYLLABLES: JavaCharacter.UnicodeBlock? + public var HANGUL_SYLLABLES: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var PRIVATE_USE_AREA: JavaCharacter.UnicodeBlock? + public var PRIVATE_USE_AREA: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var CJK_COMPATIBILITY_IDEOGRAPHS: JavaCharacter.UnicodeBlock? + public var CJK_COMPATIBILITY_IDEOGRAPHS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var ALPHABETIC_PRESENTATION_FORMS: JavaCharacter.UnicodeBlock? + public var ALPHABETIC_PRESENTATION_FORMS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var ARABIC_PRESENTATION_FORMS_A: JavaCharacter.UnicodeBlock? + public var ARABIC_PRESENTATION_FORMS_A: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var COMBINING_HALF_MARKS: JavaCharacter.UnicodeBlock? + public var COMBINING_HALF_MARKS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var CJK_COMPATIBILITY_FORMS: JavaCharacter.UnicodeBlock? + public var CJK_COMPATIBILITY_FORMS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var SMALL_FORM_VARIANTS: JavaCharacter.UnicodeBlock? + public var SMALL_FORM_VARIANTS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var ARABIC_PRESENTATION_FORMS_B: JavaCharacter.UnicodeBlock? + public var ARABIC_PRESENTATION_FORMS_B: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var HALFWIDTH_AND_FULLWIDTH_FORMS: JavaCharacter.UnicodeBlock? + public var HALFWIDTH_AND_FULLWIDTH_FORMS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var SPECIALS: JavaCharacter.UnicodeBlock? + public var SPECIALS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var SURROGATES_AREA: JavaCharacter.UnicodeBlock? + public var SURROGATES_AREA: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var SYRIAC: JavaCharacter.UnicodeBlock? + public var SYRIAC: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var THAANA: JavaCharacter.UnicodeBlock? + public var THAANA: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var SINHALA: JavaCharacter.UnicodeBlock? + public var SINHALA: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var MYANMAR: JavaCharacter.UnicodeBlock? + public var MYANMAR: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var ETHIOPIC: JavaCharacter.UnicodeBlock? + public var ETHIOPIC: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var CHEROKEE: JavaCharacter.UnicodeBlock? + public var CHEROKEE: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS: JavaCharacter.UnicodeBlock? + public var UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var OGHAM: JavaCharacter.UnicodeBlock? + public var OGHAM: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var RUNIC: JavaCharacter.UnicodeBlock? + public var RUNIC: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var KHMER: JavaCharacter.UnicodeBlock? + public var KHMER: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var MONGOLIAN: JavaCharacter.UnicodeBlock? + public var MONGOLIAN: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var BRAILLE_PATTERNS: JavaCharacter.UnicodeBlock? + public var BRAILLE_PATTERNS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var CJK_RADICALS_SUPPLEMENT: JavaCharacter.UnicodeBlock? + public var CJK_RADICALS_SUPPLEMENT: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var KANGXI_RADICALS: JavaCharacter.UnicodeBlock? + public var KANGXI_RADICALS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var IDEOGRAPHIC_DESCRIPTION_CHARACTERS: JavaCharacter.UnicodeBlock? + public var IDEOGRAPHIC_DESCRIPTION_CHARACTERS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var BOPOMOFO_EXTENDED: JavaCharacter.UnicodeBlock? + public var BOPOMOFO_EXTENDED: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A: JavaCharacter.UnicodeBlock? + public var CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var YI_SYLLABLES: JavaCharacter.UnicodeBlock? + public var YI_SYLLABLES: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var YI_RADICALS: JavaCharacter.UnicodeBlock? + public var YI_RADICALS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var CYRILLIC_SUPPLEMENTARY: JavaCharacter.UnicodeBlock? + public var CYRILLIC_SUPPLEMENTARY: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var TAGALOG: JavaCharacter.UnicodeBlock? + public var TAGALOG: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var HANUNOO: JavaCharacter.UnicodeBlock? + public var HANUNOO: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var BUHID: JavaCharacter.UnicodeBlock? + public var BUHID: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var TAGBANWA: JavaCharacter.UnicodeBlock? + public var TAGBANWA: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var LIMBU: JavaCharacter.UnicodeBlock? + public var LIMBU: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var TAI_LE: JavaCharacter.UnicodeBlock? + public var TAI_LE: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var KHMER_SYMBOLS: JavaCharacter.UnicodeBlock? + public var KHMER_SYMBOLS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var PHONETIC_EXTENSIONS: JavaCharacter.UnicodeBlock? + public var PHONETIC_EXTENSIONS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var MISCELLANEOUS_MATHEMATICAL_SYMBOLS_A: JavaCharacter.UnicodeBlock? + public var MISCELLANEOUS_MATHEMATICAL_SYMBOLS_A: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var SUPPLEMENTAL_ARROWS_A: JavaCharacter.UnicodeBlock? + public var SUPPLEMENTAL_ARROWS_A: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var SUPPLEMENTAL_ARROWS_B: JavaCharacter.UnicodeBlock? + public var SUPPLEMENTAL_ARROWS_B: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var MISCELLANEOUS_MATHEMATICAL_SYMBOLS_B: JavaCharacter.UnicodeBlock? + public var MISCELLANEOUS_MATHEMATICAL_SYMBOLS_B: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var SUPPLEMENTAL_MATHEMATICAL_OPERATORS: JavaCharacter.UnicodeBlock? + public var SUPPLEMENTAL_MATHEMATICAL_OPERATORS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var MISCELLANEOUS_SYMBOLS_AND_ARROWS: JavaCharacter.UnicodeBlock? + public var MISCELLANEOUS_SYMBOLS_AND_ARROWS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var KATAKANA_PHONETIC_EXTENSIONS: JavaCharacter.UnicodeBlock? + public var KATAKANA_PHONETIC_EXTENSIONS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var YIJING_HEXAGRAM_SYMBOLS: JavaCharacter.UnicodeBlock? + public var YIJING_HEXAGRAM_SYMBOLS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var VARIATION_SELECTORS: JavaCharacter.UnicodeBlock? + public var VARIATION_SELECTORS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var LINEAR_B_SYLLABARY: JavaCharacter.UnicodeBlock? + public var LINEAR_B_SYLLABARY: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var LINEAR_B_IDEOGRAMS: JavaCharacter.UnicodeBlock? + public var LINEAR_B_IDEOGRAMS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var AEGEAN_NUMBERS: JavaCharacter.UnicodeBlock? + public var AEGEAN_NUMBERS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var OLD_ITALIC: JavaCharacter.UnicodeBlock? + public var OLD_ITALIC: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var GOTHIC: JavaCharacter.UnicodeBlock? + public var GOTHIC: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var UGARITIC: JavaCharacter.UnicodeBlock? + public var UGARITIC: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var DESERET: JavaCharacter.UnicodeBlock? + public var DESERET: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var SHAVIAN: JavaCharacter.UnicodeBlock? + public var SHAVIAN: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var OSMANYA: JavaCharacter.UnicodeBlock? + public var OSMANYA: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var CYPRIOT_SYLLABARY: JavaCharacter.UnicodeBlock? + public var CYPRIOT_SYLLABARY: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var BYZANTINE_MUSICAL_SYMBOLS: JavaCharacter.UnicodeBlock? + public var BYZANTINE_MUSICAL_SYMBOLS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var MUSICAL_SYMBOLS: JavaCharacter.UnicodeBlock? + public var MUSICAL_SYMBOLS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var TAI_XUAN_JING_SYMBOLS: JavaCharacter.UnicodeBlock? + public var TAI_XUAN_JING_SYMBOLS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var MATHEMATICAL_ALPHANUMERIC_SYMBOLS: JavaCharacter.UnicodeBlock? + public var MATHEMATICAL_ALPHANUMERIC_SYMBOLS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B: JavaCharacter.UnicodeBlock? + public var CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT: JavaCharacter.UnicodeBlock? + public var CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var TAGS: JavaCharacter.UnicodeBlock? + public var TAGS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var VARIATION_SELECTORS_SUPPLEMENT: JavaCharacter.UnicodeBlock? + public var VARIATION_SELECTORS_SUPPLEMENT: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var SUPPLEMENTARY_PRIVATE_USE_AREA_A: JavaCharacter.UnicodeBlock? + public var SUPPLEMENTARY_PRIVATE_USE_AREA_A: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var SUPPLEMENTARY_PRIVATE_USE_AREA_B: JavaCharacter.UnicodeBlock? + public var SUPPLEMENTARY_PRIVATE_USE_AREA_B: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var HIGH_SURROGATES: JavaCharacter.UnicodeBlock? + public var HIGH_SURROGATES: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var HIGH_PRIVATE_USE_SURROGATES: JavaCharacter.UnicodeBlock? + public var HIGH_PRIVATE_USE_SURROGATES: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var LOW_SURROGATES: JavaCharacter.UnicodeBlock? + public var LOW_SURROGATES: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var ARABIC_SUPPLEMENT: JavaCharacter.UnicodeBlock? + public var ARABIC_SUPPLEMENT: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var NKO: JavaCharacter.UnicodeBlock? + public var NKO: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var SAMARITAN: JavaCharacter.UnicodeBlock? + public var SAMARITAN: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var MANDAIC: JavaCharacter.UnicodeBlock? + public var MANDAIC: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var ETHIOPIC_SUPPLEMENT: JavaCharacter.UnicodeBlock? + public var ETHIOPIC_SUPPLEMENT: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS_EXTENDED: JavaCharacter.UnicodeBlock? + public var UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS_EXTENDED: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var NEW_TAI_LUE: JavaCharacter.UnicodeBlock? + public var NEW_TAI_LUE: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var BUGINESE: JavaCharacter.UnicodeBlock? + public var BUGINESE: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var TAI_THAM: JavaCharacter.UnicodeBlock? + public var TAI_THAM: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var BALINESE: JavaCharacter.UnicodeBlock? + public var BALINESE: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var SUNDANESE: JavaCharacter.UnicodeBlock? + public var SUNDANESE: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var BATAK: JavaCharacter.UnicodeBlock? + public var BATAK: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var LEPCHA: JavaCharacter.UnicodeBlock? + public var LEPCHA: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var OL_CHIKI: JavaCharacter.UnicodeBlock? + public var OL_CHIKI: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var VEDIC_EXTENSIONS: JavaCharacter.UnicodeBlock? + public var VEDIC_EXTENSIONS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var PHONETIC_EXTENSIONS_SUPPLEMENT: JavaCharacter.UnicodeBlock? + public var PHONETIC_EXTENSIONS_SUPPLEMENT: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var COMBINING_DIACRITICAL_MARKS_SUPPLEMENT: JavaCharacter.UnicodeBlock? + public var COMBINING_DIACRITICAL_MARKS_SUPPLEMENT: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var GLAGOLITIC: JavaCharacter.UnicodeBlock? + public var GLAGOLITIC: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var LATIN_EXTENDED_C: JavaCharacter.UnicodeBlock? + public var LATIN_EXTENDED_C: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var COPTIC: JavaCharacter.UnicodeBlock? + public var COPTIC: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var GEORGIAN_SUPPLEMENT: JavaCharacter.UnicodeBlock? + public var GEORGIAN_SUPPLEMENT: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var TIFINAGH: JavaCharacter.UnicodeBlock? + public var TIFINAGH: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var ETHIOPIC_EXTENDED: JavaCharacter.UnicodeBlock? + public var ETHIOPIC_EXTENDED: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var CYRILLIC_EXTENDED_A: JavaCharacter.UnicodeBlock? + public var CYRILLIC_EXTENDED_A: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var SUPPLEMENTAL_PUNCTUATION: JavaCharacter.UnicodeBlock? + public var SUPPLEMENTAL_PUNCTUATION: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var CJK_STROKES: JavaCharacter.UnicodeBlock? + public var CJK_STROKES: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var LISU: JavaCharacter.UnicodeBlock? + public var LISU: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var VAI: JavaCharacter.UnicodeBlock? + public var VAI: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var CYRILLIC_EXTENDED_B: JavaCharacter.UnicodeBlock? + public var CYRILLIC_EXTENDED_B: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var BAMUM: JavaCharacter.UnicodeBlock? + public var BAMUM: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var MODIFIER_TONE_LETTERS: JavaCharacter.UnicodeBlock? + public var MODIFIER_TONE_LETTERS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var LATIN_EXTENDED_D: JavaCharacter.UnicodeBlock? + public var LATIN_EXTENDED_D: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var SYLOTI_NAGRI: JavaCharacter.UnicodeBlock? + public var SYLOTI_NAGRI: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var COMMON_INDIC_NUMBER_FORMS: JavaCharacter.UnicodeBlock? + public var COMMON_INDIC_NUMBER_FORMS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var PHAGS_PA: JavaCharacter.UnicodeBlock? + public var PHAGS_PA: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var SAURASHTRA: JavaCharacter.UnicodeBlock? + public var SAURASHTRA: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var DEVANAGARI_EXTENDED: JavaCharacter.UnicodeBlock? + public var DEVANAGARI_EXTENDED: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var KAYAH_LI: JavaCharacter.UnicodeBlock? + public var KAYAH_LI: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var REJANG: JavaCharacter.UnicodeBlock? + public var REJANG: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var HANGUL_JAMO_EXTENDED_A: JavaCharacter.UnicodeBlock? + public var HANGUL_JAMO_EXTENDED_A: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var JAVANESE: JavaCharacter.UnicodeBlock? + public var JAVANESE: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var CHAM: JavaCharacter.UnicodeBlock? + public var CHAM: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var MYANMAR_EXTENDED_A: JavaCharacter.UnicodeBlock? + public var MYANMAR_EXTENDED_A: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var TAI_VIET: JavaCharacter.UnicodeBlock? + public var TAI_VIET: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var ETHIOPIC_EXTENDED_A: JavaCharacter.UnicodeBlock? + public var ETHIOPIC_EXTENDED_A: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var MEETEI_MAYEK: JavaCharacter.UnicodeBlock? + public var MEETEI_MAYEK: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var HANGUL_JAMO_EXTENDED_B: JavaCharacter.UnicodeBlock? + public var HANGUL_JAMO_EXTENDED_B: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var VERTICAL_FORMS: JavaCharacter.UnicodeBlock? + public var VERTICAL_FORMS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var ANCIENT_GREEK_NUMBERS: JavaCharacter.UnicodeBlock? + public var ANCIENT_GREEK_NUMBERS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var ANCIENT_SYMBOLS: JavaCharacter.UnicodeBlock? + public var ANCIENT_SYMBOLS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var PHAISTOS_DISC: JavaCharacter.UnicodeBlock? + public var PHAISTOS_DISC: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var LYCIAN: JavaCharacter.UnicodeBlock? + public var LYCIAN: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var CARIAN: JavaCharacter.UnicodeBlock? + public var CARIAN: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var OLD_PERSIAN: JavaCharacter.UnicodeBlock? + public var OLD_PERSIAN: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var IMPERIAL_ARAMAIC: JavaCharacter.UnicodeBlock? + public var IMPERIAL_ARAMAIC: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var PHOENICIAN: JavaCharacter.UnicodeBlock? + public var PHOENICIAN: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var LYDIAN: JavaCharacter.UnicodeBlock? + public var LYDIAN: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var KHAROSHTHI: JavaCharacter.UnicodeBlock? + public var KHAROSHTHI: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var OLD_SOUTH_ARABIAN: JavaCharacter.UnicodeBlock? + public var OLD_SOUTH_ARABIAN: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var AVESTAN: JavaCharacter.UnicodeBlock? + public var AVESTAN: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var INSCRIPTIONAL_PARTHIAN: JavaCharacter.UnicodeBlock? + public var INSCRIPTIONAL_PARTHIAN: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var INSCRIPTIONAL_PAHLAVI: JavaCharacter.UnicodeBlock? + public var INSCRIPTIONAL_PAHLAVI: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var OLD_TURKIC: JavaCharacter.UnicodeBlock? + public var OLD_TURKIC: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var RUMI_NUMERAL_SYMBOLS: JavaCharacter.UnicodeBlock? + public var RUMI_NUMERAL_SYMBOLS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var BRAHMI: JavaCharacter.UnicodeBlock? + public var BRAHMI: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var KAITHI: JavaCharacter.UnicodeBlock? + public var KAITHI: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var CUNEIFORM: JavaCharacter.UnicodeBlock? + public var CUNEIFORM: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var CUNEIFORM_NUMBERS_AND_PUNCTUATION: JavaCharacter.UnicodeBlock? + public var CUNEIFORM_NUMBERS_AND_PUNCTUATION: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var EGYPTIAN_HIEROGLYPHS: JavaCharacter.UnicodeBlock? + public var EGYPTIAN_HIEROGLYPHS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var BAMUM_SUPPLEMENT: JavaCharacter.UnicodeBlock? + public var BAMUM_SUPPLEMENT: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var KANA_SUPPLEMENT: JavaCharacter.UnicodeBlock? + public var KANA_SUPPLEMENT: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var ANCIENT_GREEK_MUSICAL_NOTATION: JavaCharacter.UnicodeBlock? + public var ANCIENT_GREEK_MUSICAL_NOTATION: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var COUNTING_ROD_NUMERALS: JavaCharacter.UnicodeBlock? + public var COUNTING_ROD_NUMERALS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var MAHJONG_TILES: JavaCharacter.UnicodeBlock? + public var MAHJONG_TILES: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var DOMINO_TILES: JavaCharacter.UnicodeBlock? + public var DOMINO_TILES: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var PLAYING_CARDS: JavaCharacter.UnicodeBlock? + public var PLAYING_CARDS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var ENCLOSED_ALPHANUMERIC_SUPPLEMENT: JavaCharacter.UnicodeBlock? + public var ENCLOSED_ALPHANUMERIC_SUPPLEMENT: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var ENCLOSED_IDEOGRAPHIC_SUPPLEMENT: JavaCharacter.UnicodeBlock? + public var ENCLOSED_IDEOGRAPHIC_SUPPLEMENT: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var MISCELLANEOUS_SYMBOLS_AND_PICTOGRAPHS: JavaCharacter.UnicodeBlock? + public var MISCELLANEOUS_SYMBOLS_AND_PICTOGRAPHS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var EMOTICONS: JavaCharacter.UnicodeBlock? + public var EMOTICONS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var TRANSPORT_AND_MAP_SYMBOLS: JavaCharacter.UnicodeBlock? + public var TRANSPORT_AND_MAP_SYMBOLS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var ALCHEMICAL_SYMBOLS: JavaCharacter.UnicodeBlock? + public var ALCHEMICAL_SYMBOLS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var CJK_UNIFIED_IDEOGRAPHS_EXTENSION_C: JavaCharacter.UnicodeBlock? + public var CJK_UNIFIED_IDEOGRAPHS_EXTENSION_C: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var CJK_UNIFIED_IDEOGRAPHS_EXTENSION_D: JavaCharacter.UnicodeBlock? + public var CJK_UNIFIED_IDEOGRAPHS_EXTENSION_D: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var ARABIC_EXTENDED_A: JavaCharacter.UnicodeBlock? + public var ARABIC_EXTENDED_A: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var SUNDANESE_SUPPLEMENT: JavaCharacter.UnicodeBlock? + public var SUNDANESE_SUPPLEMENT: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var MEETEI_MAYEK_EXTENSIONS: JavaCharacter.UnicodeBlock? + public var MEETEI_MAYEK_EXTENSIONS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var MEROITIC_HIEROGLYPHS: JavaCharacter.UnicodeBlock? + public var MEROITIC_HIEROGLYPHS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var MEROITIC_CURSIVE: JavaCharacter.UnicodeBlock? + public var MEROITIC_CURSIVE: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var SORA_SOMPENG: JavaCharacter.UnicodeBlock? + public var SORA_SOMPENG: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var CHAKMA: JavaCharacter.UnicodeBlock? + public var CHAKMA: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var SHARADA: JavaCharacter.UnicodeBlock? + public var SHARADA: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var TAKRI: JavaCharacter.UnicodeBlock? + public var TAKRI: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var MIAO: JavaCharacter.UnicodeBlock? + public var MIAO: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var ARABIC_MATHEMATICAL_ALPHABETIC_SYMBOLS: JavaCharacter.UnicodeBlock? + public var ARABIC_MATHEMATICAL_ALPHABETIC_SYMBOLS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var COMBINING_DIACRITICAL_MARKS_EXTENDED: JavaCharacter.UnicodeBlock? + public var COMBINING_DIACRITICAL_MARKS_EXTENDED: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var MYANMAR_EXTENDED_B: JavaCharacter.UnicodeBlock? + public var MYANMAR_EXTENDED_B: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var LATIN_EXTENDED_E: JavaCharacter.UnicodeBlock? + public var LATIN_EXTENDED_E: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var COPTIC_EPACT_NUMBERS: JavaCharacter.UnicodeBlock? + public var COPTIC_EPACT_NUMBERS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var OLD_PERMIC: JavaCharacter.UnicodeBlock? + public var OLD_PERMIC: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var ELBASAN: JavaCharacter.UnicodeBlock? + public var ELBASAN: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var CAUCASIAN_ALBANIAN: JavaCharacter.UnicodeBlock? + public var CAUCASIAN_ALBANIAN: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var LINEAR_A: JavaCharacter.UnicodeBlock? + public var LINEAR_A: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var PALMYRENE: JavaCharacter.UnicodeBlock? + public var PALMYRENE: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var NABATAEAN: JavaCharacter.UnicodeBlock? + public var NABATAEAN: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var OLD_NORTH_ARABIAN: JavaCharacter.UnicodeBlock? + public var OLD_NORTH_ARABIAN: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var MANICHAEAN: JavaCharacter.UnicodeBlock? + public var MANICHAEAN: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var PSALTER_PAHLAVI: JavaCharacter.UnicodeBlock? + public var PSALTER_PAHLAVI: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var MAHAJANI: JavaCharacter.UnicodeBlock? + public var MAHAJANI: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var SINHALA_ARCHAIC_NUMBERS: JavaCharacter.UnicodeBlock? + public var SINHALA_ARCHAIC_NUMBERS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var KHOJKI: JavaCharacter.UnicodeBlock? + public var KHOJKI: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var KHUDAWADI: JavaCharacter.UnicodeBlock? + public var KHUDAWADI: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var GRANTHA: JavaCharacter.UnicodeBlock? + public var GRANTHA: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var TIRHUTA: JavaCharacter.UnicodeBlock? + public var TIRHUTA: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var SIDDHAM: JavaCharacter.UnicodeBlock? + public var SIDDHAM: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var MODI: JavaCharacter.UnicodeBlock? + public var MODI: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var WARANG_CITI: JavaCharacter.UnicodeBlock? + public var WARANG_CITI: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var PAU_CIN_HAU: JavaCharacter.UnicodeBlock? + public var PAU_CIN_HAU: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var MRO: JavaCharacter.UnicodeBlock? + public var MRO: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var BASSA_VAH: JavaCharacter.UnicodeBlock? + public var BASSA_VAH: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var PAHAWH_HMONG: JavaCharacter.UnicodeBlock? + public var PAHAWH_HMONG: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var DUPLOYAN: JavaCharacter.UnicodeBlock? + public var DUPLOYAN: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var SHORTHAND_FORMAT_CONTROLS: JavaCharacter.UnicodeBlock? + public var SHORTHAND_FORMAT_CONTROLS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var MENDE_KIKAKUI: JavaCharacter.UnicodeBlock? + public var MENDE_KIKAKUI: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var ORNAMENTAL_DINGBATS: JavaCharacter.UnicodeBlock? + public var ORNAMENTAL_DINGBATS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var GEOMETRIC_SHAPES_EXTENDED: JavaCharacter.UnicodeBlock? + public var GEOMETRIC_SHAPES_EXTENDED: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var SUPPLEMENTAL_ARROWS_C: JavaCharacter.UnicodeBlock? + public var SUPPLEMENTAL_ARROWS_C: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var CHEROKEE_SUPPLEMENT: JavaCharacter.UnicodeBlock? + public var CHEROKEE_SUPPLEMENT: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var HATRAN: JavaCharacter.UnicodeBlock? + public var HATRAN: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var OLD_HUNGARIAN: JavaCharacter.UnicodeBlock? + public var OLD_HUNGARIAN: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var MULTANI: JavaCharacter.UnicodeBlock? + public var MULTANI: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var AHOM: JavaCharacter.UnicodeBlock? + public var AHOM: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var EARLY_DYNASTIC_CUNEIFORM: JavaCharacter.UnicodeBlock? + public var EARLY_DYNASTIC_CUNEIFORM: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var ANATOLIAN_HIEROGLYPHS: JavaCharacter.UnicodeBlock? + public var ANATOLIAN_HIEROGLYPHS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var SUTTON_SIGNWRITING: JavaCharacter.UnicodeBlock? + public var SUTTON_SIGNWRITING: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var SUPPLEMENTAL_SYMBOLS_AND_PICTOGRAPHS: JavaCharacter.UnicodeBlock? + public var SUPPLEMENTAL_SYMBOLS_AND_PICTOGRAPHS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var CJK_UNIFIED_IDEOGRAPHS_EXTENSION_E: JavaCharacter.UnicodeBlock? + public var CJK_UNIFIED_IDEOGRAPHS_EXTENSION_E: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var SYRIAC_SUPPLEMENT: JavaCharacter.UnicodeBlock? + public var SYRIAC_SUPPLEMENT: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var CYRILLIC_EXTENDED_C: JavaCharacter.UnicodeBlock? + public var CYRILLIC_EXTENDED_C: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var OSAGE: JavaCharacter.UnicodeBlock? + public var OSAGE: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var NEWA: JavaCharacter.UnicodeBlock? + public var NEWA: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var MONGOLIAN_SUPPLEMENT: JavaCharacter.UnicodeBlock? + public var MONGOLIAN_SUPPLEMENT: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var MARCHEN: JavaCharacter.UnicodeBlock? + public var MARCHEN: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var IDEOGRAPHIC_SYMBOLS_AND_PUNCTUATION: JavaCharacter.UnicodeBlock? + public var IDEOGRAPHIC_SYMBOLS_AND_PUNCTUATION: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var TANGUT: JavaCharacter.UnicodeBlock? + public var TANGUT: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var TANGUT_COMPONENTS: JavaCharacter.UnicodeBlock? + public var TANGUT_COMPONENTS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var KANA_EXTENDED_A: JavaCharacter.UnicodeBlock? + public var KANA_EXTENDED_A: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var GLAGOLITIC_SUPPLEMENT: JavaCharacter.UnicodeBlock? + public var GLAGOLITIC_SUPPLEMENT: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var ADLAM: JavaCharacter.UnicodeBlock? + public var ADLAM: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var MASARAM_GONDI: JavaCharacter.UnicodeBlock? + public var MASARAM_GONDI: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var ZANABAZAR_SQUARE: JavaCharacter.UnicodeBlock? + public var ZANABAZAR_SQUARE: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var NUSHU: JavaCharacter.UnicodeBlock? + public var NUSHU: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var SOYOMBO: JavaCharacter.UnicodeBlock? + public var SOYOMBO: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var BHAIKSUKI: JavaCharacter.UnicodeBlock? + public var BHAIKSUKI: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var CJK_UNIFIED_IDEOGRAPHS_EXTENSION_F: JavaCharacter.UnicodeBlock? + public var CJK_UNIFIED_IDEOGRAPHS_EXTENSION_F: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var GEORGIAN_EXTENDED: JavaCharacter.UnicodeBlock? + public var GEORGIAN_EXTENDED: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var HANIFI_ROHINGYA: JavaCharacter.UnicodeBlock? + public var HANIFI_ROHINGYA: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var OLD_SOGDIAN: JavaCharacter.UnicodeBlock? + public var OLD_SOGDIAN: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var SOGDIAN: JavaCharacter.UnicodeBlock? + public var SOGDIAN: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var DOGRA: JavaCharacter.UnicodeBlock? + public var DOGRA: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var GUNJALA_GONDI: JavaCharacter.UnicodeBlock? + public var GUNJALA_GONDI: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var MAKASAR: JavaCharacter.UnicodeBlock? + public var MAKASAR: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var MEDEFAIDRIN: JavaCharacter.UnicodeBlock? + public var MEDEFAIDRIN: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var MAYAN_NUMERALS: JavaCharacter.UnicodeBlock? + public var MAYAN_NUMERALS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var INDIC_SIYAQ_NUMBERS: JavaCharacter.UnicodeBlock? + public var INDIC_SIYAQ_NUMBERS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var CHESS_SYMBOLS: JavaCharacter.UnicodeBlock? + public var CHESS_SYMBOLS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var ELYMAIC: JavaCharacter.UnicodeBlock? + public var ELYMAIC: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var NANDINAGARI: JavaCharacter.UnicodeBlock? + public var NANDINAGARI: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var TAMIL_SUPPLEMENT: JavaCharacter.UnicodeBlock? + public var TAMIL_SUPPLEMENT: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var EGYPTIAN_HIEROGLYPH_FORMAT_CONTROLS: JavaCharacter.UnicodeBlock? + public var EGYPTIAN_HIEROGLYPH_FORMAT_CONTROLS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var SMALL_KANA_EXTENSION: JavaCharacter.UnicodeBlock? + public var SMALL_KANA_EXTENSION: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var NYIAKENG_PUACHUE_HMONG: JavaCharacter.UnicodeBlock? + public var NYIAKENG_PUACHUE_HMONG: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var WANCHO: JavaCharacter.UnicodeBlock? + public var WANCHO: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var OTTOMAN_SIYAQ_NUMBERS: JavaCharacter.UnicodeBlock? + public var OTTOMAN_SIYAQ_NUMBERS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var SYMBOLS_AND_PICTOGRAPHS_EXTENDED_A: JavaCharacter.UnicodeBlock? + public var SYMBOLS_AND_PICTOGRAPHS_EXTENDED_A: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var YEZIDI: JavaCharacter.UnicodeBlock? + public var YEZIDI: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var CHORASMIAN: JavaCharacter.UnicodeBlock? + public var CHORASMIAN: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var DIVES_AKURU: JavaCharacter.UnicodeBlock? + public var DIVES_AKURU: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var LISU_SUPPLEMENT: JavaCharacter.UnicodeBlock? + public var LISU_SUPPLEMENT: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var KHITAN_SMALL_SCRIPT: JavaCharacter.UnicodeBlock? + public var KHITAN_SMALL_SCRIPT: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var TANGUT_SUPPLEMENT: JavaCharacter.UnicodeBlock? + public var TANGUT_SUPPLEMENT: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var SYMBOLS_FOR_LEGACY_COMPUTING: JavaCharacter.UnicodeBlock? + public var SYMBOLS_FOR_LEGACY_COMPUTING: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var CJK_UNIFIED_IDEOGRAPHS_EXTENSION_G: JavaCharacter.UnicodeBlock? + public var CJK_UNIFIED_IDEOGRAPHS_EXTENSION_G: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var ARABIC_EXTENDED_B: JavaCharacter.UnicodeBlock? + public var ARABIC_EXTENDED_B: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var VITHKUQI: JavaCharacter.UnicodeBlock? + public var VITHKUQI: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var LATIN_EXTENDED_F: JavaCharacter.UnicodeBlock? + public var LATIN_EXTENDED_F: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var OLD_UYGHUR: JavaCharacter.UnicodeBlock? + public var OLD_UYGHUR: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS_EXTENDED_A: JavaCharacter.UnicodeBlock? + public var UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS_EXTENDED_A: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var CYPRO_MINOAN: JavaCharacter.UnicodeBlock? + public var CYPRO_MINOAN: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var TANGSA: JavaCharacter.UnicodeBlock? + public var TANGSA: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var KANA_EXTENDED_B: JavaCharacter.UnicodeBlock? + public var KANA_EXTENDED_B: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var ZNAMENNY_MUSICAL_NOTATION: JavaCharacter.UnicodeBlock? + public var ZNAMENNY_MUSICAL_NOTATION: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var LATIN_EXTENDED_G: JavaCharacter.UnicodeBlock? + public var LATIN_EXTENDED_G: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var TOTO: JavaCharacter.UnicodeBlock? + public var TOTO: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var ETHIOPIC_EXTENDED_B: JavaCharacter.UnicodeBlock? + public var ETHIOPIC_EXTENDED_B: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var ARABIC_EXTENDED_C: JavaCharacter.UnicodeBlock? + public var ARABIC_EXTENDED_C: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var DEVANAGARI_EXTENDED_A: JavaCharacter.UnicodeBlock? + public var DEVANAGARI_EXTENDED_A: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var KAWI: JavaCharacter.UnicodeBlock? + public var KAWI: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var KAKTOVIK_NUMERALS: JavaCharacter.UnicodeBlock? + public var KAKTOVIK_NUMERALS: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var CYRILLIC_EXTENDED_D: JavaCharacter.UnicodeBlock? + public var CYRILLIC_EXTENDED_D: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var NAG_MUNDARI: JavaCharacter.UnicodeBlock? + public var NAG_MUNDARI: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var CJK_UNIFIED_IDEOGRAPHS_EXTENSION_H: JavaCharacter.UnicodeBlock? + public var CJK_UNIFIED_IDEOGRAPHS_EXTENSION_H: JavaCharacter.UnicodeBlock! @JavaStaticField(isFinal: true) - public var CJK_UNIFIED_IDEOGRAPHS_EXTENSION_I: JavaCharacter.UnicodeBlock? + public var CJK_UNIFIED_IDEOGRAPHS_EXTENSION_I: JavaCharacter.UnicodeBlock! @JavaStaticMethod - public func forName(_ arg0: String) -> JavaCharacter.UnicodeBlock? + public func forName(_ arg0: String) -> JavaCharacter.UnicodeBlock! @JavaStaticMethod - public func of(_ arg0: Int32) -> JavaCharacter.UnicodeBlock? + public func of(_ arg0: Int32) -> JavaCharacter.UnicodeBlock! @JavaStaticMethod - public func of(_ arg0: UInt16) -> JavaCharacter.UnicodeBlock? + public func of(_ arg0: UInt16) -> JavaCharacter.UnicodeBlock! } extension JavaCharacter { @JavaClass("java.lang.Character$UnicodeScript") @@ -1240,7 +1240,7 @@ extension JavaCharacter { case UNKNOWN } - public var enumValue: UnicodeScriptCases? { + public var enumValue: UnicodeScriptCases! { let classObj = self.javaClass if self.equals(classObj.COMMON?.as(JavaObject.self)) { return UnicodeScriptCases.COMMON @@ -2589,7 +2589,7 @@ extension JavaCharacter { public func ordinal() -> Int32 @JavaMethod - public func getClass() -> JavaClass? + public func getClass() -> JavaClass! @JavaMethod public func notify() @@ -2623,7 +2623,7 @@ extension JavaCharacter.UnicodeScript { public func hashCode() -> Int32 @JavaMethod - public func getClass() -> JavaClass? + public func getClass() -> JavaClass! @JavaMethod public func notify() @@ -2643,508 +2643,508 @@ extension JavaCharacter.UnicodeScript { } extension JavaClass { @JavaStaticField(isFinal: true) - public var COMMON: JavaCharacter.UnicodeScript? + public var COMMON: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var LATIN: JavaCharacter.UnicodeScript? + public var LATIN: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var GREEK: JavaCharacter.UnicodeScript? + public var GREEK: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var CYRILLIC: JavaCharacter.UnicodeScript? + public var CYRILLIC: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var ARMENIAN: JavaCharacter.UnicodeScript? + public var ARMENIAN: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var HEBREW: JavaCharacter.UnicodeScript? + public var HEBREW: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var ARABIC: JavaCharacter.UnicodeScript? + public var ARABIC: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var SYRIAC: JavaCharacter.UnicodeScript? + public var SYRIAC: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var THAANA: JavaCharacter.UnicodeScript? + public var THAANA: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var DEVANAGARI: JavaCharacter.UnicodeScript? + public var DEVANAGARI: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var BENGALI: JavaCharacter.UnicodeScript? + public var BENGALI: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var GURMUKHI: JavaCharacter.UnicodeScript? + public var GURMUKHI: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var GUJARATI: JavaCharacter.UnicodeScript? + public var GUJARATI: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var ORIYA: JavaCharacter.UnicodeScript? + public var ORIYA: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var TAMIL: JavaCharacter.UnicodeScript? + public var TAMIL: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var TELUGU: JavaCharacter.UnicodeScript? + public var TELUGU: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var KANNADA: JavaCharacter.UnicodeScript? + public var KANNADA: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var MALAYALAM: JavaCharacter.UnicodeScript? + public var MALAYALAM: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var SINHALA: JavaCharacter.UnicodeScript? + public var SINHALA: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var THAI: JavaCharacter.UnicodeScript? + public var THAI: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var LAO: JavaCharacter.UnicodeScript? + public var LAO: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var TIBETAN: JavaCharacter.UnicodeScript? + public var TIBETAN: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var MYANMAR: JavaCharacter.UnicodeScript? + public var MYANMAR: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var GEORGIAN: JavaCharacter.UnicodeScript? + public var GEORGIAN: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var HANGUL: JavaCharacter.UnicodeScript? + public var HANGUL: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var ETHIOPIC: JavaCharacter.UnicodeScript? + public var ETHIOPIC: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var CHEROKEE: JavaCharacter.UnicodeScript? + public var CHEROKEE: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var CANADIAN_ABORIGINAL: JavaCharacter.UnicodeScript? + public var CANADIAN_ABORIGINAL: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var OGHAM: JavaCharacter.UnicodeScript? + public var OGHAM: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var RUNIC: JavaCharacter.UnicodeScript? + public var RUNIC: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var KHMER: JavaCharacter.UnicodeScript? + public var KHMER: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var MONGOLIAN: JavaCharacter.UnicodeScript? + public var MONGOLIAN: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var HIRAGANA: JavaCharacter.UnicodeScript? + public var HIRAGANA: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var KATAKANA: JavaCharacter.UnicodeScript? + public var KATAKANA: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var BOPOMOFO: JavaCharacter.UnicodeScript? + public var BOPOMOFO: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var HAN: JavaCharacter.UnicodeScript? + public var HAN: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var YI: JavaCharacter.UnicodeScript? + public var YI: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var OLD_ITALIC: JavaCharacter.UnicodeScript? + public var OLD_ITALIC: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var GOTHIC: JavaCharacter.UnicodeScript? + public var GOTHIC: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var DESERET: JavaCharacter.UnicodeScript? + public var DESERET: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var INHERITED: JavaCharacter.UnicodeScript? + public var INHERITED: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var TAGALOG: JavaCharacter.UnicodeScript? + public var TAGALOG: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var HANUNOO: JavaCharacter.UnicodeScript? + public var HANUNOO: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var BUHID: JavaCharacter.UnicodeScript? + public var BUHID: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var TAGBANWA: JavaCharacter.UnicodeScript? + public var TAGBANWA: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var LIMBU: JavaCharacter.UnicodeScript? + public var LIMBU: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var TAI_LE: JavaCharacter.UnicodeScript? + public var TAI_LE: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var LINEAR_B: JavaCharacter.UnicodeScript? + public var LINEAR_B: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var UGARITIC: JavaCharacter.UnicodeScript? + public var UGARITIC: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var SHAVIAN: JavaCharacter.UnicodeScript? + public var SHAVIAN: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var OSMANYA: JavaCharacter.UnicodeScript? + public var OSMANYA: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var CYPRIOT: JavaCharacter.UnicodeScript? + public var CYPRIOT: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var BRAILLE: JavaCharacter.UnicodeScript? + public var BRAILLE: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var BUGINESE: JavaCharacter.UnicodeScript? + public var BUGINESE: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var COPTIC: JavaCharacter.UnicodeScript? + public var COPTIC: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var NEW_TAI_LUE: JavaCharacter.UnicodeScript? + public var NEW_TAI_LUE: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var GLAGOLITIC: JavaCharacter.UnicodeScript? + public var GLAGOLITIC: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var TIFINAGH: JavaCharacter.UnicodeScript? + public var TIFINAGH: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var SYLOTI_NAGRI: JavaCharacter.UnicodeScript? + public var SYLOTI_NAGRI: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var OLD_PERSIAN: JavaCharacter.UnicodeScript? + public var OLD_PERSIAN: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var KHAROSHTHI: JavaCharacter.UnicodeScript? + public var KHAROSHTHI: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var BALINESE: JavaCharacter.UnicodeScript? + public var BALINESE: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var CUNEIFORM: JavaCharacter.UnicodeScript? + public var CUNEIFORM: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var PHOENICIAN: JavaCharacter.UnicodeScript? + public var PHOENICIAN: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var PHAGS_PA: JavaCharacter.UnicodeScript? + public var PHAGS_PA: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var NKO: JavaCharacter.UnicodeScript? + public var NKO: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var SUNDANESE: JavaCharacter.UnicodeScript? + public var SUNDANESE: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var BATAK: JavaCharacter.UnicodeScript? + public var BATAK: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var LEPCHA: JavaCharacter.UnicodeScript? + public var LEPCHA: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var OL_CHIKI: JavaCharacter.UnicodeScript? + public var OL_CHIKI: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var VAI: JavaCharacter.UnicodeScript? + public var VAI: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var SAURASHTRA: JavaCharacter.UnicodeScript? + public var SAURASHTRA: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var KAYAH_LI: JavaCharacter.UnicodeScript? + public var KAYAH_LI: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var REJANG: JavaCharacter.UnicodeScript? + public var REJANG: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var LYCIAN: JavaCharacter.UnicodeScript? + public var LYCIAN: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var CARIAN: JavaCharacter.UnicodeScript? + public var CARIAN: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var LYDIAN: JavaCharacter.UnicodeScript? + public var LYDIAN: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var CHAM: JavaCharacter.UnicodeScript? + public var CHAM: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var TAI_THAM: JavaCharacter.UnicodeScript? + public var TAI_THAM: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var TAI_VIET: JavaCharacter.UnicodeScript? + public var TAI_VIET: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var AVESTAN: JavaCharacter.UnicodeScript? + public var AVESTAN: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var EGYPTIAN_HIEROGLYPHS: JavaCharacter.UnicodeScript? + public var EGYPTIAN_HIEROGLYPHS: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var SAMARITAN: JavaCharacter.UnicodeScript? + public var SAMARITAN: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var MANDAIC: JavaCharacter.UnicodeScript? + public var MANDAIC: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var LISU: JavaCharacter.UnicodeScript? + public var LISU: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var BAMUM: JavaCharacter.UnicodeScript? + public var BAMUM: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var JAVANESE: JavaCharacter.UnicodeScript? + public var JAVANESE: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var MEETEI_MAYEK: JavaCharacter.UnicodeScript? + public var MEETEI_MAYEK: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var IMPERIAL_ARAMAIC: JavaCharacter.UnicodeScript? + public var IMPERIAL_ARAMAIC: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var OLD_SOUTH_ARABIAN: JavaCharacter.UnicodeScript? + public var OLD_SOUTH_ARABIAN: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var INSCRIPTIONAL_PARTHIAN: JavaCharacter.UnicodeScript? + public var INSCRIPTIONAL_PARTHIAN: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var INSCRIPTIONAL_PAHLAVI: JavaCharacter.UnicodeScript? + public var INSCRIPTIONAL_PAHLAVI: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var OLD_TURKIC: JavaCharacter.UnicodeScript? + public var OLD_TURKIC: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var BRAHMI: JavaCharacter.UnicodeScript? + public var BRAHMI: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var KAITHI: JavaCharacter.UnicodeScript? + public var KAITHI: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var MEROITIC_HIEROGLYPHS: JavaCharacter.UnicodeScript? + public var MEROITIC_HIEROGLYPHS: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var MEROITIC_CURSIVE: JavaCharacter.UnicodeScript? + public var MEROITIC_CURSIVE: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var SORA_SOMPENG: JavaCharacter.UnicodeScript? + public var SORA_SOMPENG: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var CHAKMA: JavaCharacter.UnicodeScript? + public var CHAKMA: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var SHARADA: JavaCharacter.UnicodeScript? + public var SHARADA: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var TAKRI: JavaCharacter.UnicodeScript? + public var TAKRI: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var MIAO: JavaCharacter.UnicodeScript? + public var MIAO: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var CAUCASIAN_ALBANIAN: JavaCharacter.UnicodeScript? + public var CAUCASIAN_ALBANIAN: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var BASSA_VAH: JavaCharacter.UnicodeScript? + public var BASSA_VAH: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var DUPLOYAN: JavaCharacter.UnicodeScript? + public var DUPLOYAN: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var ELBASAN: JavaCharacter.UnicodeScript? + public var ELBASAN: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var GRANTHA: JavaCharacter.UnicodeScript? + public var GRANTHA: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var PAHAWH_HMONG: JavaCharacter.UnicodeScript? + public var PAHAWH_HMONG: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var KHOJKI: JavaCharacter.UnicodeScript? + public var KHOJKI: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var LINEAR_A: JavaCharacter.UnicodeScript? + public var LINEAR_A: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var MAHAJANI: JavaCharacter.UnicodeScript? + public var MAHAJANI: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var MANICHAEAN: JavaCharacter.UnicodeScript? + public var MANICHAEAN: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var MENDE_KIKAKUI: JavaCharacter.UnicodeScript? + public var MENDE_KIKAKUI: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var MODI: JavaCharacter.UnicodeScript? + public var MODI: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var MRO: JavaCharacter.UnicodeScript? + public var MRO: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var OLD_NORTH_ARABIAN: JavaCharacter.UnicodeScript? + public var OLD_NORTH_ARABIAN: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var NABATAEAN: JavaCharacter.UnicodeScript? + public var NABATAEAN: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var PALMYRENE: JavaCharacter.UnicodeScript? + public var PALMYRENE: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var PAU_CIN_HAU: JavaCharacter.UnicodeScript? + public var PAU_CIN_HAU: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var OLD_PERMIC: JavaCharacter.UnicodeScript? + public var OLD_PERMIC: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var PSALTER_PAHLAVI: JavaCharacter.UnicodeScript? + public var PSALTER_PAHLAVI: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var SIDDHAM: JavaCharacter.UnicodeScript? + public var SIDDHAM: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var KHUDAWADI: JavaCharacter.UnicodeScript? + public var KHUDAWADI: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var TIRHUTA: JavaCharacter.UnicodeScript? + public var TIRHUTA: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var WARANG_CITI: JavaCharacter.UnicodeScript? + public var WARANG_CITI: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var AHOM: JavaCharacter.UnicodeScript? + public var AHOM: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var ANATOLIAN_HIEROGLYPHS: JavaCharacter.UnicodeScript? + public var ANATOLIAN_HIEROGLYPHS: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var HATRAN: JavaCharacter.UnicodeScript? + public var HATRAN: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var MULTANI: JavaCharacter.UnicodeScript? + public var MULTANI: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var OLD_HUNGARIAN: JavaCharacter.UnicodeScript? + public var OLD_HUNGARIAN: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var SIGNWRITING: JavaCharacter.UnicodeScript? + public var SIGNWRITING: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var ADLAM: JavaCharacter.UnicodeScript? + public var ADLAM: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var BHAIKSUKI: JavaCharacter.UnicodeScript? + public var BHAIKSUKI: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var MARCHEN: JavaCharacter.UnicodeScript? + public var MARCHEN: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var NEWA: JavaCharacter.UnicodeScript? + public var NEWA: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var OSAGE: JavaCharacter.UnicodeScript? + public var OSAGE: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var TANGUT: JavaCharacter.UnicodeScript? + public var TANGUT: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var MASARAM_GONDI: JavaCharacter.UnicodeScript? + public var MASARAM_GONDI: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var NUSHU: JavaCharacter.UnicodeScript? + public var NUSHU: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var SOYOMBO: JavaCharacter.UnicodeScript? + public var SOYOMBO: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var ZANABAZAR_SQUARE: JavaCharacter.UnicodeScript? + public var ZANABAZAR_SQUARE: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var HANIFI_ROHINGYA: JavaCharacter.UnicodeScript? + public var HANIFI_ROHINGYA: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var OLD_SOGDIAN: JavaCharacter.UnicodeScript? + public var OLD_SOGDIAN: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var SOGDIAN: JavaCharacter.UnicodeScript? + public var SOGDIAN: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var DOGRA: JavaCharacter.UnicodeScript? + public var DOGRA: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var GUNJALA_GONDI: JavaCharacter.UnicodeScript? + public var GUNJALA_GONDI: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var MAKASAR: JavaCharacter.UnicodeScript? + public var MAKASAR: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var MEDEFAIDRIN: JavaCharacter.UnicodeScript? + public var MEDEFAIDRIN: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var ELYMAIC: JavaCharacter.UnicodeScript? + public var ELYMAIC: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var NANDINAGARI: JavaCharacter.UnicodeScript? + public var NANDINAGARI: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var NYIAKENG_PUACHUE_HMONG: JavaCharacter.UnicodeScript? + public var NYIAKENG_PUACHUE_HMONG: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var WANCHO: JavaCharacter.UnicodeScript? + public var WANCHO: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var YEZIDI: JavaCharacter.UnicodeScript? + public var YEZIDI: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var CHORASMIAN: JavaCharacter.UnicodeScript? + public var CHORASMIAN: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var DIVES_AKURU: JavaCharacter.UnicodeScript? + public var DIVES_AKURU: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var KHITAN_SMALL_SCRIPT: JavaCharacter.UnicodeScript? + public var KHITAN_SMALL_SCRIPT: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var VITHKUQI: JavaCharacter.UnicodeScript? + public var VITHKUQI: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var OLD_UYGHUR: JavaCharacter.UnicodeScript? + public var OLD_UYGHUR: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var CYPRO_MINOAN: JavaCharacter.UnicodeScript? + public var CYPRO_MINOAN: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var TANGSA: JavaCharacter.UnicodeScript? + public var TANGSA: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var TOTO: JavaCharacter.UnicodeScript? + public var TOTO: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var KAWI: JavaCharacter.UnicodeScript? + public var KAWI: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var NAG_MUNDARI: JavaCharacter.UnicodeScript? + public var NAG_MUNDARI: JavaCharacter.UnicodeScript! @JavaStaticField(isFinal: true) - public var UNKNOWN: JavaCharacter.UnicodeScript? + public var UNKNOWN: JavaCharacter.UnicodeScript! @JavaStaticMethod - public func forName(_ arg0: String) -> JavaCharacter.UnicodeScript? + public func forName(_ arg0: String) -> JavaCharacter.UnicodeScript! @JavaStaticMethod public func values() -> [JavaCharacter.UnicodeScript?] @JavaStaticMethod - public func valueOf(_ arg0: String) -> JavaCharacter.UnicodeScript? + public func valueOf(_ arg0: String) -> JavaCharacter.UnicodeScript! @JavaStaticMethod - public func of(_ arg0: Int32) -> JavaCharacter.UnicodeScript? + public func of(_ arg0: Int32) -> JavaCharacter.UnicodeScript! } extension JavaCharacter { @JavaClass("java.lang.Character$Subset") @@ -3159,7 +3159,7 @@ extension JavaCharacter { public func hashCode() -> Int32 @JavaMethod - public func getClass() -> JavaClass? + public func getClass() -> JavaClass! @JavaMethod public func notify() @@ -3191,7 +3191,7 @@ extension JavaClass { public var MAX_VALUE: UInt16 @JavaStaticField(isFinal: true) - public var TYPE: JavaClass? + public var TYPE: JavaClass! @JavaStaticField(isFinal: true) public var UNASSIGNED: Int8 @@ -3443,7 +3443,7 @@ extension JavaClass { public func compare(_ arg0: UInt16, _ arg1: UInt16) -> Int32 @JavaStaticMethod - public func valueOf(_ arg0: UInt16) -> JavaCharacter? + public func valueOf(_ arg0: UInt16) -> JavaCharacter! @JavaStaticMethod public func toChars(_ arg0: Int32) -> [UInt16] diff --git a/Sources/JavaKit/generated/JavaClass.swift b/Sources/JavaKit/generated/JavaClass.swift index 1696db8a..f41cab3b 100644 --- a/Sources/JavaKit/generated/JavaClass.swift +++ b/Sources/JavaKit/generated/JavaClass.swift @@ -31,16 +31,16 @@ public struct JavaClass { public func isHidden() -> Bool @JavaMethod - public func getSuperclass() -> JavaClass? + public func getSuperclass() -> JavaClass! @JavaMethod - public func cast(_ arg0: JavaObject?) -> JavaObject? + public func cast(_ arg0: JavaObject?) -> JavaObject! @JavaMethod - public func componentType() -> JavaClass? + public func componentType() -> JavaClass! @JavaMethod - public func getComponentType() -> JavaClass? + public func getComponentType() -> JavaClass! @JavaMethod public func isAnnotation() -> Bool @@ -52,7 +52,7 @@ public struct JavaClass { public func isRecord() -> Bool @JavaMethod - public func newInstance() throws -> JavaObject? + public func newInstance() throws -> JavaObject! @JavaMethod public func getInterfaces() -> [JavaClass?] @@ -67,10 +67,10 @@ public struct JavaClass { public func isAnonymousClass() -> Bool @JavaMethod - public func getEnclosingClass() throws -> JavaClass? + public func getEnclosingClass() throws -> JavaClass! @JavaMethod - public func arrayType() -> JavaClass? + public func arrayType() -> JavaClass! @JavaMethod public func getSimpleName() -> String @@ -85,7 +85,7 @@ public struct JavaClass { public func desiredAssertionStatus() -> Bool @JavaMethod - public func getNestHost() -> JavaClass? + public func getNestHost() -> JavaClass! @JavaMethod public func descriptorString() -> String @@ -103,7 +103,7 @@ public struct JavaClass { public func getSigners() -> [JavaObject?] @JavaMethod - public func getDeclaringClass() throws -> JavaClass? + public func getDeclaringClass() throws -> JavaClass! @JavaMethod public func getTypeName() -> String @@ -118,7 +118,7 @@ public struct JavaClass { public func getEnumConstants() -> [JavaObject?] @JavaMethod - public func asSubclass(_ arg0: JavaClass?) -> JavaClass? + public func asSubclass(_ arg0: JavaClass?) -> JavaClass! @JavaMethod public func isNestmateOf(_ arg0: JavaClass?) -> Bool @@ -136,7 +136,7 @@ public struct JavaClass { public func hashCode() -> Int32 @JavaMethod - public func getClass() -> JavaClass? + public func getClass() -> JavaClass! @JavaMethod public func notify() @@ -155,8 +155,8 @@ public struct JavaClass { } extension JavaClass { @JavaStaticMethod - public func forName(_ arg0: String) throws -> JavaClass? where ObjectType == JavaClass + public func forName(_ arg0: String) throws -> JavaClass! where ObjectType == JavaClass @JavaStaticMethod - public func forPrimitiveName(_ arg0: String) -> JavaClass? where ObjectType == JavaClass + public func forPrimitiveName(_ arg0: String) -> JavaClass! where ObjectType == JavaClass } diff --git a/Sources/JavaKit/generated/JavaDouble.swift b/Sources/JavaKit/generated/JavaDouble.swift index d5279a31..da2eb571 100644 --- a/Sources/JavaKit/generated/JavaDouble.swift +++ b/Sources/JavaKit/generated/JavaDouble.swift @@ -49,7 +49,7 @@ public struct JavaDouble { public func isNaN() -> Bool @JavaMethod - public func getClass() -> JavaClass? + public func getClass() -> JavaClass! @JavaMethod public func notify() @@ -101,7 +101,7 @@ extension JavaClass { public var BYTES: Int32 @JavaStaticField(isFinal: true) - public var TYPE: JavaClass? + public var TYPE: JavaClass! @JavaStaticMethod public func toString(_ arg0: Double) -> String @@ -134,10 +134,10 @@ extension JavaClass { public func compare(_ arg0: Double, _ arg1: Double) -> Int32 @JavaStaticMethod - public func valueOf(_ arg0: String) throws -> JavaDouble? + public func valueOf(_ arg0: String) throws -> JavaDouble! @JavaStaticMethod - public func valueOf(_ arg0: Double) -> JavaDouble? + public func valueOf(_ arg0: Double) -> JavaDouble! @JavaStaticMethod public func toHexString(_ arg0: Double) -> String diff --git a/Sources/JavaKit/generated/JavaError.swift b/Sources/JavaKit/generated/JavaError.swift index 62abca63..86398c9b 100644 --- a/Sources/JavaKit/generated/JavaError.swift +++ b/Sources/JavaKit/generated/JavaError.swift @@ -19,13 +19,13 @@ public struct JavaError { public func printStackTrace() @JavaMethod - public func fillInStackTrace() -> Throwable? + public func fillInStackTrace() -> Throwable! @JavaMethod - public func getCause() -> Throwable? + public func getCause() -> Throwable! @JavaMethod - public func initCause(_ arg0: Throwable?) -> Throwable? + public func initCause(_ arg0: Throwable?) -> Throwable! @JavaMethod public func toString() -> String @@ -49,7 +49,7 @@ public struct JavaError { public func hashCode() -> Int32 @JavaMethod - public func getClass() -> JavaClass? + public func getClass() -> JavaClass! @JavaMethod public func notify() diff --git a/Sources/JavaKit/generated/JavaFloat.swift b/Sources/JavaKit/generated/JavaFloat.swift index 5ff972c2..4df63cbb 100644 --- a/Sources/JavaKit/generated/JavaFloat.swift +++ b/Sources/JavaKit/generated/JavaFloat.swift @@ -52,7 +52,7 @@ public struct JavaFloat { public func isNaN() -> Bool @JavaMethod - public func getClass() -> JavaClass? + public func getClass() -> JavaClass! @JavaMethod public func notify() @@ -104,7 +104,7 @@ extension JavaClass { public var BYTES: Int32 @JavaStaticField(isFinal: true) - public var TYPE: JavaClass? + public var TYPE: JavaClass! @JavaStaticMethod public func toString(_ arg0: Float) -> String @@ -143,10 +143,10 @@ extension JavaClass { public func compare(_ arg0: Float, _ arg1: Float) -> Int32 @JavaStaticMethod - public func valueOf(_ arg0: Float) -> JavaFloat? + public func valueOf(_ arg0: Float) -> JavaFloat! @JavaStaticMethod - public func valueOf(_ arg0: String) throws -> JavaFloat? + public func valueOf(_ arg0: String) throws -> JavaFloat! @JavaStaticMethod public func toHexString(_ arg0: Float) -> String diff --git a/Sources/JavaKit/generated/JavaInteger.swift b/Sources/JavaKit/generated/JavaInteger.swift index f923016a..6e6a64fa 100644 --- a/Sources/JavaKit/generated/JavaInteger.swift +++ b/Sources/JavaKit/generated/JavaInteger.swift @@ -43,7 +43,7 @@ public struct JavaInteger { public func doubleValue() -> Double @JavaMethod - public func getClass() -> JavaClass? + public func getClass() -> JavaClass! @JavaMethod public func notify() @@ -68,7 +68,7 @@ extension JavaClass { public var MAX_VALUE: Int32 @JavaStaticField(isFinal: true) - public var TYPE: JavaClass? + public var TYPE: JavaClass! @JavaStaticField(isFinal: true) public var SIZE: Int32 @@ -128,19 +128,19 @@ extension JavaClass { public func compare(_ arg0: Int32, _ arg1: Int32) -> Int32 @JavaStaticMethod - public func valueOf(_ arg0: String) throws -> JavaInteger? + public func valueOf(_ arg0: String) throws -> JavaInteger! @JavaStaticMethod - public func valueOf(_ arg0: String, _ arg1: Int32) throws -> JavaInteger? + public func valueOf(_ arg0: String, _ arg1: Int32) throws -> JavaInteger! @JavaStaticMethod - public func valueOf(_ arg0: Int32) -> JavaInteger? + public func valueOf(_ arg0: Int32) -> JavaInteger! @JavaStaticMethod public func toHexString(_ arg0: Int32) -> String @JavaStaticMethod - public func decode(_ arg0: String) throws -> JavaInteger? + public func decode(_ arg0: String) throws -> JavaInteger! @JavaStaticMethod public func parseInt(_ arg0: String) throws -> Int32 @@ -167,13 +167,13 @@ extension JavaClass { public func parseUnsignedInt(_ arg0: String, _ arg1: Int32) throws -> Int32 @JavaStaticMethod - public func getInteger(_ arg0: String, _ arg1: JavaInteger?) -> JavaInteger? + public func getInteger(_ arg0: String, _ arg1: JavaInteger?) -> JavaInteger! @JavaStaticMethod - public func getInteger(_ arg0: String, _ arg1: Int32) -> JavaInteger? + public func getInteger(_ arg0: String, _ arg1: Int32) -> JavaInteger! @JavaStaticMethod - public func getInteger(_ arg0: String) -> JavaInteger? + public func getInteger(_ arg0: String) -> JavaInteger! @JavaStaticMethod public func toOctalString(_ arg0: Int32) -> String diff --git a/Sources/JavaKit/generated/JavaLong.swift b/Sources/JavaKit/generated/JavaLong.swift index 64aeed13..fa02f070 100644 --- a/Sources/JavaKit/generated/JavaLong.swift +++ b/Sources/JavaKit/generated/JavaLong.swift @@ -43,7 +43,7 @@ public struct JavaLong { public func doubleValue() -> Double @JavaMethod - public func getClass() -> JavaClass? + public func getClass() -> JavaClass! @JavaMethod public func notify() @@ -68,7 +68,7 @@ extension JavaClass { public var MAX_VALUE: Int64 @JavaStaticField(isFinal: true) - public var TYPE: JavaClass? + public var TYPE: JavaClass! @JavaStaticField(isFinal: true) public var SIZE: Int32 @@ -125,31 +125,31 @@ extension JavaClass { public func compress(_ arg0: Int64, _ arg1: Int64) -> Int64 @JavaStaticMethod - public func getLong(_ arg0: String, _ arg1: JavaLong?) -> JavaLong? + public func getLong(_ arg0: String, _ arg1: JavaLong?) -> JavaLong! @JavaStaticMethod - public func getLong(_ arg0: String) -> JavaLong? + public func getLong(_ arg0: String) -> JavaLong! @JavaStaticMethod - public func getLong(_ arg0: String, _ arg1: Int64) -> JavaLong? + public func getLong(_ arg0: String, _ arg1: Int64) -> JavaLong! @JavaStaticMethod public func compare(_ arg0: Int64, _ arg1: Int64) -> Int32 @JavaStaticMethod - public func valueOf(_ arg0: String) throws -> JavaLong? + public func valueOf(_ arg0: String) throws -> JavaLong! @JavaStaticMethod - public func valueOf(_ arg0: Int64) -> JavaLong? + public func valueOf(_ arg0: Int64) -> JavaLong! @JavaStaticMethod - public func valueOf(_ arg0: String, _ arg1: Int32) throws -> JavaLong? + public func valueOf(_ arg0: String, _ arg1: Int32) throws -> JavaLong! @JavaStaticMethod public func toHexString(_ arg0: Int64) -> String @JavaStaticMethod - public func decode(_ arg0: String) throws -> JavaLong? + public func decode(_ arg0: String) throws -> JavaLong! @JavaStaticMethod public func sum(_ arg0: Int64, _ arg1: Int64) -> Int64 diff --git a/Sources/JavaKit/generated/JavaNumber.swift b/Sources/JavaKit/generated/JavaNumber.swift index 42864a37..49150d72 100644 --- a/Sources/JavaKit/generated/JavaNumber.swift +++ b/Sources/JavaKit/generated/JavaNumber.swift @@ -34,7 +34,7 @@ public struct JavaNumber { public func hashCode() -> Int32 @JavaMethod - public func getClass() -> JavaClass? + public func getClass() -> JavaClass! @JavaMethod public func notify() diff --git a/Sources/JavaKit/generated/JavaObject.swift b/Sources/JavaKit/generated/JavaObject.swift index 809d1418..8e7a20fc 100644 --- a/Sources/JavaKit/generated/JavaObject.swift +++ b/Sources/JavaKit/generated/JavaObject.swift @@ -16,7 +16,7 @@ public struct JavaObject { public func hashCode() -> Int32 @JavaMethod - public func getClass() -> JavaClass? + public func getClass() -> JavaClass! @JavaMethod public func notify() diff --git a/Sources/JavaKit/generated/JavaShort.swift b/Sources/JavaKit/generated/JavaShort.swift index 6d5da70c..58cb4e26 100644 --- a/Sources/JavaKit/generated/JavaShort.swift +++ b/Sources/JavaKit/generated/JavaShort.swift @@ -43,7 +43,7 @@ public struct JavaShort { public func doubleValue() -> Double @JavaMethod - public func getClass() -> JavaClass? + public func getClass() -> JavaClass! @JavaMethod public func notify() @@ -68,7 +68,7 @@ extension JavaClass { public var MAX_VALUE: Int16 @JavaStaticField(isFinal: true) - public var TYPE: JavaClass? + public var TYPE: JavaClass! @JavaStaticField(isFinal: true) public var SIZE: Int32 @@ -92,16 +92,16 @@ extension JavaClass { public func compare(_ arg0: Int16, _ arg1: Int16) -> Int32 @JavaStaticMethod - public func valueOf(_ arg0: String, _ arg1: Int32) throws -> JavaShort? + public func valueOf(_ arg0: String, _ arg1: Int32) throws -> JavaShort! @JavaStaticMethod - public func valueOf(_ arg0: String) throws -> JavaShort? + public func valueOf(_ arg0: String) throws -> JavaShort! @JavaStaticMethod - public func valueOf(_ arg0: Int16) -> JavaShort? + public func valueOf(_ arg0: Int16) -> JavaShort! @JavaStaticMethod - public func decode(_ arg0: String) throws -> JavaShort? + public func decode(_ arg0: String) throws -> JavaShort! @JavaStaticMethod public func toUnsignedLong(_ arg0: Int16) -> Int64 diff --git a/Sources/JavaKit/generated/JavaVoid.swift b/Sources/JavaKit/generated/JavaVoid.swift index 4baedada..8a0ec266 100644 --- a/Sources/JavaKit/generated/JavaVoid.swift +++ b/Sources/JavaKit/generated/JavaVoid.swift @@ -13,7 +13,7 @@ public struct JavaVoid { public func hashCode() -> Int32 @JavaMethod - public func getClass() -> JavaClass? + public func getClass() -> JavaClass! @JavaMethod public func notify() @@ -32,5 +32,5 @@ public struct JavaVoid { } extension JavaClass { @JavaStaticField(isFinal: true) - public var TYPE: JavaClass? + public var TYPE: JavaClass! } diff --git a/Sources/JavaKit/generated/RuntimeException.swift b/Sources/JavaKit/generated/RuntimeException.swift index 5686efd9..6ef0988f 100644 --- a/Sources/JavaKit/generated/RuntimeException.swift +++ b/Sources/JavaKit/generated/RuntimeException.swift @@ -19,13 +19,13 @@ public struct RuntimeException { public func printStackTrace() @JavaMethod - public func fillInStackTrace() -> Throwable? + public func fillInStackTrace() -> Throwable! @JavaMethod - public func getCause() -> Throwable? + public func getCause() -> Throwable! @JavaMethod - public func initCause(_ arg0: Throwable?) -> Throwable? + public func initCause(_ arg0: Throwable?) -> Throwable! @JavaMethod public func toString() -> String @@ -49,7 +49,7 @@ public struct RuntimeException { public func hashCode() -> Int32 @JavaMethod - public func getClass() -> JavaClass? + public func getClass() -> JavaClass! @JavaMethod public func notify() diff --git a/Sources/JavaKit/generated/Throwable.swift b/Sources/JavaKit/generated/Throwable.swift index 98a4fda2..e292efa0 100644 --- a/Sources/JavaKit/generated/Throwable.swift +++ b/Sources/JavaKit/generated/Throwable.swift @@ -19,13 +19,13 @@ public struct Throwable { public func printStackTrace() @JavaMethod - public func fillInStackTrace() -> Throwable? + public func fillInStackTrace() -> Throwable! @JavaMethod - public func getCause() -> Throwable? + public func getCause() -> Throwable! @JavaMethod - public func initCause(_ arg0: Throwable?) -> Throwable? + public func initCause(_ arg0: Throwable?) -> Throwable! @JavaMethod public func toString() -> String @@ -49,7 +49,7 @@ public struct Throwable { public func hashCode() -> Int32 @JavaMethod - public func getClass() -> JavaClass? + public func getClass() -> JavaClass! @JavaMethod public func notify() diff --git a/Sources/JavaKitCollection/generated/ArrayDeque.swift b/Sources/JavaKitCollection/generated/ArrayDeque.swift index 6d84d201..9c7af8bf 100644 --- a/Sources/JavaKitCollection/generated/ArrayDeque.swift +++ b/Sources/JavaKitCollection/generated/ArrayDeque.swift @@ -14,7 +14,7 @@ public struct ArrayDeque { public init(_ arg0: JavaCollection?, environment: JNIEnvironment? = nil) @JavaMethod - public func remove() -> JavaObject? + public func remove() -> JavaObject! @JavaMethod public func remove(_ arg0: JavaObject?) -> Bool @@ -23,7 +23,7 @@ public struct ArrayDeque { public func size() -> Int32 @JavaMethod - public func clone() -> ArrayDeque? + public func clone() -> ArrayDeque! @JavaMethod public func clear() @@ -41,7 +41,7 @@ public struct ArrayDeque { public func toArray() -> [JavaObject?] @JavaMethod - public func iterator() -> JavaIterator? + public func iterator() -> JavaIterator! @JavaMethod public func contains(_ arg0: JavaObject?) -> Bool @@ -50,16 +50,16 @@ public struct ArrayDeque { public func addAll(_ arg0: JavaCollection?) -> Bool @JavaMethod - public func peek() -> JavaObject? + public func peek() -> JavaObject! @JavaMethod - public func getFirst() -> JavaObject? + public func getFirst() -> JavaObject! @JavaMethod - public func getLast() -> JavaObject? + public func getLast() -> JavaObject! @JavaMethod - public func element() -> JavaObject? + public func element() -> JavaObject! @JavaMethod public func addFirst(_ arg0: JavaObject?) @@ -68,10 +68,10 @@ public struct ArrayDeque { public func addLast(_ arg0: JavaObject?) @JavaMethod - public func removeFirst() -> JavaObject? + public func removeFirst() -> JavaObject! @JavaMethod - public func removeLast() -> JavaObject? + public func removeLast() -> JavaObject! @JavaMethod public func removeAll(_ arg0: JavaCollection?) -> Bool @@ -80,25 +80,25 @@ public struct ArrayDeque { public func retainAll(_ arg0: JavaCollection?) -> Bool @JavaMethod - public func poll() -> JavaObject? + public func poll() -> JavaObject! @JavaMethod public func push(_ arg0: JavaObject?) @JavaMethod - public func pop() -> JavaObject? + public func pop() -> JavaObject! @JavaMethod - public func pollFirst() -> JavaObject? + public func pollFirst() -> JavaObject! @JavaMethod - public func pollLast() -> JavaObject? + public func pollLast() -> JavaObject! @JavaMethod public func offerLast(_ arg0: JavaObject?) -> Bool @JavaMethod - public func peekFirst() -> JavaObject? + public func peekFirst() -> JavaObject! @JavaMethod public func removeFirstOccurrence(_ arg0: JavaObject?) -> Bool @@ -107,7 +107,7 @@ public struct ArrayDeque { public func offerFirst(_ arg0: JavaObject?) -> Bool @JavaMethod - public func peekLast() -> JavaObject? + public func peekLast() -> JavaObject! @JavaMethod public func removeLastOccurrence(_ arg0: JavaObject?) -> Bool @@ -116,7 +116,7 @@ public struct ArrayDeque { public func offer(_ arg0: JavaObject?) -> Bool @JavaMethod - public func descendingIterator() -> JavaIterator? + public func descendingIterator() -> JavaIterator! @JavaMethod public func toString() -> String @@ -131,7 +131,7 @@ public struct ArrayDeque { public func hashCode() -> Int32 @JavaMethod - public func getClass() -> JavaClass? + public func getClass() -> JavaClass! @JavaMethod public func notify() diff --git a/Sources/JavaKitCollection/generated/ArrayList.swift b/Sources/JavaKitCollection/generated/ArrayList.swift index 2b8f1608..0ff6a923 100644 --- a/Sources/JavaKitCollection/generated/ArrayList.swift +++ b/Sources/JavaKitCollection/generated/ArrayList.swift @@ -17,13 +17,13 @@ public struct ArrayList { public func remove(_ arg0: JavaObject?) -> Bool @JavaMethod - public func remove(_ arg0: Int32) -> JavaObject? + public func remove(_ arg0: Int32) -> JavaObject! @JavaMethod public func size() -> Int32 @JavaMethod - public func get(_ arg0: Int32) -> JavaObject? + public func get(_ arg0: Int32) -> JavaObject! @JavaMethod public func equals(_ arg0: JavaObject?) -> Bool @@ -32,7 +32,7 @@ public struct ArrayList { public func hashCode() -> Int32 @JavaMethod - public func clone() -> JavaObject? + public func clone() -> JavaObject! @JavaMethod public func indexOf(_ arg0: JavaObject?) -> Int32 @@ -53,7 +53,7 @@ public struct ArrayList { public func add(_ arg0: Int32, _ arg1: JavaObject?) @JavaMethod - public func subList(_ arg0: Int32, _ arg1: Int32) -> List? + public func subList(_ arg0: Int32, _ arg1: Int32) -> List! @JavaMethod public func toArray() -> [JavaObject?] @@ -62,7 +62,7 @@ public struct ArrayList { public func toArray(_ arg0: [JavaObject?]) -> [JavaObject?] @JavaMethod - public func iterator() -> JavaIterator? + public func iterator() -> JavaIterator! @JavaMethod public func contains(_ arg0: JavaObject?) -> Bool @@ -74,7 +74,7 @@ public struct ArrayList { public func addAll(_ arg0: JavaCollection?) -> Bool @JavaMethod - public func set(_ arg0: Int32, _ arg1: JavaObject?) -> JavaObject? + public func set(_ arg0: Int32, _ arg1: JavaObject?) -> JavaObject! @JavaMethod public func ensureCapacity(_ arg0: Int32) @@ -83,10 +83,10 @@ public struct ArrayList { public func trimToSize() @JavaMethod - public func getFirst() -> JavaObject? + public func getFirst() -> JavaObject! @JavaMethod - public func getLast() -> JavaObject? + public func getLast() -> JavaObject! @JavaMethod public func addFirst(_ arg0: JavaObject?) @@ -95,10 +95,10 @@ public struct ArrayList { public func addLast(_ arg0: JavaObject?) @JavaMethod - public func removeFirst() -> JavaObject? + public func removeFirst() -> JavaObject! @JavaMethod - public func removeLast() -> JavaObject? + public func removeLast() -> JavaObject! @JavaMethod public func removeAll(_ arg0: JavaCollection?) -> Bool @@ -107,10 +107,10 @@ public struct ArrayList { public func retainAll(_ arg0: JavaCollection?) -> Bool @JavaMethod - public func listIterator(_ arg0: Int32) -> ListIterator? + public func listIterator(_ arg0: Int32) -> ListIterator! @JavaMethod - public func listIterator() -> ListIterator? + public func listIterator() -> ListIterator! @JavaMethod public func toString() -> String @@ -119,7 +119,7 @@ public struct ArrayList { public func containsAll(_ arg0: JavaCollection?) -> Bool @JavaMethod - public func getClass() -> JavaClass? + public func getClass() -> JavaClass! @JavaMethod public func notify() @@ -137,5 +137,5 @@ public struct ArrayList { public func wait() throws @JavaMethod - public func reversed() -> List? + public func reversed() -> List! } diff --git a/Sources/JavaKitCollection/generated/BitSet.swift b/Sources/JavaKitCollection/generated/BitSet.swift index d5371c67..99425771 100644 --- a/Sources/JavaKitCollection/generated/BitSet.swift +++ b/Sources/JavaKitCollection/generated/BitSet.swift @@ -32,7 +32,7 @@ public struct BitSet { public func size() -> Int32 @JavaMethod - public func get(_ arg0: Int32, _ arg1: Int32) -> BitSet? + public func get(_ arg0: Int32, _ arg1: Int32) -> BitSet! @JavaMethod public func get(_ arg0: Int32) -> Bool @@ -50,7 +50,7 @@ public struct BitSet { public func hashCode() -> Int32 @JavaMethod - public func clone() -> JavaObject? + public func clone() -> JavaObject! @JavaMethod public func clear(_ arg0: Int32) @@ -101,7 +101,7 @@ public struct BitSet { public func andNot(_ arg0: BitSet?) @JavaMethod - public func getClass() -> JavaClass? + public func getClass() -> JavaClass! @JavaMethod public func notify() @@ -120,8 +120,8 @@ public struct BitSet { } extension JavaClass { @JavaStaticMethod - public func valueOf(_ arg0: [Int64]) -> BitSet? + public func valueOf(_ arg0: [Int64]) -> BitSet! @JavaStaticMethod - public func valueOf(_ arg0: [Int8]) -> BitSet? + public func valueOf(_ arg0: [Int8]) -> BitSet! } diff --git a/Sources/JavaKitCollection/generated/Enumeration.swift b/Sources/JavaKitCollection/generated/Enumeration.swift index be0936d3..492cc3b2 100644 --- a/Sources/JavaKitCollection/generated/Enumeration.swift +++ b/Sources/JavaKitCollection/generated/Enumeration.swift @@ -5,11 +5,11 @@ import JavaRuntime @JavaInterface("java.util.Enumeration") public struct Enumeration { @JavaMethod - public func asIterator() -> JavaIterator? + public func asIterator() -> JavaIterator! @JavaMethod public func hasMoreElements() -> Bool @JavaMethod - public func nextElement() -> JavaObject? + public func nextElement() -> JavaObject! } diff --git a/Sources/JavaKitCollection/generated/HashMap.swift b/Sources/JavaKitCollection/generated/HashMap.swift index 8bd86744..287593f5 100644 --- a/Sources/JavaKitCollection/generated/HashMap.swift +++ b/Sources/JavaKitCollection/generated/HashMap.swift @@ -14,7 +14,7 @@ public struct HashMap { public init(environment: JNIEnvironment? = nil) @JavaMethod - public func remove(_ arg0: JavaObject?) -> JavaObject? + public func remove(_ arg0: JavaObject?) -> JavaObject! @JavaMethod public func remove(_ arg0: JavaObject?, _ arg1: JavaObject?) -> Bool @@ -23,16 +23,16 @@ public struct HashMap { public func size() -> Int32 @JavaMethod - public func get(_ arg0: JavaObject?) -> JavaObject? + public func get(_ arg0: JavaObject?) -> JavaObject! @JavaMethod - public func put(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject? + public func put(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject! @JavaMethod - public func values() -> JavaCollection? + public func values() -> JavaCollection! @JavaMethod - public func clone() -> JavaObject? + public func clone() -> JavaObject! @JavaMethod public func clear() @@ -41,25 +41,25 @@ public struct HashMap { public func isEmpty() -> Bool @JavaMethod - public func replace(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject? + public func replace(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject! @JavaMethod public func replace(_ arg0: JavaObject?, _ arg1: JavaObject?, _ arg2: JavaObject?) -> Bool @JavaMethod - public func putIfAbsent(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject? + public func putIfAbsent(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject! @JavaMethod public func containsKey(_ arg0: JavaObject?) -> Bool @JavaMethod - public func keySet() -> JavaSet? + public func keySet() -> JavaSet! @JavaMethod public func containsValue(_ arg0: JavaObject?) -> Bool @JavaMethod - public func getOrDefault(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject? + public func getOrDefault(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject! @JavaMethod public func equals(_ arg0: JavaObject?) -> Bool @@ -71,7 +71,7 @@ public struct HashMap { public func hashCode() -> Int32 @JavaMethod - public func getClass() -> JavaClass? + public func getClass() -> JavaClass! @JavaMethod public func notify() @@ -90,5 +90,5 @@ public struct HashMap { } extension JavaClass { @JavaStaticMethod - public func newHashMap(_ arg0: Int32) -> HashMap? where ObjectType == HashMap + public func newHashMap(_ arg0: Int32) -> HashMap! where ObjectType == HashMap } diff --git a/Sources/JavaKitCollection/generated/HashSet.swift b/Sources/JavaKitCollection/generated/HashSet.swift index ff194343..9ec5b088 100644 --- a/Sources/JavaKitCollection/generated/HashSet.swift +++ b/Sources/JavaKitCollection/generated/HashSet.swift @@ -23,7 +23,7 @@ public struct HashSet { public func size() -> Int32 @JavaMethod - public func clone() -> JavaObject? + public func clone() -> JavaObject! @JavaMethod public func clear() @@ -41,7 +41,7 @@ public struct HashSet { public func toArray() -> [JavaObject?] @JavaMethod - public func iterator() -> JavaIterator? + public func iterator() -> JavaIterator! @JavaMethod public func contains(_ arg0: JavaObject?) -> Bool @@ -68,7 +68,7 @@ public struct HashSet { public func containsAll(_ arg0: JavaCollection?) -> Bool @JavaMethod - public func getClass() -> JavaClass? + public func getClass() -> JavaClass! @JavaMethod public func notify() @@ -87,5 +87,5 @@ public struct HashSet { } extension JavaClass { @JavaStaticMethod - public func newHashSet(_ arg0: Int32) -> HashSet? where ObjectType == HashSet + public func newHashSet(_ arg0: Int32) -> HashSet! where ObjectType == HashSet } diff --git a/Sources/JavaKitCollection/generated/JavaCollection.swift b/Sources/JavaKitCollection/generated/JavaCollection.swift index 84b44739..26ca6827 100644 --- a/Sources/JavaKitCollection/generated/JavaCollection.swift +++ b/Sources/JavaKitCollection/generated/JavaCollection.swift @@ -32,7 +32,7 @@ public struct JavaCollection { public func toArray() -> [JavaObject?] @JavaMethod - public func iterator() -> JavaIterator? + public func iterator() -> JavaIterator! @JavaMethod public func contains(_ arg0: JavaObject?) -> Bool diff --git a/Sources/JavaKitCollection/generated/JavaDictionary.swift b/Sources/JavaKitCollection/generated/JavaDictionary.swift index 6e46c942..5bebe233 100644 --- a/Sources/JavaKitCollection/generated/JavaDictionary.swift +++ b/Sources/JavaKitCollection/generated/JavaDictionary.swift @@ -8,25 +8,25 @@ public struct JavaDictionary { public init(environment: JNIEnvironment? = nil) @JavaMethod - public func remove(_ arg0: JavaObject?) -> JavaObject? + public func remove(_ arg0: JavaObject?) -> JavaObject! @JavaMethod public func size() -> Int32 @JavaMethod - public func get(_ arg0: JavaObject?) -> JavaObject? + public func get(_ arg0: JavaObject?) -> JavaObject! @JavaMethod - public func put(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject? + public func put(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject! @JavaMethod public func isEmpty() -> Bool @JavaMethod - public func elements() -> Enumeration? + public func elements() -> Enumeration! @JavaMethod - public func keys() -> Enumeration? + public func keys() -> Enumeration! @JavaMethod public func equals(_ arg0: JavaObject?) -> Bool @@ -38,7 +38,7 @@ public struct JavaDictionary { public func hashCode() -> Int32 @JavaMethod - public func getClass() -> JavaClass? + public func getClass() -> JavaClass! @JavaMethod public func notify() diff --git a/Sources/JavaKitCollection/generated/JavaIterator.swift b/Sources/JavaKitCollection/generated/JavaIterator.swift index 893e43a9..382c44e5 100644 --- a/Sources/JavaKitCollection/generated/JavaIterator.swift +++ b/Sources/JavaKitCollection/generated/JavaIterator.swift @@ -11,5 +11,5 @@ public struct JavaIterator { public func hasNext() -> Bool @JavaMethod - public func next() -> JavaObject? + public func next() -> JavaObject! } diff --git a/Sources/JavaKitCollection/generated/JavaSet.swift b/Sources/JavaKitCollection/generated/JavaSet.swift index b1412c9d..d924d2d1 100644 --- a/Sources/JavaKitCollection/generated/JavaSet.swift +++ b/Sources/JavaKitCollection/generated/JavaSet.swift @@ -32,7 +32,7 @@ public struct JavaSet { public func toArray(_ arg0: [JavaObject?]) -> [JavaObject?] @JavaMethod - public func iterator() -> JavaIterator? + public func iterator() -> JavaIterator! @JavaMethod public func contains(_ arg0: JavaObject?) -> Bool @@ -51,41 +51,41 @@ public struct JavaSet { } extension JavaClass { @JavaStaticMethod - public func copyOf(_ arg0: JavaCollection?) -> JavaSet? where ObjectType == JavaSet + public func copyOf(_ arg0: JavaCollection?) -> JavaSet! where ObjectType == JavaSet @JavaStaticMethod - public func of(_ arg0: JavaObject?, _ arg1: JavaObject?, _ arg2: JavaObject?, _ arg3: JavaObject?, _ arg4: JavaObject?, _ arg5: JavaObject?) -> JavaSet? where ObjectType == JavaSet + public func of(_ arg0: JavaObject?, _ arg1: JavaObject?, _ arg2: JavaObject?, _ arg3: JavaObject?, _ arg4: JavaObject?, _ arg5: JavaObject?) -> JavaSet! where ObjectType == JavaSet @JavaStaticMethod - public func of(_ arg0: JavaObject?, _ arg1: JavaObject?, _ arg2: JavaObject?, _ arg3: JavaObject?, _ arg4: JavaObject?) -> JavaSet? where ObjectType == JavaSet + public func of(_ arg0: JavaObject?, _ arg1: JavaObject?, _ arg2: JavaObject?, _ arg3: JavaObject?, _ arg4: JavaObject?) -> JavaSet! where ObjectType == JavaSet @JavaStaticMethod - public func of(_ arg0: JavaObject?, _ arg1: JavaObject?, _ arg2: JavaObject?, _ arg3: JavaObject?) -> JavaSet? where ObjectType == JavaSet + public func of(_ arg0: JavaObject?, _ arg1: JavaObject?, _ arg2: JavaObject?, _ arg3: JavaObject?) -> JavaSet! where ObjectType == JavaSet @JavaStaticMethod - public func of() -> JavaSet? where ObjectType == JavaSet + public func of() -> JavaSet! where ObjectType == JavaSet @JavaStaticMethod - public func of(_ arg0: JavaObject?, _ arg1: JavaObject?, _ arg2: JavaObject?, _ arg3: JavaObject?, _ arg4: JavaObject?, _ arg5: JavaObject?, _ arg6: JavaObject?, _ arg7: JavaObject?, _ arg8: JavaObject?, _ arg9: JavaObject?) -> JavaSet? where ObjectType == JavaSet + public func of(_ arg0: JavaObject?, _ arg1: JavaObject?, _ arg2: JavaObject?, _ arg3: JavaObject?, _ arg4: JavaObject?, _ arg5: JavaObject?, _ arg6: JavaObject?, _ arg7: JavaObject?, _ arg8: JavaObject?, _ arg9: JavaObject?) -> JavaSet! where ObjectType == JavaSet @JavaStaticMethod - public func of(_ arg0: JavaObject?, _ arg1: JavaObject?, _ arg2: JavaObject?, _ arg3: JavaObject?, _ arg4: JavaObject?, _ arg5: JavaObject?, _ arg6: JavaObject?, _ arg7: JavaObject?, _ arg8: JavaObject?) -> JavaSet? where ObjectType == JavaSet + public func of(_ arg0: JavaObject?, _ arg1: JavaObject?, _ arg2: JavaObject?, _ arg3: JavaObject?, _ arg4: JavaObject?, _ arg5: JavaObject?, _ arg6: JavaObject?, _ arg7: JavaObject?, _ arg8: JavaObject?) -> JavaSet! where ObjectType == JavaSet @JavaStaticMethod - public func of(_ arg0: JavaObject?, _ arg1: JavaObject?, _ arg2: JavaObject?, _ arg3: JavaObject?, _ arg4: JavaObject?, _ arg5: JavaObject?, _ arg6: JavaObject?, _ arg7: JavaObject?) -> JavaSet? where ObjectType == JavaSet + public func of(_ arg0: JavaObject?, _ arg1: JavaObject?, _ arg2: JavaObject?, _ arg3: JavaObject?, _ arg4: JavaObject?, _ arg5: JavaObject?, _ arg6: JavaObject?, _ arg7: JavaObject?) -> JavaSet! where ObjectType == JavaSet @JavaStaticMethod - public func of(_ arg0: JavaObject?, _ arg1: JavaObject?, _ arg2: JavaObject?, _ arg3: JavaObject?, _ arg4: JavaObject?, _ arg5: JavaObject?, _ arg6: JavaObject?) -> JavaSet? where ObjectType == JavaSet + public func of(_ arg0: JavaObject?, _ arg1: JavaObject?, _ arg2: JavaObject?, _ arg3: JavaObject?, _ arg4: JavaObject?, _ arg5: JavaObject?, _ arg6: JavaObject?) -> JavaSet! where ObjectType == JavaSet @JavaStaticMethod - public func of(_ arg0: [JavaObject?]) -> JavaSet? where ObjectType == JavaSet + public func of(_ arg0: [JavaObject?]) -> JavaSet! where ObjectType == JavaSet @JavaStaticMethod - public func of(_ arg0: JavaObject?, _ arg1: JavaObject?, _ arg2: JavaObject?) -> JavaSet? where ObjectType == JavaSet + public func of(_ arg0: JavaObject?, _ arg1: JavaObject?, _ arg2: JavaObject?) -> JavaSet! where ObjectType == JavaSet @JavaStaticMethod - public func of(_ arg0: JavaObject?) -> JavaSet? where ObjectType == JavaSet + public func of(_ arg0: JavaObject?) -> JavaSet! where ObjectType == JavaSet @JavaStaticMethod - public func of(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaSet? where ObjectType == JavaSet + public func of(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaSet! where ObjectType == JavaSet } diff --git a/Sources/JavaKitCollection/generated/List.swift b/Sources/JavaKitCollection/generated/List.swift index fb323301..b264f88e 100644 --- a/Sources/JavaKitCollection/generated/List.swift +++ b/Sources/JavaKitCollection/generated/List.swift @@ -5,7 +5,7 @@ import JavaRuntime @JavaInterface("java.util.List") public struct List { @JavaMethod - public func remove(_ arg0: Int32) -> JavaObject? + public func remove(_ arg0: Int32) -> JavaObject! @JavaMethod public func remove(_ arg0: JavaObject?) -> Bool @@ -14,7 +14,7 @@ public struct List { public func size() -> Int32 @JavaMethod - public func get(_ arg0: Int32) -> JavaObject? + public func get(_ arg0: Int32) -> JavaObject! @JavaMethod public func equals(_ arg0: JavaObject?) -> Bool @@ -41,7 +41,7 @@ public struct List { public func add(_ arg0: Int32, _ arg1: JavaObject?) @JavaMethod - public func subList(_ arg0: Int32, _ arg1: Int32) -> List? + public func subList(_ arg0: Int32, _ arg1: Int32) -> List! @JavaMethod public func toArray() -> [JavaObject?] @@ -50,7 +50,7 @@ public struct List { public func toArray(_ arg0: [JavaObject?]) -> [JavaObject?] @JavaMethod - public func iterator() -> JavaIterator? + public func iterator() -> JavaIterator! @JavaMethod public func contains(_ arg0: JavaObject?) -> Bool @@ -62,13 +62,13 @@ public struct List { public func addAll(_ arg0: JavaCollection?) -> Bool @JavaMethod - public func set(_ arg0: Int32, _ arg1: JavaObject?) -> JavaObject? + public func set(_ arg0: Int32, _ arg1: JavaObject?) -> JavaObject! @JavaMethod - public func getFirst() -> JavaObject? + public func getFirst() -> JavaObject! @JavaMethod - public func getLast() -> JavaObject? + public func getLast() -> JavaObject! @JavaMethod public func addFirst(_ arg0: JavaObject?) @@ -77,10 +77,10 @@ public struct List { public func addLast(_ arg0: JavaObject?) @JavaMethod - public func removeFirst() -> JavaObject? + public func removeFirst() -> JavaObject! @JavaMethod - public func removeLast() -> JavaObject? + public func removeLast() -> JavaObject! @JavaMethod public func removeAll(_ arg0: JavaCollection?) -> Bool @@ -89,54 +89,54 @@ public struct List { public func retainAll(_ arg0: JavaCollection?) -> Bool @JavaMethod - public func listIterator() -> ListIterator? + public func listIterator() -> ListIterator! @JavaMethod - public func listIterator(_ arg0: Int32) -> ListIterator? + public func listIterator(_ arg0: Int32) -> ListIterator! @JavaMethod - public func reversed() -> List? + public func reversed() -> List! @JavaMethod public func containsAll(_ arg0: JavaCollection?) -> Bool } extension JavaClass { @JavaStaticMethod - public func copyOf(_ arg0: JavaCollection?) -> List? where ObjectType == List + public func copyOf(_ arg0: JavaCollection?) -> List! where ObjectType == List @JavaStaticMethod - public func of(_ arg0: JavaObject?, _ arg1: JavaObject?, _ arg2: JavaObject?, _ arg3: JavaObject?, _ arg4: JavaObject?, _ arg5: JavaObject?, _ arg6: JavaObject?) -> List? where ObjectType == List + public func of(_ arg0: JavaObject?, _ arg1: JavaObject?, _ arg2: JavaObject?, _ arg3: JavaObject?, _ arg4: JavaObject?, _ arg5: JavaObject?, _ arg6: JavaObject?) -> List! where ObjectType == List @JavaStaticMethod - public func of(_ arg0: JavaObject?, _ arg1: JavaObject?) -> List? where ObjectType == List + public func of(_ arg0: JavaObject?, _ arg1: JavaObject?) -> List! where ObjectType == List @JavaStaticMethod - public func of(_ arg0: JavaObject?) -> List? where ObjectType == List + public func of(_ arg0: JavaObject?) -> List! where ObjectType == List @JavaStaticMethod - public func of() -> List? where ObjectType == List + public func of() -> List! where ObjectType == List @JavaStaticMethod - public func of(_ arg0: JavaObject?, _ arg1: JavaObject?, _ arg2: JavaObject?, _ arg3: JavaObject?, _ arg4: JavaObject?, _ arg5: JavaObject?, _ arg6: JavaObject?, _ arg7: JavaObject?, _ arg8: JavaObject?) -> List? where ObjectType == List + public func of(_ arg0: JavaObject?, _ arg1: JavaObject?, _ arg2: JavaObject?, _ arg3: JavaObject?, _ arg4: JavaObject?, _ arg5: JavaObject?, _ arg6: JavaObject?, _ arg7: JavaObject?, _ arg8: JavaObject?) -> List! where ObjectType == List @JavaStaticMethod - public func of(_ arg0: JavaObject?, _ arg1: JavaObject?, _ arg2: JavaObject?, _ arg3: JavaObject?) -> List? where ObjectType == List + public func of(_ arg0: JavaObject?, _ arg1: JavaObject?, _ arg2: JavaObject?, _ arg3: JavaObject?) -> List! where ObjectType == List @JavaStaticMethod - public func of(_ arg0: JavaObject?, _ arg1: JavaObject?, _ arg2: JavaObject?, _ arg3: JavaObject?, _ arg4: JavaObject?) -> List? where ObjectType == List + public func of(_ arg0: JavaObject?, _ arg1: JavaObject?, _ arg2: JavaObject?, _ arg3: JavaObject?, _ arg4: JavaObject?) -> List! where ObjectType == List @JavaStaticMethod - public func of(_ arg0: JavaObject?, _ arg1: JavaObject?, _ arg2: JavaObject?) -> List? where ObjectType == List + public func of(_ arg0: JavaObject?, _ arg1: JavaObject?, _ arg2: JavaObject?) -> List! where ObjectType == List @JavaStaticMethod - public func of(_ arg0: JavaObject?, _ arg1: JavaObject?, _ arg2: JavaObject?, _ arg3: JavaObject?, _ arg4: JavaObject?, _ arg5: JavaObject?) -> List? where ObjectType == List + public func of(_ arg0: JavaObject?, _ arg1: JavaObject?, _ arg2: JavaObject?, _ arg3: JavaObject?, _ arg4: JavaObject?, _ arg5: JavaObject?) -> List! where ObjectType == List @JavaStaticMethod - public func of(_ arg0: JavaObject?, _ arg1: JavaObject?, _ arg2: JavaObject?, _ arg3: JavaObject?, _ arg4: JavaObject?, _ arg5: JavaObject?, _ arg6: JavaObject?, _ arg7: JavaObject?) -> List? where ObjectType == List + public func of(_ arg0: JavaObject?, _ arg1: JavaObject?, _ arg2: JavaObject?, _ arg3: JavaObject?, _ arg4: JavaObject?, _ arg5: JavaObject?, _ arg6: JavaObject?, _ arg7: JavaObject?) -> List! where ObjectType == List @JavaStaticMethod - public func of(_ arg0: [JavaObject?]) -> List? where ObjectType == List + public func of(_ arg0: [JavaObject?]) -> List! where ObjectType == List @JavaStaticMethod - public func of(_ arg0: JavaObject?, _ arg1: JavaObject?, _ arg2: JavaObject?, _ arg3: JavaObject?, _ arg4: JavaObject?, _ arg5: JavaObject?, _ arg6: JavaObject?, _ arg7: JavaObject?, _ arg8: JavaObject?, _ arg9: JavaObject?) -> List? where ObjectType == List + public func of(_ arg0: JavaObject?, _ arg1: JavaObject?, _ arg2: JavaObject?, _ arg3: JavaObject?, _ arg4: JavaObject?, _ arg5: JavaObject?, _ arg6: JavaObject?, _ arg7: JavaObject?, _ arg8: JavaObject?, _ arg9: JavaObject?) -> List! where ObjectType == List } diff --git a/Sources/JavaKitCollection/generated/ListIterator.swift b/Sources/JavaKitCollection/generated/ListIterator.swift index a918ea16..7b273160 100644 --- a/Sources/JavaKitCollection/generated/ListIterator.swift +++ b/Sources/JavaKitCollection/generated/ListIterator.swift @@ -14,7 +14,7 @@ public struct ListIterator { public func hasNext() -> Bool @JavaMethod - public func next() -> JavaObject? + public func next() -> JavaObject! @JavaMethod public func set(_ arg0: JavaObject?) @@ -29,5 +29,5 @@ public struct ListIterator { public func hasPrevious() -> Bool @JavaMethod - public func previous() -> JavaObject? + public func previous() -> JavaObject! } diff --git a/Sources/JavaKitCollection/generated/PriorityQueue.swift b/Sources/JavaKitCollection/generated/PriorityQueue.swift index ec1f2cca..c3df172d 100644 --- a/Sources/JavaKitCollection/generated/PriorityQueue.swift +++ b/Sources/JavaKitCollection/generated/PriorityQueue.swift @@ -35,13 +35,13 @@ public struct PriorityQueue { public func toArray() -> [JavaObject?] @JavaMethod - public func iterator() -> JavaIterator? + public func iterator() -> JavaIterator! @JavaMethod public func contains(_ arg0: JavaObject?) -> Bool @JavaMethod - public func peek() -> JavaObject? + public func peek() -> JavaObject! @JavaMethod public func removeAll(_ arg0: JavaCollection?) -> Bool @@ -50,19 +50,19 @@ public struct PriorityQueue { public func retainAll(_ arg0: JavaCollection?) -> Bool @JavaMethod - public func poll() -> JavaObject? + public func poll() -> JavaObject! @JavaMethod public func offer(_ arg0: JavaObject?) -> Bool @JavaMethod - public func remove() -> JavaObject? + public func remove() -> JavaObject! @JavaMethod public func addAll(_ arg0: JavaCollection?) -> Bool @JavaMethod - public func element() -> JavaObject? + public func element() -> JavaObject! @JavaMethod public func toString() -> String @@ -80,7 +80,7 @@ public struct PriorityQueue { public func hashCode() -> Int32 @JavaMethod - public func getClass() -> JavaClass? + public func getClass() -> JavaClass! @JavaMethod public func notify() diff --git a/Sources/JavaKitCollection/generated/Queue.swift b/Sources/JavaKitCollection/generated/Queue.swift index 33bf05f9..44373fce 100644 --- a/Sources/JavaKitCollection/generated/Queue.swift +++ b/Sources/JavaKitCollection/generated/Queue.swift @@ -5,19 +5,19 @@ import JavaRuntime @JavaInterface("java.util.Queue", extends: JavaCollection.self) public struct Queue { @JavaMethod - public func remove() -> JavaObject? + public func remove() -> JavaObject! @JavaMethod public func add(_ arg0: JavaObject?) -> Bool @JavaMethod - public func peek() -> JavaObject? + public func peek() -> JavaObject! @JavaMethod - public func element() -> JavaObject? + public func element() -> JavaObject! @JavaMethod - public func poll() -> JavaObject? + public func poll() -> JavaObject! @JavaMethod public func offer(_ arg0: JavaObject?) -> Bool @@ -47,7 +47,7 @@ public struct Queue { public func toArray() -> [JavaObject?] @JavaMethod - public func iterator() -> JavaIterator? + public func iterator() -> JavaIterator! @JavaMethod public func contains(_ arg0: JavaObject?) -> Bool diff --git a/Sources/JavaKitCollection/generated/Stack.swift b/Sources/JavaKitCollection/generated/Stack.swift index d3a883b5..a9d0aa5a 100644 --- a/Sources/JavaKitCollection/generated/Stack.swift +++ b/Sources/JavaKitCollection/generated/Stack.swift @@ -11,16 +11,16 @@ public struct Stack { public func empty() -> Bool @JavaMethod - public func peek() -> JavaObject? + public func peek() -> JavaObject! @JavaMethod public func search(_ arg0: JavaObject?) -> Int32 @JavaMethod - public func push(_ arg0: JavaObject?) -> JavaObject? + public func push(_ arg0: JavaObject?) -> JavaObject! @JavaMethod - public func pop() -> JavaObject? + public func pop() -> JavaObject! @JavaMethod public func addElement(_ arg0: JavaObject?) @@ -38,16 +38,16 @@ public struct Stack { public func removeAllElements() @JavaMethod - public func firstElement() -> JavaObject? + public func firstElement() -> JavaObject! @JavaMethod - public func lastElement() -> JavaObject? + public func lastElement() -> JavaObject! @JavaMethod public func setElementAt(_ arg0: JavaObject?, _ arg1: Int32) @JavaMethod - public func remove(_ arg0: Int32) -> JavaObject? + public func remove(_ arg0: Int32) -> JavaObject! @JavaMethod public func remove(_ arg0: JavaObject?) -> Bool @@ -56,7 +56,7 @@ public struct Stack { public func size() -> Int32 @JavaMethod - public func get(_ arg0: Int32) -> JavaObject? + public func get(_ arg0: Int32) -> JavaObject! @JavaMethod public func equals(_ arg0: JavaObject?) -> Bool @@ -68,7 +68,7 @@ public struct Stack { public func hashCode() -> Int32 @JavaMethod - public func clone() -> JavaObject? + public func clone() -> JavaObject! @JavaMethod public func indexOf(_ arg0: JavaObject?, _ arg1: Int32) -> Int32 @@ -95,7 +95,7 @@ public struct Stack { public func add(_ arg0: JavaObject?) -> Bool @JavaMethod - public func subList(_ arg0: Int32, _ arg1: Int32) -> List? + public func subList(_ arg0: Int32, _ arg1: Int32) -> List! @JavaMethod public func toArray(_ arg0: [JavaObject?]) -> [JavaObject?] @@ -104,13 +104,13 @@ public struct Stack { public func toArray() -> [JavaObject?] @JavaMethod - public func iterator() -> JavaIterator? + public func iterator() -> JavaIterator! @JavaMethod public func contains(_ arg0: JavaObject?) -> Bool @JavaMethod - public func elements() -> Enumeration? + public func elements() -> Enumeration! @JavaMethod public func addAll(_ arg0: Int32, _ arg1: JavaCollection?) -> Bool @@ -119,7 +119,7 @@ public struct Stack { public func addAll(_ arg0: JavaCollection?) -> Bool @JavaMethod - public func set(_ arg0: Int32, _ arg1: JavaObject?) -> JavaObject? + public func set(_ arg0: Int32, _ arg1: JavaObject?) -> JavaObject! @JavaMethod public func capacity() -> Int32 @@ -131,7 +131,7 @@ public struct Stack { public func trimToSize() @JavaMethod - public func elementAt(_ arg0: Int32) -> JavaObject? + public func elementAt(_ arg0: Int32) -> JavaObject! @JavaMethod public func removeAll(_ arg0: JavaCollection?) -> Bool @@ -140,10 +140,10 @@ public struct Stack { public func retainAll(_ arg0: JavaCollection?) -> Bool @JavaMethod - public func listIterator() -> ListIterator? + public func listIterator() -> ListIterator! @JavaMethod - public func listIterator(_ arg0: Int32) -> ListIterator? + public func listIterator(_ arg0: Int32) -> ListIterator! @JavaMethod public func containsAll(_ arg0: JavaCollection?) -> Bool @@ -155,7 +155,7 @@ public struct Stack { public func copyInto(_ arg0: [JavaObject?]) @JavaMethod - public func getClass() -> JavaClass? + public func getClass() -> JavaClass! @JavaMethod public func notify() @@ -173,10 +173,10 @@ public struct Stack { public func wait() throws @JavaMethod - public func getFirst() -> JavaObject? + public func getFirst() -> JavaObject! @JavaMethod - public func getLast() -> JavaObject? + public func getLast() -> JavaObject! @JavaMethod public func addFirst(_ arg0: JavaObject?) @@ -185,11 +185,11 @@ public struct Stack { public func addLast(_ arg0: JavaObject?) @JavaMethod - public func removeFirst() -> JavaObject? + public func removeFirst() -> JavaObject! @JavaMethod - public func removeLast() -> JavaObject? + public func removeLast() -> JavaObject! @JavaMethod - public func reversed() -> List? + public func reversed() -> List! } diff --git a/Sources/JavaKitCollection/generated/TreeMap.swift b/Sources/JavaKitCollection/generated/TreeMap.swift index 75eb36c1..fbdc5b7e 100644 --- a/Sources/JavaKitCollection/generated/TreeMap.swift +++ b/Sources/JavaKitCollection/generated/TreeMap.swift @@ -8,22 +8,22 @@ public struct TreeMap { public init(environment: JNIEnvironment? = nil) @JavaMethod - public func remove(_ arg0: JavaObject?) -> JavaObject? + public func remove(_ arg0: JavaObject?) -> JavaObject! @JavaMethod public func size() -> Int32 @JavaMethod - public func get(_ arg0: JavaObject?) -> JavaObject? + public func get(_ arg0: JavaObject?) -> JavaObject! @JavaMethod - public func put(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject? + public func put(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject! @JavaMethod - public func values() -> JavaCollection? + public func values() -> JavaCollection! @JavaMethod - public func clone() -> JavaObject? + public func clone() -> JavaObject! @JavaMethod public func clear() @@ -32,43 +32,43 @@ public struct TreeMap { public func replace(_ arg0: JavaObject?, _ arg1: JavaObject?, _ arg2: JavaObject?) -> Bool @JavaMethod - public func replace(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject? + public func replace(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject! @JavaMethod - public func putIfAbsent(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject? + public func putIfAbsent(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject! @JavaMethod public func containsKey(_ arg0: JavaObject?) -> Bool @JavaMethod - public func keySet() -> JavaSet? + public func keySet() -> JavaSet! @JavaMethod public func containsValue(_ arg0: JavaObject?) -> Bool @JavaMethod - public func firstKey() -> JavaObject? + public func firstKey() -> JavaObject! @JavaMethod - public func putFirst(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject? + public func putFirst(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject! @JavaMethod - public func putLast(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject? + public func putLast(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject! @JavaMethod - public func lowerKey(_ arg0: JavaObject?) -> JavaObject? + public func lowerKey(_ arg0: JavaObject?) -> JavaObject! @JavaMethod - public func floorKey(_ arg0: JavaObject?) -> JavaObject? + public func floorKey(_ arg0: JavaObject?) -> JavaObject! @JavaMethod - public func ceilingKey(_ arg0: JavaObject?) -> JavaObject? + public func ceilingKey(_ arg0: JavaObject?) -> JavaObject! @JavaMethod - public func higherKey(_ arg0: JavaObject?) -> JavaObject? + public func higherKey(_ arg0: JavaObject?) -> JavaObject! @JavaMethod - public func lastKey() -> JavaObject? + public func lastKey() -> JavaObject! @JavaMethod public func equals(_ arg0: JavaObject?) -> Bool @@ -83,7 +83,7 @@ public struct TreeMap { public func isEmpty() -> Bool @JavaMethod - public func getClass() -> JavaClass? + public func getClass() -> JavaClass! @JavaMethod public func notify() @@ -104,7 +104,7 @@ public struct TreeMap { public func remove(_ arg0: JavaObject?, _ arg1: JavaObject?) -> Bool @JavaMethod - public func getOrDefault(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject? + public func getOrDefault(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject! } extension TreeMap { @JavaClass("java.util.AbstractMap$SimpleImmutableEntry") @@ -122,16 +122,16 @@ extension TreeMap { public func hashCode() -> Int32 @JavaMethod - public func getValue() -> JavaObject? + public func getValue() -> JavaObject! @JavaMethod - public func getKey() -> JavaObject? + public func getKey() -> JavaObject! @JavaMethod - public func setValue(_ arg0: JavaObject?) -> JavaObject? + public func setValue(_ arg0: JavaObject?) -> JavaObject! @JavaMethod - public func getClass() -> JavaClass? + public func getClass() -> JavaClass! @JavaMethod public func notify() @@ -165,16 +165,16 @@ extension TreeMap { public func hashCode() -> Int32 @JavaMethod - public func getValue() -> JavaObject? + public func getValue() -> JavaObject! @JavaMethod - public func getKey() -> JavaObject? + public func getKey() -> JavaObject! @JavaMethod - public func setValue(_ arg0: JavaObject?) -> JavaObject? + public func setValue(_ arg0: JavaObject?) -> JavaObject! @JavaMethod - public func getClass() -> JavaClass? + public func getClass() -> JavaClass! @JavaMethod public func notify() diff --git a/Sources/JavaKitCollection/generated/TreeSet.swift b/Sources/JavaKitCollection/generated/TreeSet.swift index 7c1e0c86..985d6837 100644 --- a/Sources/JavaKitCollection/generated/TreeSet.swift +++ b/Sources/JavaKitCollection/generated/TreeSet.swift @@ -17,10 +17,10 @@ public struct TreeSet { public func size() -> Int32 @JavaMethod - public func clone() -> JavaObject? + public func clone() -> JavaObject! @JavaMethod - public func floor(_ arg0: JavaObject?) -> JavaObject? + public func floor(_ arg0: JavaObject?) -> JavaObject! @JavaMethod public func clear() @@ -32,19 +32,19 @@ public struct TreeSet { public func add(_ arg0: JavaObject?) -> Bool @JavaMethod - public func iterator() -> JavaIterator? + public func iterator() -> JavaIterator! @JavaMethod public func contains(_ arg0: JavaObject?) -> Bool @JavaMethod - public func last() -> JavaObject? + public func last() -> JavaObject! @JavaMethod public func addAll(_ arg0: JavaCollection?) -> Bool @JavaMethod - public func first() -> JavaObject? + public func first() -> JavaObject! @JavaMethod public func addFirst(_ arg0: JavaObject?) @@ -53,22 +53,22 @@ public struct TreeSet { public func addLast(_ arg0: JavaObject?) @JavaMethod - public func lower(_ arg0: JavaObject?) -> JavaObject? + public func lower(_ arg0: JavaObject?) -> JavaObject! @JavaMethod - public func pollFirst() -> JavaObject? + public func pollFirst() -> JavaObject! @JavaMethod - public func pollLast() -> JavaObject? + public func pollLast() -> JavaObject! @JavaMethod - public func descendingIterator() -> JavaIterator? + public func descendingIterator() -> JavaIterator! @JavaMethod - public func ceiling(_ arg0: JavaObject?) -> JavaObject? + public func ceiling(_ arg0: JavaObject?) -> JavaObject! @JavaMethod - public func higher(_ arg0: JavaObject?) -> JavaObject? + public func higher(_ arg0: JavaObject?) -> JavaObject! @JavaMethod public func equals(_ arg0: JavaObject?) -> Bool @@ -95,7 +95,7 @@ public struct TreeSet { public func containsAll(_ arg0: JavaCollection?) -> Bool @JavaMethod - public func getClass() -> JavaClass? + public func getClass() -> JavaClass! @JavaMethod public func notify() @@ -113,14 +113,14 @@ public struct TreeSet { public func wait() throws @JavaMethod - public func removeFirst() -> JavaObject? + public func removeFirst() -> JavaObject! @JavaMethod - public func removeLast() -> JavaObject? + public func removeLast() -> JavaObject! @JavaMethod - public func getFirst() -> JavaObject? + public func getFirst() -> JavaObject! @JavaMethod - public func getLast() -> JavaObject? + public func getLast() -> JavaObject! } diff --git a/Sources/JavaKitJar/generated/Attributes.swift b/Sources/JavaKitJar/generated/Attributes.swift index 8e3d0ca9..5014c44b 100644 --- a/Sources/JavaKitJar/generated/Attributes.swift +++ b/Sources/JavaKitJar/generated/Attributes.swift @@ -15,28 +15,28 @@ public struct Attributes { public init(environment: JNIEnvironment? = nil) @JavaMethod - public func remove(_ arg0: JavaObject?) -> JavaObject? + public func remove(_ arg0: JavaObject?) -> JavaObject! @JavaMethod public func size() -> Int32 @JavaMethod - public func get(_ arg0: JavaObject?) -> JavaObject? + public func get(_ arg0: JavaObject?) -> JavaObject! @JavaMethod - public func put(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject? + public func put(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject! @JavaMethod public func equals(_ arg0: JavaObject?) -> Bool @JavaMethod - public func values() -> JavaCollection? + public func values() -> JavaCollection! @JavaMethod public func hashCode() -> Int32 @JavaMethod - public func clone() -> JavaObject? + public func clone() -> JavaObject! @JavaMethod public func clear() @@ -54,7 +54,7 @@ public struct Attributes { public func containsKey(_ arg0: JavaObject?) -> Bool @JavaMethod - public func keySet() -> JavaSet? + public func keySet() -> JavaSet! @JavaMethod public func containsValue(_ arg0: JavaObject?) -> Bool @@ -66,7 +66,7 @@ public struct Attributes { public func toString() -> String @JavaMethod - public func getClass() -> JavaClass? + public func getClass() -> JavaClass! @JavaMethod public func notify() @@ -90,13 +90,13 @@ public struct Attributes { public func replace(_ arg0: JavaObject?, _ arg1: JavaObject?, _ arg2: JavaObject?) -> Bool @JavaMethod - public func replace(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject? + public func replace(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject! @JavaMethod - public func putIfAbsent(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject? + public func putIfAbsent(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject! @JavaMethod - public func getOrDefault(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject? + public func getOrDefault(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject! } extension Attributes { @JavaClass("java.util.jar.Attributes$Name") @@ -114,7 +114,7 @@ extension Attributes { public func hashCode() -> Int32 @JavaMethod - public func getClass() -> JavaClass? + public func getClass() -> JavaClass! @JavaMethod public func notify() @@ -134,56 +134,56 @@ extension Attributes { } extension JavaClass { @JavaStaticField(isFinal: true) - public var MANIFEST_VERSION: Attributes.Name? + public var MANIFEST_VERSION: Attributes.Name! @JavaStaticField(isFinal: true) - public var SIGNATURE_VERSION: Attributes.Name? + public var SIGNATURE_VERSION: Attributes.Name! @JavaStaticField(isFinal: true) - public var CONTENT_TYPE: Attributes.Name? + public var CONTENT_TYPE: Attributes.Name! @JavaStaticField(isFinal: true) - public var CLASS_PATH: Attributes.Name? + public var CLASS_PATH: Attributes.Name! @JavaStaticField(isFinal: true) - public var MAIN_CLASS: Attributes.Name? + public var MAIN_CLASS: Attributes.Name! @JavaStaticField(isFinal: true) - public var SEALED: Attributes.Name? + public var SEALED: Attributes.Name! @JavaStaticField(isFinal: true) - public var EXTENSION_LIST: Attributes.Name? + public var EXTENSION_LIST: Attributes.Name! @JavaStaticField(isFinal: true) - public var EXTENSION_NAME: Attributes.Name? + public var EXTENSION_NAME: Attributes.Name! @JavaStaticField(isFinal: true) - public var EXTENSION_INSTALLATION: Attributes.Name? + public var EXTENSION_INSTALLATION: Attributes.Name! @JavaStaticField(isFinal: true) - public var IMPLEMENTATION_TITLE: Attributes.Name? + public var IMPLEMENTATION_TITLE: Attributes.Name! @JavaStaticField(isFinal: true) - public var IMPLEMENTATION_VERSION: Attributes.Name? + public var IMPLEMENTATION_VERSION: Attributes.Name! @JavaStaticField(isFinal: true) - public var IMPLEMENTATION_VENDOR: Attributes.Name? + public var IMPLEMENTATION_VENDOR: Attributes.Name! @JavaStaticField(isFinal: true) - public var IMPLEMENTATION_VENDOR_ID: Attributes.Name? + public var IMPLEMENTATION_VENDOR_ID: Attributes.Name! @JavaStaticField(isFinal: true) - public var IMPLEMENTATION_URL: Attributes.Name? + public var IMPLEMENTATION_URL: Attributes.Name! @JavaStaticField(isFinal: true) - public var SPECIFICATION_TITLE: Attributes.Name? + public var SPECIFICATION_TITLE: Attributes.Name! @JavaStaticField(isFinal: true) - public var SPECIFICATION_VERSION: Attributes.Name? + public var SPECIFICATION_VERSION: Attributes.Name! @JavaStaticField(isFinal: true) - public var SPECIFICATION_VENDOR: Attributes.Name? + public var SPECIFICATION_VENDOR: Attributes.Name! @JavaStaticField(isFinal: true) - public var MULTI_RELEASE: Attributes.Name? + public var MULTI_RELEASE: Attributes.Name! } diff --git a/Sources/JavaKitJar/generated/JarEntry.swift b/Sources/JavaKitJar/generated/JarEntry.swift index fa688559..dd0e30ab 100644 --- a/Sources/JavaKitJar/generated/JarEntry.swift +++ b/Sources/JavaKitJar/generated/JarEntry.swift @@ -14,7 +14,7 @@ public struct JarEntry { public func getRealName() -> String @JavaMethod - public func getAttributes() throws -> Attributes? + public func getAttributes() throws -> Attributes! @JavaMethod public func getName() -> String @@ -26,7 +26,7 @@ public struct JarEntry { public func hashCode() -> Int32 @JavaMethod - public func clone() -> JavaObject? + public func clone() -> JavaObject! @JavaMethod public func getMethod() -> Int32 @@ -77,7 +77,7 @@ public struct JarEntry { public func equals(_ arg0: JavaObject?) -> Bool @JavaMethod - public func getClass() -> JavaClass? + public func getClass() -> JavaClass! @JavaMethod public func notify() diff --git a/Sources/JavaKitJar/generated/JarFile.swift b/Sources/JavaKitJar/generated/JarFile.swift index 60f51883..9da57d98 100644 --- a/Sources/JavaKitJar/generated/JarFile.swift +++ b/Sources/JavaKitJar/generated/JarFile.swift @@ -12,13 +12,13 @@ public struct JarFile { public init(_ arg0: String, environment: JNIEnvironment? = nil) throws @JavaMethod - public func entries() -> Enumeration? + public func entries() -> Enumeration! @JavaMethod - public func getManifest() throws -> Manifest? + public func getManifest() throws -> Manifest! @JavaMethod - public func getJarEntry(_ arg0: String) -> JarEntry? + public func getJarEntry(_ arg0: String) -> JarEntry! @JavaMethod public func isMultiRelease() -> Bool @@ -45,7 +45,7 @@ public struct JarFile { public func hashCode() -> Int32 @JavaMethod - public func getClass() -> JavaClass? + public func getClass() -> JavaClass! @JavaMethod public func notify() diff --git a/Sources/JavaKitJar/generated/JarInputStream.swift b/Sources/JavaKitJar/generated/JarInputStream.swift index 185636cd..580202e4 100644 --- a/Sources/JavaKitJar/generated/JarInputStream.swift +++ b/Sources/JavaKitJar/generated/JarInputStream.swift @@ -5,13 +5,13 @@ import JavaRuntime @JavaClass("java.util.jar.JarInputStream") public struct JarInputStream { @JavaMethod - public func getNextJarEntry() throws -> JarEntry? + public func getNextJarEntry() throws -> JarEntry! @JavaMethod public func read(_ arg0: [Int8], _ arg1: Int32, _ arg2: Int32) throws -> Int32 @JavaMethod - public func getManifest() -> Manifest? + public func getManifest() -> Manifest! @JavaMethod public func closeEntry() throws @@ -62,7 +62,7 @@ public struct JarInputStream { public func hashCode() -> Int32 @JavaMethod - public func getClass() -> JavaClass? + public func getClass() -> JavaClass! @JavaMethod public func notify() diff --git a/Sources/JavaKitJar/generated/JarOutputStream.swift b/Sources/JavaKitJar/generated/JarOutputStream.swift index cc915fe6..57a13841 100644 --- a/Sources/JavaKitJar/generated/JarOutputStream.swift +++ b/Sources/JavaKitJar/generated/JarOutputStream.swift @@ -44,7 +44,7 @@ public struct JarOutputStream { public func hashCode() -> Int32 @JavaMethod - public func getClass() -> JavaClass? + public func getClass() -> JavaClass! @JavaMethod public func notify() diff --git a/Sources/JavaKitJar/generated/Manifest.swift b/Sources/JavaKitJar/generated/Manifest.swift index 1cd2ae64..9a5fb6c6 100644 --- a/Sources/JavaKitJar/generated/Manifest.swift +++ b/Sources/JavaKitJar/generated/Manifest.swift @@ -17,22 +17,22 @@ public struct Manifest { public func hashCode() -> Int32 @JavaMethod - public func clone() -> JavaObject? + public func clone() -> JavaObject! @JavaMethod public func clear() @JavaMethod - public func getMainAttributes() -> Attributes? + public func getMainAttributes() -> Attributes! @JavaMethod - public func getAttributes(_ arg0: String) -> Attributes? + public func getAttributes(_ arg0: String) -> Attributes! @JavaMethod public func toString() -> String @JavaMethod - public func getClass() -> JavaClass? + public func getClass() -> JavaClass! @JavaMethod public func notify() diff --git a/Sources/JavaKitNetwork/generated/URI.swift b/Sources/JavaKitNetwork/generated/URI.swift index 3135e466..6992566d 100644 --- a/Sources/JavaKitNetwork/generated/URI.swift +++ b/Sources/JavaKitNetwork/generated/URI.swift @@ -38,10 +38,10 @@ public struct URI { public func isAbsolute() -> Bool @JavaMethod - public func resolve(_ arg0: String) -> URI? + public func resolve(_ arg0: String) -> URI! @JavaMethod - public func resolve(_ arg0: URI?) -> URI? + public func resolve(_ arg0: URI?) -> URI! @JavaMethod public func getScheme() -> String @@ -80,19 +80,19 @@ public struct URI { public func getUserInfo() -> String @JavaMethod - public func toURL() throws -> URL? + public func toURL() throws -> URL! @JavaMethod - public func normalize() -> URI? + public func normalize() -> URI! @JavaMethod - public func relativize(_ arg0: URI?) -> URI? + public func relativize(_ arg0: URI?) -> URI! @JavaMethod public func getRawSchemeSpecificPart() -> String @JavaMethod - public func parseServerAuthority() throws -> URI? + public func parseServerAuthority() throws -> URI! @JavaMethod public func getSchemeSpecificPart() -> String @@ -107,7 +107,7 @@ public struct URI { public func toASCIIString() -> String @JavaMethod - public func getClass() -> JavaClass? + public func getClass() -> JavaClass! @JavaMethod public func notify() @@ -126,5 +126,5 @@ public struct URI { } extension JavaClass { @JavaStaticMethod - public func create(_ arg0: String) -> URI? + public func create(_ arg0: String) -> URI! } diff --git a/Sources/JavaKitNetwork/generated/URL.swift b/Sources/JavaKitNetwork/generated/URL.swift index 86c6c46a..6cb6573a 100644 --- a/Sources/JavaKitNetwork/generated/URL.swift +++ b/Sources/JavaKitNetwork/generated/URL.swift @@ -41,10 +41,10 @@ public struct URL { public func toExternalForm() -> String @JavaMethod - public func getContent() throws -> JavaObject? + public func getContent() throws -> JavaObject! @JavaMethod - public func getContent(_ arg0: [JavaClass?]) throws -> JavaObject? + public func getContent(_ arg0: [JavaClass?]) throws -> JavaObject! @JavaMethod public func getProtocol() -> String @@ -68,10 +68,10 @@ public struct URL { public func getUserInfo() -> String @JavaMethod - public func toURI() throws -> URI? + public func toURI() throws -> URI! @JavaMethod - public func getClass() -> JavaClass? + public func getClass() -> JavaClass! @JavaMethod public func notify() diff --git a/Sources/JavaKitNetwork/generated/URLClassLoader.swift b/Sources/JavaKitNetwork/generated/URLClassLoader.swift index 2f83d963..64b26dda 100644 --- a/Sources/JavaKitNetwork/generated/URLClassLoader.swift +++ b/Sources/JavaKitNetwork/generated/URLClassLoader.swift @@ -9,10 +9,10 @@ public struct URLClassLoader { public init(_ arg0: [URL?], environment: JNIEnvironment? = nil) @JavaMethod - public func findResource(_ arg0: String) -> URL? + public func findResource(_ arg0: String) -> URL! @JavaMethod - public func findResources(_ arg0: String) throws -> Enumeration? + public func findResources(_ arg0: String) throws -> Enumeration! @JavaMethod public func close() throws @@ -24,13 +24,13 @@ public struct URLClassLoader { public func getName() -> String @JavaMethod - public func loadClass(_ arg0: String) throws -> JavaClass? + public func loadClass(_ arg0: String) throws -> JavaClass! @JavaMethod - public func getResource(_ arg0: String) -> URL? + public func getResource(_ arg0: String) -> URL! @JavaMethod - public func getResources(_ arg0: String) throws -> Enumeration? + public func getResources(_ arg0: String) throws -> Enumeration! @JavaMethod public func isRegisteredAsParallelCapable() -> Bool @@ -57,7 +57,7 @@ public struct URLClassLoader { public func hashCode() -> Int32 @JavaMethod - public func getClass() -> JavaClass? + public func getClass() -> JavaClass! @JavaMethod public func notify() @@ -76,11 +76,11 @@ public struct URLClassLoader { } extension JavaClass { @JavaStaticMethod - public func newInstance(_ arg0: [URL?]) -> URLClassLoader? + public func newInstance(_ arg0: [URL?]) -> URLClassLoader! @JavaStaticMethod - public func getSystemResource(_ arg0: String) -> URL? + public func getSystemResource(_ arg0: String) -> URL! @JavaStaticMethod - public func getSystemResources(_ arg0: String) throws -> Enumeration? + public func getSystemResources(_ arg0: String) throws -> Enumeration! } diff --git a/Sources/JavaKitReflection/generated/AccessibleObject.swift b/Sources/JavaKitReflection/generated/AccessibleObject.swift index c54fd33a..5dc090c8 100644 --- a/Sources/JavaKitReflection/generated/AccessibleObject.swift +++ b/Sources/JavaKitReflection/generated/AccessibleObject.swift @@ -8,7 +8,7 @@ public struct AccessibleObject { public func isAnnotationPresent(_ arg0: JavaClass?) -> Bool @JavaMethod - public func getAnnotation(_ arg0: JavaClass?) -> Annotation? + public func getAnnotation(_ arg0: JavaClass?) -> Annotation! @JavaMethod public func getAnnotationsByType(_ arg0: JavaClass?) -> [Annotation?] @@ -17,7 +17,7 @@ public struct AccessibleObject { public func getAnnotations() -> [Annotation?] @JavaMethod - public func getDeclaredAnnotation(_ arg0: JavaClass?) -> Annotation? + public func getDeclaredAnnotation(_ arg0: JavaClass?) -> Annotation! @JavaMethod public func getDeclaredAnnotationsByType(_ arg0: JavaClass?) -> [Annotation?] @@ -47,7 +47,7 @@ public struct AccessibleObject { public func hashCode() -> Int32 @JavaMethod - public func getClass() -> JavaClass? + public func getClass() -> JavaClass! @JavaMethod public func notify() diff --git a/Sources/JavaKitReflection/generated/AnnotatedType.swift b/Sources/JavaKitReflection/generated/AnnotatedType.swift index 68bbe44a..ca9b9994 100644 --- a/Sources/JavaKitReflection/generated/AnnotatedType.swift +++ b/Sources/JavaKitReflection/generated/AnnotatedType.swift @@ -5,10 +5,10 @@ import JavaRuntime @JavaInterface("java.lang.reflect.AnnotatedType") public struct AnnotatedType { @JavaMethod - public func getAnnotatedOwnerType() -> AnnotatedType? + public func getAnnotatedOwnerType() -> AnnotatedType! @JavaMethod - public func getAnnotation(_ arg0: JavaClass?) -> Annotation? + public func getAnnotation(_ arg0: JavaClass?) -> Annotation! @JavaMethod public func getAnnotations() -> [Annotation?] @@ -17,7 +17,7 @@ public struct AnnotatedType { public func getDeclaredAnnotations() -> [Annotation?] @JavaMethod - public func getType() -> Type? + public func getType() -> Type! @JavaMethod public func isAnnotationPresent(_ arg0: JavaClass?) -> Bool @@ -26,7 +26,7 @@ public struct AnnotatedType { public func getAnnotationsByType(_ arg0: JavaClass?) -> [Annotation?] @JavaMethod - public func getDeclaredAnnotation(_ arg0: JavaClass?) -> Annotation? + public func getDeclaredAnnotation(_ arg0: JavaClass?) -> Annotation! @JavaMethod public func getDeclaredAnnotationsByType(_ arg0: JavaClass?) -> [Annotation?] diff --git a/Sources/JavaKitReflection/generated/Annotation.swift b/Sources/JavaKitReflection/generated/Annotation.swift index 74377550..269c0f9e 100644 --- a/Sources/JavaKitReflection/generated/Annotation.swift +++ b/Sources/JavaKitReflection/generated/Annotation.swift @@ -14,5 +14,5 @@ public struct Annotation { public func hashCode() -> Int32 @JavaMethod - public func annotationType() -> JavaClass? + public func annotationType() -> JavaClass! } diff --git a/Sources/JavaKitReflection/generated/Constructor.swift b/Sources/JavaKitReflection/generated/Constructor.swift index 58ac5690..c3e48a15 100644 --- a/Sources/JavaKitReflection/generated/Constructor.swift +++ b/Sources/JavaKitReflection/generated/Constructor.swift @@ -24,7 +24,7 @@ public struct Constructor { public func getTypeParameters() -> [TypeVariable>?] @JavaMethod - public func newInstance(_ arg0: [JavaObject?]) throws -> JavaObject? + public func newInstance(_ arg0: [JavaObject?]) throws -> JavaObject! @JavaMethod public func getParameterTypes() -> [JavaClass?] @@ -36,10 +36,10 @@ public struct Constructor { public func isSynthetic() -> Bool @JavaMethod - public func getDeclaringClass() -> JavaClass? + public func getDeclaringClass() -> JavaClass! @JavaMethod - public func getAnnotation(_ arg0: JavaClass?) -> Annotation? + public func getAnnotation(_ arg0: JavaClass?) -> Annotation! @JavaMethod public func getDeclaredAnnotations() -> [Annotation?] @@ -66,10 +66,10 @@ public struct Constructor { public func getExceptionTypes() -> [JavaClass?] @JavaMethod - public func getAnnotatedReturnType() -> AnnotatedType? + public func getAnnotatedReturnType() -> AnnotatedType! @JavaMethod - public func getAnnotatedReceiverType() -> AnnotatedType? + public func getAnnotatedReceiverType() -> AnnotatedType! @JavaMethod public func getAnnotationsByType(_ arg0: JavaClass?) -> [Annotation?] @@ -90,7 +90,7 @@ public struct Constructor { public func getAnnotations() -> [Annotation?] @JavaMethod - public func getDeclaredAnnotation(_ arg0: JavaClass?) -> Annotation? + public func getDeclaredAnnotation(_ arg0: JavaClass?) -> Annotation! @JavaMethod public func getDeclaredAnnotationsByType(_ arg0: JavaClass?) -> [Annotation?] @@ -105,7 +105,7 @@ public struct Constructor { public func isAccessible() -> Bool @JavaMethod - public func getClass() -> JavaClass? + public func getClass() -> JavaClass! @JavaMethod public func notify() diff --git a/Sources/JavaKitReflection/generated/Executable.swift b/Sources/JavaKitReflection/generated/Executable.swift index 6f1fa6d8..da1635f6 100644 --- a/Sources/JavaKitReflection/generated/Executable.swift +++ b/Sources/JavaKitReflection/generated/Executable.swift @@ -24,10 +24,10 @@ public struct Executable { public func isSynthetic() -> Bool @JavaMethod - public func getDeclaringClass() -> JavaClass? + public func getDeclaringClass() -> JavaClass! @JavaMethod - public func getAnnotation(_ arg0: JavaClass?) -> Annotation? + public func getAnnotation(_ arg0: JavaClass?) -> Annotation! @JavaMethod public func getAnnotationsByType(_ arg0: JavaClass?) -> [Annotation?] @@ -57,13 +57,13 @@ public struct Executable { public func getExceptionTypes() -> [JavaClass?] @JavaMethod - public func getAnnotatedReturnType() -> AnnotatedType? + public func getAnnotatedReturnType() -> AnnotatedType! @JavaMethod public func getParameters() -> [Parameter?] @JavaMethod - public func getAnnotatedReceiverType() -> AnnotatedType? + public func getAnnotatedReceiverType() -> AnnotatedType! @JavaMethod public func getAnnotatedExceptionTypes() -> [AnnotatedType?] @@ -75,7 +75,7 @@ public struct Executable { public func getAnnotations() -> [Annotation?] @JavaMethod - public func getDeclaredAnnotation(_ arg0: JavaClass?) -> Annotation? + public func getDeclaredAnnotation(_ arg0: JavaClass?) -> Annotation! @JavaMethod public func getDeclaredAnnotationsByType(_ arg0: JavaClass?) -> [Annotation?] @@ -102,7 +102,7 @@ public struct Executable { public func hashCode() -> Int32 @JavaMethod - public func getClass() -> JavaClass? + public func getClass() -> JavaClass! @JavaMethod public func notify() diff --git a/Sources/JavaKitReflection/generated/Field.swift b/Sources/JavaKitReflection/generated/Field.swift index d68700b3..41e71afb 100644 --- a/Sources/JavaKitReflection/generated/Field.swift +++ b/Sources/JavaKitReflection/generated/Field.swift @@ -9,7 +9,7 @@ public struct Field { public func getName() -> String @JavaMethod - public func get(_ arg0: JavaObject?) throws -> JavaObject? + public func get(_ arg0: JavaObject?) throws -> JavaObject! @JavaMethod public func equals(_ arg0: JavaObject?) -> Bool @@ -54,10 +54,10 @@ public struct Field { public func isSynthetic() -> Bool @JavaMethod - public func getDeclaringClass() -> JavaClass? + public func getDeclaringClass() -> JavaClass! @JavaMethod - public func getAnnotation(_ arg0: JavaClass?) -> Annotation? + public func getAnnotation(_ arg0: JavaClass?) -> Annotation! @JavaMethod public func getAnnotationsByType(_ arg0: JavaClass?) -> [Annotation?] @@ -72,10 +72,10 @@ public struct Field { public func setAccessible(_ arg0: Bool) @JavaMethod - public func getGenericType() -> Type? + public func getGenericType() -> Type! @JavaMethod - public func getType() -> JavaClass? + public func getType() -> JavaClass! @JavaMethod public func setBoolean(_ arg0: JavaObject?, _ arg1: Bool) throws @@ -105,7 +105,7 @@ public struct Field { public func isEnumConstant() -> Bool @JavaMethod - public func getAnnotatedType() -> AnnotatedType? + public func getAnnotatedType() -> AnnotatedType! @JavaMethod public func isAnnotationPresent(_ arg0: JavaClass?) -> Bool @@ -114,7 +114,7 @@ public struct Field { public func getAnnotations() -> [Annotation?] @JavaMethod - public func getDeclaredAnnotation(_ arg0: JavaClass?) -> Annotation? + public func getDeclaredAnnotation(_ arg0: JavaClass?) -> Annotation! @JavaMethod public func getDeclaredAnnotationsByType(_ arg0: JavaClass?) -> [Annotation?] @@ -129,7 +129,7 @@ public struct Field { public func isAccessible() -> Bool @JavaMethod - public func getClass() -> JavaClass? + public func getClass() -> JavaClass! @JavaMethod public func notify() diff --git a/Sources/JavaKitReflection/generated/GenericArrayType.swift b/Sources/JavaKitReflection/generated/GenericArrayType.swift index 074e14b2..6f96a0d2 100644 --- a/Sources/JavaKitReflection/generated/GenericArrayType.swift +++ b/Sources/JavaKitReflection/generated/GenericArrayType.swift @@ -5,7 +5,7 @@ import JavaRuntime @JavaInterface("java.lang.reflect.GenericArrayType", extends: Type.self) public struct GenericArrayType { @JavaMethod - public func getGenericComponentType() -> Type? + public func getGenericComponentType() -> Type! @JavaMethod public func getTypeName() -> String diff --git a/Sources/JavaKitReflection/generated/GenericDeclaration.swift b/Sources/JavaKitReflection/generated/GenericDeclaration.swift index 586f1657..7a86bd8a 100644 --- a/Sources/JavaKitReflection/generated/GenericDeclaration.swift +++ b/Sources/JavaKitReflection/generated/GenericDeclaration.swift @@ -11,7 +11,7 @@ public struct GenericDeclaration { public func isAnnotationPresent(_ arg0: JavaClass?) -> Bool @JavaMethod - public func getAnnotation(_ arg0: JavaClass?) -> Annotation? + public func getAnnotation(_ arg0: JavaClass?) -> Annotation! @JavaMethod public func getAnnotationsByType(_ arg0: JavaClass?) -> [Annotation?] @@ -20,7 +20,7 @@ public struct GenericDeclaration { public func getAnnotations() -> [Annotation?] @JavaMethod - public func getDeclaredAnnotation(_ arg0: JavaClass?) -> Annotation? + public func getDeclaredAnnotation(_ arg0: JavaClass?) -> Annotation! @JavaMethod public func getDeclaredAnnotationsByType(_ arg0: JavaClass?) -> [Annotation?] diff --git a/Sources/JavaKitReflection/generated/Method.swift b/Sources/JavaKitReflection/generated/Method.swift index 74e74e10..3a67073c 100644 --- a/Sources/JavaKitReflection/generated/Method.swift +++ b/Sources/JavaKitReflection/generated/Method.swift @@ -6,7 +6,7 @@ import JavaRuntime @JavaClass("java.lang.reflect.Method", extends: Executable.self) public struct Method { @JavaMethod - public func invoke(_ arg0: JavaObject?, _ arg1: [JavaObject?]) throws -> JavaObject? + public func invoke(_ arg0: JavaObject?, _ arg1: [JavaObject?]) throws -> JavaObject! @JavaMethod public func getName() -> String @@ -27,7 +27,7 @@ public struct Method { public func getTypeParameters() -> [TypeVariable?] @JavaMethod - public func getReturnType() -> JavaClass? + public func getReturnType() -> JavaClass! @JavaMethod public func getParameterTypes() -> [JavaClass?] @@ -39,10 +39,10 @@ public struct Method { public func isSynthetic() -> Bool @JavaMethod - public func getDeclaringClass() -> JavaClass? + public func getDeclaringClass() -> JavaClass! @JavaMethod - public func getAnnotation(_ arg0: JavaClass?) -> Annotation? + public func getAnnotation(_ arg0: JavaClass?) -> Annotation! @JavaMethod public func getDeclaredAnnotations() -> [Annotation?] @@ -69,7 +69,7 @@ public struct Method { public func isDefault() -> Bool @JavaMethod - public func getGenericReturnType() -> Type? + public func getGenericReturnType() -> Type! @JavaMethod public func getExceptionTypes() -> [JavaClass?] @@ -78,10 +78,10 @@ public struct Method { public func isBridge() -> Bool @JavaMethod - public func getDefaultValue() -> JavaObject? + public func getDefaultValue() -> JavaObject! @JavaMethod - public func getAnnotatedReturnType() -> AnnotatedType? + public func getAnnotatedReturnType() -> AnnotatedType! @JavaMethod public func getAnnotationsByType(_ arg0: JavaClass?) -> [Annotation?] @@ -93,7 +93,7 @@ public struct Method { public func getParameters() -> [Parameter?] @JavaMethod - public func getAnnotatedReceiverType() -> AnnotatedType? + public func getAnnotatedReceiverType() -> AnnotatedType! @JavaMethod public func getAnnotatedExceptionTypes() -> [AnnotatedType?] @@ -105,7 +105,7 @@ public struct Method { public func getAnnotations() -> [Annotation?] @JavaMethod - public func getDeclaredAnnotation(_ arg0: JavaClass?) -> Annotation? + public func getDeclaredAnnotation(_ arg0: JavaClass?) -> Annotation! @JavaMethod public func getDeclaredAnnotationsByType(_ arg0: JavaClass?) -> [Annotation?] @@ -120,7 +120,7 @@ public struct Method { public func isAccessible() -> Bool @JavaMethod - public func getClass() -> JavaClass? + public func getClass() -> JavaClass! @JavaMethod public func notify() diff --git a/Sources/JavaKitReflection/generated/Parameter.swift b/Sources/JavaKitReflection/generated/Parameter.swift index 36f68dd0..f55b6507 100644 --- a/Sources/JavaKitReflection/generated/Parameter.swift +++ b/Sources/JavaKitReflection/generated/Parameter.swift @@ -24,7 +24,7 @@ public struct Parameter { public func isSynthetic() -> Bool @JavaMethod - public func getAnnotation(_ arg0: JavaClass?) -> Annotation? + public func getAnnotation(_ arg0: JavaClass?) -> Annotation! @JavaMethod public func getAnnotationsByType(_ arg0: JavaClass?) -> [Annotation?] @@ -33,7 +33,7 @@ public struct Parameter { public func getAnnotations() -> [Annotation?] @JavaMethod - public func getDeclaredAnnotation(_ arg0: JavaClass?) -> Annotation? + public func getDeclaredAnnotation(_ arg0: JavaClass?) -> Annotation! @JavaMethod public func getDeclaredAnnotationsByType(_ arg0: JavaClass?) -> [Annotation?] @@ -42,13 +42,13 @@ public struct Parameter { public func getDeclaredAnnotations() -> [Annotation?] @JavaMethod - public func getType() -> JavaClass? + public func getType() -> JavaClass! @JavaMethod - public func getAnnotatedType() -> AnnotatedType? + public func getAnnotatedType() -> AnnotatedType! @JavaMethod - public func getParameterizedType() -> Type? + public func getParameterizedType() -> Type! @JavaMethod public func isVarArgs() -> Bool @@ -57,13 +57,13 @@ public struct Parameter { public func isNamePresent() -> Bool @JavaMethod - public func getDeclaringExecutable() -> Executable? + public func getDeclaringExecutable() -> Executable! @JavaMethod public func isImplicit() -> Bool @JavaMethod - public func getClass() -> JavaClass? + public func getClass() -> JavaClass! @JavaMethod public func notify() diff --git a/Sources/JavaKitReflection/generated/ParameterizedType.swift b/Sources/JavaKitReflection/generated/ParameterizedType.swift index ec67dfd9..3e413714 100644 --- a/Sources/JavaKitReflection/generated/ParameterizedType.swift +++ b/Sources/JavaKitReflection/generated/ParameterizedType.swift @@ -5,10 +5,10 @@ import JavaRuntime @JavaInterface("java.lang.reflect.ParameterizedType", extends: Type.self) public struct ParameterizedType { @JavaMethod - public func getOwnerType() -> Type? + public func getOwnerType() -> Type! @JavaMethod - public func getRawType() -> Type? + public func getRawType() -> Type! @JavaMethod public func getActualTypeArguments() -> [Type?] diff --git a/Sources/JavaKitReflection/generated/TypeVariable.swift b/Sources/JavaKitReflection/generated/TypeVariable.swift index d68bd3c4..c925cdcf 100644 --- a/Sources/JavaKitReflection/generated/TypeVariable.swift +++ b/Sources/JavaKitReflection/generated/TypeVariable.swift @@ -5,7 +5,7 @@ import JavaRuntime @JavaInterface("java.lang.reflect.TypeVariable", extends: Type.self) public struct TypeVariable { @JavaMethod - public func getGenericDeclaration() -> GenericDeclaration? + public func getGenericDeclaration() -> GenericDeclaration! @JavaMethod public func getAnnotatedBounds() -> [AnnotatedType?] @@ -23,7 +23,7 @@ public struct TypeVariable { public func isAnnotationPresent(_ arg0: JavaClass?) -> Bool @JavaMethod - public func getAnnotation(_ arg0: JavaClass?) -> Annotation? + public func getAnnotation(_ arg0: JavaClass?) -> Annotation! @JavaMethod public func getAnnotationsByType(_ arg0: JavaClass?) -> [Annotation?] @@ -32,7 +32,7 @@ public struct TypeVariable { public func getAnnotations() -> [Annotation?] @JavaMethod - public func getDeclaredAnnotation(_ arg0: JavaClass?) -> Annotation? + public func getDeclaredAnnotation(_ arg0: JavaClass?) -> Annotation! @JavaMethod public func getDeclaredAnnotationsByType(_ arg0: JavaClass?) -> [Annotation?] From 7c0d9b5073eb94c778d86bf3bf670170b2f6e8b9 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Mon, 28 Oct 2024 12:03:51 -0700 Subject: [PATCH 137/426] Java2Swift: Don't omit "extends" clause when it's extending JavaObject There's no reason to skip this; be more regular about it. --- Sources/Java2SwiftLib/JavaClassTranslator.swift | 5 +---- Tests/Java2SwiftTests/Java2SwiftTests.swift | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/Sources/Java2SwiftLib/JavaClassTranslator.swift b/Sources/Java2SwiftLib/JavaClassTranslator.swift index 59477f3f..232c9338 100644 --- a/Sources/Java2SwiftLib/JavaClassTranslator.swift +++ b/Sources/Java2SwiftLib/JavaClassTranslator.swift @@ -110,10 +110,7 @@ struct JavaClassTranslator { self.nestedClasses = translator.nestedClasses[fullName] ?? [] // Superclass. - if !javaClass.isInterface(), - let javaSuperclass = javaClass.getSuperclass(), - javaSuperclass.getName() != "java.lang.Object" - { + if !javaClass.isInterface(), let javaSuperclass = javaClass.getSuperclass() { do { self.swiftSuperclass = try translator.getSwiftTypeName(javaSuperclass).swiftName } catch { diff --git a/Tests/Java2SwiftTests/Java2SwiftTests.swift b/Tests/Java2SwiftTests/Java2SwiftTests.swift index d1e19551..85240305 100644 --- a/Tests/Java2SwiftTests/Java2SwiftTests.swift +++ b/Tests/Java2SwiftTests/Java2SwiftTests.swift @@ -69,7 +69,7 @@ class Java2SwiftTests: XCTestCase { expectedChunks: [ "import JavaKit", """ - @JavaClass("java.lang.Class") + @JavaClass("java.lang.Class", extends: JavaObject.self) public struct MyJavaClass { """, """ From 91e4a6b3d090706ac3556a357b0e88dceb20fd3b Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Mon, 28 Oct 2024 12:07:03 -0700 Subject: [PATCH 138/426] Regenerate JavaKit generated sources --- Sources/JavaKit/generated/JavaBoolean.swift | 2 +- Sources/JavaKit/generated/JavaCharacter.swift | 4 +- Sources/JavaKit/generated/JavaClass.swift | 2 +- Sources/JavaKit/generated/JavaNumber.swift | 2 +- Sources/JavaKit/generated/JavaVoid.swift | 2 +- Sources/JavaKit/generated/Throwable.swift | 2 +- .../JavaKitCollection/generated/BitSet.swift | 2 +- .../JavaKitCollection/generated/HashMap.swift | 86 +++++++++++++++++++ .../generated/JavaDictionary.swift | 2 +- .../JavaKitCollection/generated/TreeMap.swift | 86 ------------------- Sources/JavaKitJar/generated/Attributes.swift | 4 +- Sources/JavaKitJar/generated/Manifest.swift | 2 +- Sources/JavaKitNetwork/generated/URI.swift | 2 +- Sources/JavaKitNetwork/generated/URL.swift | 2 +- .../generated/AccessibleObject.swift | 2 +- .../generated/Parameter.swift | 2 +- 16 files changed, 102 insertions(+), 102 deletions(-) diff --git a/Sources/JavaKit/generated/JavaBoolean.swift b/Sources/JavaKit/generated/JavaBoolean.swift index b5fc9067..e942fb44 100644 --- a/Sources/JavaKit/generated/JavaBoolean.swift +++ b/Sources/JavaKit/generated/JavaBoolean.swift @@ -1,7 +1,7 @@ // Auto-generated by Java-to-Swift wrapper generator. import JavaRuntime -@JavaClass("java.lang.Boolean") +@JavaClass("java.lang.Boolean", extends: JavaObject.self) public struct JavaBoolean { @JavaMethod public init(_ arg0: Bool, environment: JNIEnvironment? = nil) diff --git a/Sources/JavaKit/generated/JavaCharacter.swift b/Sources/JavaKit/generated/JavaCharacter.swift index 4e9ee4b5..739cc260 100644 --- a/Sources/JavaKit/generated/JavaCharacter.swift +++ b/Sources/JavaKit/generated/JavaCharacter.swift @@ -1,7 +1,7 @@ // Auto-generated by Java-to-Swift wrapper generator. import JavaRuntime -@JavaClass("java.lang.Character") +@JavaClass("java.lang.Character", extends: JavaObject.self) public struct JavaCharacter { @JavaMethod public init(_ arg0: UInt16, environment: JNIEnvironment? = nil) @@ -3147,7 +3147,7 @@ extension JavaClass { public func of(_ arg0: Int32) -> JavaCharacter.UnicodeScript! } extension JavaCharacter { - @JavaClass("java.lang.Character$Subset") + @JavaClass("java.lang.Character$Subset", extends: JavaObject.self) public struct Subset { @JavaMethod public func equals(_ arg0: JavaObject?) -> Bool diff --git a/Sources/JavaKit/generated/JavaClass.swift b/Sources/JavaKit/generated/JavaClass.swift index f41cab3b..a3d52d21 100644 --- a/Sources/JavaKit/generated/JavaClass.swift +++ b/Sources/JavaKit/generated/JavaClass.swift @@ -1,7 +1,7 @@ // Auto-generated by Java-to-Swift wrapper generator. import JavaRuntime -@JavaClass("java.lang.Class") +@JavaClass("java.lang.Class", extends: JavaObject.self) public struct JavaClass { @JavaMethod public func getName() -> String diff --git a/Sources/JavaKit/generated/JavaNumber.swift b/Sources/JavaKit/generated/JavaNumber.swift index 49150d72..acd461fe 100644 --- a/Sources/JavaKit/generated/JavaNumber.swift +++ b/Sources/JavaKit/generated/JavaNumber.swift @@ -1,7 +1,7 @@ // Auto-generated by Java-to-Swift wrapper generator. import JavaRuntime -@JavaClass("java.lang.Number") +@JavaClass("java.lang.Number", extends: JavaObject.self) public struct JavaNumber { @JavaMethod public init(environment: JNIEnvironment? = nil) diff --git a/Sources/JavaKit/generated/JavaVoid.swift b/Sources/JavaKit/generated/JavaVoid.swift index 8a0ec266..f9a21828 100644 --- a/Sources/JavaKit/generated/JavaVoid.swift +++ b/Sources/JavaKit/generated/JavaVoid.swift @@ -1,7 +1,7 @@ // Auto-generated by Java-to-Swift wrapper generator. import JavaRuntime -@JavaClass("java.lang.Void") +@JavaClass("java.lang.Void", extends: JavaObject.self) public struct JavaVoid { @JavaMethod public func equals(_ arg0: JavaObject?) -> Bool diff --git a/Sources/JavaKit/generated/Throwable.swift b/Sources/JavaKit/generated/Throwable.swift index e292efa0..171835d8 100644 --- a/Sources/JavaKit/generated/Throwable.swift +++ b/Sources/JavaKit/generated/Throwable.swift @@ -1,7 +1,7 @@ // Auto-generated by Java-to-Swift wrapper generator. import JavaRuntime -@JavaClass("java.lang.Throwable") +@JavaClass("java.lang.Throwable", extends: JavaObject.self) public struct Throwable { @JavaMethod public init(_ arg0: Throwable?, environment: JNIEnvironment? = nil) diff --git a/Sources/JavaKitCollection/generated/BitSet.swift b/Sources/JavaKitCollection/generated/BitSet.swift index 99425771..d00f539d 100644 --- a/Sources/JavaKitCollection/generated/BitSet.swift +++ b/Sources/JavaKitCollection/generated/BitSet.swift @@ -2,7 +2,7 @@ import JavaKit import JavaRuntime -@JavaClass("java.util.BitSet") +@JavaClass("java.util.BitSet", extends: JavaObject.self) public struct BitSet { @JavaMethod public init(environment: JNIEnvironment? = nil) diff --git a/Sources/JavaKitCollection/generated/HashMap.swift b/Sources/JavaKitCollection/generated/HashMap.swift index 287593f5..90e50295 100644 --- a/Sources/JavaKitCollection/generated/HashMap.swift +++ b/Sources/JavaKitCollection/generated/HashMap.swift @@ -88,6 +88,92 @@ public struct HashMap { @JavaMethod public func wait() throws } +extension HashMap { + @JavaClass("java.util.AbstractMap$SimpleImmutableEntry", extends: JavaObject.self) + public struct SimpleImmutableEntry { + @JavaMethod + public init(_ arg0: JavaObject?, _ arg1: JavaObject?, environment: JNIEnvironment? = nil) + + @JavaMethod + public func equals(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func toString() -> String + + @JavaMethod + public func hashCode() -> Int32 + + @JavaMethod + public func getValue() -> JavaObject! + + @JavaMethod + public func getKey() -> JavaObject! + + @JavaMethod + public func setValue(_ arg0: JavaObject?) -> JavaObject! + + @JavaMethod + public func getClass() -> JavaClass! + + @JavaMethod + public func notify() + + @JavaMethod + public func notifyAll() + + @JavaMethod + public func wait(_ arg0: Int64) throws + + @JavaMethod + public func wait(_ arg0: Int64, _ arg1: Int32) throws + + @JavaMethod + public func wait() throws + } +} +extension HashMap { + @JavaClass("java.util.AbstractMap$SimpleEntry", extends: JavaObject.self) + public struct SimpleEntry { + @JavaMethod + public init(_ arg0: JavaObject?, _ arg1: JavaObject?, environment: JNIEnvironment? = nil) + + @JavaMethod + public func equals(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func toString() -> String + + @JavaMethod + public func hashCode() -> Int32 + + @JavaMethod + public func getValue() -> JavaObject! + + @JavaMethod + public func getKey() -> JavaObject! + + @JavaMethod + public func setValue(_ arg0: JavaObject?) -> JavaObject! + + @JavaMethod + public func getClass() -> JavaClass! + + @JavaMethod + public func notify() + + @JavaMethod + public func notifyAll() + + @JavaMethod + public func wait(_ arg0: Int64) throws + + @JavaMethod + public func wait(_ arg0: Int64, _ arg1: Int32) throws + + @JavaMethod + public func wait() throws + } +} extension JavaClass { @JavaStaticMethod public func newHashMap(_ arg0: Int32) -> HashMap! where ObjectType == HashMap diff --git a/Sources/JavaKitCollection/generated/JavaDictionary.swift b/Sources/JavaKitCollection/generated/JavaDictionary.swift index 5bebe233..df1bdc87 100644 --- a/Sources/JavaKitCollection/generated/JavaDictionary.swift +++ b/Sources/JavaKitCollection/generated/JavaDictionary.swift @@ -2,7 +2,7 @@ import JavaKit import JavaRuntime -@JavaClass("java.util.Dictionary") +@JavaClass("java.util.Dictionary", extends: JavaObject.self) public struct JavaDictionary { @JavaMethod public init(environment: JNIEnvironment? = nil) diff --git a/Sources/JavaKitCollection/generated/TreeMap.swift b/Sources/JavaKitCollection/generated/TreeMap.swift index fbdc5b7e..3c45b998 100644 --- a/Sources/JavaKitCollection/generated/TreeMap.swift +++ b/Sources/JavaKitCollection/generated/TreeMap.swift @@ -106,89 +106,3 @@ public struct TreeMap { @JavaMethod public func getOrDefault(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject! } -extension TreeMap { - @JavaClass("java.util.AbstractMap$SimpleImmutableEntry") - public struct SimpleImmutableEntry { - @JavaMethod - public init(_ arg0: JavaObject?, _ arg1: JavaObject?, environment: JNIEnvironment? = nil) - - @JavaMethod - public func equals(_ arg0: JavaObject?) -> Bool - - @JavaMethod - public func toString() -> String - - @JavaMethod - public func hashCode() -> Int32 - - @JavaMethod - public func getValue() -> JavaObject! - - @JavaMethod - public func getKey() -> JavaObject! - - @JavaMethod - public func setValue(_ arg0: JavaObject?) -> JavaObject! - - @JavaMethod - public func getClass() -> JavaClass! - - @JavaMethod - public func notify() - - @JavaMethod - public func notifyAll() - - @JavaMethod - public func wait(_ arg0: Int64) throws - - @JavaMethod - public func wait(_ arg0: Int64, _ arg1: Int32) throws - - @JavaMethod - public func wait() throws - } -} -extension TreeMap { - @JavaClass("java.util.AbstractMap$SimpleEntry") - public struct SimpleEntry { - @JavaMethod - public init(_ arg0: JavaObject?, _ arg1: JavaObject?, environment: JNIEnvironment? = nil) - - @JavaMethod - public func equals(_ arg0: JavaObject?) -> Bool - - @JavaMethod - public func toString() -> String - - @JavaMethod - public func hashCode() -> Int32 - - @JavaMethod - public func getValue() -> JavaObject! - - @JavaMethod - public func getKey() -> JavaObject! - - @JavaMethod - public func setValue(_ arg0: JavaObject?) -> JavaObject! - - @JavaMethod - public func getClass() -> JavaClass! - - @JavaMethod - public func notify() - - @JavaMethod - public func notifyAll() - - @JavaMethod - public func wait(_ arg0: Int64) throws - - @JavaMethod - public func wait(_ arg0: Int64, _ arg1: Int32) throws - - @JavaMethod - public func wait() throws - } -} diff --git a/Sources/JavaKitJar/generated/Attributes.swift b/Sources/JavaKitJar/generated/Attributes.swift index 5014c44b..1ecde6f7 100644 --- a/Sources/JavaKitJar/generated/Attributes.swift +++ b/Sources/JavaKitJar/generated/Attributes.swift @@ -3,7 +3,7 @@ import JavaKit import JavaKitCollection import JavaRuntime -@JavaClass("java.util.jar.Attributes") +@JavaClass("java.util.jar.Attributes", extends: JavaObject.self) public struct Attributes { @JavaMethod public init(_ arg0: Attributes?, environment: JNIEnvironment? = nil) @@ -99,7 +99,7 @@ public struct Attributes { public func getOrDefault(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject! } extension Attributes { - @JavaClass("java.util.jar.Attributes$Name") + @JavaClass("java.util.jar.Attributes$Name", extends: JavaObject.self) public struct Name { @JavaMethod public init(_ arg0: String, environment: JNIEnvironment? = nil) diff --git a/Sources/JavaKitJar/generated/Manifest.swift b/Sources/JavaKitJar/generated/Manifest.swift index 9a5fb6c6..6400f33c 100644 --- a/Sources/JavaKitJar/generated/Manifest.swift +++ b/Sources/JavaKitJar/generated/Manifest.swift @@ -2,7 +2,7 @@ import JavaKit import JavaRuntime -@JavaClass("java.util.jar.Manifest") +@JavaClass("java.util.jar.Manifest", extends: JavaObject.self) public struct Manifest { @JavaMethod public init(_ arg0: Manifest?, environment: JNIEnvironment? = nil) diff --git a/Sources/JavaKitNetwork/generated/URI.swift b/Sources/JavaKitNetwork/generated/URI.swift index 6992566d..a8b35bcb 100644 --- a/Sources/JavaKitNetwork/generated/URI.swift +++ b/Sources/JavaKitNetwork/generated/URI.swift @@ -2,7 +2,7 @@ import JavaKit import JavaRuntime -@JavaClass("java.net.URI") +@JavaClass("java.net.URI", extends: JavaObject.self) public struct URI { @JavaMethod public init(_ arg0: String, _ arg1: String, _ arg2: String, _ arg3: String, _ arg4: String, environment: JNIEnvironment? = nil) throws diff --git a/Sources/JavaKitNetwork/generated/URL.swift b/Sources/JavaKitNetwork/generated/URL.swift index 6cb6573a..c9fb0832 100644 --- a/Sources/JavaKitNetwork/generated/URL.swift +++ b/Sources/JavaKitNetwork/generated/URL.swift @@ -2,7 +2,7 @@ import JavaKit import JavaRuntime -@JavaClass("java.net.URL") +@JavaClass("java.net.URL", extends: JavaObject.self) public struct URL { @JavaMethod public init(_ arg0: URL?, _ arg1: String, environment: JNIEnvironment? = nil) throws diff --git a/Sources/JavaKitReflection/generated/AccessibleObject.swift b/Sources/JavaKitReflection/generated/AccessibleObject.swift index 5dc090c8..1c474fb4 100644 --- a/Sources/JavaKitReflection/generated/AccessibleObject.swift +++ b/Sources/JavaKitReflection/generated/AccessibleObject.swift @@ -2,7 +2,7 @@ import JavaKit import JavaRuntime -@JavaClass("java.lang.reflect.AccessibleObject") +@JavaClass("java.lang.reflect.AccessibleObject", extends: JavaObject.self) public struct AccessibleObject { @JavaMethod public func isAnnotationPresent(_ arg0: JavaClass?) -> Bool diff --git a/Sources/JavaKitReflection/generated/Parameter.swift b/Sources/JavaKitReflection/generated/Parameter.swift index f55b6507..5788f089 100644 --- a/Sources/JavaKitReflection/generated/Parameter.swift +++ b/Sources/JavaKitReflection/generated/Parameter.swift @@ -3,7 +3,7 @@ import JavaKit import JavaKitCollection import JavaRuntime -@JavaClass("java.lang.reflect.Parameter") +@JavaClass("java.lang.reflect.Parameter", extends: JavaObject.self) public struct Parameter { @JavaMethod public func getName() -> String From 5a61886e5e476f405c026c07ba855c192b7eafc1 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Mon, 28 Oct 2024 13:38:15 -0700 Subject: [PATCH 139/426] JavaClass macro: stop generating javaThis and javaEnvironment members Provide these properties via an extension to AnyJavaObject, accessing the holder values, rather than splatting that same code into every @JavaClass. --- Sources/JavaKit/AnyJavaObject.swift | 12 ++++++++---- Sources/JavaKit/Macros.swift | 4 ---- Sources/JavaKitMacros/JavaClassMacro.swift | 14 -------------- Tests/JavaKitMacroTests/JavaClassMacroTests.swift | 8 -------- 4 files changed, 8 insertions(+), 30 deletions(-) diff --git a/Sources/JavaKit/AnyJavaObject.swift b/Sources/JavaKit/AnyJavaObject.swift index 8f28c098..711b953d 100644 --- a/Sources/JavaKit/AnyJavaObject.swift +++ b/Sources/JavaKit/AnyJavaObject.swift @@ -50,15 +50,19 @@ public protocol AnyJavaObject { /// The Swift instance that keeps the Java holder alive. var javaHolder: JavaObjectHolder { get } +} +extension AnyJavaObject { /// Retrieve the underlying Java object. - var javaThis: jobject { get } + public var javaThis: jobject { + javaHolder.object! + } /// Retrieve the environment in which this Java object resides. - var javaEnvironment: JNIEnvironment { get } -} + public var javaEnvironment: JNIEnvironment { + javaHolder.environment + } -extension AnyJavaObject { /// The full Java class name, where each component is separated by a "/". static var fullJavaClassNameWithSlashes: String { let seq = fullJavaClassName.map { $0 == "." ? "/" as Character : $0 } diff --git a/Sources/JavaKit/Macros.swift b/Sources/JavaKit/Macros.swift index 4caef659..029344d8 100644 --- a/Sources/JavaKit/Macros.swift +++ b/Sources/JavaKit/Macros.swift @@ -34,8 +34,6 @@ member, names: named(fullJavaClassName), named(javaHolder), - named(javaThis), - named(javaEnvironment), named(init(javaHolder:)), named(JavaSuperclass), named(`as`) @@ -70,8 +68,6 @@ public macro JavaClass( member, names: named(fullJavaClassName), named(javaHolder), - named(javaThis), - named(javaEnvironment), named(init(javaHolder:)), named(JavaSuperclass), named(`as`) diff --git a/Sources/JavaKitMacros/JavaClassMacro.swift b/Sources/JavaKitMacros/JavaClassMacro.swift index 2f0783f1..5a6e25cb 100644 --- a/Sources/JavaKitMacros/JavaClassMacro.swift +++ b/Sources/JavaKitMacros/JavaClassMacro.swift @@ -69,18 +69,6 @@ extension JavaClassMacro: MemberMacro { public var javaHolder: JavaObjectHolder """ - let javaThisMember: DeclSyntax = """ - public var javaThis: jobject { - javaHolder.object! - } - """ - - let javaEnvironmentMember: DeclSyntax = """ - public var javaEnvironment: JNIEnvironment { - javaHolder.environment - } - """ - let initMember: DeclSyntax = """ public init(javaHolder: JavaObjectHolder) { self.javaHolder = javaHolder @@ -98,8 +86,6 @@ extension JavaClassMacro: MemberMacro { fullJavaClassNameMember, superclassTypealias, javaHolderMember, - javaThisMember, - javaEnvironmentMember, initMember, nonOptionalAs, ] diff --git a/Tests/JavaKitMacroTests/JavaClassMacroTests.swift b/Tests/JavaKitMacroTests/JavaClassMacroTests.swift index 42ce532f..e83356c0 100644 --- a/Tests/JavaKitMacroTests/JavaClassMacroTests.swift +++ b/Tests/JavaKitMacroTests/JavaClassMacroTests.swift @@ -102,14 +102,6 @@ class JavaKitMacroTests: XCTestCase { public var javaHolder: JavaObjectHolder - public var javaThis: jobject { - javaHolder.object! - } - - public var javaEnvironment: JNIEnvironment { - javaHolder.environment - } - public init(javaHolder: JavaObjectHolder) { self.javaHolder = javaHolder } From b1aeb73561299b4b89707aadb6102c48dba7e445 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Mon, 28 Oct 2024 16:30:11 -0700 Subject: [PATCH 140/426] Java2Swift: Separate "reference type" from "value type" mappings While in general we want to map Java classes to Swift value types, there are places where we need to work with the class type, such as generic parameters. Identify those places where it is okay to bridge to a value type (e.g., parameters, results, field types) and do so. Elsewhere, use the Swift type that directly wraps the Java class. For example, when dealing with superclasses or with generic arguments to Java generic classes. As part of this, provide a class mapping for java.lang.String (as JavaString) and Java arrays (as the non-generic JavaArray) so we have a way to refer to such types in positions that cannot use the value type. Test this out with a few APIs that need it. Fixes issue #128. --- Sources/Java2Swift/JavaToSwift.swift | 5 +- .../Java2SwiftLib/JavaClassTranslator.swift | 37 ++- .../JavaTranslator+Configuration.swift | 3 +- Sources/Java2SwiftLib/JavaTranslator.swift | 115 +++++--- Sources/Java2SwiftLib/OptionalKind.swift | 9 + Sources/JavaKit/Java2Swift.config | 2 + Sources/JavaKit/generated/JavaArray.swift | 96 +++++++ Sources/JavaKit/generated/JavaCharacter.swift | 62 ++-- Sources/JavaKit/generated/JavaString.swift | 264 ++++++++++++++++++ .../JavaKitCollection/generated/HashMap.swift | 86 ------ .../JavaKitCollection/generated/TreeMap.swift | 86 ++++++ .../JavaKitJar/generated/JarInputStream.swift | 12 +- .../generated/JarOutputStream.swift | 6 +- Sources/JavaTypes/JavaType+SwiftNames.swift | 9 +- Tests/Java2SwiftTests/Java2SwiftTests.swift | 89 ++++-- 15 files changed, 689 insertions(+), 192 deletions(-) create mode 100644 Sources/JavaKit/generated/JavaArray.swift create mode 100644 Sources/JavaKit/generated/JavaString.swift diff --git a/Sources/Java2Swift/JavaToSwift.swift b/Sources/Java2Swift/JavaToSwift.swift index 205c6a43..15e346ae 100644 --- a/Sources/Java2Swift/JavaToSwift.swift +++ b/Sources/Java2Swift/JavaToSwift.swift @@ -252,7 +252,7 @@ struct JavaToSwift: ParsableCommand { let swiftName = "\(currentSwiftName).\(swiftUnqualifiedName)" - translator.translatedClasses[javaClassName] = (swiftName, nil, true) + translator.translatedClasses[javaClassName] = (swiftName, nil) return nestedClass } @@ -279,7 +279,8 @@ struct JavaToSwift: ParsableCommand { """ - let swiftFileName = try! translator.getSwiftTypeName(javaClass).swiftName.replacing(".", with: "+") + ".swift" + let swiftFileName = try! translator.getSwiftTypeName(javaClass, preferValueTypes: false) + .swiftName.replacing(".", with: "+") + ".swift" try writeContents( swiftFileText, to: swiftFileName, diff --git a/Sources/Java2SwiftLib/JavaClassTranslator.swift b/Sources/Java2SwiftLib/JavaClassTranslator.swift index 232c9338..1df6d683 100644 --- a/Sources/Java2SwiftLib/JavaClassTranslator.swift +++ b/Sources/Java2SwiftLib/JavaClassTranslator.swift @@ -103,7 +103,11 @@ struct JavaClassTranslator { let fullName = javaClass.getName() self.javaClass = javaClass self.translator = translator - self.swiftTypeName = try translator.getSwiftTypeNameFromJavaClassName(fullName, escapeMemberNames: false) + self.swiftTypeName = try translator.getSwiftTypeNameFromJavaClassName( + fullName, + preferValueTypes: false, + escapeMemberNames: false + ) // Type parameters. self.javaTypeParameters = javaClass.getTypeParameters().compactMap { $0 } @@ -112,7 +116,7 @@ struct JavaClassTranslator { // Superclass. if !javaClass.isInterface(), let javaSuperclass = javaClass.getSuperclass() { do { - self.swiftSuperclass = try translator.getSwiftTypeName(javaSuperclass).swiftName + self.swiftSuperclass = try translator.getSwiftTypeName(javaSuperclass, preferValueTypes: false).swiftName } catch { translator.logUntranslated("Unable to translate '\(fullName)' superclass: \(error)") self.swiftSuperclass = nil @@ -128,7 +132,11 @@ struct JavaClassTranslator { } do { - let typeName = try translator.getSwiftTypeNameAsString(javaType, outerOptional: .nonoptional) + let typeName = try translator.getSwiftTypeNameAsString( + javaType, + preferValueTypes: false, + outerOptional: .nonoptional + ) return "\(typeName)" } catch { translator.logUntranslated("Unable to translate '\(fullName)' interface '\(javaType.getTypeName())': \(error)") @@ -314,7 +322,10 @@ extension JavaClassTranslator { /// Render any nested classes that will not be rendered separately. func renderNestedClasses() -> [DeclSyntax] { - return nestedClasses.compactMap { clazz in + return nestedClasses + .sorted { + $0.getName() < $1.getName() + }.compactMap { clazz in do { return try translator.translateClass(clazz) } catch { @@ -456,7 +467,11 @@ extension JavaClassTranslator { // Map the result type. let resultTypeStr: String - let resultType = try translator.getSwiftTypeNameAsString(javaMethod.getGenericReturnType()!, outerOptional: .implicitlyUnwrappedOptional) + let resultType = try translator.getSwiftTypeNameAsString( + javaMethod.getGenericReturnType()!, + preferValueTypes: true, + outerOptional: .implicitlyUnwrappedOptional + ) if resultType != "Void" { resultTypeStr = " -> \(resultType)" } else { @@ -477,7 +492,11 @@ extension JavaClassTranslator { /// Render a single Java field into the corresponding Swift property, or /// throw an error if that is not possible for any reason. package func renderField(_ javaField: Field) throws -> DeclSyntax { - let typeName = try translator.getSwiftTypeNameAsString(javaField.getGenericType()!, outerOptional: .implicitlyUnwrappedOptional) + let typeName = try translator.getSwiftTypeNameAsString( + javaField.getGenericType()!, + preferValueTypes: true, + outerOptional: .implicitlyUnwrappedOptional + ) let fieldAttribute: AttributeSyntax = javaField.isStatic ? "@JavaStaticField" : "@JavaField"; let swiftFieldName = javaField.getName().escapedSwiftName return """ @@ -544,7 +563,11 @@ extension JavaClassTranslator { return try parameters.compactMap { javaParameter in guard let javaParameter else { return nil } - let typeName = try translator.getSwiftTypeNameAsString(javaParameter.getParameterizedType()!, outerOptional: .optional) + let typeName = try translator.getSwiftTypeNameAsString( + javaParameter.getParameterizedType()!, + preferValueTypes: true, + outerOptional: .optional + ) let paramName = javaParameter.getName() return "_ \(raw: paramName): \(raw: typeName)" } diff --git a/Sources/Java2SwiftLib/JavaTranslator+Configuration.swift b/Sources/Java2SwiftLib/JavaTranslator+Configuration.swift index f13a8cce..b84d7a1e 100644 --- a/Sources/Java2SwiftLib/JavaTranslator+Configuration.swift +++ b/Sources/Java2SwiftLib/JavaTranslator+Configuration.swift @@ -27,8 +27,7 @@ extension JavaTranslator { for (javaClassName, swiftName) in config.classes { translatedClasses[javaClassName] = ( swiftType: swiftName, - swiftModule: swiftModule, - isOptional: true + swiftModule: swiftModule ) } } diff --git a/Sources/Java2SwiftLib/JavaTranslator.swift b/Sources/Java2SwiftLib/JavaTranslator.swift index 9f5fa292..5889a193 100644 --- a/Sources/Java2SwiftLib/JavaTranslator.swift +++ b/Sources/Java2SwiftLib/JavaTranslator.swift @@ -28,11 +28,20 @@ package class JavaTranslator { let environment: JNIEnvironment let format: BasicFormat - /// A mapping from the canonical name of Java classes to the corresponding - /// Swift type name, its Swift module, and whether we need to be working - /// with optionals. - package var translatedClasses: [String: (swiftType: String, swiftModule: String?, isOptional: Bool)] = - defaultTranslatedClasses + /// A mapping from the name of each known Java class to the corresponding + /// Swift type name and its Swift module. + package var translatedClasses: [String: (swiftType: String, swiftModule: String?)] = [:] + + /// A mapping from the name of each known Java class with the Swift value type + /// (and its module) to which it is mapped. + /// + /// The Java classes here can also be part of `translatedClasses`. The entry in + /// `translatedClasses` should map to a representation of the Java class (i.e., + /// an AnyJavaObject-conforming type) whereas the entry here should map to + /// a value type. + package let translatedToValueTypes: [String: (swiftType: String, swiftModule: String) ] = [ + "java.lang.String": ("String", "JavaKit"), + ] /// The set of Swift modules that need to be imported to make the generated /// code compile. Use `getImportDecls()` to format this into a list of @@ -80,13 +89,6 @@ extension JavaTranslator { "JavaKit", "JavaRuntime", ] - - /// The default set of translated classes that do not come from JavaKit - /// itself. This should only be used to refer to types that are built-in to - /// JavaKit and therefore aren't captured in any configuration file. - package static let defaultTranslatedClasses: [String: (swiftType: String, swiftModule: String?, isOptional: Bool)] = [ - "java.lang.String": ("String", "JavaKit", false), - ] } // MARK: Import translation @@ -104,13 +106,21 @@ extension JavaTranslator { // MARK: Type translation extension JavaTranslator { /// Turn a Java type into a string. - func getSwiftTypeNameAsString(_ javaType: Type, outerOptional: OptionalKind) throws -> String { + func getSwiftTypeNameAsString( + _ javaType: Type, + preferValueTypes: Bool, + outerOptional: OptionalKind + ) throws -> String { // Replace type variables with their bounds. if let typeVariable = javaType.as(TypeVariable.self), typeVariable.getBounds().count == 1, let bound = typeVariable.getBounds()[0] { - return try getSwiftTypeNameAsString(bound, outerOptional: outerOptional) + return try getSwiftTypeNameAsString( + bound, + preferValueTypes: preferValueTypes, + outerOptional: outerOptional + ) } // Replace wildcards with their upper bound. @@ -119,13 +129,30 @@ extension JavaTranslator { let bound = wildcardType.getUpperBounds()[0] { // Replace a wildcard type with its first bound. - return try getSwiftTypeNameAsString(bound, outerOptional: outerOptional) + return try getSwiftTypeNameAsString( + bound, + preferValueTypes: preferValueTypes, + outerOptional: outerOptional + ) } // Handle array types by recursing into the component type. if let arrayType = javaType.as(GenericArrayType.self) { - let elementType = try getSwiftTypeNameAsString(arrayType.getGenericComponentType()!, outerOptional: .optional) - return "[\(elementType)]" + if preferValueTypes { + let elementType = try getSwiftTypeNameAsString( + arrayType.getGenericComponentType()!, + preferValueTypes: preferValueTypes, + outerOptional: .optional + ) + return "[\(elementType)]" + } + + let (swiftName, _) = try getSwiftTypeName( + JavaClass().as(JavaClass.self)!, + preferValueTypes: false + ) + + return outerOptional.adjustTypeName(swiftName) } // Handle parameterized types by recursing on the raw type and the type @@ -133,7 +160,11 @@ extension JavaTranslator { if let parameterizedType = javaType.as(ParameterizedType.self), let rawJavaType = parameterizedType.getRawType() { - var rawSwiftType = try getSwiftTypeNameAsString(rawJavaType, outerOptional: outerOptional) + var rawSwiftType = try getSwiftTypeNameAsString( + rawJavaType, + preferValueTypes: false, + outerOptional: outerOptional + ) let optionalSuffix: String if let lastChar = rawSwiftType.last, lastChar == "?" || lastChar == "!" { @@ -145,7 +176,7 @@ extension JavaTranslator { let typeArguments = try parameterizedType.getActualTypeArguments().compactMap { typeArg in try typeArg.map { typeArg in - try getSwiftTypeNameAsString(typeArg, outerOptional: .nonoptional) + try getSwiftTypeNameAsString(typeArg, preferValueTypes: false, outerOptional: .nonoptional) } } @@ -157,38 +188,50 @@ extension JavaTranslator { throw TranslationError.unhandledJavaType(javaType) } - let (swiftName, isOptional) = try getSwiftTypeName(javaClass) + let (swiftName, isOptional) = try getSwiftTypeName(javaClass, preferValueTypes: preferValueTypes) var resultString = swiftName if isOptional { - switch outerOptional { - case .implicitlyUnwrappedOptional: - resultString += "!" - case .optional: - resultString += "?" - case .nonoptional: - break - } + resultString = outerOptional.adjustTypeName(resultString) } return resultString } /// Translate a Java class into its corresponding Swift type name. - package func getSwiftTypeName(_ javaClass: JavaClass) throws -> (swiftName: String, isOptional: Bool) { + package func getSwiftTypeName( + _ javaClass: JavaClass, + preferValueTypes: Bool + ) throws -> (swiftName: String, isOptional: Bool) { let javaType = try JavaType(javaTypeName: javaClass.getName()) - let isSwiftOptional = javaType.isSwiftOptional - return ( - try javaType.swiftTypeName { javaClassName in - try self.getSwiftTypeNameFromJavaClassName(javaClassName) - }, - isSwiftOptional - ) + let isSwiftOptional = javaType.isSwiftOptional(stringIsValueType: preferValueTypes) + + let swiftTypeName: String + if !preferValueTypes, case .array(_) = javaType { + swiftTypeName = try self.getSwiftTypeNameFromJavaClassName("java.lang.reflect.Array", preferValueTypes: false) + } else { + swiftTypeName = try javaType.swiftTypeName { javaClassName in + try self.getSwiftTypeNameFromJavaClassName(javaClassName, preferValueTypes: preferValueTypes) + } + } + + return (swiftTypeName, isSwiftOptional) } /// Map a Java class name to its corresponding Swift type. func getSwiftTypeNameFromJavaClassName( _ name: String, + preferValueTypes: Bool, escapeMemberNames: Bool = true ) throws -> String { + // If we want a value type, look for one. + if preferValueTypes, let translatedValueType = translatedToValueTypes[name] { + // Note that we need to import this Swift module. + if translatedValueType.swiftModule != swiftModuleName { + importedSwiftModules.insert(translatedValueType.swiftModule) + } + + return translatedValueType.swiftType + } + if let translated = translatedClasses[name] { // Note that we need to import this Swift module. if let swiftModule = translated.swiftModule, swiftModule != swiftModuleName { diff --git a/Sources/Java2SwiftLib/OptionalKind.swift b/Sources/Java2SwiftLib/OptionalKind.swift index 57951fa4..c05bff18 100644 --- a/Sources/Java2SwiftLib/OptionalKind.swift +++ b/Sources/Java2SwiftLib/OptionalKind.swift @@ -22,4 +22,13 @@ enum OptionalKind { /// The value uses an implicitly-unwrapped optional. case implicitlyUnwrappedOptional + + /// Adjust the given type name string based on the optionality of this type. + func adjustTypeName(_ string: String) -> String { + switch self { + case .implicitlyUnwrappedOptional: return string + "!" + case .optional: return string + "?" + case .nonoptional: return string + } + } } diff --git a/Sources/JavaKit/Java2Swift.config b/Sources/JavaKit/Java2Swift.config index bace061f..ed284d31 100644 --- a/Sources/JavaKit/Java2Swift.config +++ b/Sources/JavaKit/Java2Swift.config @@ -1,5 +1,6 @@ { "classes" : { + "java.lang.reflect.Array" : "JavaArray", "java.lang.Boolean" : "JavaBoolean", "java.lang.Byte" : "JavaByte", "java.lang.Character" : "JavaCharacter", @@ -14,6 +15,7 @@ "java.lang.Object" : "JavaObject", "java.lang.RuntimeException" : "RuntimeException", "java.lang.Short" : "JavaShort", + "java.lang.String" : "JavaString", "java.lang.Throwable" : "Throwable", "java.lang.Void" : "JavaVoid" } diff --git a/Sources/JavaKit/generated/JavaArray.swift b/Sources/JavaKit/generated/JavaArray.swift new file mode 100644 index 00000000..805b3929 --- /dev/null +++ b/Sources/JavaKit/generated/JavaArray.swift @@ -0,0 +1,96 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaRuntime + +@JavaClass("java.lang.reflect.Array", extends: JavaObject.self) +public struct JavaArray { + @JavaMethod + public func equals(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func toString() -> String + + @JavaMethod + public func hashCode() -> Int32 + + @JavaMethod + public func getClass() -> JavaClass! + + @JavaMethod + public func notify() + + @JavaMethod + public func notifyAll() + + @JavaMethod + public func wait(_ arg0: Int64) throws + + @JavaMethod + public func wait(_ arg0: Int64, _ arg1: Int32) throws + + @JavaMethod + public func wait() throws +} +extension JavaClass { + @JavaStaticMethod + public func get(_ arg0: JavaObject?, _ arg1: Int32) throws -> JavaObject! + + @JavaStaticMethod + public func getLength(_ arg0: JavaObject?) throws -> Int32 + + @JavaStaticMethod + public func getBoolean(_ arg0: JavaObject?, _ arg1: Int32) throws -> Bool + + @JavaStaticMethod + public func getByte(_ arg0: JavaObject?, _ arg1: Int32) throws -> Int8 + + @JavaStaticMethod + public func getShort(_ arg0: JavaObject?, _ arg1: Int32) throws -> Int16 + + @JavaStaticMethod + public func getChar(_ arg0: JavaObject?, _ arg1: Int32) throws -> UInt16 + + @JavaStaticMethod + public func getInt(_ arg0: JavaObject?, _ arg1: Int32) throws -> Int32 + + @JavaStaticMethod + public func getLong(_ arg0: JavaObject?, _ arg1: Int32) throws -> Int64 + + @JavaStaticMethod + public func getFloat(_ arg0: JavaObject?, _ arg1: Int32) throws -> Float + + @JavaStaticMethod + public func getDouble(_ arg0: JavaObject?, _ arg1: Int32) throws -> Double + + @JavaStaticMethod + public func newInstance(_ arg0: JavaClass?, _ arg1: Int32) throws -> JavaObject! + + @JavaStaticMethod + public func newInstance(_ arg0: JavaClass?, _ arg1: [Int32]) throws -> JavaObject! + + @JavaStaticMethod + public func set(_ arg0: JavaObject?, _ arg1: Int32, _ arg2: JavaObject?) throws + + @JavaStaticMethod + public func setBoolean(_ arg0: JavaObject?, _ arg1: Int32, _ arg2: Bool) throws + + @JavaStaticMethod + public func setByte(_ arg0: JavaObject?, _ arg1: Int32, _ arg2: Int8) throws + + @JavaStaticMethod + public func setChar(_ arg0: JavaObject?, _ arg1: Int32, _ arg2: UInt16) throws + + @JavaStaticMethod + public func setShort(_ arg0: JavaObject?, _ arg1: Int32, _ arg2: Int16) throws + + @JavaStaticMethod + public func setInt(_ arg0: JavaObject?, _ arg1: Int32, _ arg2: Int32) throws + + @JavaStaticMethod + public func setLong(_ arg0: JavaObject?, _ arg1: Int32, _ arg2: Int64) throws + + @JavaStaticMethod + public func setFloat(_ arg0: JavaObject?, _ arg1: Int32, _ arg2: Float) throws + + @JavaStaticMethod + public func setDouble(_ arg0: JavaObject?, _ arg1: Int32, _ arg2: Double) throws +} diff --git a/Sources/JavaKit/generated/JavaCharacter.swift b/Sources/JavaKit/generated/JavaCharacter.swift index 739cc260..1ebb7625 100644 --- a/Sources/JavaKit/generated/JavaCharacter.swift +++ b/Sources/JavaKit/generated/JavaCharacter.swift @@ -42,6 +42,37 @@ public struct JavaCharacter { @JavaMethod public func wait() throws } +extension JavaCharacter { + @JavaClass("java.lang.Character$Subset", extends: JavaObject.self) + public struct Subset { + @JavaMethod + public func equals(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func toString() -> String + + @JavaMethod + public func hashCode() -> Int32 + + @JavaMethod + public func getClass() -> JavaClass! + + @JavaMethod + public func notify() + + @JavaMethod + public func notifyAll() + + @JavaMethod + public func wait(_ arg0: Int64) throws + + @JavaMethod + public func wait(_ arg0: Int64, _ arg1: Int32) throws + + @JavaMethod + public func wait() throws + } +} extension JavaCharacter { @JavaClass("java.lang.Character$UnicodeBlock", extends: JavaCharacter.Subset.self) public struct UnicodeBlock { @@ -3146,37 +3177,6 @@ extension JavaClass { @JavaStaticMethod public func of(_ arg0: Int32) -> JavaCharacter.UnicodeScript! } -extension JavaCharacter { - @JavaClass("java.lang.Character$Subset", extends: JavaObject.self) - public struct Subset { - @JavaMethod - public func equals(_ arg0: JavaObject?) -> Bool - - @JavaMethod - public func toString() -> String - - @JavaMethod - public func hashCode() -> Int32 - - @JavaMethod - public func getClass() -> JavaClass! - - @JavaMethod - public func notify() - - @JavaMethod - public func notifyAll() - - @JavaMethod - public func wait(_ arg0: Int64) throws - - @JavaMethod - public func wait(_ arg0: Int64, _ arg1: Int32) throws - - @JavaMethod - public func wait() throws - } -} extension JavaClass { @JavaStaticField(isFinal: true) public var MIN_RADIX: Int32 diff --git a/Sources/JavaKit/generated/JavaString.swift b/Sources/JavaKit/generated/JavaString.swift new file mode 100644 index 00000000..c062dc0d --- /dev/null +++ b/Sources/JavaKit/generated/JavaString.swift @@ -0,0 +1,264 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaRuntime + +@JavaClass("java.lang.String", extends: JavaObject.self) +public struct JavaString { + @JavaMethod + public init(_ arg0: [Int8], _ arg1: String, environment: JNIEnvironment? = nil) throws + + @JavaMethod + public init(_ arg0: [Int8], _ arg1: Int32, _ arg2: Int32, environment: JNIEnvironment? = nil) + + @JavaMethod + public init(_ arg0: [Int8], environment: JNIEnvironment? = nil) + + @JavaMethod + public init(_ arg0: [UInt16], _ arg1: Int32, _ arg2: Int32, environment: JNIEnvironment? = nil) + + @JavaMethod + public init(_ arg0: [UInt16], environment: JNIEnvironment? = nil) + + @JavaMethod + public init(_ arg0: String, environment: JNIEnvironment? = nil) + + @JavaMethod + public init(environment: JNIEnvironment? = nil) + + @JavaMethod + public init(_ arg0: [Int8], _ arg1: Int32, _ arg2: Int32, _ arg3: String, environment: JNIEnvironment? = nil) throws + + @JavaMethod + public init(_ arg0: [Int8], _ arg1: Int32, environment: JNIEnvironment? = nil) + + @JavaMethod + public init(_ arg0: [Int8], _ arg1: Int32, _ arg2: Int32, _ arg3: Int32, environment: JNIEnvironment? = nil) + + @JavaMethod + public init(_ arg0: [Int32], _ arg1: Int32, _ arg2: Int32, environment: JNIEnvironment? = nil) + + @JavaMethod + public func equals(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func length() -> Int32 + + @JavaMethod + public func toString() -> String + + @JavaMethod + public func hashCode() -> Int32 + + @JavaMethod + public func getChars(_ arg0: Int32, _ arg1: Int32, _ arg2: [UInt16], _ arg3: Int32) + + @JavaMethod + public func compareTo(_ arg0: JavaObject?) -> Int32 + + @JavaMethod + public func compareTo(_ arg0: String) -> Int32 + + @JavaMethod + public func indexOf(_ arg0: String, _ arg1: Int32, _ arg2: Int32) -> Int32 + + @JavaMethod + public func indexOf(_ arg0: String) -> Int32 + + @JavaMethod + public func indexOf(_ arg0: Int32) -> Int32 + + @JavaMethod + public func indexOf(_ arg0: Int32, _ arg1: Int32) -> Int32 + + @JavaMethod + public func indexOf(_ arg0: Int32, _ arg1: Int32, _ arg2: Int32) -> Int32 + + @JavaMethod + public func indexOf(_ arg0: String, _ arg1: Int32) -> Int32 + + @JavaMethod + public func charAt(_ arg0: Int32) -> UInt16 + + @JavaMethod + public func codePointAt(_ arg0: Int32) -> Int32 + + @JavaMethod + public func codePointBefore(_ arg0: Int32) -> Int32 + + @JavaMethod + public func codePointCount(_ arg0: Int32, _ arg1: Int32) -> Int32 + + @JavaMethod + public func offsetByCodePoints(_ arg0: Int32, _ arg1: Int32) -> Int32 + + @JavaMethod + public func getBytes() -> [Int8] + + @JavaMethod + public func getBytes(_ arg0: String) throws -> [Int8] + + @JavaMethod + public func getBytes(_ arg0: Int32, _ arg1: Int32, _ arg2: [Int8], _ arg3: Int32) + + @JavaMethod + public func regionMatches(_ arg0: Bool, _ arg1: Int32, _ arg2: String, _ arg3: Int32, _ arg4: Int32) -> Bool + + @JavaMethod + public func regionMatches(_ arg0: Int32, _ arg1: String, _ arg2: Int32, _ arg3: Int32) -> Bool + + @JavaMethod + public func startsWith(_ arg0: String) -> Bool + + @JavaMethod + public func startsWith(_ arg0: String, _ arg1: Int32) -> Bool + + @JavaMethod + public func lastIndexOf(_ arg0: String) -> Int32 + + @JavaMethod + public func lastIndexOf(_ arg0: Int32, _ arg1: Int32) -> Int32 + + @JavaMethod + public func lastIndexOf(_ arg0: String, _ arg1: Int32) -> Int32 + + @JavaMethod + public func lastIndexOf(_ arg0: Int32) -> Int32 + + @JavaMethod + public func substring(_ arg0: Int32) -> String + + @JavaMethod + public func substring(_ arg0: Int32, _ arg1: Int32) -> String + + @JavaMethod + public func isEmpty() -> Bool + + @JavaMethod + public func replace(_ arg0: UInt16, _ arg1: UInt16) -> String + + @JavaMethod + public func matches(_ arg0: String) -> Bool + + @JavaMethod + public func replaceFirst(_ arg0: String, _ arg1: String) -> String + + @JavaMethod + public func replaceAll(_ arg0: String, _ arg1: String) -> String + + @JavaMethod + public func split(_ arg0: String) -> [String] + + @JavaMethod + public func split(_ arg0: String, _ arg1: Int32) -> [String] + + @JavaMethod + public func splitWithDelimiters(_ arg0: String, _ arg1: Int32) -> [String] + + @JavaMethod + public func toLowerCase() -> String + + @JavaMethod + public func toUpperCase() -> String + + @JavaMethod + public func trim() -> String + + @JavaMethod + public func strip() -> String + + @JavaMethod + public func stripLeading() -> String + + @JavaMethod + public func stripTrailing() -> String + + @JavaMethod + public func `repeat`(_ arg0: Int32) -> String + + @JavaMethod + public func isBlank() -> Bool + + @JavaMethod + public func toCharArray() -> [UInt16] + + @JavaMethod + public func equalsIgnoreCase(_ arg0: String) -> Bool + + @JavaMethod + public func compareToIgnoreCase(_ arg0: String) -> Int32 + + @JavaMethod + public func endsWith(_ arg0: String) -> Bool + + @JavaMethod + public func concat(_ arg0: String) -> String + + @JavaMethod + public func indent(_ arg0: Int32) -> String + + @JavaMethod + public func stripIndent() -> String + + @JavaMethod + public func translateEscapes() -> String + + @JavaMethod + public func formatted(_ arg0: [JavaObject?]) -> String + + @JavaMethod + public func intern() -> String + + @JavaMethod + public func getClass() -> JavaClass! + + @JavaMethod + public func notify() + + @JavaMethod + public func notifyAll() + + @JavaMethod + public func wait(_ arg0: Int64) throws + + @JavaMethod + public func wait(_ arg0: Int64, _ arg1: Int32) throws + + @JavaMethod + public func wait() throws +} +extension JavaClass { + @JavaStaticMethod + public func valueOf(_ arg0: Int64) -> String + + @JavaStaticMethod + public func valueOf(_ arg0: [UInt16]) -> String + + @JavaStaticMethod + public func valueOf(_ arg0: JavaObject?) -> String + + @JavaStaticMethod + public func valueOf(_ arg0: [UInt16], _ arg1: Int32, _ arg2: Int32) -> String + + @JavaStaticMethod + public func valueOf(_ arg0: Float) -> String + + @JavaStaticMethod + public func valueOf(_ arg0: Double) -> String + + @JavaStaticMethod + public func valueOf(_ arg0: UInt16) -> String + + @JavaStaticMethod + public func valueOf(_ arg0: Bool) -> String + + @JavaStaticMethod + public func valueOf(_ arg0: Int32) -> String + + @JavaStaticMethod + public func format(_ arg0: String, _ arg1: [JavaObject?]) -> String + + @JavaStaticMethod + public func copyValueOf(_ arg0: [UInt16]) -> String + + @JavaStaticMethod + public func copyValueOf(_ arg0: [UInt16], _ arg1: Int32, _ arg2: Int32) -> String +} diff --git a/Sources/JavaKitCollection/generated/HashMap.swift b/Sources/JavaKitCollection/generated/HashMap.swift index 90e50295..287593f5 100644 --- a/Sources/JavaKitCollection/generated/HashMap.swift +++ b/Sources/JavaKitCollection/generated/HashMap.swift @@ -88,92 +88,6 @@ public struct HashMap { @JavaMethod public func wait() throws } -extension HashMap { - @JavaClass("java.util.AbstractMap$SimpleImmutableEntry", extends: JavaObject.self) - public struct SimpleImmutableEntry { - @JavaMethod - public init(_ arg0: JavaObject?, _ arg1: JavaObject?, environment: JNIEnvironment? = nil) - - @JavaMethod - public func equals(_ arg0: JavaObject?) -> Bool - - @JavaMethod - public func toString() -> String - - @JavaMethod - public func hashCode() -> Int32 - - @JavaMethod - public func getValue() -> JavaObject! - - @JavaMethod - public func getKey() -> JavaObject! - - @JavaMethod - public func setValue(_ arg0: JavaObject?) -> JavaObject! - - @JavaMethod - public func getClass() -> JavaClass! - - @JavaMethod - public func notify() - - @JavaMethod - public func notifyAll() - - @JavaMethod - public func wait(_ arg0: Int64) throws - - @JavaMethod - public func wait(_ arg0: Int64, _ arg1: Int32) throws - - @JavaMethod - public func wait() throws - } -} -extension HashMap { - @JavaClass("java.util.AbstractMap$SimpleEntry", extends: JavaObject.self) - public struct SimpleEntry { - @JavaMethod - public init(_ arg0: JavaObject?, _ arg1: JavaObject?, environment: JNIEnvironment? = nil) - - @JavaMethod - public func equals(_ arg0: JavaObject?) -> Bool - - @JavaMethod - public func toString() -> String - - @JavaMethod - public func hashCode() -> Int32 - - @JavaMethod - public func getValue() -> JavaObject! - - @JavaMethod - public func getKey() -> JavaObject! - - @JavaMethod - public func setValue(_ arg0: JavaObject?) -> JavaObject! - - @JavaMethod - public func getClass() -> JavaClass! - - @JavaMethod - public func notify() - - @JavaMethod - public func notifyAll() - - @JavaMethod - public func wait(_ arg0: Int64) throws - - @JavaMethod - public func wait(_ arg0: Int64, _ arg1: Int32) throws - - @JavaMethod - public func wait() throws - } -} extension JavaClass { @JavaStaticMethod public func newHashMap(_ arg0: Int32) -> HashMap! where ObjectType == HashMap diff --git a/Sources/JavaKitCollection/generated/TreeMap.swift b/Sources/JavaKitCollection/generated/TreeMap.swift index 3c45b998..706d5339 100644 --- a/Sources/JavaKitCollection/generated/TreeMap.swift +++ b/Sources/JavaKitCollection/generated/TreeMap.swift @@ -106,3 +106,89 @@ public struct TreeMap { @JavaMethod public func getOrDefault(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject! } +extension TreeMap { + @JavaClass("java.util.AbstractMap$SimpleEntry", extends: JavaObject.self) + public struct SimpleEntry { + @JavaMethod + public init(_ arg0: JavaObject?, _ arg1: JavaObject?, environment: JNIEnvironment? = nil) + + @JavaMethod + public func equals(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func toString() -> String + + @JavaMethod + public func hashCode() -> Int32 + + @JavaMethod + public func getValue() -> JavaObject! + + @JavaMethod + public func getKey() -> JavaObject! + + @JavaMethod + public func setValue(_ arg0: JavaObject?) -> JavaObject! + + @JavaMethod + public func getClass() -> JavaClass! + + @JavaMethod + public func notify() + + @JavaMethod + public func notifyAll() + + @JavaMethod + public func wait(_ arg0: Int64) throws + + @JavaMethod + public func wait(_ arg0: Int64, _ arg1: Int32) throws + + @JavaMethod + public func wait() throws + } +} +extension TreeMap { + @JavaClass("java.util.AbstractMap$SimpleImmutableEntry", extends: JavaObject.self) + public struct SimpleImmutableEntry { + @JavaMethod + public init(_ arg0: JavaObject?, _ arg1: JavaObject?, environment: JNIEnvironment? = nil) + + @JavaMethod + public func equals(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func toString() -> String + + @JavaMethod + public func hashCode() -> Int32 + + @JavaMethod + public func getValue() -> JavaObject! + + @JavaMethod + public func getKey() -> JavaObject! + + @JavaMethod + public func setValue(_ arg0: JavaObject?) -> JavaObject! + + @JavaMethod + public func getClass() -> JavaClass! + + @JavaMethod + public func notify() + + @JavaMethod + public func notifyAll() + + @JavaMethod + public func wait(_ arg0: Int64) throws + + @JavaMethod + public func wait(_ arg0: Int64, _ arg1: Int32) throws + + @JavaMethod + public func wait() throws + } +} diff --git a/Sources/JavaKitJar/generated/JarInputStream.swift b/Sources/JavaKitJar/generated/JarInputStream.swift index 580202e4..de063bb9 100644 --- a/Sources/JavaKitJar/generated/JarInputStream.swift +++ b/Sources/JavaKitJar/generated/JarInputStream.swift @@ -4,9 +4,6 @@ import JavaRuntime @JavaClass("java.util.jar.JarInputStream") public struct JarInputStream { - @JavaMethod - public func getNextJarEntry() throws -> JarEntry! - @JavaMethod public func read(_ arg0: [Int8], _ arg1: Int32, _ arg2: Int32) throws -> Int32 @@ -14,7 +11,7 @@ public struct JarInputStream { public func getManifest() -> Manifest! @JavaMethod - public func closeEntry() throws + public func getNextJarEntry() throws -> JarEntry! @JavaMethod public func read() throws -> Int32 @@ -26,10 +23,10 @@ public struct JarInputStream { public func readAllBytes() throws -> [Int8] @JavaMethod - public func readNBytes(_ arg0: [Int8], _ arg1: Int32, _ arg2: Int32) throws -> Int32 + public func readNBytes(_ arg0: Int32) throws -> [Int8] @JavaMethod - public func readNBytes(_ arg0: Int32) throws -> [Int8] + public func readNBytes(_ arg0: [Int8], _ arg1: Int32, _ arg2: Int32) throws -> Int32 @JavaMethod public func skip(_ arg0: Int64) throws -> Int64 @@ -40,6 +37,9 @@ public struct JarInputStream { @JavaMethod public func skipNBytes(_ arg0: Int64) throws + @JavaMethod + public func closeEntry() throws + @JavaMethod public func reset() throws diff --git a/Sources/JavaKitJar/generated/JarOutputStream.swift b/Sources/JavaKitJar/generated/JarOutputStream.swift index 57a13841..542a784f 100644 --- a/Sources/JavaKitJar/generated/JarOutputStream.swift +++ b/Sources/JavaKitJar/generated/JarOutputStream.swift @@ -4,9 +4,6 @@ import JavaRuntime @JavaClass("java.util.jar.JarOutputStream") public struct JarOutputStream { - @JavaMethod - public func closeEntry() throws - @JavaMethod public func write(_ arg0: [Int8], _ arg1: Int32, _ arg2: Int32) throws @@ -25,6 +22,9 @@ public struct JarOutputStream { @JavaMethod public func setLevel(_ arg0: Int32) + @JavaMethod + public func closeEntry() throws + @JavaMethod public func flush() throws diff --git a/Sources/JavaTypes/JavaType+SwiftNames.swift b/Sources/JavaTypes/JavaType+SwiftNames.swift index 8577640e..e1604eaa 100644 --- a/Sources/JavaTypes/JavaType+SwiftNames.swift +++ b/Sources/JavaTypes/JavaType+SwiftNames.swift @@ -19,12 +19,15 @@ public typealias JavaToSwiftClassNameResolver = (String) throws -> String extension JavaType { /// Whether this Java type needs to be represented by a Swift optional. - public var isSwiftOptional: Bool { + public func isSwiftOptional(stringIsValueType: Bool) -> Bool { switch self { case .boolean, .byte, .char, .short, .int, .long, .float, .double, .void, - .array, .class(package: "java.lang", name: "String"): + .array: return false + case .class(package: "java.lang", name: "String"): + return !stringIsValueType + case .class: return true } @@ -56,7 +59,7 @@ extension JavaType { case .void: return "Void" case .array(let elementType): let elementTypeName = try elementType.swiftTypeName(resolver: resolver) - let elementIsOptional = elementType.isSwiftOptional + let elementIsOptional = elementType.isSwiftOptional(stringIsValueType: true) return "[\(elementTypeName)\(elementIsOptional ? "?" : "")]" case .class: return try resolver(description) diff --git a/Tests/Java2SwiftTests/Java2SwiftTests.swift b/Tests/Java2SwiftTests/Java2SwiftTests.swift index 85240305..80c86fc0 100644 --- a/Tests/Java2SwiftTests/Java2SwiftTests.swift +++ b/Tests/Java2SwiftTests/Java2SwiftTests.swift @@ -63,8 +63,7 @@ class Java2SwiftTests: XCTestCase { JavaClass.self, swiftTypeName: "MyJavaClass", translatedClasses: [ - "java.lang.Object": ("JavaObject", nil, true), - "java.lang.String": ("JavaString", nil, true), + "java.lang.Object": ("JavaObject", nil), ], expectedChunks: [ "import JavaKit", @@ -74,7 +73,7 @@ class Java2SwiftTests: XCTestCase { """, """ @JavaStaticMethod - public func forName(_ arg0: JavaString) throws -> MyJavaClass! where ObjectType == MyJavaClass + public func forName(_ arg0: String) throws -> MyJavaClass! where ObjectType == MyJavaClass """, ] ) @@ -115,13 +114,19 @@ class Java2SwiftTests: XCTestCase { MyArrayList.self, swiftTypeName: "JavaArrayList", translatedClasses: [ - "java.lang.Object": ("JavaObject", nil, true), - "java.util.List": ("JavaList", nil, true), + "java.lang.Object": ("JavaObject", nil), + "java.lang.reflect.Array": ("JavaArray", nil), + "java.util.List": ("JavaList", nil), + "java.util.function.IntFunction": ("MyJavaIntFunction", nil), ], expectedChunks: [ """ @JavaMethod public func subList(_ arg0: Int32, _ arg1: Int32) -> JavaList! + """, + """ + @JavaMethod + public func toArray(_ arg0: MyJavaIntFunction?) -> [JavaObject?] """ ] ) @@ -132,8 +137,8 @@ class Java2SwiftTests: XCTestCase { MyLinkedList.self, swiftTypeName: "JavaLinkedList", translatedClasses: [ - "java.lang.Object": ("JavaObject", nil, true), - "java.util.List": ("JavaList", nil, true), + "java.lang.Object": ("JavaObject", nil), + "java.util.List": ("JavaList", nil), ], expectedChunks: [ """ @@ -149,9 +154,9 @@ class Java2SwiftTests: XCTestCase { ProcessBuilder.self, swiftTypeName: "ProcessBuilder", translatedClasses: [ - "java.lang.ProcessBuilder": ("ProcessBuilder", nil, true), - "java.lang.ProcessBuilder$Redirect": ("ProcessBuilder.Redirect", nil, true), - "java.lang.ProcessBuilder$Redirect$Type": ("ProcessBuilder.Redirect.Type", nil, true), + "java.lang.ProcessBuilder": ("ProcessBuilder", nil), + "java.lang.ProcessBuilder$Redirect": ("ProcessBuilder.Redirect", nil), + "java.lang.ProcessBuilder$Redirect$Type": ("ProcessBuilder.Redirect.Type", nil), ], nestedClasses: [ "java.lang.ProcessBuilder": [JavaClass().as(JavaClass.self)!], @@ -189,9 +194,9 @@ class Java2SwiftTests: XCTestCase { ProcessBuilder.self, swiftTypeName: "ProcessBuilder", translatedClasses: [ - "java.lang.ProcessBuilder": ("ProcessBuilder", nil, true), - "java.lang.ProcessBuilder$Redirect": ("ProcessBuilder.PBRedirect", nil, true), - "java.lang.ProcessBuilder$Redirect$Type": ("ProcessBuilder.PBRedirect.JavaType", nil, true), + "java.lang.ProcessBuilder": ("ProcessBuilder", nil), + "java.lang.ProcessBuilder$Redirect": ("ProcessBuilder.PBRedirect", nil), + "java.lang.ProcessBuilder$Redirect$Type": ("ProcessBuilder.PBRedirect.JavaType", nil), ], nestedClasses: [ "java.lang.ProcessBuilder": [JavaClass().as(JavaClass.self)!], @@ -223,6 +228,44 @@ class Java2SwiftTests: XCTestCase { ] ) } + + func testJavaString() throws { + try assertTranslatedClass( + MyJavaString.self, + swiftTypeName: "JavaString", + expectedChunks: [ + """ + @JavaClass("java.lang.String") + public struct JavaString { + """ + ] + ) + } + + func testJavaObjects() throws { + try assertTranslatedClass( + MyObjects.self, + swiftTypeName: "MyJavaObjects", + translatedClasses: [ + "java.lang.Object" : ("JavaObject", "JavaKit"), + "java.util.function.Supplier" : ("MySupplier", "JavaKitFunction"), + "java.lang.String" : ("JavaString", "JavaKit"), + ], + expectedChunks: [ + """ + import JavaKitFunction + """, + """ + @JavaClass("java.util.Objects", extends: JavaObject.self) + public struct MyJavaObjects { + """, + """ + @JavaStaticMethod + public func requireNonNull(_ arg0: JavaObject?, _ arg1: MySupplier?) -> JavaObject! + """, + ] + ) + } } @JavaClass("java.util.ArrayList") @@ -233,14 +276,28 @@ public struct MyArrayList { public struct MyLinkedList { } +@JavaClass("java.lang.String") +public struct MyJavaString { +} + +@JavaClass("java.util.Objects") +public struct MyObjects { } + +@JavaInterface("java.util.function.Supplier") +public struct MySupplier { } + +@JavaInterface("java.util.function.IntFunction") +public struct MyJavaIntFunction { +} + /// Translate a Java class and assert that the translated output contains /// each of the expected "chunks" of text. func assertTranslatedClass( _ javaType: JavaClassType.Type, swiftTypeName: String, translatedClasses: [ - String: (swiftType: String, swiftModule: String?, isOptional: Bool) - ] = JavaTranslator.defaultTranslatedClasses, + String: (swiftType: String, swiftModule: String?) + ] = [:], nestedClasses: [String: [JavaClass]] = [:], expectedChunks: [String], file: StaticString = #filePath, @@ -253,7 +310,7 @@ func assertTranslatedClass( ) translator.translatedClasses = translatedClasses - translator.translatedClasses[javaType.fullJavaClassName] = (swiftTypeName, nil, true) + translator.translatedClasses[javaType.fullJavaClassName] = (swiftTypeName, nil) translator.nestedClasses = nestedClasses translator.startNewFile() let translatedDecls = try translator.translateClass( From d1e4b8f4451046af34034dc33f68f5370d98bb8c Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Tue, 29 Oct 2024 11:57:44 +0900 Subject: [PATCH 141/426] SwiftArena.ofAuto() which uses GC to manage swift instances (and destroy them) (#133) --- .../swiftkit/AutoSwiftMemorySession.java | 70 ++++++++++++ .../swift/swiftkit/ClosableSwiftArena.java | 28 +++++ .../swiftkit/ConfinedSwiftMemorySession.java | 86 ++++++++++++++ .../java/org/swift/swiftkit/SwiftArena.java | 105 +++--------------- .../swift/swiftkit/SwiftInstanceCleanup.java | 34 ++++-- .../org/swift/swiftkit/AutoArenaTest.java | 80 +++++++++++++ 6 files changed, 309 insertions(+), 94 deletions(-) create mode 100644 SwiftKit/src/main/java/org/swift/swiftkit/AutoSwiftMemorySession.java create mode 100644 SwiftKit/src/main/java/org/swift/swiftkit/ClosableSwiftArena.java create mode 100644 SwiftKit/src/main/java/org/swift/swiftkit/ConfinedSwiftMemorySession.java create mode 100644 SwiftKit/src/test/java/org/swift/swiftkit/AutoArenaTest.java diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/AutoSwiftMemorySession.java b/SwiftKit/src/main/java/org/swift/swiftkit/AutoSwiftMemorySession.java new file mode 100644 index 00000000..9d25ad12 --- /dev/null +++ b/SwiftKit/src/main/java/org/swift/swiftkit/AutoSwiftMemorySession.java @@ -0,0 +1,70 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package org.swift.swiftkit; + +import java.lang.foreign.MemorySegment; +import java.lang.ref.Cleaner; +import java.util.Objects; +import java.util.concurrent.ThreadFactory; + +/** + * A memory session which manages registered objects via the Garbage Collector. + * + *

When registered Java wrapper classes around native Swift instances {@link SwiftInstance}, + * are eligible for collection, this will trigger the cleanup of the native resources as well. + * + *

This memory session is LESS reliable than using a {@link ConfinedSwiftMemorySession} because + * the timing of when the native resources are cleaned up is somewhat undefined, and rely on the + * system GC. Meaning, that if an object nas been promoted to an old generation, there may be a + * long time between the resource no longer being referenced "in Java" and its native memory being released, + * and also the deinit of the Swift type being run. + * + *

This can be problematic for Swift applications which rely on quick release of resources, and may expect + * the deinits to run in expected and "quick" succession. + * + *

Whenever possible, prefer using an explicitly managed {@link SwiftArena}, such as {@link SwiftArena#ofConfined()}. + */ +final class AutoSwiftMemorySession implements SwiftArena { + + private final Cleaner cleaner; + + public AutoSwiftMemorySession(ThreadFactory cleanerThreadFactory) { + this.cleaner = Cleaner.create(cleanerThreadFactory); + } + + @Override + public void register(SwiftHeapObject object) { + SwiftHeapObjectCleanup cleanupAction = new SwiftHeapObjectCleanup(object.$memorySegment(), object.$swiftType()); + register(object, cleanupAction); + } + + // visible for testing + void register(SwiftHeapObject object, SwiftHeapObjectCleanup cleanupAction) { + Objects.requireNonNull(object, "obj"); + Objects.requireNonNull(cleanupAction, "cleanupAction"); + + + cleaner.register(object, cleanupAction); + } + + @Override + public void register(SwiftValue value) { + Objects.requireNonNull(value, "value"); + MemorySegment resource = value.$memorySegment(); + var cleanupAction = new SwiftValueCleanup(resource); + cleaner.register(value, cleanupAction); + } + +} diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/ClosableSwiftArena.java b/SwiftKit/src/main/java/org/swift/swiftkit/ClosableSwiftArena.java new file mode 100644 index 00000000..c257ae57 --- /dev/null +++ b/SwiftKit/src/main/java/org/swift/swiftkit/ClosableSwiftArena.java @@ -0,0 +1,28 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package org.swift.swiftkit; + +/** + * Auto-closable version of {@link SwiftArena}. + */ +public interface ClosableSwiftArena extends SwiftArena, AutoCloseable { + + /** + * Close the arena and make sure all objects it managed are released. + * Throws if unable to verify all resources have been release (e.g. over retained Swift classes) + */ + void close(); + +} diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/ConfinedSwiftMemorySession.java b/SwiftKit/src/main/java/org/swift/swiftkit/ConfinedSwiftMemorySession.java new file mode 100644 index 00000000..e727f5db --- /dev/null +++ b/SwiftKit/src/main/java/org/swift/swiftkit/ConfinedSwiftMemorySession.java @@ -0,0 +1,86 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package org.swift.swiftkit; + +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; + +final class ConfinedSwiftMemorySession implements ClosableSwiftArena { + + final static int CLOSED = 0; + final static int ACTIVE = 1; + + final Thread owner; + final AtomicInteger state; + + final ConfinedResourceList resources; + + public ConfinedSwiftMemorySession(Thread owner) { + this.owner = owner; + this.state = new AtomicInteger(ACTIVE); + this.resources = new ConfinedResourceList(); + } + + public void checkValid() throws RuntimeException { + if (this.owner != null && this.owner != Thread.currentThread()) { + throw new WrongThreadException("ConfinedSwift arena is confined to %s but was closed from %s!".formatted(this.owner, Thread.currentThread())); + } else if (this.state.get() < ACTIVE) { + throw new RuntimeException("SwiftArena is already closed!"); + } + } + + @Override + public void close() { + checkValid(); + + // Cleanup all resources + if (this.state.compareAndExchange(ACTIVE, CLOSED) == ACTIVE) { + this.resources.runCleanup(); + } // else, was already closed; do nothing + } + + @Override + public void register(SwiftHeapObject object) { + checkValid(); + + var cleanup = new SwiftHeapObjectCleanup(object.$memorySegment(), object.$swiftType()); + this.resources.add(cleanup); + } + + @Override + public void register(SwiftValue value) { + checkValid(); + + var cleanup = new SwiftValueCleanup(value.$memorySegment()); + this.resources.add(cleanup); + } + + static final class ConfinedResourceList implements SwiftResourceList { + // TODO: Could use intrusive linked list to avoid one indirection here + final List resourceCleanups = new LinkedList<>(); + + void add(SwiftInstanceCleanup cleanup) { + resourceCleanups.add(cleanup); + } + + @Override + public void runCleanup() { + for (SwiftInstanceCleanup cleanup : resourceCleanups) { + cleanup.run(); + } + } + } +} diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftArena.java b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftArena.java index 98bfd5ef..02c1b599 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftArena.java +++ b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftArena.java @@ -14,23 +14,26 @@ package org.swift.swiftkit; -import java.util.LinkedList; -import java.util.List; -import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.ThreadFactory; /** * A Swift arena manages Swift allocated memory for classes, structs, enums etc. * When an arena is closed, it will destroy all managed swift objects in a way appropriate to their type. - *

- * A confined arena has an associated owner thread that confines some operations to - * associated owner thread such as {@link #close()}. + * + *

A confined arena has an associated owner thread that confines some operations to + * associated owner thread such as {@link ClosableSwiftArena#close()}. */ -public interface SwiftArena extends AutoCloseable { +public interface SwiftArena { - static SwiftArena ofConfined() { + static ClosableSwiftArena ofConfined() { return new ConfinedSwiftMemorySession(Thread.currentThread()); } + static SwiftArena ofAuto() { + ThreadFactory cleanerThreadFactory = r -> new Thread(r, "AutoSwiftArenaCleanerThread"); + return new AutoSwiftMemorySession(cleanerThreadFactory); + } + /** * Register a Swift reference counted heap object with this arena (such as a {@code class} or {@code actor}). * Its memory should be considered managed by this arena, and be destroyed when the arena is closed. @@ -43,91 +46,18 @@ static SwiftArena ofConfined() { */ void register(SwiftValue value); - /** - * Close the arena and make sure all objects it managed are released. - * Throws if unable to verify all resources have been release (e.g. over retained Swift classes) - */ - void close(); - } -final class ConfinedSwiftMemorySession implements SwiftArena { - -// final Arena underlying; - final Thread owner; - final SwiftResourceList resources; - - final int CLOSED = 0; - final int ACTIVE = 1; - final AtomicInteger state; - - public ConfinedSwiftMemorySession(Thread owner) { - this.owner = owner; - resources = new ConfinedResourceList(); - state = new AtomicInteger(ACTIVE); - } - - public void checkValid() throws RuntimeException { - if (this.owner != null && this.owner != Thread.currentThread()) { - throw new WrongThreadException("ConfinedSwift arena is confined to %s but was closed from %s!".formatted(this.owner, Thread.currentThread())); - } else if (this.state.get() < ACTIVE) { - throw new RuntimeException("Arena is already closed!"); - } - } - - @Override - public void register(SwiftHeapObject object) { - this.resources.add(new SwiftHeapObjectCleanup(object)); - } - - @Override - public void register(SwiftValue value) { - this.resources.add(new SwiftValueCleanup(value.$memorySegment())); - } - - @Override - public void close() { - checkValid(); - - // Cleanup all resources - if (this.state.compareAndExchange(ACTIVE, CLOSED) == ACTIVE) { - this.resources.cleanup(); - } // else, was already closed; do nothing - } - - /** - * Represents a list of resources that need a cleanup, e.g. allocated classes/structs. - */ - static abstract class SwiftResourceList implements Runnable { - // TODO: Could use intrusive linked list to avoid one indirection here - final List resourceCleanups = new LinkedList<>(); - - abstract void add(SwiftInstanceCleanup cleanup); - - public abstract void cleanup(); - - public final void run() { - cleanup(); // cleaner interop - } - } - - static final class ConfinedResourceList extends SwiftResourceList { - @Override - void add(SwiftInstanceCleanup cleanup) { - resourceCleanups.add(cleanup); - } - - @Override - public void cleanup() { - for (SwiftInstanceCleanup cleanup : resourceCleanups) { - cleanup.run(); - } - } - } +/** + * Represents a list of resources that need a cleanup, e.g. allocated classes/structs. + */ +interface SwiftResourceList { + void runCleanup(); } + final class UnexpectedRetainCountException extends RuntimeException { public UnexpectedRetainCountException(Object resource, long retainCount, int expectedRetainCount) { super(("Attempting to cleanup managed memory segment %s, but it's retain count was different than [%d] (was %d)! " + @@ -135,3 +65,4 @@ public UnexpectedRetainCountException(Object resource, long retainCount, int exp ).formatted(resource, expectedRetainCount, retainCount)); } } + diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftInstanceCleanup.java b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftInstanceCleanup.java index a20a7599..8ac62793 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftInstanceCleanup.java +++ b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftInstanceCleanup.java @@ -19,23 +19,43 @@ /** * A Swift memory instance cleanup, e.g. count-down a reference count and destroy a class, or destroy struct/enum etc. */ -sealed interface SwiftInstanceCleanup extends Runnable { +interface SwiftInstanceCleanup extends Runnable { } -record SwiftHeapObjectCleanup(SwiftHeapObject instance) implements SwiftInstanceCleanup { +/** + * Implements cleaning up a Swift {@link SwiftHeapObject}. + *

+ * This class does not store references to the Java wrapper class, and therefore the wrapper may be subject to GC, + * which may trigger a cleanup (using this class), which will clean up its underlying native memory resource. + */ +// non-final for testing +class SwiftHeapObjectCleanup implements SwiftInstanceCleanup { + + final MemorySegment selfPointer; + final SwiftAnyType selfType; + + /** + * This constructor on purpose does not just take a {@link SwiftHeapObject} in order to make it very + * clear that it does not take ownership of it, but we ONLY manage the native resource here. + * + * This is important for {@link AutoSwiftMemorySession} which relies on the wrapper type to be GC-able, + * when no longer "in use" on the Java side. + */ + SwiftHeapObjectCleanup(MemorySegment selfPointer, SwiftAnyType selfType) { + this.selfPointer = selfPointer; + this.selfType = selfType; + } @Override public void run() throws UnexpectedRetainCountException { // Verify we're only destroying an object that's indeed not retained by anyone else: - long retainedCount = SwiftKit.retainCount(this.instance); + long retainedCount = SwiftKit.retainCount(selfPointer); if (retainedCount > 1) { - throw new UnexpectedRetainCountException(this.instance, retainedCount, 1); + throw new UnexpectedRetainCountException(selfPointer, retainedCount, 1); } // Destroy (and deinit) the object: - var ty = this.instance.$swiftType(); - - SwiftValueWitnessTable.destroy(ty, this.instance.$memorySegment()); + SwiftValueWitnessTable.destroy(selfType, selfPointer); // Invalidate the Java wrapper class, in order to prevent effectively use-after-free issues. // FIXME: some trouble with setting the pointer to null, need to figure out an appropriate way to do this diff --git a/SwiftKit/src/test/java/org/swift/swiftkit/AutoArenaTest.java b/SwiftKit/src/test/java/org/swift/swiftkit/AutoArenaTest.java new file mode 100644 index 00000000..7ba215ab --- /dev/null +++ b/SwiftKit/src/test/java/org/swift/swiftkit/AutoArenaTest.java @@ -0,0 +1,80 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package org.swift.swiftkit; + +import org.junit.jupiter.api.Test; + +import java.lang.foreign.GroupLayout; +import java.lang.foreign.MemorySegment; +import java.lang.ref.Cleaner; +import java.util.concurrent.CountDownLatch; + +public class AutoArenaTest { + + + @Test + @SuppressWarnings("removal") // System.runFinalization() will be removed + public void cleaner_releases_native_resource() { + SwiftHeapObject object = new FakeSwiftHeapObject(); + + // Latch waiting for the cleanup of the object + var cleanupLatch = new CountDownLatch(1); + + // we're retaining the `object`, register it with the arena: + AutoSwiftMemorySession arena = (AutoSwiftMemorySession) SwiftArena.ofAuto(); + arena.register(object, new SwiftHeapObjectCleanup(object.$memorySegment(), object.$swiftType()) { + @Override + public void run() throws UnexpectedRetainCountException { + cleanupLatch.countDown(); + } + }); + + // Release the object and hope it gets GC-ed soon + + //noinspection UnusedAssignment + object = null; + + var i = 1_000; + while (cleanupLatch.getCount() != 0) { + System.runFinalization(); + System.gc(); + + if (i-- < 1) { + throw new RuntimeException("Reference was not cleaned up! Did Cleaner not pick up the release?"); + } + } + + } + + private static class FakeSwiftHeapObject implements SwiftHeapObject { + public FakeSwiftHeapObject() { + } + + @Override + public MemorySegment $memorySegment() { + return MemorySegment.NULL; + } + + @Override + public GroupLayout $layout() { + return null; + } + + @Override + public SwiftAnyType $swiftType() { + return null; + } + } +} From 2d7c2c339115884ee32192fd0eb4bf7c81de759b Mon Sep 17 00:00:00 2001 From: helmetcrest Date: Mon, 28 Oct 2024 21:54:59 -0700 Subject: [PATCH 142/426] Add placeholder ordo-benchmark and JMH benchmarks --- .github/workflows/pull_request.yml | 4 +- .../JavaApiCallBenchmarks.swift | 34 +++++++++ Makefile | 4 +- Package.swift | 49 +++++++++---- Samples/SwiftKitSampleApp/build.gradle | 70 +++++++------------ .../swift/swiftkit/JavaToSwiftBenchmark.java | 53 ++++++++++++++ .../org/swift/swiftkit/MySwiftClassTest.java | 7 +- .../ExampleSwiftLibrary/MySwiftLibrary.swift | 4 ++ 8 files changed, 158 insertions(+), 67 deletions(-) create mode 100644 Benchmarks/JavaApiCallBenchmarks/JavaApiCallBenchmarks.swift create mode 100644 Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/JavaToSwiftBenchmark.java diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 0005f1c4..6fb3a0ff 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -29,7 +29,7 @@ jobs: steps: - uses: actions/checkout@v4 - name: Install System Dependencies - run: apt-get -qq update && apt-get -qq install -y make curl wget + run: apt-get -qq update && apt-get -qq install -y make curl wget libjemalloc2 libjemalloc-dev - name: Cache JDK id: cache-jdk uses: actions/cache@v4 @@ -86,7 +86,7 @@ jobs: steps: - uses: actions/checkout@v4 - name: Install System Dependencies - run: apt-get -qq update && apt-get -qq install -y make curl wget + run: apt-get -qq update && apt-get -qq install -y make curl wget libjemalloc2 libjemalloc-dev - name: Cache JDK id: cache-jdk uses: actions/cache@v4 diff --git a/Benchmarks/JavaApiCallBenchmarks/JavaApiCallBenchmarks.swift b/Benchmarks/JavaApiCallBenchmarks/JavaApiCallBenchmarks.swift new file mode 100644 index 00000000..25c67074 --- /dev/null +++ b/Benchmarks/JavaApiCallBenchmarks/JavaApiCallBenchmarks.swift @@ -0,0 +1,34 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import Benchmark +import Foundation +import JavaKit +import JavaKitNetwork + +@MainActor let benchmarks = { + var jvm: JavaVirtualMachine { + get throws { + try .shared() + } + } + Benchmark("Simple call to Java library") { benchmark in + for _ in benchmark.scaledIterations { + let environment = try jvm.environment() + + let urlConnectionClass = try JavaClass(environment: environment) + blackHole(urlConnectionClass.getDefaultAllowUserInteraction()) + } + } +} diff --git a/Makefile b/Makefile index 4aee0561..aeb3eedd 100644 --- a/Makefile +++ b/Makefile @@ -133,12 +133,12 @@ jextract-generate: jextract-swift generate-JExtract-interface-files swift run jextract-swift \ --package-name com.example.swift.generated \ --swift-module ExampleSwiftLibrary \ - --output-directory ${SAMPLES_DIR}/SwiftKitSampleApp/src/generated/java \ + --output-directory ${SAMPLES_DIR}/SwiftKitSampleApp/build/generated/sources/jextract/main \ $(BUILD_DIR)/jextract/ExampleSwiftLibrary/MySwiftLibrary.swiftinterface; \ swift run jextract-swift \ --package-name org.swift.swiftkit.generated \ --swift-module SwiftKitSwift \ - --output-directory ${SAMPLES_DIR}/SwiftKitSampleApp/src/generated/java \ + --output-directory ${SAMPLES_DIR}/SwiftKitSampleApp/build/generated/sources/jextract/main \ $(BUILD_DIR)/jextract/SwiftKitSwift/SwiftKit.swiftinterface diff --git a/Package.swift b/Package.swift index 006562b2..d4078695 100644 --- a/Package.swift +++ b/Package.swift @@ -94,18 +94,18 @@ let package = Package( // ==== Plugin for building Java code .plugin( - name: "JavaCompilerPlugin", - targets: [ - "JavaCompilerPlugin" - ] + name: "JavaCompilerPlugin", + targets: [ + "JavaCompilerPlugin" + ] ), // ==== Plugin for wrapping Java classes in Swift .plugin( - name: "Java2SwiftPlugin", - targets: [ - "Java2SwiftPlugin" - ] + name: "Java2SwiftPlugin", + targets: [ + "Java2SwiftPlugin" + ] ), // ==== jextract-swift (extract Java accessors from Swift interface files) @@ -140,6 +140,7 @@ let package = Package( .package(url: "https://github.com/swiftlang/swift-syntax.git", branch: "main"), .package(url: "https://github.com/apple/swift-argument-parser", from: "1.5.0"), .package(url: "https://github.com/apple/swift-collections.git", .upToNextMinor(from: "1.1.0")), + .package(url: "https://github.com/ordo-one/package-benchmark", .upToNextMajor(from: "1.4.0")), ], targets: [ .macro( @@ -225,16 +226,16 @@ let package = Package( ] ), .plugin( - name: "JavaCompilerPlugin", - capability: .buildTool() + name: "JavaCompilerPlugin", + capability: .buildTool() ), .plugin( - name: "Java2SwiftPlugin", - capability: .buildTool(), - dependencies: [ - "Java2Swift" - ] + name: "Java2SwiftPlugin", + capability: .buildTool(), + dependencies: [ + "Java2Swift" + ] ), .target( @@ -374,5 +375,23 @@ let package = Package( .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) ] ), + + .executableTarget( + name: "JavaApiCallBenchmarks", + dependencies: [ + "JavaRuntime", + "JavaKit", + "JavaKitNetwork", + .product(name: "Benchmark", package: "package-benchmark"), + ], + path: "Benchmarks/JavaApiCallBenchmarks", + swiftSettings: [ + .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]), + .swiftLanguageMode(.v5), + ], + plugins: [ + .plugin(name: "BenchmarkPlugin", package: "package-benchmark") + ], + ), ] ) diff --git a/Samples/SwiftKitSampleApp/build.gradle b/Samples/SwiftKitSampleApp/build.gradle index e1b3d78d..7522d182 100644 --- a/Samples/SwiftKitSampleApp/build.gradle +++ b/Samples/SwiftKitSampleApp/build.gradle @@ -16,6 +16,7 @@ import org.swift.swiftkit.gradle.BuildUtils plugins { id("build-logic.java-application-conventions") + id "me.champeau.jmh" version "0.7.2" } group = "org.swift.swiftkit" @@ -31,43 +32,38 @@ java { } } -sourceSets { - generated { - java.srcDir "${buildDir}/generated/src/java/" - } - // Make the 'main' and 'test' source sets depend on the generated sources - main { - compileClasspath += sourceSets.generated.output - runtimeClasspath += sourceSets.generated.output - } - test { - compileClasspath += sourceSets.main.output - runtimeClasspath += sourceSets.main.output +def jextract = tasks.register("jextract", Exec) { + description = "Extracts Java accessor sources using jextract" + + outputs.dir(layout.buildDirectory.dir("generated/sources/jextract/main")) + inputs.dir("$rootDir/Sources/ExampleSwiftLibrary") // monitored library + + // any changes in the source generator sources also mean the resulting output might change + inputs.dir("$rootDir/Sources/JExtractSwift") + inputs.dir("$rootDir/Sources/JExtractSwiftTool") - compileClasspath += sourceSets.generated.output - runtimeClasspath += sourceSets.generated.output + workingDir = rootDir + commandLine "make" + args "jextract-generate" +} + +sourceSets { + main { + java { + srcDir(jextract) + } } } dependencies { implementation(project(':SwiftKit')) - generatedImplementation(project(':SwiftKit')) testImplementation(platform("org.junit:junit-bom:5.10.0")) testImplementation("org.junit.jupiter:junit-jupiter") } -configurations { - generatedImplementation.extendsFrom(mainImplementation) - generatedRuntimeOnly.extendsFrom(mainRuntimeOnly) -} - -tasks.named("compileJava").configure { - dependsOn("jextract") -} - -tasks.test { +tasks.named('test', Test) { useJUnitPlatform() } @@ -84,27 +80,15 @@ application { "--enable-native-access=ALL-UNNAMED", // Include the library paths where our dylibs are that we want to load and call - "-Djava.library.path=" + BuildUtils.javaLibraryPaths().join(":"), + "-Djava.library.path=" + BuildUtils.javaLibraryPaths(rootDir).join(":"), // Enable tracing downcalls (to Swift) "-Djextract.trace.downcalls=true" ] } -task jextract(type: Exec) { - description = "Extracts Java accessor sources using jextract" - outputs.dir(layout.buildDirectory.dir("generated")) - inputs.dir("$rootDir/Sources/ExampleSwiftLibrary") // monitored library - - // any changes in the source generator sources also mean the resulting output might change - inputs.dir("$rootDir/Sources/JExtractSwift") - inputs.dir("$rootDir/Sources/JExtractSwiftTool") - - workingDir = rootDir - commandLine "make" - args "jextract-generate" -} - -tasks.named("compileGeneratedJava").configure { - dependsOn jextract -} +jmh { + jvmArgsAppend = [ + "-Djava.library.path=" + BuildUtils.javaLibraryPaths(rootDir).join(":"), + ] +} \ No newline at end of file diff --git a/Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/JavaToSwiftBenchmark.java b/Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/JavaToSwiftBenchmark.java new file mode 100644 index 00000000..5ce9ee6b --- /dev/null +++ b/Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/JavaToSwiftBenchmark.java @@ -0,0 +1,53 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package org.swift.swiftkit; + +import java.util.concurrent.TimeUnit; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.infra.Blackhole; + +import com.example.swift.generated.MySwiftClass; + +public class JavaToSwiftBenchmark { + + @State(Scope.Benchmark) + public static class BenchmarkState { + MySwiftClass obj; + + @Setup(Level.Trial) + public void beforeALl() { + System.loadLibrary("swiftCore"); + System.loadLibrary("ExampleSwiftLibrary"); + + // Tune down debug statements so they don't fill up stdout + System.setProperty("jextract.trace.downcalls", "false"); + + obj = new MySwiftClass(1, 2); + } + } + + @Benchmark @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.NANOSECONDS) + public void simpleSwiftApiCall(BenchmarkState state, Blackhole blackhole) { + blackhole.consume(state.obj.makeRandomIntMethod()); + } +} diff --git a/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/MySwiftClassTest.java b/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/MySwiftClassTest.java index 1b98d1e0..069a4e41 100644 --- a/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/MySwiftClassTest.java +++ b/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/MySwiftClassTest.java @@ -14,14 +14,11 @@ package org.swift.swiftkit; -import com.example.swift.generated.MySwiftClass; +import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.condition.DisabledOnOs; -import org.junit.jupiter.api.condition.OS; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; +import com.example.swift.generated.MySwiftClass; public class MySwiftClassTest { diff --git a/Sources/ExampleSwiftLibrary/MySwiftLibrary.swift b/Sources/ExampleSwiftLibrary/MySwiftLibrary.swift index 146601d0..b5c8f5fd 100644 --- a/Sources/ExampleSwiftLibrary/MySwiftLibrary.swift +++ b/Sources/ExampleSwiftLibrary/MySwiftLibrary.swift @@ -78,6 +78,10 @@ public class MySwiftClass { p("make int -> 12") return 12 } + + public func makeRandomIntMethod() -> Int { + return Int.random(in: 1..<256) + } } @_silgen_name("swift_getTypeByMangledNameInEnvironment") From a96d07761042e99d8f44a13f4446fc8928ab8f2e Mon Sep 17 00:00:00 2001 From: helmetcrest Date: Wed, 30 Oct 2024 03:47:35 +0000 Subject: [PATCH 143/426] Fix build error --- .../JavaApiCallBenchmarks.swift | 0 Benchmarks/Package.swift | 69 +++++++++++++++++++ Package.swift | 20 +----- Samples/SwiftKitSampleApp/build.gradle | 4 +- docker/Dockerfile | 4 +- 5 files changed, 75 insertions(+), 22 deletions(-) rename Benchmarks/{ => Benchmarks}/JavaApiCallBenchmarks/JavaApiCallBenchmarks.swift (100%) create mode 100644 Benchmarks/Package.swift diff --git a/Benchmarks/JavaApiCallBenchmarks/JavaApiCallBenchmarks.swift b/Benchmarks/Benchmarks/JavaApiCallBenchmarks/JavaApiCallBenchmarks.swift similarity index 100% rename from Benchmarks/JavaApiCallBenchmarks/JavaApiCallBenchmarks.swift rename to Benchmarks/Benchmarks/JavaApiCallBenchmarks/JavaApiCallBenchmarks.swift diff --git a/Benchmarks/Package.swift b/Benchmarks/Package.swift new file mode 100644 index 00000000..b8fbe580 --- /dev/null +++ b/Benchmarks/Package.swift @@ -0,0 +1,69 @@ +// swift-tools-version: 6.0 + +import PackageDescription + +import class Foundation.FileManager +import class Foundation.ProcessInfo + +// Note: the JAVA_HOME environment variable must be set to point to where +// Java is installed, e.g., +// Library/Java/JavaVirtualMachines/openjdk-21.jdk/Contents/Home. +func findJavaHome() -> String { + if let home = ProcessInfo.processInfo.environment["JAVA_HOME"] { + return home + } + + // This is a workaround for envs (some IDEs) which have trouble with + // picking up env variables during the build process + let path = "\(FileManager.default.homeDirectoryForCurrentUser.path()).java_home" + if let home = try? String(contentsOfFile: path, encoding: .utf8) { + if let lastChar = home.last, lastChar.isNewline { + return String(home.dropLast()) + } + + return home + } + + fatalError("Please set the JAVA_HOME environment variable to point to where Java is installed.") +} +let javaHome = findJavaHome() + +let javaIncludePath = "\(javaHome)/include" +#if os(Linux) + let javaPlatformIncludePath = "\(javaIncludePath)/linux" +#elseif os(macOS) + let javaPlatformIncludePath = "\(javaIncludePath)/darwin" +#else + // TODO: Handle windows as well + #error("Currently only macOS and Linux platforms are supported, this may change in the future.") +#endif + +let package = Package( + name: "benchmarks", + platforms: [ + .macOS("15.03") + ], + dependencies: [ + .package(path: "../"), + .package(url: "https://github.com/ordo-one/package-benchmark", .upToNextMajor(from: "1.4.0")), + ], + targets: [ + .executableTarget( + name: "JavaApiCallBenchmarks", + dependencies: [ + .product(name: "JavaRuntime", package: "swift-java"), + .product(name: "JavaKit", package: "swift-java"), + .product(name: "JavaKitNetwork", package: "swift-java"), + .product(name: "Benchmark", package: "package-benchmark"), + ], + path: "Benchmarks/JavaApiCallBenchmarks", + swiftSettings: [ + .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]), + .swiftLanguageMode(.v5), + ], + plugins: [ + .plugin(name: "BenchmarkPlugin", package: "package-benchmark") + ] + ) + ] +) diff --git a/Package.swift b/Package.swift index d4078695..ac1d6842 100644 --- a/Package.swift +++ b/Package.swift @@ -374,24 +374,6 @@ let package = Package( .swiftLanguageMode(.v5), .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) ] - ), - - .executableTarget( - name: "JavaApiCallBenchmarks", - dependencies: [ - "JavaRuntime", - "JavaKit", - "JavaKitNetwork", - .product(name: "Benchmark", package: "package-benchmark"), - ], - path: "Benchmarks/JavaApiCallBenchmarks", - swiftSettings: [ - .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]), - .swiftLanguageMode(.v5), - ], - plugins: [ - .plugin(name: "BenchmarkPlugin", package: "package-benchmark") - ], - ), + ) ] ) diff --git a/Samples/SwiftKitSampleApp/build.gradle b/Samples/SwiftKitSampleApp/build.gradle index 7522d182..3b79bd72 100644 --- a/Samples/SwiftKitSampleApp/build.gradle +++ b/Samples/SwiftKitSampleApp/build.gradle @@ -16,7 +16,7 @@ import org.swift.swiftkit.gradle.BuildUtils plugins { id("build-logic.java-application-conventions") - id "me.champeau.jmh" version "0.7.2" + id("me.champeau.jmh") version "0.7.2" } group = "org.swift.swiftkit" @@ -91,4 +91,4 @@ jmh { jvmArgsAppend = [ "-Djava.library.path=" + BuildUtils.javaLibraryPaths(rootDir).join(":"), ] -} \ No newline at end of file +} diff --git a/docker/Dockerfile b/docker/Dockerfile index 0660f117..c4711253 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -11,7 +11,9 @@ RUN apt-get update && apt-get install -y \ locales locales-all \ make \ libc6-dev \ - curl + curl \ + libjemalloc2 \ + libjemalloc-dev ENV LC_ALL=en_US.UTF-8 ENV LANG=en_US.UTF-8 ENV LANGUAGE=en_US.UTF-8 From a6780be52edb7903c38b6bec6223611d5b6700e9 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Wed, 30 Oct 2024 12:10:58 -0700 Subject: [PATCH 144/426] JavaKit: Macro and translator support for mapping Java classes to Swift classes Java classes are currently translated in Swift structs, and we use is/as functions to cast up and down the hierarchy. Start down an alternative path where we translate Java classes into Swift classes, making proper use of inheritance in Swift to reflect inheritance in Java. This step updates the @JavaClass macro implementation to check whether it is being applied to a class (rather than a struct) and adjust its behavior accordingly: * The superclass is extracted from the inheritance clause of the class rather than the "extends" argument to the macro. * The "full Java class name" static member becomes a "class" member. For everything other than JavaObject itself, it is an override. * The `javaHolder` property is only emitted into JavaObject, nowhere else. * The `init(javaHolder:)` initializer becomes required. For everything other than JavaObject, it's implemented as a super.init call. * The `JavaSuperclass` typealias is no longer emitted. All of this is keyed off the subject of the attribute being a "class" rather than a "struct", so we keep the existing struct versions working. Relatedly, extend the translator with an option to map Java classes to Swift classes. This involves a number of changes: * Emitting each as an "open class" rather than "public struct" * Emitting the superclass into the inheritance clause rather than the "extends" argument * Emitting methods as "open" rather than "public" * Only emit methods and fields declared in the class, not inherited ones This option is only currently only enabled in test cases while we stage in this functionality. --- .../Java2SwiftLib/JavaClassTranslator.swift | 21 ++- Sources/Java2SwiftLib/JavaTranslator.swift | 8 ++ Sources/JavaKit/JavaObject+MethodCalls.swift | 18 ++- Sources/JavaKitMacros/GenerationMode.swift | 2 + Sources/JavaKitMacros/JavaClassMacro.swift | 116 +++++++++++---- ...Plugin.swift => JavaKitMacrosPlugin.swift} | 0 Sources/JavaKitMacros/JavaMethodMacro.swift | 14 +- Tests/Java2SwiftTests/Java2SwiftTests.swift | 31 +++- .../JavaClassMacroTests.swift | 136 ++++++++++++++++++ 9 files changed, 304 insertions(+), 42 deletions(-) rename Sources/JavaKitMacros/{SwiftJNIMacrosPlugin.swift => JavaKitMacrosPlugin.swift} (100%) diff --git a/Sources/Java2SwiftLib/JavaClassTranslator.swift b/Sources/Java2SwiftLib/JavaClassTranslator.swift index 1df6d683..3e12c76b 100644 --- a/Sources/Java2SwiftLib/JavaClassTranslator.swift +++ b/Sources/Java2SwiftLib/JavaClassTranslator.swift @@ -161,9 +161,15 @@ struct JavaClassTranslator { } // Gather methods. - for method in javaClass.getMethods() { + let methods = translator.translateAsClass + ? javaClass.getDeclaredMethods() + : javaClass.getMethods() + for method in methods { guard let method else { continue } + // Only look at public methods here. + guard method.isPublic else { continue } + // Skip any methods that are expected to be implemented in Swift. We will // visit them in the second pass, over the *declared* methods, because // we want to see non-public methods as well. @@ -178,6 +184,7 @@ struct JavaClassTranslator { } if translator.swiftNativeImplementations.contains(javaClass.getName()) { + // Gather the native methods we're going to implement. for method in javaClass.getDeclaredMethods() { guard let method else { continue } @@ -209,6 +216,12 @@ extension JavaClassTranslator { return } + // Don't include inherited fields when translating to a class. + if translator.translateAsClass && + !field.getDeclaringClass()!.equals(javaClass.as(JavaObject.self)!) { + return + } + fields.append(field) } @@ -297,10 +310,11 @@ extension JavaClassTranslator { // Emit the struct declaration describing the java class. let classOrInterface: String = isInterface ? "JavaInterface" : "JavaClass"; + let introducer = translator.translateAsClass ? "open class" : "public struct" var classDecl: DeclSyntax = """ @\(raw: classOrInterface)(\(literal: javaClass.getName())\(raw: extends)\(raw: interfacesStr)) - public struct \(raw: swiftInnermostTypeName)\(raw: genericParameterClause) { + \(raw: introducer) \(raw: swiftInnermostTypeName)\(raw: genericParameterClause) { \(raw: members.map { $0.description }.joined(separator: "\n\n")) } """ @@ -483,7 +497,8 @@ extension JavaClassTranslator { let methodAttribute: AttributeSyntax = implementedInSwift ? "" : javaMethod.isStatic ? "@JavaStaticMethod\n" : "@JavaMethod\n"; - let accessModifier = implementedInSwift ? "" : "public " + let accessModifier = implementedInSwift ? "" + : "\(translator.defaultAccessSpecifier) " return """ \(methodAttribute)\(raw: accessModifier)func \(raw: swiftMethodName)\(raw: genericParameterClause)(\(raw: parametersStr))\(raw: throwsStr)\(raw: resultTypeStr)\(raw: whereClause) """ diff --git a/Sources/Java2SwiftLib/JavaTranslator.swift b/Sources/Java2SwiftLib/JavaTranslator.swift index 5889a193..c207edb3 100644 --- a/Sources/Java2SwiftLib/JavaTranslator.swift +++ b/Sources/Java2SwiftLib/JavaTranslator.swift @@ -26,6 +26,7 @@ package class JavaTranslator { let swiftModuleName: String let environment: JNIEnvironment + let translateAsClass: Bool let format: BasicFormat /// A mapping from the name of each known Java class to the corresponding @@ -61,10 +62,12 @@ package class JavaTranslator { package init( swiftModuleName: String, environment: JNIEnvironment, + translateAsClass: Bool = false, format: BasicFormat = JavaTranslator.defaultFormat ) { self.swiftModuleName = swiftModuleName self.environment = environment + self.translateAsClass = translateAsClass self.format = format } @@ -247,6 +250,11 @@ extension JavaTranslator { throw TranslationError.untranslatedJavaClass(name) } + + /// The default Swift access specifier for a Java method. + var defaultAccessSpecifier: String { + translateAsClass ? "open" : "public" + } } // MARK: Class translation diff --git a/Sources/JavaKit/JavaObject+MethodCalls.swift b/Sources/JavaKit/JavaObject+MethodCalls.swift index 0a48b8bd..453358ce 100644 --- a/Sources/JavaKit/JavaObject+MethodCalls.swift +++ b/Sources/JavaKit/JavaObject+MethodCalls.swift @@ -237,12 +237,22 @@ extension AnyJavaObject { ) } - /// Call a Java method with the given name and arguments, which must be of the correct - /// type, that produces the given result type. + /// Construct a new Java object with the given name and arguments and return + /// the result Java instance. public static func dynamicJavaNewObject( in environment: JNIEnvironment, arguments: repeat each Param ) throws -> Self { + let this = try dynamicJavaNewObjectInstance(in: environment, arguments: repeat each arguments) + return Self(javaThis: this, environment: environment) + } + + /// Construct a new Java object with the given name and arguments and return + /// the result Java instance. + public static func dynamicJavaNewObjectInstance( + in environment: JNIEnvironment, + arguments: repeat each Param + ) throws -> jobject { let thisClass = try Self.getJNIClass(in: environment) // Compute the method signature so we can find the right method, then look up the @@ -257,11 +267,9 @@ extension AnyJavaObject { // Retrieve the constructor, then map the arguments and call it. let jniArgs = getJValues(repeat each arguments, in: environment) - let this = try environment.translatingJNIExceptions { + return try environment.translatingJNIExceptions { environment.interface.NewObjectA!(environment, thisClass, methodID, jniArgs) }! - - return Self(javaThis: this, environment: environment) } /// Retrieve the JNI field ID for a field with the given name and type. diff --git a/Sources/JavaKitMacros/GenerationMode.swift b/Sources/JavaKitMacros/GenerationMode.swift index d000d209..2bf9fc4f 100644 --- a/Sources/JavaKitMacros/GenerationMode.swift +++ b/Sources/JavaKitMacros/GenerationMode.swift @@ -54,6 +54,8 @@ enum GenerationMode { let attributes: AttributeListSyntax if let structSyntax = lexicalContext.as(StructDeclSyntax.self) { attributes = structSyntax.attributes + } else if let classSyntax = lexicalContext.as(ClassDeclSyntax.self) { + attributes = classSyntax.attributes } else if let extSyntax = lexicalContext.as(ExtensionDeclSyntax.self) { attributes = extSyntax.attributes } else { diff --git a/Sources/JavaKitMacros/JavaClassMacro.swift b/Sources/JavaKitMacros/JavaClassMacro.swift index 5a6e25cb..f88d12e4 100644 --- a/Sources/JavaKitMacros/JavaClassMacro.swift +++ b/Sources/JavaKitMacros/JavaClassMacro.swift @@ -26,6 +26,11 @@ extension JavaClassMacro: MemberMacro { conformingTo protocols: [TypeSyntax], in context: some MacroExpansionContext ) throws -> [DeclSyntax] { + guard let namedDecl = declaration.asProtocol(NamedDeclSyntax.self) else { + throw MacroErrors.javaClassNotOnType + } + let swiftName = namedDecl.name.text + // Dig out the Java class name. guard case .argumentList(let arguments) = node.arguments, let wrapperTypeNameExpr = arguments.first?.expression, @@ -36,59 +41,99 @@ extension JavaClassMacro: MemberMacro { throw MacroErrors.classNameNotStringLiteral } - // Dig out the "superclass" clause, if there is one. - let superclass: String - if let superclassArg = arguments.dropFirst().first, - let superclassArgLabel = superclassArg.label, - superclassArgLabel.text == "extends", - let superclassMemberAccess = superclassArg.expression.as(MemberAccessExprSyntax.self), - superclassMemberAccess.declName.trimmedDescription == "self", - let superclassMemberBase = superclassMemberAccess.base - { - superclass = superclassMemberBase.trimmedDescription + // Determine whether we're exposing the Java class as a Swift class, which + // changes how we generate some of the members. + let isSwiftClass: Bool + let isJavaLangObject: Bool + let specifiedSuperclass: String? + if let classDecl = declaration.as(ClassDeclSyntax.self) { + isSwiftClass = true + isJavaLangObject = classDecl.isJavaLangObject + + // Retrieve the superclass, if there is one. + specifiedSuperclass = classDecl.inheritanceClause?.inheritedTypes.first?.trimmedDescription } else { - superclass = "JavaObject" + isSwiftClass = false + isJavaLangObject = false + + // Dig out the "extends" argument from the attribute. + if let superclassArg = arguments.dropFirst().first, + let superclassArgLabel = superclassArg.label, + superclassArgLabel.text == "extends", + let superclassMemberAccess = superclassArg.expression.as(MemberAccessExprSyntax.self), + superclassMemberAccess.declName.trimmedDescription == "self", + let superclassMemberBase = superclassMemberAccess.base + { + specifiedSuperclass = superclassMemberBase.trimmedDescription + } else { + specifiedSuperclass = nil + } } + let superclass = specifiedSuperclass ?? "JavaObject" + // Check that the class name is fully-qualified, as it should be. let className = classNameSegment.content.text if className.firstIndex(of: ".") == nil { throw MacroErrors.classNameNotFullyQualified(className) } - let fullJavaClassNameMember: DeclSyntax = """ + var members: [DeclSyntax] = [] + + // Determine the modifiers to use for the fullJavaClassName member. + let fullJavaClassNameMemberModifiers: String + switch (isSwiftClass, isJavaLangObject) { + case (false, _): + fullJavaClassNameMemberModifiers = "static" + case (true, false): + fullJavaClassNameMemberModifiers = "override class" + case (true, true): + fullJavaClassNameMemberModifiers = "class" + } + + members.append(""" /// The full Java class name for this Swift type. - public static var fullJavaClassName: String { \(literal: className) } + public \(raw: fullJavaClassNameMemberModifiers) var fullJavaClassName: String { \(literal: className) } """ + ) - let superclassTypealias: DeclSyntax = """ - public typealias JavaSuperclass = \(raw: superclass) - """ + // struct wrappers need a JavaSuperclass type. + if !isSwiftClass { + members.append(""" + public typealias JavaSuperclass = \(raw: superclass) + """ + ) + } - let javaHolderMember: DeclSyntax = """ - public var javaHolder: JavaObjectHolder - """ + // If this is for a struct or is the root java.lang.Object class, we need + // a javaHolder instance property. + if !isSwiftClass || isJavaLangObject { + members.append(""" + public var javaHolder: JavaObjectHolder + """ + ) + } - let initMember: DeclSyntax = """ - public init(javaHolder: JavaObjectHolder) { - self.javaHolder = javaHolder + let requiredModifierOpt = isSwiftClass ? "required " : "" + let initBody: CodeBlockItemSyntax = isSwiftClass && !isJavaLangObject + ? "super.init(javaHolder: javaHolder)" + : "self.javaHolder = javaHolder" + members.append(""" + public \(raw: requiredModifierOpt)init(javaHolder: JavaObjectHolder) { + \(initBody) } """ + ) - let nonOptionalAs: DeclSyntax = """ - /// Casting to ``\(raw: superclass)`` will never be nil because ``\(raw: className.split(separator: ".").last!)`` extends it. + members.append(""" + /// Casting to ``\(raw: superclass)`` will never be nil because ``\(raw: swiftName)`` extends it. public func `as`(_: \(raw: superclass).Type) -> \(raw: superclass) { return \(raw: superclass)(javaHolder: javaHolder) } """ + ) - return [ - fullJavaClassNameMember, - superclassTypealias, - javaHolderMember, - initMember, - nonOptionalAs, - ] + return members } } @@ -112,3 +157,12 @@ extension JavaClassMacro: ExtensionMacro { return [AnyJavaObjectConformance.as(ExtensionDeclSyntax.self)!] } } + +extension ClassDeclSyntax { + /// Whether this class describes java.lang.Object + var isJavaLangObject: Bool { + // FIXME: This is somewhat of a hack; we could look for + // @JavaClass("java.lang.Object") instead. + return name.text == "JavaObject" + } +} diff --git a/Sources/JavaKitMacros/SwiftJNIMacrosPlugin.swift b/Sources/JavaKitMacros/JavaKitMacrosPlugin.swift similarity index 100% rename from Sources/JavaKitMacros/SwiftJNIMacrosPlugin.swift rename to Sources/JavaKitMacros/JavaKitMacrosPlugin.swift diff --git a/Sources/JavaKitMacros/JavaMethodMacro.swift b/Sources/JavaKitMacros/JavaMethodMacro.swift index 0a4be1f0..db8a3b36 100644 --- a/Sources/JavaKitMacros/JavaMethodMacro.swift +++ b/Sources/JavaKitMacros/JavaMethodMacro.swift @@ -108,6 +108,17 @@ extension JavaMethodMacro: BodyMacro { initDecl.signature.effectSpecifiers?.throwsClause != nil ? "try" : "try!" + let objectCreation: [CodeBlockItemSyntax] + if context.lexicalContext.first?.is(ClassDeclSyntax.self) ?? false { + objectCreation = [ + "let javaThis = \(raw: tryKeyword) Self.dynamicJavaNewObjectInstance(in: _environment\(raw: arguments))\n", + "self.init(javaThis: javaThis, environment: _environment)\n", + ] + } else { + objectCreation = [ + "self = \(raw: tryKeyword) Self.dynamicJavaNewObject(in: _environment\(raw: arguments))\n" + ] + } return [ """ let _environment = if let environment { @@ -115,9 +126,8 @@ extension JavaMethodMacro: BodyMacro { } else { \(raw: tryKeyword) JavaVirtualMachine.shared().environment() } - self = \(raw: tryKeyword) Self.dynamicJavaNewObject(in: _environment\(raw: arguments)) """ - ] + ] + objectCreation } } diff --git a/Tests/Java2SwiftTests/Java2SwiftTests.swift b/Tests/Java2SwiftTests/Java2SwiftTests.swift index 80c86fc0..2d358104 100644 --- a/Tests/Java2SwiftTests/Java2SwiftTests.swift +++ b/Tests/Java2SwiftTests/Java2SwiftTests.swift @@ -266,6 +266,33 @@ class Java2SwiftTests: XCTestCase { ] ) } + + func testJavaLangObjectMappingAsClass() throws { + try assertTranslatedClass( + JavaObject.self, + swiftTypeName: "JavaObject", + asClass: true, + expectedChunks: [ + "import JavaKit", + """ + @JavaClass("java.lang.Object") + open class JavaObject { + """, + """ + @JavaMethod + public init(environment: JNIEnvironment? = nil) + """, + """ + @JavaMethod + open func toString() -> String + """, + """ + @JavaMethod + open func wait() throws + """ + ] + ) + } } @JavaClass("java.util.ArrayList") @@ -295,6 +322,7 @@ public struct MyJavaIntFunction { func assertTranslatedClass( _ javaType: JavaClassType.Type, swiftTypeName: String, + asClass: Bool = false, translatedClasses: [ String: (swiftType: String, swiftModule: String?) ] = [:], @@ -306,7 +334,8 @@ func assertTranslatedClass( let environment = try jvm.environment() let translator = JavaTranslator( swiftModuleName: "SwiftModule", - environment: environment + environment: environment, + translateAsClass: asClass ) translator.translatedClasses = translatedClasses diff --git a/Tests/JavaKitMacroTests/JavaClassMacroTests.swift b/Tests/JavaKitMacroTests/JavaClassMacroTests.swift index e83356c0..5a85c729 100644 --- a/Tests/JavaKitMacroTests/JavaClassMacroTests.swift +++ b/Tests/JavaKitMacroTests/JavaClassMacroTests.swift @@ -115,5 +115,141 @@ class JavaKitMacroTests: XCTestCase { macros: Self.javaKitMacros ) } + + func testJavaClassAsClass() throws { + assertMacroExpansion(""" + @JavaClass("org.swift.example.HelloWorld") + public class HelloWorld: OtherJavaType { + @JavaMethod + public init(environment: JNIEnvironment? = nil) + + @JavaMethod + public init(_ value: Int32, environment: JNIEnvironment? = nil) + + @JavaMethod + public func isBigEnough(_: Int32) -> Bool + + @JavaField + public var myField: Int64 + + @JavaField + public var objectField: JavaObject! + + @JavaField(isFinal: true) + public var myFinalField: Int64 + } + """, + expandedSource: """ + + public class HelloWorld: OtherJavaType { + public init(environment: JNIEnvironment? = nil) { + let _environment = if let environment { + environment + } else { + try! JavaVirtualMachine.shared().environment() + } + let javaThis = try! Self.dynamicJavaNewObjectInstance(in: _environment) + self.init(javaThis: javaThis, environment: _environment) + } + public init(_ value: Int32, environment: JNIEnvironment? = nil) { + let _environment = if let environment { + environment + } else { + try! JavaVirtualMachine.shared().environment() + } + let javaThis = try! Self.dynamicJavaNewObjectInstance(in: _environment, arguments: value.self) + self.init(javaThis: javaThis, environment: _environment) + } + public func isBigEnough(_: Int32) -> Bool { + return try! dynamicJavaMethodCall(methodName: "isBigEnough", resultType: Bool.self) + } + public var myField: Int64 { + get { + self[javaFieldName: "myField", fieldType: Int64.self] + } + nonmutating set { + self[javaFieldName: "myField", fieldType: Int64.self] = newValue + } + } + public var objectField: JavaObject! { + get { + self[javaFieldName: "objectField", fieldType: JavaObject?.self] + } + nonmutating set { + self[javaFieldName: "objectField", fieldType: JavaObject?.self] = newValue + } + } + public var myFinalField: Int64 { + get { + self[javaFieldName: "myFinalField", fieldType: Int64.self] + } + } + + /// The full Java class name for this Swift type. + public override class var fullJavaClassName: String { + "org.swift.example.HelloWorld" + } + + public required init(javaHolder: JavaObjectHolder) { + super.init(javaHolder: javaHolder) + } + + /// Casting to ``OtherJavaType`` will never be nil because ``HelloWorld`` extends it. + public func `as`(_: OtherJavaType.Type) -> OtherJavaType { + return OtherJavaType(javaHolder: javaHolder) + } + } + """, + macros: Self.javaKitMacros + ) + } + + func testJavaObjectAsClass() throws { + assertMacroExpansion(""" + @JavaClass("java.lang.Object") + public class JavaObject { + @JavaMethod + public init(environment: JNIEnvironment? = nil) + + @JavaMethod + public func isBigEnough(_: Int32) -> Bool + } + """, + expandedSource: """ + + public class JavaObject { + public init(environment: JNIEnvironment? = nil) { + let _environment = if let environment { + environment + } else { + try! JavaVirtualMachine.shared().environment() + } + let javaThis = try! Self.dynamicJavaNewObjectInstance(in: _environment) + self.init(javaThis: javaThis, environment: _environment) + } + public func isBigEnough(_: Int32) -> Bool { + return try! dynamicJavaMethodCall(methodName: "isBigEnough", resultType: Bool.self) + } + + /// The full Java class name for this Swift type. + public class var fullJavaClassName: String { + "java.lang.Object" + } + + public var javaHolder: JavaObjectHolder + + public required init(javaHolder: JavaObjectHolder) { + self.javaHolder = javaHolder + } + + /// Casting to ``JavaObject`` will never be nil because ``JavaObject`` extends it. + public func `as`(_: JavaObject.Type) -> JavaObject { + return JavaObject(javaHolder: javaHolder) + } + } + """, + macros: Self.javaKitMacros + ) + } } From 6440a3c29d302e9a9f0dffa432e27f62b8854843 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Wed, 30 Oct 2024 15:55:42 -0700 Subject: [PATCH 145/426] Java2Swift: Mark instance methods as "override" when needed --- .../Java2SwiftLib/JavaClassTranslator.swift | 40 +++++++++++++++++-- .../JavaClass+Reflection.swift | 8 +++- Tests/Java2SwiftTests/Java2SwiftTests.swift | 34 ++++++++++++++++ 3 files changed, 77 insertions(+), 5 deletions(-) diff --git a/Sources/Java2SwiftLib/JavaClassTranslator.swift b/Sources/Java2SwiftLib/JavaClassTranslator.swift index 3e12c76b..332c2ed4 100644 --- a/Sources/Java2SwiftLib/JavaClassTranslator.swift +++ b/Sources/Java2SwiftLib/JavaClassTranslator.swift @@ -296,8 +296,18 @@ extension JavaClassTranslator { // Collect all of the members of this type. let members = properties + enumDecls + initializers + instanceMethods - // Compute the "extends" clause for the superclass. - let extends = swiftSuperclass.map { ", extends: \($0).self" } ?? "" + // Compute the "extends" clause for the superclass (of the struct + // formulation) or the inheritance clause (for the class + // formulation). + let extends: String + let inheritanceClause: String + if translator.translateAsClass { + extends = "" + inheritanceClause = swiftSuperclass.map { ": \($0)" } ?? "" + } else { + extends = swiftSuperclass.map { ", extends: \($0).self" } ?? "" + inheritanceClause = "" + } // Compute the string to capture all of the interfaces. let interfacesStr: String @@ -314,7 +324,7 @@ extension JavaClassTranslator { var classDecl: DeclSyntax = """ @\(raw: classOrInterface)(\(literal: javaClass.getName())\(raw: extends)\(raw: interfacesStr)) - \(raw: introducer) \(raw: swiftInnermostTypeName)\(raw: genericParameterClause) { + \(raw: introducer) \(raw: swiftInnermostTypeName)\(raw: genericParameterClause)\(raw: inheritanceClause) { \(raw: members.map { $0.description }.joined(separator: "\n\n")) } """ @@ -499,8 +509,12 @@ extension JavaClassTranslator { : javaMethod.isStatic ? "@JavaStaticMethod\n" : "@JavaMethod\n"; let accessModifier = implementedInSwift ? "" : "\(translator.defaultAccessSpecifier) " + let overrideOpt = (translator.translateAsClass && + !javaMethod.isStatic && isOverride(javaMethod)) + ? "override " + : "" return """ - \(methodAttribute)\(raw: accessModifier)func \(raw: swiftMethodName)\(raw: genericParameterClause)(\(raw: parametersStr))\(raw: throwsStr)\(raw: resultTypeStr)\(raw: whereClause) + \(methodAttribute)\(raw: accessModifier)\(raw: overrideOpt)func \(raw: swiftMethodName)\(raw: genericParameterClause)(\(raw: parametersStr))\(raw: throwsStr)\(raw: resultTypeStr)\(raw: whereClause) """ } @@ -626,3 +640,21 @@ struct MethodCollector { methods.append(method) } } + +// MARK: Utility functions +extension JavaClassTranslator { + /// Determine whether this method is an override of another Java + /// method. + func isOverride(_ method: Method) -> Bool { + guard let javaSuperclass = javaClass.getSuperclass() else { + return false + } + + do { + let overriddenMethod = try javaSuperclass.getDeclaredMethod(method.getName(), method.getParameterTypes()) + return overriddenMethod != nil + } catch { + return false + } + } +} diff --git a/Sources/JavaKitReflection/JavaClass+Reflection.swift b/Sources/JavaKitReflection/JavaClass+Reflection.swift index 569b72e8..e5505144 100644 --- a/Sources/JavaKitReflection/JavaClass+Reflection.swift +++ b/Sources/JavaKitReflection/JavaClass+Reflection.swift @@ -22,7 +22,13 @@ extension JavaClass { @JavaMethod public func getMethods() -> [Method?] - + + @JavaMethod + public func getDeclaredMethod( + _ name: String, + _ parameterTypes: [JavaClass?] + ) throws -> Method? + @JavaMethod public func getFields() -> [Field?] diff --git a/Tests/Java2SwiftTests/Java2SwiftTests.swift b/Tests/Java2SwiftTests/Java2SwiftTests.swift index 2d358104..a58ec289 100644 --- a/Tests/Java2SwiftTests/Java2SwiftTests.swift +++ b/Tests/Java2SwiftTests/Java2SwiftTests.swift @@ -293,6 +293,40 @@ class Java2SwiftTests: XCTestCase { ] ) } + + func testJavaLangStringMappingAsClass() throws { + try assertTranslatedClass( + JavaString.self, + swiftTypeName: "JavaString", + asClass: true, + translatedClasses: [ + "java.lang.Object" : ("JavaObject", "JavaKit"), + ], + expectedChunks: [ + "import JavaKit", + """ + @JavaClass("java.lang.String") + open class JavaString: JavaObject { + """, + """ + @JavaMethod + public init(environment: JNIEnvironment? = nil) + """, + """ + @JavaMethod + open override func toString() -> String + """, + """ + @JavaMethod + open override func equals(_ arg0: JavaObject?) -> Bool + """, + """ + @JavaMethod + open func intern() -> String + """ + ] + ) + } } @JavaClass("java.util.ArrayList") From 83b0e1a1a789c3bf760f19e6b93f7f15988812bd Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Wed, 30 Oct 2024 16:19:09 -0700 Subject: [PATCH 146/426] Java2Swift: Always use the nearest imported superclass for the superclass When we import a class from Java into Swift, we check whether its superclass was also imported before generating a reference to that superclass. If it isn't there, we fell back to JavaObject. That's too conservative, because there might be a superclass in between that we could use. Instead, walk up the superclass chain until we find the most-specific superclass that *is* mapped into Swift, and use that as the generated superclass. Additionally, use this as the basis for determining when we need the "override" keyword when in the class-generating mode. --- .../Java2SwiftLib/JavaClassTranslator.swift | 28 ++++++-- Tests/Java2SwiftTests/Java2SwiftTests.swift | 71 +++++++++++++++++++ 2 files changed, 92 insertions(+), 7 deletions(-) diff --git a/Sources/Java2SwiftLib/JavaClassTranslator.swift b/Sources/Java2SwiftLib/JavaClassTranslator.swift index 332c2ed4..a86fa1f2 100644 --- a/Sources/Java2SwiftLib/JavaClassTranslator.swift +++ b/Sources/Java2SwiftLib/JavaClassTranslator.swift @@ -37,6 +37,10 @@ struct JavaClassTranslator { /// class. let swiftTypeName: String + /// The effective Java superclass object, which is the nearest + /// superclass that has been mapped into Swift. + let effectiveJavaSuperclass: JavaClass? + /// The Swift name of the superclass. let swiftSuperclass: String? @@ -114,14 +118,24 @@ struct JavaClassTranslator { self.nestedClasses = translator.nestedClasses[fullName] ?? [] // Superclass. - if !javaClass.isInterface(), let javaSuperclass = javaClass.getSuperclass() { - do { - self.swiftSuperclass = try translator.getSwiftTypeName(javaSuperclass, preferValueTypes: false).swiftName - } catch { - translator.logUntranslated("Unable to translate '\(fullName)' superclass: \(error)") - self.swiftSuperclass = nil + if !javaClass.isInterface() { + var javaSuperclass = javaClass.getSuperclass() + var swiftSuperclass: String? = nil + while let javaSuperclassNonOpt = javaSuperclass { + do { + swiftSuperclass = try translator.getSwiftTypeName(javaSuperclassNonOpt, preferValueTypes: false).swiftName + break + } catch { + translator.logUntranslated("Unable to translate '\(fullName)' superclass: \(error)") + } + + javaSuperclass = javaSuperclassNonOpt.getSuperclass() } + + self.effectiveJavaSuperclass = javaSuperclass + self.swiftSuperclass = swiftSuperclass } else { + self.effectiveJavaSuperclass = nil self.swiftSuperclass = nil } @@ -646,7 +660,7 @@ extension JavaClassTranslator { /// Determine whether this method is an override of another Java /// method. func isOverride(_ method: Method) -> Bool { - guard let javaSuperclass = javaClass.getSuperclass() else { + guard let javaSuperclass = effectiveJavaSuperclass else { return false } diff --git a/Tests/Java2SwiftTests/Java2SwiftTests.swift b/Tests/Java2SwiftTests/Java2SwiftTests.swift index a58ec289..a8007fe7 100644 --- a/Tests/Java2SwiftTests/Java2SwiftTests.swift +++ b/Tests/Java2SwiftTests/Java2SwiftTests.swift @@ -327,8 +327,79 @@ class Java2SwiftTests: XCTestCase { ] ) } + + func testURLLoaderSkipMappingAsClass() throws { + // URLClassLoader actually inherits from SecureClassLoader. However, + // that type wasn't mapped into Swift, so we find the nearest + // superclass that was mapped into Swift. + try assertTranslatedClass( + URLClassLoader.self, + swiftTypeName: "URLClassLoader", + asClass: true, + translatedClasses: [ + "java.lang.Object" : ("JavaObject", "JavaKit"), + "java.lang.ClassLoader" : ("ClassLoader", "JavaKit"), + "java.net.URL" : ("URL", "JavaKitNetwork"), + ], + expectedChunks: [ + "import JavaKit", + """ + @JavaClass("java.net.URLClassLoader") + open class URLClassLoader: ClassLoader { + """, + """ + @JavaMethod + open func close() throws + """, + """ + @JavaMethod + open override func findResource(_ arg0: String) -> URL! + """, + ] + ) + } + + func testURLLoaderSkipTwiceMappingAsClass() throws { + // URLClassLoader actually inherits from SecureClassLoader. However, + // that type wasn't mapped into Swift here, nor is ClassLoader, + // so we fall back to JavaObject. + try assertTranslatedClass( + URLClassLoader.self, + swiftTypeName: "URLClassLoader", + asClass: true, + translatedClasses: [ + "java.lang.Object" : ("JavaObject", "JavaKit"), + "java.net.URL" : ("URL", "JavaKitNetwork"), + ], + expectedChunks: [ + "import JavaKit", + """ + @JavaClass("java.net.URLClassLoader") + open class URLClassLoader: JavaObject { + """, + """ + @JavaMethod + open func close() throws + """, + """ + @JavaMethod + open func findResource(_ arg0: String) -> URL! + """, + ] + ) + } } +@JavaClass("java.lang.ClassLoader") +public struct ClassLoader { } + +@JavaClass("java.security.SecureClassLoader") +public struct SecureClassLoader { } + +@JavaClass("java.net.URLClassLoader") +public struct URLClassLoader { } + + @JavaClass("java.util.ArrayList") public struct MyArrayList { } From 819dd275c0d80ebc51fe8a8e12fcae24796a5a85 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Wed, 30 Oct 2024 16:25:30 -0700 Subject: [PATCH 147/426] Java2Swift: Regenerate generated mappings No functionality changes here; we're just more consistent about putting JavaObject in as the extended type. --- Sources/JavaKit/generated/JavaCharacter.swift | 4 ++-- .../JavaKitCollection/generated/ArrayDeque.swift | 2 +- .../JavaKitCollection/generated/ArrayList.swift | 2 +- Sources/JavaKitCollection/generated/HashMap.swift | 2 +- Sources/JavaKitCollection/generated/HashSet.swift | 2 +- .../generated/PriorityQueue.swift | 2 +- Sources/JavaKitCollection/generated/Stack.swift | 2 +- Sources/JavaKitCollection/generated/TreeMap.swift | 2 +- Sources/JavaKitCollection/generated/TreeSet.swift | 2 +- Sources/JavaKitJar/generated/JarEntry.swift | 2 +- Sources/JavaKitJar/generated/JarFile.swift | 2 +- Sources/JavaKitJar/generated/JarInputStream.swift | 14 +++++++------- Sources/JavaKitJar/generated/JarOutputStream.swift | 8 ++++---- .../JavaKitNetwork/generated/URLClassLoader.swift | 2 +- 14 files changed, 24 insertions(+), 24 deletions(-) diff --git a/Sources/JavaKit/generated/JavaCharacter.swift b/Sources/JavaKit/generated/JavaCharacter.swift index 1ebb7625..47ed2744 100644 --- a/Sources/JavaKit/generated/JavaCharacter.swift +++ b/Sources/JavaKit/generated/JavaCharacter.swift @@ -1102,7 +1102,7 @@ extension JavaClass { public func of(_ arg0: UInt16) -> JavaCharacter.UnicodeBlock! } extension JavaCharacter { - @JavaClass("java.lang.Character$UnicodeScript") + @JavaClass("java.lang.Character$UnicodeScript", extends: JavaObject.self) public struct UnicodeScript { public enum UnicodeScriptCases: Equatable { case COMMON @@ -2639,7 +2639,7 @@ extension JavaCharacter { } } extension JavaCharacter.UnicodeScript { - @JavaClass("java.lang.Enum$EnumDesc") + @JavaClass("java.lang.Enum$EnumDesc", extends: JavaObject.self) public struct EnumDesc { @JavaMethod public func toString() -> String diff --git a/Sources/JavaKitCollection/generated/ArrayDeque.swift b/Sources/JavaKitCollection/generated/ArrayDeque.swift index 9c7af8bf..d0a1134a 100644 --- a/Sources/JavaKitCollection/generated/ArrayDeque.swift +++ b/Sources/JavaKitCollection/generated/ArrayDeque.swift @@ -2,7 +2,7 @@ import JavaKit import JavaRuntime -@JavaClass("java.util.ArrayDeque") +@JavaClass("java.util.ArrayDeque", extends: JavaObject.self) public struct ArrayDeque { @JavaMethod public init(_ arg0: Int32, environment: JNIEnvironment? = nil) diff --git a/Sources/JavaKitCollection/generated/ArrayList.swift b/Sources/JavaKitCollection/generated/ArrayList.swift index 0ff6a923..7074b693 100644 --- a/Sources/JavaKitCollection/generated/ArrayList.swift +++ b/Sources/JavaKitCollection/generated/ArrayList.swift @@ -2,7 +2,7 @@ import JavaKit import JavaRuntime -@JavaClass("java.util.ArrayList", implements: List.self, RandomAccess.self) +@JavaClass("java.util.ArrayList", extends: JavaObject.self, implements: List.self, RandomAccess.self) public struct ArrayList { @JavaMethod public init(_ arg0: JavaCollection?, environment: JNIEnvironment? = nil) diff --git a/Sources/JavaKitCollection/generated/HashMap.swift b/Sources/JavaKitCollection/generated/HashMap.swift index 287593f5..9f800c63 100644 --- a/Sources/JavaKitCollection/generated/HashMap.swift +++ b/Sources/JavaKitCollection/generated/HashMap.swift @@ -2,7 +2,7 @@ import JavaKit import JavaRuntime -@JavaClass("java.util.HashMap") +@JavaClass("java.util.HashMap", extends: JavaObject.self) public struct HashMap { @JavaMethod public init(_ arg0: Int32, environment: JNIEnvironment? = nil) diff --git a/Sources/JavaKitCollection/generated/HashSet.swift b/Sources/JavaKitCollection/generated/HashSet.swift index 9ec5b088..ab2da187 100644 --- a/Sources/JavaKitCollection/generated/HashSet.swift +++ b/Sources/JavaKitCollection/generated/HashSet.swift @@ -2,7 +2,7 @@ import JavaKit import JavaRuntime -@JavaClass("java.util.HashSet", implements: JavaSet.self) +@JavaClass("java.util.HashSet", extends: JavaObject.self, implements: JavaSet.self) public struct HashSet { @JavaMethod public init(_ arg0: Int32, environment: JNIEnvironment? = nil) diff --git a/Sources/JavaKitCollection/generated/PriorityQueue.swift b/Sources/JavaKitCollection/generated/PriorityQueue.swift index c3df172d..5704db8a 100644 --- a/Sources/JavaKitCollection/generated/PriorityQueue.swift +++ b/Sources/JavaKitCollection/generated/PriorityQueue.swift @@ -2,7 +2,7 @@ import JavaKit import JavaRuntime -@JavaClass("java.util.PriorityQueue") +@JavaClass("java.util.PriorityQueue", extends: JavaObject.self) public struct PriorityQueue { @JavaMethod public init(_ arg0: PriorityQueue?, environment: JNIEnvironment? = nil) diff --git a/Sources/JavaKitCollection/generated/Stack.swift b/Sources/JavaKitCollection/generated/Stack.swift index a9d0aa5a..e79e7e07 100644 --- a/Sources/JavaKitCollection/generated/Stack.swift +++ b/Sources/JavaKitCollection/generated/Stack.swift @@ -2,7 +2,7 @@ import JavaKit import JavaRuntime -@JavaClass("java.util.Stack") +@JavaClass("java.util.Stack", extends: JavaObject.self) public struct Stack { @JavaMethod public init(environment: JNIEnvironment? = nil) diff --git a/Sources/JavaKitCollection/generated/TreeMap.swift b/Sources/JavaKitCollection/generated/TreeMap.swift index 706d5339..3d7d858a 100644 --- a/Sources/JavaKitCollection/generated/TreeMap.swift +++ b/Sources/JavaKitCollection/generated/TreeMap.swift @@ -2,7 +2,7 @@ import JavaKit import JavaRuntime -@JavaClass("java.util.TreeMap") +@JavaClass("java.util.TreeMap", extends: JavaObject.self) public struct TreeMap { @JavaMethod public init(environment: JNIEnvironment? = nil) diff --git a/Sources/JavaKitCollection/generated/TreeSet.swift b/Sources/JavaKitCollection/generated/TreeSet.swift index 985d6837..e78d6ada 100644 --- a/Sources/JavaKitCollection/generated/TreeSet.swift +++ b/Sources/JavaKitCollection/generated/TreeSet.swift @@ -2,7 +2,7 @@ import JavaKit import JavaRuntime -@JavaClass("java.util.TreeSet") +@JavaClass("java.util.TreeSet", extends: JavaObject.self) public struct TreeSet { @JavaMethod public init(_ arg0: JavaCollection?, environment: JNIEnvironment? = nil) diff --git a/Sources/JavaKitJar/generated/JarEntry.swift b/Sources/JavaKitJar/generated/JarEntry.swift index dd0e30ab..40bbef54 100644 --- a/Sources/JavaKitJar/generated/JarEntry.swift +++ b/Sources/JavaKitJar/generated/JarEntry.swift @@ -2,7 +2,7 @@ import JavaKit import JavaRuntime -@JavaClass("java.util.jar.JarEntry") +@JavaClass("java.util.jar.JarEntry", extends: JavaObject.self) public struct JarEntry { @JavaMethod public init(_ arg0: JarEntry?, environment: JNIEnvironment? = nil) diff --git a/Sources/JavaKitJar/generated/JarFile.swift b/Sources/JavaKitJar/generated/JarFile.swift index 9da57d98..4c215e05 100644 --- a/Sources/JavaKitJar/generated/JarFile.swift +++ b/Sources/JavaKitJar/generated/JarFile.swift @@ -3,7 +3,7 @@ import JavaKit import JavaKitCollection import JavaRuntime -@JavaClass("java.util.jar.JarFile") +@JavaClass("java.util.jar.JarFile", extends: JavaObject.self) public struct JarFile { @JavaMethod public init(_ arg0: String, _ arg1: Bool, environment: JNIEnvironment? = nil) throws diff --git a/Sources/JavaKitJar/generated/JarInputStream.swift b/Sources/JavaKitJar/generated/JarInputStream.swift index de063bb9..c8a25439 100644 --- a/Sources/JavaKitJar/generated/JarInputStream.swift +++ b/Sources/JavaKitJar/generated/JarInputStream.swift @@ -2,8 +2,11 @@ import JavaKit import JavaRuntime -@JavaClass("java.util.jar.JarInputStream") +@JavaClass("java.util.jar.JarInputStream", extends: JavaObject.self) public struct JarInputStream { + @JavaMethod + public func getNextJarEntry() throws -> JarEntry! + @JavaMethod public func read(_ arg0: [Int8], _ arg1: Int32, _ arg2: Int32) throws -> Int32 @@ -11,7 +14,7 @@ public struct JarInputStream { public func getManifest() -> Manifest! @JavaMethod - public func getNextJarEntry() throws -> JarEntry! + public func closeEntry() throws @JavaMethod public func read() throws -> Int32 @@ -23,10 +26,10 @@ public struct JarInputStream { public func readAllBytes() throws -> [Int8] @JavaMethod - public func readNBytes(_ arg0: Int32) throws -> [Int8] + public func readNBytes(_ arg0: [Int8], _ arg1: Int32, _ arg2: Int32) throws -> Int32 @JavaMethod - public func readNBytes(_ arg0: [Int8], _ arg1: Int32, _ arg2: Int32) throws -> Int32 + public func readNBytes(_ arg0: Int32) throws -> [Int8] @JavaMethod public func skip(_ arg0: Int64) throws -> Int64 @@ -37,9 +40,6 @@ public struct JarInputStream { @JavaMethod public func skipNBytes(_ arg0: Int64) throws - @JavaMethod - public func closeEntry() throws - @JavaMethod public func reset() throws diff --git a/Sources/JavaKitJar/generated/JarOutputStream.swift b/Sources/JavaKitJar/generated/JarOutputStream.swift index 542a784f..b10dc4b5 100644 --- a/Sources/JavaKitJar/generated/JarOutputStream.swift +++ b/Sources/JavaKitJar/generated/JarOutputStream.swift @@ -2,8 +2,11 @@ import JavaKit import JavaRuntime -@JavaClass("java.util.jar.JarOutputStream") +@JavaClass("java.util.jar.JarOutputStream", extends: JavaObject.self) public struct JarOutputStream { + @JavaMethod + public func closeEntry() throws + @JavaMethod public func write(_ arg0: [Int8], _ arg1: Int32, _ arg2: Int32) throws @@ -22,9 +25,6 @@ public struct JarOutputStream { @JavaMethod public func setLevel(_ arg0: Int32) - @JavaMethod - public func closeEntry() throws - @JavaMethod public func flush() throws diff --git a/Sources/JavaKitNetwork/generated/URLClassLoader.swift b/Sources/JavaKitNetwork/generated/URLClassLoader.swift index 64b26dda..b8e1f54f 100644 --- a/Sources/JavaKitNetwork/generated/URLClassLoader.swift +++ b/Sources/JavaKitNetwork/generated/URLClassLoader.swift @@ -3,7 +3,7 @@ import JavaKit import JavaKitCollection import JavaRuntime -@JavaClass("java.net.URLClassLoader") +@JavaClass("java.net.URLClassLoader", extends: JavaObject.self) public struct URLClassLoader { @JavaMethod public init(_ arg0: [URL?], environment: JNIEnvironment? = nil) From 2a7d841b92003603d2694ea4e6a55da3ab459f70 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Wed, 30 Oct 2024 16:46:04 -0700 Subject: [PATCH 148/426] Java2Swift: Drop the "as(superclass)" function when generating classes We don't need this function when generating classes, because we'll already get the subtype conversion for free. --- Sources/JavaKitMacros/JavaClassMacro.swift | 16 +++++++++------- .../JavaKitMacroTests/JavaClassMacroTests.swift | 10 ---------- 2 files changed, 9 insertions(+), 17 deletions(-) diff --git a/Sources/JavaKitMacros/JavaClassMacro.swift b/Sources/JavaKitMacros/JavaClassMacro.swift index f88d12e4..eb9417aa 100644 --- a/Sources/JavaKitMacros/JavaClassMacro.swift +++ b/Sources/JavaKitMacros/JavaClassMacro.swift @@ -125,13 +125,15 @@ extension JavaClassMacro: MemberMacro { """ ) - members.append(""" - /// Casting to ``\(raw: superclass)`` will never be nil because ``\(raw: swiftName)`` extends it. - public func `as`(_: \(raw: superclass).Type) -> \(raw: superclass) { - return \(raw: superclass)(javaHolder: javaHolder) - } - """ - ) + if !isSwiftClass { + members.append(""" + /// Casting to ``\(raw: superclass)`` will never be nil because ``\(raw: swiftName)`` extends it. + public func `as`(_: \(raw: superclass).Type) -> \(raw: superclass) { + return \(raw: superclass)(javaHolder: javaHolder) + } + """ + ) + } return members } diff --git a/Tests/JavaKitMacroTests/JavaClassMacroTests.swift b/Tests/JavaKitMacroTests/JavaClassMacroTests.swift index 5a85c729..0d6ac9be 100644 --- a/Tests/JavaKitMacroTests/JavaClassMacroTests.swift +++ b/Tests/JavaKitMacroTests/JavaClassMacroTests.swift @@ -193,11 +193,6 @@ class JavaKitMacroTests: XCTestCase { public required init(javaHolder: JavaObjectHolder) { super.init(javaHolder: javaHolder) } - - /// Casting to ``OtherJavaType`` will never be nil because ``HelloWorld`` extends it. - public func `as`(_: OtherJavaType.Type) -> OtherJavaType { - return OtherJavaType(javaHolder: javaHolder) - } } """, macros: Self.javaKitMacros @@ -241,11 +236,6 @@ class JavaKitMacroTests: XCTestCase { public required init(javaHolder: JavaObjectHolder) { self.javaHolder = javaHolder } - - /// Casting to ``JavaObject`` will never be nil because ``JavaObject`` extends it. - public func `as`(_: JavaObject.Type) -> JavaObject { - return JavaObject(javaHolder: javaHolder) - } } """, macros: Self.javaKitMacros From 4d833cf25f4132ac2f78eb43d6380d7af1dfe470 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Wed, 30 Oct 2024 16:53:54 -0700 Subject: [PATCH 149/426] Java2Swift: all initializers in "class mode" are convenience inits --- Sources/Java2SwiftLib/JavaClassTranslator.swift | 3 ++- Tests/Java2SwiftTests/Java2SwiftTests.swift | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Sources/Java2SwiftLib/JavaClassTranslator.swift b/Sources/Java2SwiftLib/JavaClassTranslator.swift index a86fa1f2..b05f67e6 100644 --- a/Sources/Java2SwiftLib/JavaClassTranslator.swift +++ b/Sources/Java2SwiftLib/JavaClassTranslator.swift @@ -485,9 +485,10 @@ extension JavaClassTranslator { let parametersStr = parameters.map { $0.description }.joined(separator: ", ") let throwsStr = javaConstructor.throwsCheckedException ? "throws" : "" let accessModifier = javaConstructor.isPublic ? "public " : "" + let convenienceModifier = translator.translateAsClass ? "convenience " : "" return """ @JavaMethod - \(raw: accessModifier)init(\(raw: parametersStr))\(raw: throwsStr) + \(raw: accessModifier)\(raw: convenienceModifier)init(\(raw: parametersStr))\(raw: throwsStr) """ } diff --git a/Tests/Java2SwiftTests/Java2SwiftTests.swift b/Tests/Java2SwiftTests/Java2SwiftTests.swift index a8007fe7..be93610c 100644 --- a/Tests/Java2SwiftTests/Java2SwiftTests.swift +++ b/Tests/Java2SwiftTests/Java2SwiftTests.swift @@ -280,7 +280,7 @@ class Java2SwiftTests: XCTestCase { """, """ @JavaMethod - public init(environment: JNIEnvironment? = nil) + public convenience init(environment: JNIEnvironment? = nil) """, """ @JavaMethod @@ -310,7 +310,7 @@ class Java2SwiftTests: XCTestCase { """, """ @JavaMethod - public init(environment: JNIEnvironment? = nil) + public convenience init(environment: JNIEnvironment? = nil) """, """ @JavaMethod From 1baa0957b612cb049090c67fc8c954d1e30adb69 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Wed, 30 Oct 2024 21:48:42 -0700 Subject: [PATCH 150/426] Java2Swift: Fix enum initializer for class-based generation. --- .../Java2SwiftLib/JavaClassTranslator.swift | 7 +++-- Tests/Java2SwiftTests/Java2SwiftTests.swift | 31 +++++++++++++++++++ 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/Sources/Java2SwiftLib/JavaClassTranslator.swift b/Sources/Java2SwiftLib/JavaClassTranslator.swift index b05f67e6..3e26bd9f 100644 --- a/Sources/Java2SwiftLib/JavaClassTranslator.swift +++ b/Sources/Java2SwiftLib/JavaClassTranslator.swift @@ -576,8 +576,9 @@ extension JavaClassTranslator { } """ + let convenienceModifier = translator.translateAsClass ? "convenience " : "" let initSyntax: DeclSyntax = """ - public init(_ enumValue: \(raw: name), environment: JNIEnvironment? = nil) { + public \(raw: convenienceModifier)init(_ enumValue: \(raw: name), environment: JNIEnvironment? = nil) { let _environment = if let environment { environment } else { @@ -589,7 +590,9 @@ extension JavaClassTranslator { return """ case .\($0.getName()): if let \($0.getName()) = classObj.\($0.getName()) { - self = \($0.getName()) + \(translator.translateAsClass + ? "self.init(javaHolder: \($0.getName()).javaHolder)" + : "self = \($0.getName())") } else { fatalError("Enum value \($0.getName()) was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } diff --git a/Tests/Java2SwiftTests/Java2SwiftTests.swift b/Tests/Java2SwiftTests/Java2SwiftTests.swift index be93610c..abed40a3 100644 --- a/Tests/Java2SwiftTests/Java2SwiftTests.swift +++ b/Tests/Java2SwiftTests/Java2SwiftTests.swift @@ -328,6 +328,37 @@ class Java2SwiftTests: XCTestCase { ) } + func testEnumAsClass() throws { + try assertTranslatedClass( + JavaMonth.self, + swiftTypeName: "Month", + asClass: true, + expectedChunks: [ + "import JavaKit", + "enum MonthCases: Equatable", + "case APRIL", + "public var enumValue: MonthCases!", + """ + } else if self.equals(classObj.APRIL?.as(JavaObject.self)) { + return MonthCases.APRIL + } + """, + "public convenience init(_ enumValue: MonthCases, environment: JNIEnvironment? = nil) {", + """ + case .APRIL: + if let APRIL = classObj.APRIL { + self.init(javaHolder: APRIL.javaHolder) + } else { + fatalError("Enum value APRIL was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + } + """, + """ + @JavaStaticField(isFinal: true) + public var APRIL: Month! + """ + ]) + } + func testURLLoaderSkipMappingAsClass() throws { // URLClassLoader actually inherits from SecureClassLoader. However, // that type wasn't mapped into Swift, so we find the nearest From 1715af834712a83eaa7488a0b4e44e890dbe88cb Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Wed, 30 Oct 2024 22:08:23 -0700 Subject: [PATCH 151/426] Java2Swift: Don't use Self in an invariant position in enum convenience init --- Sources/Java2SwiftLib/JavaClassTranslator.swift | 2 +- Tests/Java2SwiftTests/Java2SwiftTests.swift | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Sources/Java2SwiftLib/JavaClassTranslator.swift b/Sources/Java2SwiftLib/JavaClassTranslator.swift index 3e26bd9f..78851376 100644 --- a/Sources/Java2SwiftLib/JavaClassTranslator.swift +++ b/Sources/Java2SwiftLib/JavaClassTranslator.swift @@ -584,7 +584,7 @@ extension JavaClassTranslator { } else { try! JavaVirtualMachine.shared().environment() } - let classObj = try! JavaClass(environment: _environment) + let classObj = try! JavaClass<\(raw: swiftInnermostTypeName)>(environment: _environment) switch enumValue { \(raw: enumConstants.map { return """ diff --git a/Tests/Java2SwiftTests/Java2SwiftTests.swift b/Tests/Java2SwiftTests/Java2SwiftTests.swift index abed40a3..0222cf86 100644 --- a/Tests/Java2SwiftTests/Java2SwiftTests.swift +++ b/Tests/Java2SwiftTests/Java2SwiftTests.swift @@ -344,6 +344,9 @@ class Java2SwiftTests: XCTestCase { } """, "public convenience init(_ enumValue: MonthCases, environment: JNIEnvironment? = nil) {", + """ + let classObj = try! JavaClass(environment: _environment) + """, """ case .APRIL: if let APRIL = classObj.APRIL { From b55cd4d8f672761f6db3b2678f81a20065e3fa72 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Wed, 30 Oct 2024 22:11:32 -0700 Subject: [PATCH 152/426] Java2Swift: fullJavaClassName needs to be "open class" in class-generation mode --- Sources/JavaKitMacros/JavaClassMacro.swift | 3 ++- Tests/JavaKitMacroTests/JavaClassMacroTests.swift | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Sources/JavaKitMacros/JavaClassMacro.swift b/Sources/JavaKitMacros/JavaClassMacro.swift index eb9417aa..9a2dd4a5 100644 --- a/Sources/JavaKitMacros/JavaClassMacro.swift +++ b/Sources/JavaKitMacros/JavaClassMacro.swift @@ -91,9 +91,10 @@ extension JavaClassMacro: MemberMacro { fullJavaClassNameMemberModifiers = "class" } + let classNameAccessSpecifier = isSwiftClass ? "open" : "public" members.append(""" /// The full Java class name for this Swift type. - public \(raw: fullJavaClassNameMemberModifiers) var fullJavaClassName: String { \(literal: className) } + \(raw: classNameAccessSpecifier) \(raw: fullJavaClassNameMemberModifiers) var fullJavaClassName: String { \(literal: className) } """ ) diff --git a/Tests/JavaKitMacroTests/JavaClassMacroTests.swift b/Tests/JavaKitMacroTests/JavaClassMacroTests.swift index 0d6ac9be..9a16d773 100644 --- a/Tests/JavaKitMacroTests/JavaClassMacroTests.swift +++ b/Tests/JavaKitMacroTests/JavaClassMacroTests.swift @@ -186,7 +186,7 @@ class JavaKitMacroTests: XCTestCase { } /// The full Java class name for this Swift type. - public override class var fullJavaClassName: String { + open override class var fullJavaClassName: String { "org.swift.example.HelloWorld" } @@ -227,7 +227,7 @@ class JavaKitMacroTests: XCTestCase { } /// The full Java class name for this Swift type. - public class var fullJavaClassName: String { + open class var fullJavaClassName: String { "java.lang.Object" } From 45d195cba6ef5b52e646a636434245cd656c9d61 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Wed, 30 Oct 2024 22:22:29 -0700 Subject: [PATCH 153/426] Java2Swift: Correctly determine if a Swift method will be an override. When looking for a declared method with a given signature, we need to check all superclasses that have been mapped into Swift, not just the closest one. --- .../Java2SwiftLib/JavaClassTranslator.swift | 31 ++++++++++++++----- Tests/Java2SwiftTests/Java2SwiftTests.swift | 26 ++++++++++++++++ 2 files changed, 49 insertions(+), 8 deletions(-) diff --git a/Sources/Java2SwiftLib/JavaClassTranslator.swift b/Sources/Java2SwiftLib/JavaClassTranslator.swift index 78851376..f6a1b6eb 100644 --- a/Sources/Java2SwiftLib/JavaClassTranslator.swift +++ b/Sources/Java2SwiftLib/JavaClassTranslator.swift @@ -664,15 +664,30 @@ extension JavaClassTranslator { /// Determine whether this method is an override of another Java /// method. func isOverride(_ method: Method) -> Bool { - guard let javaSuperclass = effectiveJavaSuperclass else { - return false - } + var currentSuperclass = effectiveJavaSuperclass + while let currentSuperclassNonOpt = currentSuperclass { + // Set the loop up for the next run. + defer { + currentSuperclass = currentSuperclassNonOpt.getSuperclass() + } + + do { + // If this class didn't get translated into Swift, skip it. + if translator.translatedClasses[currentSuperclassNonOpt.getName()] == nil { + continue + } - do { - let overriddenMethod = try javaSuperclass.getDeclaredMethod(method.getName(), method.getParameterTypes()) - return overriddenMethod != nil - } catch { - return false + // If this superclass declares a method with the same parameter types, + // we have an override. + let overriddenMethod = try currentSuperclassNonOpt + .getDeclaredMethod(method.getName(), method.getParameterTypes()) + if overriddenMethod != nil { + return true + } + } catch { + } } + + return false } } diff --git a/Tests/Java2SwiftTests/Java2SwiftTests.swift b/Tests/Java2SwiftTests/Java2SwiftTests.swift index 0222cf86..6b4f9e7d 100644 --- a/Tests/Java2SwiftTests/Java2SwiftTests.swift +++ b/Tests/Java2SwiftTests/Java2SwiftTests.swift @@ -422,6 +422,32 @@ class Java2SwiftTests: XCTestCase { ] ) } + + func testOverrideSkipImmediateSuperclass() throws { + // JavaByte overrides equals() from JavaObject, which it indirectly + // inherits through JavaNumber + try assertTranslatedClass( + JavaByte.self, + swiftTypeName: "JavaByte", + asClass: true, + translatedClasses: [ + "java.lang.Object" : ("JavaObject", "JavaKit"), + "java.lang.Number" : ("JavaNumber", "JavaKit"), + "java.lang.Byte" : ("JavaByte", "JavaKit"), + ], + expectedChunks: [ + "import JavaKit", + """ + @JavaClass("java.lang.Byte") + open class JavaByte: JavaNumber { + """, + """ + @JavaMethod + open override func equals(_ arg0: JavaObject?) -> Bool + """, + ] + ) + } } @JavaClass("java.lang.ClassLoader") From 9f5fbbf1e86a7700dbcf88c45fd7e82ecd89174b Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Wed, 30 Oct 2024 22:26:55 -0700 Subject: [PATCH 154/426] Java2Swift: Java static methods need to use "public", not "open" --- Sources/Java2SwiftLib/JavaClassTranslator.swift | 3 ++- Sources/Java2SwiftLib/JavaTranslator.swift | 5 ----- Tests/Java2SwiftTests/Java2SwiftTests.swift | 4 ++++ 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Sources/Java2SwiftLib/JavaClassTranslator.swift b/Sources/Java2SwiftLib/JavaClassTranslator.swift index f6a1b6eb..30642678 100644 --- a/Sources/Java2SwiftLib/JavaClassTranslator.swift +++ b/Sources/Java2SwiftLib/JavaClassTranslator.swift @@ -523,7 +523,8 @@ extension JavaClassTranslator { ? "" : javaMethod.isStatic ? "@JavaStaticMethod\n" : "@JavaMethod\n"; let accessModifier = implementedInSwift ? "" - : "\(translator.defaultAccessSpecifier) " + : (javaMethod.isStatic || !translator.translateAsClass) ? "public " + : "open " let overrideOpt = (translator.translateAsClass && !javaMethod.isStatic && isOverride(javaMethod)) ? "override " diff --git a/Sources/Java2SwiftLib/JavaTranslator.swift b/Sources/Java2SwiftLib/JavaTranslator.swift index c207edb3..56535514 100644 --- a/Sources/Java2SwiftLib/JavaTranslator.swift +++ b/Sources/Java2SwiftLib/JavaTranslator.swift @@ -250,11 +250,6 @@ extension JavaTranslator { throw TranslationError.untranslatedJavaClass(name) } - - /// The default Swift access specifier for a Java method. - var defaultAccessSpecifier: String { - translateAsClass ? "open" : "public" - } } // MARK: Class translation diff --git a/Tests/Java2SwiftTests/Java2SwiftTests.swift b/Tests/Java2SwiftTests/Java2SwiftTests.swift index 6b4f9e7d..224c29ac 100644 --- a/Tests/Java2SwiftTests/Java2SwiftTests.swift +++ b/Tests/Java2SwiftTests/Java2SwiftTests.swift @@ -323,7 +323,11 @@ class Java2SwiftTests: XCTestCase { """ @JavaMethod open func intern() -> String + """, """ + @JavaStaticMethod + public func valueOf(_ arg0: Int64) -> String + """, ] ) } From ea6cfaaf6201a3c1dddf2d3fafb3efe304442aed Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Wed, 30 Oct 2024 22:30:30 -0700 Subject: [PATCH 155/426] Java2Swift: Include protected methods in generated classes Swift doesn't have the notion of "protected", so treat these as "open" (or "public") as approriate. --- Sources/Java2SwiftLib/JavaClassTranslator.swift | 4 ++-- Sources/JavaKitReflection/Method+Utilities.swift | 5 +++++ Tests/Java2SwiftTests/Java2SwiftTests.swift | 4 ++++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/Sources/Java2SwiftLib/JavaClassTranslator.swift b/Sources/Java2SwiftLib/JavaClassTranslator.swift index 30642678..0319b8f9 100644 --- a/Sources/Java2SwiftLib/JavaClassTranslator.swift +++ b/Sources/Java2SwiftLib/JavaClassTranslator.swift @@ -181,8 +181,8 @@ struct JavaClassTranslator { for method in methods { guard let method else { continue } - // Only look at public methods here. - guard method.isPublic else { continue } + // Only look at public and protected methods here. + guard method.isPublic || method.isProtected else { continue } // Skip any methods that are expected to be implemented in Swift. We will // visit them in the second pass, over the *declared* methods, because diff --git a/Sources/JavaKitReflection/Method+Utilities.swift b/Sources/JavaKitReflection/Method+Utilities.swift index 1b632337..6c8e4a66 100644 --- a/Sources/JavaKitReflection/Method+Utilities.swift +++ b/Sources/JavaKitReflection/Method+Utilities.swift @@ -18,6 +18,11 @@ extension Method { return (getModifiers() & 1) != 0 } + /// Whether this is a 'protected' method. + public var isProtected: Bool { + return (getModifiers() & 4) != 0 + } + /// Whether this is a 'static' method. public var isStatic: Bool { return (getModifiers() & 0x08) != 0 diff --git a/Tests/Java2SwiftTests/Java2SwiftTests.swift b/Tests/Java2SwiftTests/Java2SwiftTests.swift index 224c29ac..3413ee8a 100644 --- a/Tests/Java2SwiftTests/Java2SwiftTests.swift +++ b/Tests/Java2SwiftTests/Java2SwiftTests.swift @@ -289,7 +289,11 @@ class Java2SwiftTests: XCTestCase { """ @JavaMethod open func wait() throws + """, """ + @JavaMethod + open func clone() throws -> JavaObject! + """, ] ) } From c3337b664d26f21036a518ab4da56b7be610b09c Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Wed, 30 Oct 2024 22:40:19 -0700 Subject: [PATCH 156/426] Import java.util.zip.ZipEntry and regenerate JavaKit sources --- Sources/JavaKit/generated/JavaCharacter.swift | 2 +- .../JavaKitCollection/generated/HashMap.swift | 86 +++++++ .../JavaKitCollection/generated/TreeMap.swift | 86 ------- Sources/JavaKitJar/Java2Swift.config | 3 +- Sources/JavaKitJar/generated/JarEntry.swift | 5 +- Sources/JavaKitJar/generated/JarFile.swift | 3 + .../JavaKitJar/generated/JarInputStream.swift | 3 + .../generated/JarOutputStream.swift | 3 + Sources/JavaKitJar/generated/ZipEntry.swift | 217 ++++++++++++++++++ 9 files changed, 319 insertions(+), 89 deletions(-) create mode 100644 Sources/JavaKitJar/generated/ZipEntry.swift diff --git a/Sources/JavaKit/generated/JavaCharacter.swift b/Sources/JavaKit/generated/JavaCharacter.swift index 47ed2744..82b92a23 100644 --- a/Sources/JavaKit/generated/JavaCharacter.swift +++ b/Sources/JavaKit/generated/JavaCharacter.swift @@ -1612,7 +1612,7 @@ extension JavaCharacter { } else { try! JavaVirtualMachine.shared().environment() } - let classObj = try! JavaClass(environment: _environment) + let classObj = try! JavaClass(environment: _environment) switch enumValue { case .COMMON: if let COMMON = classObj.COMMON { diff --git a/Sources/JavaKitCollection/generated/HashMap.swift b/Sources/JavaKitCollection/generated/HashMap.swift index 9f800c63..55cea901 100644 --- a/Sources/JavaKitCollection/generated/HashMap.swift +++ b/Sources/JavaKitCollection/generated/HashMap.swift @@ -88,6 +88,92 @@ public struct HashMap { @JavaMethod public func wait() throws } +extension HashMap { + @JavaClass("java.util.AbstractMap$SimpleEntry", extends: JavaObject.self) + public struct SimpleEntry { + @JavaMethod + public init(_ arg0: JavaObject?, _ arg1: JavaObject?, environment: JNIEnvironment? = nil) + + @JavaMethod + public func equals(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func toString() -> String + + @JavaMethod + public func hashCode() -> Int32 + + @JavaMethod + public func getValue() -> JavaObject! + + @JavaMethod + public func getKey() -> JavaObject! + + @JavaMethod + public func setValue(_ arg0: JavaObject?) -> JavaObject! + + @JavaMethod + public func getClass() -> JavaClass! + + @JavaMethod + public func notify() + + @JavaMethod + public func notifyAll() + + @JavaMethod + public func wait(_ arg0: Int64) throws + + @JavaMethod + public func wait(_ arg0: Int64, _ arg1: Int32) throws + + @JavaMethod + public func wait() throws + } +} +extension HashMap { + @JavaClass("java.util.AbstractMap$SimpleImmutableEntry", extends: JavaObject.self) + public struct SimpleImmutableEntry { + @JavaMethod + public init(_ arg0: JavaObject?, _ arg1: JavaObject?, environment: JNIEnvironment? = nil) + + @JavaMethod + public func equals(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func toString() -> String + + @JavaMethod + public func hashCode() -> Int32 + + @JavaMethod + public func getValue() -> JavaObject! + + @JavaMethod + public func getKey() -> JavaObject! + + @JavaMethod + public func setValue(_ arg0: JavaObject?) -> JavaObject! + + @JavaMethod + public func getClass() -> JavaClass! + + @JavaMethod + public func notify() + + @JavaMethod + public func notifyAll() + + @JavaMethod + public func wait(_ arg0: Int64) throws + + @JavaMethod + public func wait(_ arg0: Int64, _ arg1: Int32) throws + + @JavaMethod + public func wait() throws + } +} extension JavaClass { @JavaStaticMethod public func newHashMap(_ arg0: Int32) -> HashMap! where ObjectType == HashMap diff --git a/Sources/JavaKitCollection/generated/TreeMap.swift b/Sources/JavaKitCollection/generated/TreeMap.swift index 3d7d858a..f6943b48 100644 --- a/Sources/JavaKitCollection/generated/TreeMap.swift +++ b/Sources/JavaKitCollection/generated/TreeMap.swift @@ -106,89 +106,3 @@ public struct TreeMap { @JavaMethod public func getOrDefault(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject! } -extension TreeMap { - @JavaClass("java.util.AbstractMap$SimpleEntry", extends: JavaObject.self) - public struct SimpleEntry { - @JavaMethod - public init(_ arg0: JavaObject?, _ arg1: JavaObject?, environment: JNIEnvironment? = nil) - - @JavaMethod - public func equals(_ arg0: JavaObject?) -> Bool - - @JavaMethod - public func toString() -> String - - @JavaMethod - public func hashCode() -> Int32 - - @JavaMethod - public func getValue() -> JavaObject! - - @JavaMethod - public func getKey() -> JavaObject! - - @JavaMethod - public func setValue(_ arg0: JavaObject?) -> JavaObject! - - @JavaMethod - public func getClass() -> JavaClass! - - @JavaMethod - public func notify() - - @JavaMethod - public func notifyAll() - - @JavaMethod - public func wait(_ arg0: Int64) throws - - @JavaMethod - public func wait(_ arg0: Int64, _ arg1: Int32) throws - - @JavaMethod - public func wait() throws - } -} -extension TreeMap { - @JavaClass("java.util.AbstractMap$SimpleImmutableEntry", extends: JavaObject.self) - public struct SimpleImmutableEntry { - @JavaMethod - public init(_ arg0: JavaObject?, _ arg1: JavaObject?, environment: JNIEnvironment? = nil) - - @JavaMethod - public func equals(_ arg0: JavaObject?) -> Bool - - @JavaMethod - public func toString() -> String - - @JavaMethod - public func hashCode() -> Int32 - - @JavaMethod - public func getValue() -> JavaObject! - - @JavaMethod - public func getKey() -> JavaObject! - - @JavaMethod - public func setValue(_ arg0: JavaObject?) -> JavaObject! - - @JavaMethod - public func getClass() -> JavaClass! - - @JavaMethod - public func notify() - - @JavaMethod - public func notifyAll() - - @JavaMethod - public func wait(_ arg0: Int64) throws - - @JavaMethod - public func wait(_ arg0: Int64, _ arg1: Int32) throws - - @JavaMethod - public func wait() throws - } -} diff --git a/Sources/JavaKitJar/Java2Swift.config b/Sources/JavaKitJar/Java2Swift.config index 011b169f..caf7a6f9 100644 --- a/Sources/JavaKitJar/Java2Swift.config +++ b/Sources/JavaKitJar/Java2Swift.config @@ -5,6 +5,7 @@ "java.util.jar.JarFile" : "JarFile", "java.util.jar.JarInputStream" : "JarInputStream", "java.util.jar.JarOutputStream" : "JarOutputStream", - "java.util.jar.Manifest" : "Manifest" + "java.util.jar.Manifest" : "Manifest", + "java.util.zip.ZipEntry" : "ZipEntry" } } diff --git a/Sources/JavaKitJar/generated/JarEntry.swift b/Sources/JavaKitJar/generated/JarEntry.swift index 40bbef54..85f5afe7 100644 --- a/Sources/JavaKitJar/generated/JarEntry.swift +++ b/Sources/JavaKitJar/generated/JarEntry.swift @@ -2,11 +2,14 @@ import JavaKit import JavaRuntime -@JavaClass("java.util.jar.JarEntry", extends: JavaObject.self) +@JavaClass("java.util.jar.JarEntry", extends: ZipEntry.self) public struct JarEntry { @JavaMethod public init(_ arg0: JarEntry?, environment: JNIEnvironment? = nil) + @JavaMethod + public init(_ arg0: ZipEntry?, environment: JNIEnvironment? = nil) + @JavaMethod public init(_ arg0: String, environment: JNIEnvironment? = nil) diff --git a/Sources/JavaKitJar/generated/JarFile.swift b/Sources/JavaKitJar/generated/JarFile.swift index 4c215e05..a76d645e 100644 --- a/Sources/JavaKitJar/generated/JarFile.swift +++ b/Sources/JavaKitJar/generated/JarFile.swift @@ -17,6 +17,9 @@ public struct JarFile { @JavaMethod public func getManifest() throws -> Manifest! + @JavaMethod + public func getEntry(_ arg0: String) -> ZipEntry! + @JavaMethod public func getJarEntry(_ arg0: String) -> JarEntry! diff --git a/Sources/JavaKitJar/generated/JarInputStream.swift b/Sources/JavaKitJar/generated/JarInputStream.swift index c8a25439..ac6ade3b 100644 --- a/Sources/JavaKitJar/generated/JarInputStream.swift +++ b/Sources/JavaKitJar/generated/JarInputStream.swift @@ -4,6 +4,9 @@ import JavaRuntime @JavaClass("java.util.jar.JarInputStream", extends: JavaObject.self) public struct JarInputStream { + @JavaMethod + public func getNextEntry() throws -> ZipEntry! + @JavaMethod public func getNextJarEntry() throws -> JarEntry! diff --git a/Sources/JavaKitJar/generated/JarOutputStream.swift b/Sources/JavaKitJar/generated/JarOutputStream.swift index b10dc4b5..04b544c8 100644 --- a/Sources/JavaKitJar/generated/JarOutputStream.swift +++ b/Sources/JavaKitJar/generated/JarOutputStream.swift @@ -4,6 +4,9 @@ import JavaRuntime @JavaClass("java.util.jar.JarOutputStream", extends: JavaObject.self) public struct JarOutputStream { + @JavaMethod + public func putNextEntry(_ arg0: ZipEntry?) throws + @JavaMethod public func closeEntry() throws diff --git a/Sources/JavaKitJar/generated/ZipEntry.swift b/Sources/JavaKitJar/generated/ZipEntry.swift new file mode 100644 index 00000000..2f2e16a5 --- /dev/null +++ b/Sources/JavaKitJar/generated/ZipEntry.swift @@ -0,0 +1,217 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaClass("java.util.zip.ZipEntry", extends: JavaObject.self) +public struct ZipEntry { + @JavaMethod + public init(_ arg0: String, environment: JNIEnvironment? = nil) + + @JavaMethod + public init(_ arg0: ZipEntry?, environment: JNIEnvironment? = nil) + + @JavaMethod + public func getName() -> String + + @JavaMethod + public func toString() -> String + + @JavaMethod + public func hashCode() -> Int32 + + @JavaMethod + public func clone() -> JavaObject! + + @JavaMethod + public func getMethod() -> Int32 + + @JavaMethod + public func getSize() -> Int64 + + @JavaMethod + public func isDirectory() -> Bool + + @JavaMethod + public func getTime() -> Int64 + + @JavaMethod + public func setTime(_ arg0: Int64) + + @JavaMethod + public func setSize(_ arg0: Int64) + + @JavaMethod + public func getCompressedSize() -> Int64 + + @JavaMethod + public func setCompressedSize(_ arg0: Int64) + + @JavaMethod + public func setCrc(_ arg0: Int64) + + @JavaMethod + public func getCrc() -> Int64 + + @JavaMethod + public func setMethod(_ arg0: Int32) + + @JavaMethod + public func setExtra(_ arg0: [Int8]) + + @JavaMethod + public func getExtra() -> [Int8] + + @JavaMethod + public func setComment(_ arg0: String) + + @JavaMethod + public func getComment() -> String + + @JavaMethod + public func equals(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func getClass() -> JavaClass! + + @JavaMethod + public func notify() + + @JavaMethod + public func notifyAll() + + @JavaMethod + public func wait(_ arg0: Int64) throws + + @JavaMethod + public func wait(_ arg0: Int64, _ arg1: Int32) throws + + @JavaMethod + public func wait() throws +} +extension JavaClass { + @JavaStaticField(isFinal: true) + public var STORED: Int32 + + @JavaStaticField(isFinal: true) + public var DEFLATED: Int32 + + @JavaStaticField(isFinal: true) + public var LOCSIG: Int64 + + @JavaStaticField(isFinal: true) + public var EXTSIG: Int64 + + @JavaStaticField(isFinal: true) + public var CENSIG: Int64 + + @JavaStaticField(isFinal: true) + public var ENDSIG: Int64 + + @JavaStaticField(isFinal: true) + public var LOCHDR: Int32 + + @JavaStaticField(isFinal: true) + public var EXTHDR: Int32 + + @JavaStaticField(isFinal: true) + public var CENHDR: Int32 + + @JavaStaticField(isFinal: true) + public var ENDHDR: Int32 + + @JavaStaticField(isFinal: true) + public var LOCVER: Int32 + + @JavaStaticField(isFinal: true) + public var LOCFLG: Int32 + + @JavaStaticField(isFinal: true) + public var LOCHOW: Int32 + + @JavaStaticField(isFinal: true) + public var LOCTIM: Int32 + + @JavaStaticField(isFinal: true) + public var LOCCRC: Int32 + + @JavaStaticField(isFinal: true) + public var LOCSIZ: Int32 + + @JavaStaticField(isFinal: true) + public var LOCLEN: Int32 + + @JavaStaticField(isFinal: true) + public var LOCNAM: Int32 + + @JavaStaticField(isFinal: true) + public var LOCEXT: Int32 + + @JavaStaticField(isFinal: true) + public var EXTCRC: Int32 + + @JavaStaticField(isFinal: true) + public var EXTSIZ: Int32 + + @JavaStaticField(isFinal: true) + public var EXTLEN: Int32 + + @JavaStaticField(isFinal: true) + public var CENVEM: Int32 + + @JavaStaticField(isFinal: true) + public var CENVER: Int32 + + @JavaStaticField(isFinal: true) + public var CENFLG: Int32 + + @JavaStaticField(isFinal: true) + public var CENHOW: Int32 + + @JavaStaticField(isFinal: true) + public var CENTIM: Int32 + + @JavaStaticField(isFinal: true) + public var CENCRC: Int32 + + @JavaStaticField(isFinal: true) + public var CENSIZ: Int32 + + @JavaStaticField(isFinal: true) + public var CENLEN: Int32 + + @JavaStaticField(isFinal: true) + public var CENNAM: Int32 + + @JavaStaticField(isFinal: true) + public var CENEXT: Int32 + + @JavaStaticField(isFinal: true) + public var CENCOM: Int32 + + @JavaStaticField(isFinal: true) + public var CENDSK: Int32 + + @JavaStaticField(isFinal: true) + public var CENATT: Int32 + + @JavaStaticField(isFinal: true) + public var CENATX: Int32 + + @JavaStaticField(isFinal: true) + public var CENOFF: Int32 + + @JavaStaticField(isFinal: true) + public var ENDSUB: Int32 + + @JavaStaticField(isFinal: true) + public var ENDTOT: Int32 + + @JavaStaticField(isFinal: true) + public var ENDSIZ: Int32 + + @JavaStaticField(isFinal: true) + public var ENDOFF: Int32 + + @JavaStaticField(isFinal: true) + public var ENDCOM: Int32 +} From 4b045b2d84bc69a378e096749870a714d75df5f0 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Wed, 30 Oct 2024 22:47:44 -0700 Subject: [PATCH 157/426] Java2Swift: Don't translate Java interfaces into Swift classes Keep interfaces as structs for now. Their future is yet unwritten. --- .../Java2SwiftLib/JavaClassTranslator.swift | 25 +++++++++++-------- Sources/Java2SwiftLib/JavaTranslator.swift | 3 +++ Tests/Java2SwiftTests/Java2SwiftTests.swift | 24 ++++++++++++++++++ 3 files changed, 42 insertions(+), 10 deletions(-) diff --git a/Sources/Java2SwiftLib/JavaClassTranslator.swift b/Sources/Java2SwiftLib/JavaClassTranslator.swift index 0319b8f9..13e1a8af 100644 --- a/Sources/Java2SwiftLib/JavaClassTranslator.swift +++ b/Sources/Java2SwiftLib/JavaClassTranslator.swift @@ -26,6 +26,11 @@ struct JavaClassTranslator { /// The Java class (or interface) being translated. let javaClass: JavaClass + /// Whether to translate this Java class into a Swift class. + /// + /// This will be false for Java interfaces. + let translateAsClass: Bool + /// The type parameters to the Java class or interface. let javaTypeParameters: [TypeVariable>] @@ -107,6 +112,7 @@ struct JavaClassTranslator { let fullName = javaClass.getName() self.javaClass = javaClass self.translator = translator + self.translateAsClass = translator.translateAsClass && !javaClass.isInterface() self.swiftTypeName = try translator.getSwiftTypeNameFromJavaClassName( fullName, preferValueTypes: false, @@ -175,7 +181,7 @@ struct JavaClassTranslator { } // Gather methods. - let methods = translator.translateAsClass + let methods = translateAsClass ? javaClass.getDeclaredMethods() : javaClass.getMethods() for method in methods { @@ -231,7 +237,7 @@ extension JavaClassTranslator { } // Don't include inherited fields when translating to a class. - if translator.translateAsClass && + if translateAsClass && !field.getDeclaringClass()!.equals(javaClass.as(JavaObject.self)!) { return } @@ -315,7 +321,7 @@ extension JavaClassTranslator { // formulation). let extends: String let inheritanceClause: String - if translator.translateAsClass { + if translateAsClass { extends = "" inheritanceClause = swiftSuperclass.map { ": \($0)" } ?? "" } else { @@ -334,7 +340,7 @@ extension JavaClassTranslator { // Emit the struct declaration describing the java class. let classOrInterface: String = isInterface ? "JavaInterface" : "JavaClass"; - let introducer = translator.translateAsClass ? "open class" : "public struct" + let introducer = translateAsClass ? "open class" : "public struct" var classDecl: DeclSyntax = """ @\(raw: classOrInterface)(\(literal: javaClass.getName())\(raw: extends)\(raw: interfacesStr)) @@ -485,7 +491,7 @@ extension JavaClassTranslator { let parametersStr = parameters.map { $0.description }.joined(separator: ", ") let throwsStr = javaConstructor.throwsCheckedException ? "throws" : "" let accessModifier = javaConstructor.isPublic ? "public " : "" - let convenienceModifier = translator.translateAsClass ? "convenience " : "" + let convenienceModifier = translateAsClass ? "convenience " : "" return """ @JavaMethod \(raw: accessModifier)\(raw: convenienceModifier)init(\(raw: parametersStr))\(raw: throwsStr) @@ -523,10 +529,9 @@ extension JavaClassTranslator { ? "" : javaMethod.isStatic ? "@JavaStaticMethod\n" : "@JavaMethod\n"; let accessModifier = implementedInSwift ? "" - : (javaMethod.isStatic || !translator.translateAsClass) ? "public " + : (javaMethod.isStatic || !translateAsClass) ? "public " : "open " - let overrideOpt = (translator.translateAsClass && - !javaMethod.isStatic && isOverride(javaMethod)) + let overrideOpt = (translateAsClass && !javaMethod.isStatic && isOverride(javaMethod)) ? "override " : "" return """ @@ -577,7 +582,7 @@ extension JavaClassTranslator { } """ - let convenienceModifier = translator.translateAsClass ? "convenience " : "" + let convenienceModifier = translateAsClass ? "convenience " : "" let initSyntax: DeclSyntax = """ public \(raw: convenienceModifier)init(_ enumValue: \(raw: name), environment: JNIEnvironment? = nil) { let _environment = if let environment { @@ -591,7 +596,7 @@ extension JavaClassTranslator { return """ case .\($0.getName()): if let \($0.getName()) = classObj.\($0.getName()) { - \(translator.translateAsClass + \(translateAsClass ? "self.init(javaHolder: \($0.getName()).javaHolder)" : "self = \($0.getName())") } else { diff --git a/Sources/Java2SwiftLib/JavaTranslator.swift b/Sources/Java2SwiftLib/JavaTranslator.swift index 56535514..69edac6c 100644 --- a/Sources/Java2SwiftLib/JavaTranslator.swift +++ b/Sources/Java2SwiftLib/JavaTranslator.swift @@ -26,7 +26,10 @@ package class JavaTranslator { let swiftModuleName: String let environment: JNIEnvironment + + /// Whether to translate Java classes into classes (rather than structs). let translateAsClass: Bool + let format: BasicFormat /// A mapping from the name of each known Java class to the corresponding diff --git a/Tests/Java2SwiftTests/Java2SwiftTests.swift b/Tests/Java2SwiftTests/Java2SwiftTests.swift index 3413ee8a..74127a0c 100644 --- a/Tests/Java2SwiftTests/Java2SwiftTests.swift +++ b/Tests/Java2SwiftTests/Java2SwiftTests.swift @@ -456,6 +456,30 @@ class Java2SwiftTests: XCTestCase { ] ) } + + func testJavaInterfaceAsClassNOT() throws { + try assertTranslatedClass( + MyJavaIntFunction.self, + swiftTypeName: "MyJavaIntFunction", + asClass: true, + translatedClasses: [ + "java.lang.Object" : ("JavaObject", "JavaKit"), + "java.util.function.IntFunction": ("MyJavaIntFunction", nil), + ], + expectedChunks: [ + "import JavaKit", + """ + @JavaInterface("java.util.function.IntFunction") + public struct MyJavaIntFunction { + """, + """ + @JavaMethod + public func apply(_ arg0: Int32) -> JavaObject! + """, + ] + ) + + } } @JavaClass("java.lang.ClassLoader") From 374c847262ce4818b151a1c9c0fe2ca0e1df59e6 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Wed, 30 Oct 2024 23:12:02 -0700 Subject: [PATCH 158/426] JavaField macro: within a class, don't generate "nonmutating" modifier --- Sources/JavaKitMacros/JavaFieldMacro.swift | 7 ++++++- Tests/JavaKitMacroTests/JavaClassMacroTests.swift | 4 ++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/Sources/JavaKitMacros/JavaFieldMacro.swift b/Sources/JavaKitMacros/JavaFieldMacro.swift index 02280570..40bf7113 100644 --- a/Sources/JavaKitMacros/JavaFieldMacro.swift +++ b/Sources/JavaKitMacros/JavaFieldMacro.swift @@ -64,9 +64,14 @@ extension JavaFieldMacro: AccessorMacro { getter ] + let nonmutatingModifier = + (context.lexicalContext.first?.is(ClassDeclSyntax.self) ?? false) + ? "" + : "nonmutating " + if createSetter { let setter: AccessorDeclSyntax = """ - nonmutating set { self[javaFieldName: \(literal: fieldName), fieldType: \(fieldType).self] = newValue } + \(raw: nonmutatingModifier)set { self[javaFieldName: \(literal: fieldName), fieldType: \(fieldType).self] = newValue } """ accessors.append(setter) } diff --git a/Tests/JavaKitMacroTests/JavaClassMacroTests.swift b/Tests/JavaKitMacroTests/JavaClassMacroTests.swift index 9a16d773..e639800b 100644 --- a/Tests/JavaKitMacroTests/JavaClassMacroTests.swift +++ b/Tests/JavaKitMacroTests/JavaClassMacroTests.swift @@ -167,7 +167,7 @@ class JavaKitMacroTests: XCTestCase { get { self[javaFieldName: "myField", fieldType: Int64.self] } - nonmutating set { + set { self[javaFieldName: "myField", fieldType: Int64.self] = newValue } } @@ -175,7 +175,7 @@ class JavaKitMacroTests: XCTestCase { get { self[javaFieldName: "objectField", fieldType: JavaObject?.self] } - nonmutating set { + set { self[javaFieldName: "objectField", fieldType: JavaObject?.self] = newValue } } From 7346359ea124e816ddc40456718f4f3e46d383c1 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Wed, 30 Oct 2024 23:36:04 -0700 Subject: [PATCH 159/426] Java2Swift: Account for differences in covariant overrides between Java and Swift Java allows more subtyping relationships for the result types in a covariant method override than Swift does, such as covariant arrays and wildcards. Take the Swift semantics into account when determining whether to apply the `override` keyword. --- Sources/Java2Swift/JavaToSwift.swift | 3 +- .../Java2SwiftLib/JavaClassTranslator.swift | 141 +++++++++++++++++- .../JavaKitCollection/generated/HashMap.swift | 86 ----------- .../JavaKitCollection/generated/TreeMap.swift | 86 +++++++++++ Tests/Java2SwiftTests/Java2SwiftTests.swift | 83 +++++++++++ 5 files changed, 309 insertions(+), 90 deletions(-) diff --git a/Sources/Java2Swift/JavaToSwift.swift b/Sources/Java2Swift/JavaToSwift.swift index 15e346ae..112c015b 100644 --- a/Sources/Java2Swift/JavaToSwift.swift +++ b/Sources/Java2Swift/JavaToSwift.swift @@ -183,7 +183,8 @@ struct JavaToSwift: ParsableCommand { ) throws { let translator = JavaTranslator( swiftModuleName: moduleName, - environment: environment + environment: environment, + translateAsClass: false ) // Keep track of all of the Java classes that will have diff --git a/Sources/Java2SwiftLib/JavaClassTranslator.swift b/Sources/Java2SwiftLib/JavaClassTranslator.swift index 13e1a8af..061c8744 100644 --- a/Sources/Java2SwiftLib/JavaClassTranslator.swift +++ b/Sources/Java2SwiftLib/JavaClassTranslator.swift @@ -685,9 +685,21 @@ extension JavaClassTranslator { // If this superclass declares a method with the same parameter types, // we have an override. - let overriddenMethod = try currentSuperclassNonOpt - .getDeclaredMethod(method.getName(), method.getParameterTypes()) - if overriddenMethod != nil { + guard let overriddenMethod = try currentSuperclassNonOpt + .getDeclaredMethod(method.getName(), method.getParameterTypes()) else { + continue + } + + // Ignore non-public, non-protected methods because they would not + // have been render into the Swift superclass. + if !overriddenMethod.isPublic && !overriddenMethod.isProtected { + continue + } + + // We know that Java considers this method an override. However, it is + // possible that Swift will not consider it an override, because Java + // has subtyping relations that Swift does not. + if method.getGenericReturnType().isEqualToOrSubtypeOf(overriddenMethod.getGenericReturnType()) { return true } } catch { @@ -697,3 +709,126 @@ extension JavaClassTranslator { return false } } + +extension [Type?] { + /// Determine whether the types in the array match the other array. + func allTypesEqual(_ other: [Type?]) -> Bool { + if self.count != other.count { + return false + } + + for (selfType, otherType) in zip(self, other) { + if !selfType!.isEqualTo(otherType!) { + return false + } + } + + return true + } +} + +extension Type { + /// Adjust the given type to use its bounds, mirroring what we do in + /// mapping Java types into Swift. + func adjustToJavaBounds(adjusted: inout Bool) -> Type { + if let typeVariable = self.as(TypeVariable.self), + typeVariable.getBounds().count == 1, + let bound = typeVariable.getBounds()[0] { + adjusted = true + return bound + } + + if let wildcardType = self.as(WildcardType.self), + wildcardType.getUpperBounds().count == 1, + let bound = wildcardType.getUpperBounds()[0] { + adjusted = true + return bound + } + + return self + } + + /// Determine whether this type is equivalent to or a subtype of the other + /// type. + func isEqualTo(_ other: Type) -> Bool { + // First, adjust types to their bounds, if we need to. + var anyAdjusted: Bool = false + let adjustedSelf = self.adjustToJavaBounds(adjusted: &anyAdjusted) + let adjustedOther = other.adjustToJavaBounds(adjusted: &anyAdjusted) + if anyAdjusted { + return adjustedSelf.isEqualTo(adjustedOther) + } + + // If both are classes, check for equivalence. + if let selfClass = self.as(JavaClass.self), + let otherClass = other.as(JavaClass.self) { + return selfClass.equals(otherClass.as(JavaObject.self)) + } + + // If both are arrays, check that their component types are equivalent. + if let selfArray = self.as(GenericArrayType.self), + let otherArray = other.as(GenericArrayType.self) { + return selfArray.getGenericComponentType().isEqualTo(otherArray.getGenericComponentType()) + } + + // If both are parameterized types, check their raw type and type + // arguments for equivalence. + if let selfParameterizedType = self.as(ParameterizedType.self), + let otherParameterizedType = other.as(ParameterizedType.self) { + if !selfParameterizedType.getRawType().isEqualTo(otherParameterizedType.getRawType()) { + return false + } + + return selfParameterizedType.getActualTypeArguments() + .allTypesEqual(otherParameterizedType.getActualTypeArguments()) + } + + // If both are type variables, compare their bounds. + // FIXME: This is a hack. + if let selfTypeVariable = self.as(TypeVariable.self), + let otherTypeVariable = other.as(TypeVariable.self) { + return selfTypeVariable.getBounds().allTypesEqual(otherTypeVariable.getBounds()) + } + + // If both are wildcards, compare their upper and lower bounds. + if let selfWildcard = self.as(WildcardType.self), + let otherWildcard = other.as(WildcardType.self) { + return selfWildcard.getUpperBounds().allTypesEqual(otherWildcard.getUpperBounds()) + && selfWildcard.getLowerBounds().allTypesEqual(otherWildcard.getLowerBounds()) + } + + return false + } + + /// Determine whether this type is equivalent to or a subtype of the + /// other type. + func isEqualToOrSubtypeOf(_ other: Type) -> Bool { + // First, adjust types to their bounds, if we need to. + var anyAdjusted: Bool = false + let adjustedSelf = self.adjustToJavaBounds(adjusted: &anyAdjusted) + let adjustedOther = other.adjustToJavaBounds(adjusted: &anyAdjusted) + if anyAdjusted { + return adjustedSelf.isEqualToOrSubtypeOf(adjustedOther) + } + + if isEqualTo(other) { + return true + } + + // If both are classes, check for subclassing. + if let selfClass = self.as(JavaClass.self), + let otherClass = other.as(JavaClass.self) { + return selfClass.isSubclass(of: otherClass) + } + + // Anything object-like is a subclass of java.lang.Object + if let otherClass = other.as(JavaClass.self), + otherClass.getName() == "java.lang.Object" { + if self.is(GenericArrayType.self) || self.is(ParameterizedType.self) || + self.is(WildcardType.self) || self.is(TypeVariable.self) { + return true + } + } + return false + } +} diff --git a/Sources/JavaKitCollection/generated/HashMap.swift b/Sources/JavaKitCollection/generated/HashMap.swift index 55cea901..9f800c63 100644 --- a/Sources/JavaKitCollection/generated/HashMap.swift +++ b/Sources/JavaKitCollection/generated/HashMap.swift @@ -88,92 +88,6 @@ public struct HashMap { @JavaMethod public func wait() throws } -extension HashMap { - @JavaClass("java.util.AbstractMap$SimpleEntry", extends: JavaObject.self) - public struct SimpleEntry { - @JavaMethod - public init(_ arg0: JavaObject?, _ arg1: JavaObject?, environment: JNIEnvironment? = nil) - - @JavaMethod - public func equals(_ arg0: JavaObject?) -> Bool - - @JavaMethod - public func toString() -> String - - @JavaMethod - public func hashCode() -> Int32 - - @JavaMethod - public func getValue() -> JavaObject! - - @JavaMethod - public func getKey() -> JavaObject! - - @JavaMethod - public func setValue(_ arg0: JavaObject?) -> JavaObject! - - @JavaMethod - public func getClass() -> JavaClass! - - @JavaMethod - public func notify() - - @JavaMethod - public func notifyAll() - - @JavaMethod - public func wait(_ arg0: Int64) throws - - @JavaMethod - public func wait(_ arg0: Int64, _ arg1: Int32) throws - - @JavaMethod - public func wait() throws - } -} -extension HashMap { - @JavaClass("java.util.AbstractMap$SimpleImmutableEntry", extends: JavaObject.self) - public struct SimpleImmutableEntry { - @JavaMethod - public init(_ arg0: JavaObject?, _ arg1: JavaObject?, environment: JNIEnvironment? = nil) - - @JavaMethod - public func equals(_ arg0: JavaObject?) -> Bool - - @JavaMethod - public func toString() -> String - - @JavaMethod - public func hashCode() -> Int32 - - @JavaMethod - public func getValue() -> JavaObject! - - @JavaMethod - public func getKey() -> JavaObject! - - @JavaMethod - public func setValue(_ arg0: JavaObject?) -> JavaObject! - - @JavaMethod - public func getClass() -> JavaClass! - - @JavaMethod - public func notify() - - @JavaMethod - public func notifyAll() - - @JavaMethod - public func wait(_ arg0: Int64) throws - - @JavaMethod - public func wait(_ arg0: Int64, _ arg1: Int32) throws - - @JavaMethod - public func wait() throws - } -} extension JavaClass { @JavaStaticMethod public func newHashMap(_ arg0: Int32) -> HashMap! where ObjectType == HashMap diff --git a/Sources/JavaKitCollection/generated/TreeMap.swift b/Sources/JavaKitCollection/generated/TreeMap.swift index f6943b48..3d7d858a 100644 --- a/Sources/JavaKitCollection/generated/TreeMap.swift +++ b/Sources/JavaKitCollection/generated/TreeMap.swift @@ -106,3 +106,89 @@ public struct TreeMap { @JavaMethod public func getOrDefault(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject! } +extension TreeMap { + @JavaClass("java.util.AbstractMap$SimpleEntry", extends: JavaObject.self) + public struct SimpleEntry { + @JavaMethod + public init(_ arg0: JavaObject?, _ arg1: JavaObject?, environment: JNIEnvironment? = nil) + + @JavaMethod + public func equals(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func toString() -> String + + @JavaMethod + public func hashCode() -> Int32 + + @JavaMethod + public func getValue() -> JavaObject! + + @JavaMethod + public func getKey() -> JavaObject! + + @JavaMethod + public func setValue(_ arg0: JavaObject?) -> JavaObject! + + @JavaMethod + public func getClass() -> JavaClass! + + @JavaMethod + public func notify() + + @JavaMethod + public func notifyAll() + + @JavaMethod + public func wait(_ arg0: Int64) throws + + @JavaMethod + public func wait(_ arg0: Int64, _ arg1: Int32) throws + + @JavaMethod + public func wait() throws + } +} +extension TreeMap { + @JavaClass("java.util.AbstractMap$SimpleImmutableEntry", extends: JavaObject.self) + public struct SimpleImmutableEntry { + @JavaMethod + public init(_ arg0: JavaObject?, _ arg1: JavaObject?, environment: JNIEnvironment? = nil) + + @JavaMethod + public func equals(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func toString() -> String + + @JavaMethod + public func hashCode() -> Int32 + + @JavaMethod + public func getValue() -> JavaObject! + + @JavaMethod + public func getKey() -> JavaObject! + + @JavaMethod + public func setValue(_ arg0: JavaObject?) -> JavaObject! + + @JavaMethod + public func getClass() -> JavaClass! + + @JavaMethod + public func notify() + + @JavaMethod + public func notifyAll() + + @JavaMethod + public func wait(_ arg0: Int64) throws + + @JavaMethod + public func wait(_ arg0: Int64, _ arg1: Int32) throws + + @JavaMethod + public func wait() throws + } +} diff --git a/Tests/Java2SwiftTests/Java2SwiftTests.swift b/Tests/Java2SwiftTests/Java2SwiftTests.swift index 74127a0c..a9274436 100644 --- a/Tests/Java2SwiftTests/Java2SwiftTests.swift +++ b/Tests/Java2SwiftTests/Java2SwiftTests.swift @@ -478,7 +478,74 @@ class Java2SwiftTests: XCTestCase { """, ] ) + } + func testCovariantInJavaNotInSwiftOverride() throws { + try assertTranslatedClass( + Method.self, + swiftTypeName: "Method", + asClass: true, + translatedClasses: [ + "java.lang.Object" : ("JavaObject", "JavaKit"), + "java.lang.Class" : ("JavaClass", "JavaKit"), + "java.lang.reflect.Executable": ("Executable", "JavaKitReflection"), + "java.lang.reflect.Method": ("Method", "JavaKitReflection"), + "java.lang.reflect.TypeVariable" : ("TypeVariable", "JavaKitReflection"), + ], + expectedChunks: [ + "import JavaKitReflection", + """ + @JavaClass("java.lang.reflect.Method") + open class Method: Executable { + """, + """ + @JavaMethod + open func getTypeParameters() -> [TypeVariable?] + """, + """ + @JavaMethod + open override func getParameterTypes() -> [JavaClass?] + """, + """ + @JavaMethod + open override func getDeclaringClass() -> JavaClass! + """, + ] + ) + } + + func testCovariantInJavaNotInSwiftOverride2() throws { + try assertTranslatedClass( + Constructor.self, + swiftTypeName: "Constructor", + asClass: true, + translatedClasses: [ + "java.lang.Object" : ("JavaObject", "JavaKit"), + "java.lang.Class" : ("JavaClass", "JavaKit"), + "java.lang.reflect.Executable": ("Executable", "JavaKitReflection"), + "java.lang.reflect.Method": ("Method", "JavaKitReflection"), + "java.lang.reflect.TypeVariable" : ("TypeVariable", "JavaKitReflection"), + ], + expectedChunks: [ + "import JavaKitReflection", + """ + @JavaClass("java.lang.reflect.Constructor") + open class Constructor: Executable { + """, + """ + @JavaMethod + open func getTypeParameters() -> [TypeVariable>?] + """, + """ + @JavaMethod + open override func getParameterTypes() -> [JavaClass?] + """, + """ + @JavaMethod + open override func getDeclaringClass() -> JavaClass! + """, + ] + ) } } @@ -514,6 +581,22 @@ public struct MySupplier { } public struct MyJavaIntFunction { } +@JavaClass("java.lang.reflect.Method", extends: Executable.self) +public struct Method { +} + +@JavaClass("java.lang.reflect.Constructor", extends: Executable.self) +public struct Constructor { +} + +@JavaClass("java.lang.reflect.Executable") +public struct Executable { +} + +@JavaInterface("java.lang.reflect.TypeVariable") +public struct TypeVariable { +} + /// Translate a Java class and assert that the translated output contains /// each of the expected "chunks" of text. func assertTranslatedClass( From 0e3fc536684cdc037ccdc2dad8e5c1af0afe759f Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Thu, 31 Oct 2024 01:00:48 -0700 Subject: [PATCH 160/426] Java2Swift: Use `@_nonoverride` on generated convenience initializers Swift has inheritance of initializers, while Java does not have inheritance of constructors. This means that Swift's attempt to treat a convenience initializer as an override within a subclass can cause problems with mismatched signatures. Use `@_nonoverride` to avoid this problem. --- Sources/Java2SwiftLib/JavaClassTranslator.swift | 3 ++- Tests/Java2SwiftTests/Java2SwiftTests.swift | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Sources/Java2SwiftLib/JavaClassTranslator.swift b/Sources/Java2SwiftLib/JavaClassTranslator.swift index 061c8744..afcac639 100644 --- a/Sources/Java2SwiftLib/JavaClassTranslator.swift +++ b/Sources/Java2SwiftLib/JavaClassTranslator.swift @@ -492,9 +492,10 @@ extension JavaClassTranslator { let throwsStr = javaConstructor.throwsCheckedException ? "throws" : "" let accessModifier = javaConstructor.isPublic ? "public " : "" let convenienceModifier = translateAsClass ? "convenience " : "" + let nonoverrideAttribute = translateAsClass ? "@_nonoverride " : "" return """ @JavaMethod - \(raw: accessModifier)\(raw: convenienceModifier)init(\(raw: parametersStr))\(raw: throwsStr) + \(raw: nonoverrideAttribute)\(raw: accessModifier)\(raw: convenienceModifier)init(\(raw: parametersStr))\(raw: throwsStr) """ } diff --git a/Tests/Java2SwiftTests/Java2SwiftTests.swift b/Tests/Java2SwiftTests/Java2SwiftTests.swift index a9274436..445c501c 100644 --- a/Tests/Java2SwiftTests/Java2SwiftTests.swift +++ b/Tests/Java2SwiftTests/Java2SwiftTests.swift @@ -280,7 +280,7 @@ class Java2SwiftTests: XCTestCase { """, """ @JavaMethod - public convenience init(environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(environment: JNIEnvironment? = nil) """, """ @JavaMethod @@ -314,7 +314,7 @@ class Java2SwiftTests: XCTestCase { """, """ @JavaMethod - public convenience init(environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(environment: JNIEnvironment? = nil) """, """ @JavaMethod From 0a1b74252aeca1643cffcbed37b3d760b1ac9e9c Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Thu, 31 Oct 2024 18:21:22 +0900 Subject: [PATCH 161/426] add benchmarking readme --- README.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/README.md b/README.md index 6bf9df2f..aae218ba 100644 --- a/README.md +++ b/README.md @@ -111,6 +111,28 @@ To run a simple example app showcasing the jextract (Java calling Swift) approac This will also generate the necessary sources (by invoking jextract, extracting the `Sources/ExampleSwiftLibrary`) and generating Java sources in `src/generated/java`. +## Benchmarks + +You can run Swift [ordo-one/package-benchmark](https://github.com/ordo-one/package-benchmark) and OpenJDK [JMH](https://github.com/openjdk/jmh) benchmarks in this project. + +Swift benchmarks are located under `Benchmarks/` and JMH benchmarks are currently part of the SwiftKit sample project: `Samples/SwiftKitSampleApp/src/jmh` because they depend on generated sources from the sample. + +To run **Swift benchmarks** you can: + +```bash +cd Benchmarks +swift package benchmark +``` + +In order to run JMH benchmarks you can: + +```bash +cd Samples/SwiftKitSampleApp +gradle jmh +``` + +Please read documentation of both performance testing tools and understand that results must be interpreted and not just taken at face value. Benchmarking is tricky and environment sensitive task, so please be careful when constructing and reading benchmarks and their results. If in doubt, please reach out on the forums. + ## User Guide More details about the project and how it can be used are available in [USER_GUIDE.md](USER_GUIDE.md) From 1d231bc21a78282e2d5c9070148d06a7557ce8e7 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Thu, 31 Oct 2024 18:31:15 +0900 Subject: [PATCH 162/426] Include benchmarks in PR validation: both JMH and Swift --- .github/workflows/pull_request.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 6fb3a0ff..7635abf2 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -69,6 +69,9 @@ jobs: run: | ./gradlew build -x test --no-daemon # just build ./gradlew build --info --no-daemon + - name: Gradle build (benchmarks) + run: | + ./gradlew compileJmh --info --no-daemon test-swift: name: Swift tests (swift:${{ matrix.swift_version }} jdk:${{matrix.jdk_vendor}} os:${{ matrix.os_version }}) @@ -130,3 +133,5 @@ jobs: - name: Build (Swift) Sample Apps run: | find Samples/ -name Package.swift -maxdepth 2 -exec swift build --package-path $(dirname {}) \;; + - name: Build (Swift) Benchmarks + run: "swift package --package-path Benchmarks/ benchmark list" From 80f91a0f3dfe5bb87f512ca48a8404a6a2328ab8 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Thu, 31 Oct 2024 18:47:07 +0900 Subject: [PATCH 163/426] disable Swift benchmark building in CI --- .github/workflows/pull_request.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 7635abf2..eea13444 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -133,5 +133,6 @@ jobs: - name: Build (Swift) Sample Apps run: | find Samples/ -name Package.swift -maxdepth 2 -exec swift build --package-path $(dirname {}) \;; - - name: Build (Swift) Benchmarks - run: "swift package --package-path Benchmarks/ benchmark list" + # TODO: Benchmark compile crashes in CI, enable when nightly toolchains in better shape. + # - name: Build (Swift) Benchmarks + # run: "swift package --package-path Benchmarks/ benchmark list" From 4c86346eaac4f8527f441625b13e9a8b73239b2e Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Thu, 31 Oct 2024 01:11:58 -0700 Subject: [PATCH 164/426] JavaKit: Enable imported Java classes as Swift classes by default Flip the switch to have Java2Swift generate Swift classes to represent each imported Java class, and make the (relatively few) adjustments needed to the JavaKit library to make that work. Implements issue #132. --- Sources/Java2Swift/JavaToSwift.swift | 2 +- Sources/JavaKit/AnyJavaObject.swift | 3 - .../JavaKit/Exceptions/Exception+Error.swift | 7 - .../JavaKit/JavaClass+Initialization.swift | 3 +- Sources/JavaKit/JavaObject+Inheritance.swift | 5 - Sources/JavaKit/JavaObject+MethodCalls.swift | 2 +- Sources/JavaKit/generated/Exception.swift | 63 +-- Sources/JavaKit/generated/JavaArray.swift | 29 +- Sources/JavaKit/generated/JavaBoolean.swift | 38 +- Sources/JavaKit/generated/JavaByte.swift | 48 +- Sources/JavaKit/generated/JavaCharacter.swift | 496 +++++++----------- Sources/JavaKit/generated/JavaClass.swift | 112 ++-- Sources/JavaKit/generated/JavaDouble.swift | 52 +- Sources/JavaKit/generated/JavaError.swift | 63 +-- Sources/JavaKit/generated/JavaFloat.swift | 54 +- Sources/JavaKit/generated/JavaInteger.swift | 48 +- Sources/JavaKit/generated/JavaLong.swift | 48 +- Sources/JavaKit/generated/JavaNumber.swift | 45 +- Sources/JavaKit/generated/JavaObject.swift | 28 +- Sources/JavaKit/generated/JavaShort.swift | 48 +- Sources/JavaKit/generated/JavaString.swift | 158 +++--- Sources/JavaKit/generated/JavaVoid.swift | 29 +- .../JavaKit/generated/RuntimeException.swift | 63 +-- Sources/JavaKit/generated/Throwable.swift | 54 +- .../generated/ArrayDeque.swift | 110 ++-- .../generated/ArrayList.swift | 102 ++-- .../JavaKitCollection/generated/BitSet.swift | 86 ++- .../JavaKitCollection/generated/HashMap.swift | 69 +-- .../JavaKitCollection/generated/HashSet.swift | 71 +-- .../generated/JavaDictionary.swift | 47 +- .../generated/PriorityQueue.swift | 80 +-- .../JavaKitCollection/generated/Stack.swift | 187 +------ .../JavaKitCollection/generated/TreeMap.swift | 156 ++---- .../JavaKitCollection/generated/TreeSet.swift | 102 +--- Sources/JavaKitJar/generated/Attributes.swift | 108 +--- Sources/JavaKitJar/generated/JarEntry.swift | 92 +--- Sources/JavaKitJar/generated/JarFile.swift | 57 +- .../JavaKitJar/generated/JarInputStream.swift | 77 +-- .../generated/JarOutputStream.swift | 63 +-- Sources/JavaKitJar/generated/Manifest.swift | 41 +- Sources/JavaKitJar/generated/ZipEntry.swift | 67 +-- Sources/JavaKitNetwork/generated/URI.swift | 90 ++-- Sources/JavaKitNetwork/generated/URL.swift | 66 +-- .../generated/URLClassLoader.swift | 72 +-- .../Constructor+Utilities.swift | 5 - .../JavaKitReflection/Method+Utilities.swift | 5 - .../generated/AccessibleObject.swift | 53 +- .../generated/Constructor.swift | 103 +--- .../generated/Executable.swift | 100 +--- .../JavaKitReflection/generated/Field.swift | 114 ++-- .../JavaKitReflection/generated/Method.swift | 114 +--- .../generated/Parameter.swift | 63 +-- Tests/JavaKitTests/BasicRuntimeTests.swift | 2 +- 53 files changed, 1026 insertions(+), 2774 deletions(-) diff --git a/Sources/Java2Swift/JavaToSwift.swift b/Sources/Java2Swift/JavaToSwift.swift index 112c015b..1434629f 100644 --- a/Sources/Java2Swift/JavaToSwift.swift +++ b/Sources/Java2Swift/JavaToSwift.swift @@ -184,7 +184,7 @@ struct JavaToSwift: ParsableCommand { let translator = JavaTranslator( swiftModuleName: moduleName, environment: environment, - translateAsClass: false + translateAsClass: true ) // Keep track of all of the Java classes that will have diff --git a/Sources/JavaKit/AnyJavaObject.swift b/Sources/JavaKit/AnyJavaObject.swift index 711b953d..6e39766a 100644 --- a/Sources/JavaKit/AnyJavaObject.swift +++ b/Sources/JavaKit/AnyJavaObject.swift @@ -42,9 +42,6 @@ public protocol AnyJavaObject { /// Retrieve the full Java class name (e.g., java.util.Vector) static var fullJavaClassName: String { get } - /// The Java superclass type - associatedtype JavaSuperclass: AnyJavaObject - /// Initialize a Java object from the Swift instance that keeps it alive. init(javaHolder: JavaObjectHolder) diff --git a/Sources/JavaKit/Exceptions/Exception+Error.swift b/Sources/JavaKit/Exceptions/Exception+Error.swift index 688ae9d0..e0075179 100644 --- a/Sources/JavaKit/Exceptions/Exception+Error.swift +++ b/Sources/JavaKit/Exceptions/Exception+Error.swift @@ -12,13 +12,6 @@ // //===----------------------------------------------------------------------===// -// Translate all Java Exception instances in a Swift error. -extension Exception: Error, CustomStringConvertible { - public var description: String { - return getMessage() - } -} - extension JavaClass { /// Determine whether this instance is a checked exception (which must be /// handled) vs. an unchecked exception (which is not handled). diff --git a/Sources/JavaKit/JavaClass+Initialization.swift b/Sources/JavaKit/JavaClass+Initialization.swift index a9302bd8..9881e0dc 100644 --- a/Sources/JavaKit/JavaClass+Initialization.swift +++ b/Sources/JavaKit/JavaClass+Initialization.swift @@ -18,7 +18,8 @@ extension JavaClass { public typealias ObjectType = T /// Lookup this Java class within the given environment. - public init(environment: JNIEnvironment? = nil) throws { + @_nonoverride + public convenience init(environment: JNIEnvironment? = nil) throws { let environment = try environment ?? JavaVirtualMachine.shared().environment() self.init( javaThis: try ObjectType.getJNIClass(in: environment), diff --git a/Sources/JavaKit/JavaObject+Inheritance.swift b/Sources/JavaKit/JavaObject+Inheritance.swift index cbd27c91..a8557b97 100644 --- a/Sources/JavaKit/JavaObject+Inheritance.swift +++ b/Sources/JavaKit/JavaObject+Inheritance.swift @@ -15,11 +15,6 @@ import JavaRuntime extension AnyJavaObject { - /// Retrieve the same object instance but with the superclass type. - public var `super`: JavaSuperclass { - JavaSuperclass(javaHolder: javaHolder) - } - /// Look up the other class type /// /// - Returns: `nil` when either `OtherClass` isn't known to the diff --git a/Sources/JavaKit/JavaObject+MethodCalls.swift b/Sources/JavaKit/JavaObject+MethodCalls.swift index 453358ce..28558d49 100644 --- a/Sources/JavaKit/JavaObject+MethodCalls.swift +++ b/Sources/JavaKit/JavaObject+MethodCalls.swift @@ -387,7 +387,7 @@ extension JavaClass { return FieldType(fromJNI: jniMethod(javaEnvironment, javaThis, fieldID), in: javaEnvironment) } - nonmutating set { + set { let fieldID = getJNIStaticFieldID(fieldName, fieldType: fieldType)! let jniMethod = FieldType.jniStaticFieldSet(in: javaEnvironment) jniMethod(javaEnvironment, javaThis, fieldID, newValue.getJNIValue(in: javaEnvironment)) diff --git a/Sources/JavaKit/generated/Exception.swift b/Sources/JavaKit/generated/Exception.swift index 694dc112..6fc9de8c 100644 --- a/Sources/JavaKit/generated/Exception.swift +++ b/Sources/JavaKit/generated/Exception.swift @@ -1,68 +1,17 @@ // Auto-generated by Java-to-Swift wrapper generator. import JavaRuntime -@JavaClass("java.lang.Exception", extends: Throwable.self) -public struct Exception { +@JavaClass("java.lang.Exception") +open class Exception: Throwable { @JavaMethod - public init(_ arg0: Throwable?, environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(_ arg0: Throwable?, environment: JNIEnvironment? = nil) @JavaMethod - public init(_ arg0: String, _ arg1: Throwable?, environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(_ arg0: String, _ arg1: Throwable?, environment: JNIEnvironment? = nil) @JavaMethod - public init(_ arg0: String, environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(_ arg0: String, environment: JNIEnvironment? = nil) @JavaMethod - public init(environment: JNIEnvironment? = nil) - - @JavaMethod - public func printStackTrace() - - @JavaMethod - public func fillInStackTrace() -> Throwable! - - @JavaMethod - public func getCause() -> Throwable! - - @JavaMethod - public func initCause(_ arg0: Throwable?) -> Throwable! - - @JavaMethod - public func toString() -> String - - @JavaMethod - public func getMessage() -> String - - @JavaMethod - public func getSuppressed() -> [Throwable?] - - @JavaMethod - public func getLocalizedMessage() -> String - - @JavaMethod - public func addSuppressed(_ arg0: Throwable?) - - @JavaMethod - public func equals(_ arg0: JavaObject?) -> Bool - - @JavaMethod - public func hashCode() -> Int32 - - @JavaMethod - public func getClass() -> JavaClass! - - @JavaMethod - public func notify() - - @JavaMethod - public func notifyAll() - - @JavaMethod - public func wait(_ arg0: Int64) throws - - @JavaMethod - public func wait(_ arg0: Int64, _ arg1: Int32) throws - - @JavaMethod - public func wait() throws + @_nonoverride public convenience init(environment: JNIEnvironment? = nil) } diff --git a/Sources/JavaKit/generated/JavaArray.swift b/Sources/JavaKit/generated/JavaArray.swift index 805b3929..147f24df 100644 --- a/Sources/JavaKit/generated/JavaArray.swift +++ b/Sources/JavaKit/generated/JavaArray.swift @@ -1,34 +1,9 @@ // Auto-generated by Java-to-Swift wrapper generator. import JavaRuntime -@JavaClass("java.lang.reflect.Array", extends: JavaObject.self) -public struct JavaArray { - @JavaMethod - public func equals(_ arg0: JavaObject?) -> Bool +@JavaClass("java.lang.reflect.Array") +open class JavaArray: JavaObject { - @JavaMethod - public func toString() -> String - - @JavaMethod - public func hashCode() -> Int32 - - @JavaMethod - public func getClass() -> JavaClass! - - @JavaMethod - public func notify() - - @JavaMethod - public func notifyAll() - - @JavaMethod - public func wait(_ arg0: Int64) throws - - @JavaMethod - public func wait(_ arg0: Int64, _ arg1: Int32) throws - - @JavaMethod - public func wait() throws } extension JavaClass { @JavaStaticMethod diff --git a/Sources/JavaKit/generated/JavaBoolean.swift b/Sources/JavaKit/generated/JavaBoolean.swift index e942fb44..0ab51f6d 100644 --- a/Sources/JavaKit/generated/JavaBoolean.swift +++ b/Sources/JavaKit/generated/JavaBoolean.swift @@ -1,49 +1,31 @@ // Auto-generated by Java-to-Swift wrapper generator. import JavaRuntime -@JavaClass("java.lang.Boolean", extends: JavaObject.self) -public struct JavaBoolean { +@JavaClass("java.lang.Boolean") +open class JavaBoolean: JavaObject { @JavaMethod - public init(_ arg0: Bool, environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(_ arg0: Bool, environment: JNIEnvironment? = nil) @JavaMethod - public init(_ arg0: String, environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(_ arg0: String, environment: JNIEnvironment? = nil) @JavaMethod - public func equals(_ arg0: JavaObject?) -> Bool + open override func equals(_ arg0: JavaObject?) -> Bool @JavaMethod - public func toString() -> String + open override func toString() -> String @JavaMethod - public func hashCode() -> Int32 + open override func hashCode() -> Int32 @JavaMethod - public func compareTo(_ arg0: JavaBoolean?) -> Int32 + open func compareTo(_ arg0: JavaBoolean?) -> Int32 @JavaMethod - public func compareTo(_ arg0: JavaObject?) -> Int32 + open func compareTo(_ arg0: JavaObject?) -> Int32 @JavaMethod - public func booleanValue() -> Bool - - @JavaMethod - public func getClass() -> JavaClass! - - @JavaMethod - public func notify() - - @JavaMethod - public func notifyAll() - - @JavaMethod - public func wait(_ arg0: Int64) throws - - @JavaMethod - public func wait(_ arg0: Int64, _ arg1: Int32) throws - - @JavaMethod - public func wait() throws + open func booleanValue() -> Bool } extension JavaClass { @JavaStaticField(isFinal: true) diff --git a/Sources/JavaKit/generated/JavaByte.swift b/Sources/JavaKit/generated/JavaByte.swift index 7b832217..e75c5996 100644 --- a/Sources/JavaKit/generated/JavaByte.swift +++ b/Sources/JavaKit/generated/JavaByte.swift @@ -1,64 +1,46 @@ // Auto-generated by Java-to-Swift wrapper generator. import JavaRuntime -@JavaClass("java.lang.Byte", extends: JavaNumber.self) -public struct JavaByte { +@JavaClass("java.lang.Byte") +open class JavaByte: JavaNumber { @JavaMethod - public init(_ arg0: Int8, environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(_ arg0: Int8, environment: JNIEnvironment? = nil) @JavaMethod - public init(_ arg0: String, environment: JNIEnvironment? = nil) throws + @_nonoverride public convenience init(_ arg0: String, environment: JNIEnvironment? = nil) throws @JavaMethod - public func equals(_ arg0: JavaObject?) -> Bool + open override func equals(_ arg0: JavaObject?) -> Bool @JavaMethod - public func toString() -> String + open override func toString() -> String @JavaMethod - public func hashCode() -> Int32 + open override func hashCode() -> Int32 @JavaMethod - public func compareTo(_ arg0: JavaByte?) -> Int32 + open func compareTo(_ arg0: JavaByte?) -> Int32 @JavaMethod - public func compareTo(_ arg0: JavaObject?) -> Int32 + open func compareTo(_ arg0: JavaObject?) -> Int32 @JavaMethod - public func byteValue() -> Int8 + open override func byteValue() -> Int8 @JavaMethod - public func shortValue() -> Int16 + open override func shortValue() -> Int16 @JavaMethod - public func intValue() -> Int32 + open override func intValue() -> Int32 @JavaMethod - public func longValue() -> Int64 + open override func longValue() -> Int64 @JavaMethod - public func floatValue() -> Float + open override func floatValue() -> Float @JavaMethod - public func doubleValue() -> Double - - @JavaMethod - public func getClass() -> JavaClass! - - @JavaMethod - public func notify() - - @JavaMethod - public func notifyAll() - - @JavaMethod - public func wait(_ arg0: Int64) throws - - @JavaMethod - public func wait(_ arg0: Int64, _ arg1: Int32) throws - - @JavaMethod - public func wait() throws + open override func doubleValue() -> Double } extension JavaClass { @JavaStaticField(isFinal: true) diff --git a/Sources/JavaKit/generated/JavaCharacter.swift b/Sources/JavaKit/generated/JavaCharacter.swift index 82b92a23..eead7dfd 100644 --- a/Sources/JavaKit/generated/JavaCharacter.swift +++ b/Sources/JavaKit/generated/JavaCharacter.swift @@ -1,107 +1,46 @@ // Auto-generated by Java-to-Swift wrapper generator. import JavaRuntime -@JavaClass("java.lang.Character", extends: JavaObject.self) -public struct JavaCharacter { +@JavaClass("java.lang.Character") +open class JavaCharacter: JavaObject { @JavaMethod - public init(_ arg0: UInt16, environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(_ arg0: UInt16, environment: JNIEnvironment? = nil) @JavaMethod - public func equals(_ arg0: JavaObject?) -> Bool + open override func equals(_ arg0: JavaObject?) -> Bool @JavaMethod - public func toString() -> String + open override func toString() -> String @JavaMethod - public func hashCode() -> Int32 + open override func hashCode() -> Int32 @JavaMethod - public func compareTo(_ arg0: JavaCharacter?) -> Int32 + open func compareTo(_ arg0: JavaCharacter?) -> Int32 @JavaMethod - public func compareTo(_ arg0: JavaObject?) -> Int32 + open func compareTo(_ arg0: JavaObject?) -> Int32 @JavaMethod - public func charValue() -> UInt16 - - @JavaMethod - public func getClass() -> JavaClass! - - @JavaMethod - public func notify() - - @JavaMethod - public func notifyAll() - - @JavaMethod - public func wait(_ arg0: Int64) throws - - @JavaMethod - public func wait(_ arg0: Int64, _ arg1: Int32) throws - - @JavaMethod - public func wait() throws + open func charValue() -> UInt16 } extension JavaCharacter { - @JavaClass("java.lang.Character$Subset", extends: JavaObject.self) - public struct Subset { - @JavaMethod - public func equals(_ arg0: JavaObject?) -> Bool - - @JavaMethod - public func toString() -> String - + @JavaClass("java.lang.Character$Subset") + open class Subset: JavaObject { @JavaMethod - public func hashCode() -> Int32 + open override func equals(_ arg0: JavaObject?) -> Bool @JavaMethod - public func getClass() -> JavaClass! + open override func toString() -> String @JavaMethod - public func notify() - - @JavaMethod - public func notifyAll() - - @JavaMethod - public func wait(_ arg0: Int64) throws - - @JavaMethod - public func wait(_ arg0: Int64, _ arg1: Int32) throws - - @JavaMethod - public func wait() throws + open override func hashCode() -> Int32 } } extension JavaCharacter { - @JavaClass("java.lang.Character$UnicodeBlock", extends: JavaCharacter.Subset.self) - public struct UnicodeBlock { - @JavaMethod - public func equals(_ arg0: JavaObject?) -> Bool - - @JavaMethod - public func toString() -> String - - @JavaMethod - public func hashCode() -> Int32 - - @JavaMethod - public func getClass() -> JavaClass! + @JavaClass("java.lang.Character$UnicodeBlock") + open class UnicodeBlock: JavaCharacter.Subset { - @JavaMethod - public func notify() - - @JavaMethod - public func notifyAll() - - @JavaMethod - public func wait(_ arg0: Int64) throws - - @JavaMethod - public func wait(_ arg0: Int64, _ arg1: Int32) throws - - @JavaMethod - public func wait() throws } } extension JavaClass { @@ -1102,8 +1041,8 @@ extension JavaClass { public func of(_ arg0: UInt16) -> JavaCharacter.UnicodeBlock! } extension JavaCharacter { - @JavaClass("java.lang.Character$UnicodeScript", extends: JavaObject.self) - public struct UnicodeScript { + @JavaClass("java.lang.Character$UnicodeScript") + open class UnicodeScript: JavaObject { public enum UnicodeScriptCases: Equatable { case COMMON case LATIN @@ -1606,7 +1545,7 @@ extension JavaCharacter { } } - public init(_ enumValue: UnicodeScriptCases, environment: JNIEnvironment? = nil) { + public convenience init(_ enumValue: UnicodeScriptCases, environment: JNIEnvironment? = nil) { let _environment = if let environment { environment } else { @@ -1616,1060 +1555,997 @@ extension JavaCharacter { switch enumValue { case .COMMON: if let COMMON = classObj.COMMON { - self = COMMON + self.init(javaHolder: COMMON.javaHolder) } else { fatalError("Enum value COMMON was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .LATIN: if let LATIN = classObj.LATIN { - self = LATIN + self.init(javaHolder: LATIN.javaHolder) } else { fatalError("Enum value LATIN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .GREEK: if let GREEK = classObj.GREEK { - self = GREEK + self.init(javaHolder: GREEK.javaHolder) } else { fatalError("Enum value GREEK was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .CYRILLIC: if let CYRILLIC = classObj.CYRILLIC { - self = CYRILLIC + self.init(javaHolder: CYRILLIC.javaHolder) } else { fatalError("Enum value CYRILLIC was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .ARMENIAN: if let ARMENIAN = classObj.ARMENIAN { - self = ARMENIAN + self.init(javaHolder: ARMENIAN.javaHolder) } else { fatalError("Enum value ARMENIAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .HEBREW: if let HEBREW = classObj.HEBREW { - self = HEBREW + self.init(javaHolder: HEBREW.javaHolder) } else { fatalError("Enum value HEBREW was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .ARABIC: if let ARABIC = classObj.ARABIC { - self = ARABIC + self.init(javaHolder: ARABIC.javaHolder) } else { fatalError("Enum value ARABIC was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .SYRIAC: if let SYRIAC = classObj.SYRIAC { - self = SYRIAC + self.init(javaHolder: SYRIAC.javaHolder) } else { fatalError("Enum value SYRIAC was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .THAANA: if let THAANA = classObj.THAANA { - self = THAANA + self.init(javaHolder: THAANA.javaHolder) } else { fatalError("Enum value THAANA was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .DEVANAGARI: if let DEVANAGARI = classObj.DEVANAGARI { - self = DEVANAGARI + self.init(javaHolder: DEVANAGARI.javaHolder) } else { fatalError("Enum value DEVANAGARI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .BENGALI: if let BENGALI = classObj.BENGALI { - self = BENGALI + self.init(javaHolder: BENGALI.javaHolder) } else { fatalError("Enum value BENGALI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .GURMUKHI: if let GURMUKHI = classObj.GURMUKHI { - self = GURMUKHI + self.init(javaHolder: GURMUKHI.javaHolder) } else { fatalError("Enum value GURMUKHI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .GUJARATI: if let GUJARATI = classObj.GUJARATI { - self = GUJARATI + self.init(javaHolder: GUJARATI.javaHolder) } else { fatalError("Enum value GUJARATI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .ORIYA: if let ORIYA = classObj.ORIYA { - self = ORIYA + self.init(javaHolder: ORIYA.javaHolder) } else { fatalError("Enum value ORIYA was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .TAMIL: if let TAMIL = classObj.TAMIL { - self = TAMIL + self.init(javaHolder: TAMIL.javaHolder) } else { fatalError("Enum value TAMIL was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .TELUGU: if let TELUGU = classObj.TELUGU { - self = TELUGU + self.init(javaHolder: TELUGU.javaHolder) } else { fatalError("Enum value TELUGU was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .KANNADA: if let KANNADA = classObj.KANNADA { - self = KANNADA + self.init(javaHolder: KANNADA.javaHolder) } else { fatalError("Enum value KANNADA was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .MALAYALAM: if let MALAYALAM = classObj.MALAYALAM { - self = MALAYALAM + self.init(javaHolder: MALAYALAM.javaHolder) } else { fatalError("Enum value MALAYALAM was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .SINHALA: if let SINHALA = classObj.SINHALA { - self = SINHALA + self.init(javaHolder: SINHALA.javaHolder) } else { fatalError("Enum value SINHALA was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .THAI: if let THAI = classObj.THAI { - self = THAI + self.init(javaHolder: THAI.javaHolder) } else { fatalError("Enum value THAI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .LAO: if let LAO = classObj.LAO { - self = LAO + self.init(javaHolder: LAO.javaHolder) } else { fatalError("Enum value LAO was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .TIBETAN: if let TIBETAN = classObj.TIBETAN { - self = TIBETAN + self.init(javaHolder: TIBETAN.javaHolder) } else { fatalError("Enum value TIBETAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .MYANMAR: if let MYANMAR = classObj.MYANMAR { - self = MYANMAR + self.init(javaHolder: MYANMAR.javaHolder) } else { fatalError("Enum value MYANMAR was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .GEORGIAN: if let GEORGIAN = classObj.GEORGIAN { - self = GEORGIAN + self.init(javaHolder: GEORGIAN.javaHolder) } else { fatalError("Enum value GEORGIAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .HANGUL: if let HANGUL = classObj.HANGUL { - self = HANGUL + self.init(javaHolder: HANGUL.javaHolder) } else { fatalError("Enum value HANGUL was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .ETHIOPIC: if let ETHIOPIC = classObj.ETHIOPIC { - self = ETHIOPIC + self.init(javaHolder: ETHIOPIC.javaHolder) } else { fatalError("Enum value ETHIOPIC was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .CHEROKEE: if let CHEROKEE = classObj.CHEROKEE { - self = CHEROKEE + self.init(javaHolder: CHEROKEE.javaHolder) } else { fatalError("Enum value CHEROKEE was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .CANADIAN_ABORIGINAL: if let CANADIAN_ABORIGINAL = classObj.CANADIAN_ABORIGINAL { - self = CANADIAN_ABORIGINAL + self.init(javaHolder: CANADIAN_ABORIGINAL.javaHolder) } else { fatalError("Enum value CANADIAN_ABORIGINAL was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .OGHAM: if let OGHAM = classObj.OGHAM { - self = OGHAM + self.init(javaHolder: OGHAM.javaHolder) } else { fatalError("Enum value OGHAM was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .RUNIC: if let RUNIC = classObj.RUNIC { - self = RUNIC + self.init(javaHolder: RUNIC.javaHolder) } else { fatalError("Enum value RUNIC was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .KHMER: if let KHMER = classObj.KHMER { - self = KHMER + self.init(javaHolder: KHMER.javaHolder) } else { fatalError("Enum value KHMER was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .MONGOLIAN: if let MONGOLIAN = classObj.MONGOLIAN { - self = MONGOLIAN + self.init(javaHolder: MONGOLIAN.javaHolder) } else { fatalError("Enum value MONGOLIAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .HIRAGANA: if let HIRAGANA = classObj.HIRAGANA { - self = HIRAGANA + self.init(javaHolder: HIRAGANA.javaHolder) } else { fatalError("Enum value HIRAGANA was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .KATAKANA: if let KATAKANA = classObj.KATAKANA { - self = KATAKANA + self.init(javaHolder: KATAKANA.javaHolder) } else { fatalError("Enum value KATAKANA was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .BOPOMOFO: if let BOPOMOFO = classObj.BOPOMOFO { - self = BOPOMOFO + self.init(javaHolder: BOPOMOFO.javaHolder) } else { fatalError("Enum value BOPOMOFO was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .HAN: if let HAN = classObj.HAN { - self = HAN + self.init(javaHolder: HAN.javaHolder) } else { fatalError("Enum value HAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .YI: if let YI = classObj.YI { - self = YI + self.init(javaHolder: YI.javaHolder) } else { fatalError("Enum value YI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .OLD_ITALIC: if let OLD_ITALIC = classObj.OLD_ITALIC { - self = OLD_ITALIC + self.init(javaHolder: OLD_ITALIC.javaHolder) } else { fatalError("Enum value OLD_ITALIC was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .GOTHIC: if let GOTHIC = classObj.GOTHIC { - self = GOTHIC + self.init(javaHolder: GOTHIC.javaHolder) } else { fatalError("Enum value GOTHIC was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .DESERET: if let DESERET = classObj.DESERET { - self = DESERET + self.init(javaHolder: DESERET.javaHolder) } else { fatalError("Enum value DESERET was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .INHERITED: if let INHERITED = classObj.INHERITED { - self = INHERITED + self.init(javaHolder: INHERITED.javaHolder) } else { fatalError("Enum value INHERITED was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .TAGALOG: if let TAGALOG = classObj.TAGALOG { - self = TAGALOG + self.init(javaHolder: TAGALOG.javaHolder) } else { fatalError("Enum value TAGALOG was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .HANUNOO: if let HANUNOO = classObj.HANUNOO { - self = HANUNOO + self.init(javaHolder: HANUNOO.javaHolder) } else { fatalError("Enum value HANUNOO was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .BUHID: if let BUHID = classObj.BUHID { - self = BUHID + self.init(javaHolder: BUHID.javaHolder) } else { fatalError("Enum value BUHID was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .TAGBANWA: if let TAGBANWA = classObj.TAGBANWA { - self = TAGBANWA + self.init(javaHolder: TAGBANWA.javaHolder) } else { fatalError("Enum value TAGBANWA was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .LIMBU: if let LIMBU = classObj.LIMBU { - self = LIMBU + self.init(javaHolder: LIMBU.javaHolder) } else { fatalError("Enum value LIMBU was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .TAI_LE: if let TAI_LE = classObj.TAI_LE { - self = TAI_LE + self.init(javaHolder: TAI_LE.javaHolder) } else { fatalError("Enum value TAI_LE was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .LINEAR_B: if let LINEAR_B = classObj.LINEAR_B { - self = LINEAR_B + self.init(javaHolder: LINEAR_B.javaHolder) } else { fatalError("Enum value LINEAR_B was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .UGARITIC: if let UGARITIC = classObj.UGARITIC { - self = UGARITIC + self.init(javaHolder: UGARITIC.javaHolder) } else { fatalError("Enum value UGARITIC was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .SHAVIAN: if let SHAVIAN = classObj.SHAVIAN { - self = SHAVIAN + self.init(javaHolder: SHAVIAN.javaHolder) } else { fatalError("Enum value SHAVIAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .OSMANYA: if let OSMANYA = classObj.OSMANYA { - self = OSMANYA + self.init(javaHolder: OSMANYA.javaHolder) } else { fatalError("Enum value OSMANYA was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .CYPRIOT: if let CYPRIOT = classObj.CYPRIOT { - self = CYPRIOT + self.init(javaHolder: CYPRIOT.javaHolder) } else { fatalError("Enum value CYPRIOT was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .BRAILLE: if let BRAILLE = classObj.BRAILLE { - self = BRAILLE + self.init(javaHolder: BRAILLE.javaHolder) } else { fatalError("Enum value BRAILLE was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .BUGINESE: if let BUGINESE = classObj.BUGINESE { - self = BUGINESE + self.init(javaHolder: BUGINESE.javaHolder) } else { fatalError("Enum value BUGINESE was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .COPTIC: if let COPTIC = classObj.COPTIC { - self = COPTIC + self.init(javaHolder: COPTIC.javaHolder) } else { fatalError("Enum value COPTIC was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .NEW_TAI_LUE: if let NEW_TAI_LUE = classObj.NEW_TAI_LUE { - self = NEW_TAI_LUE + self.init(javaHolder: NEW_TAI_LUE.javaHolder) } else { fatalError("Enum value NEW_TAI_LUE was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .GLAGOLITIC: if let GLAGOLITIC = classObj.GLAGOLITIC { - self = GLAGOLITIC + self.init(javaHolder: GLAGOLITIC.javaHolder) } else { fatalError("Enum value GLAGOLITIC was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .TIFINAGH: if let TIFINAGH = classObj.TIFINAGH { - self = TIFINAGH + self.init(javaHolder: TIFINAGH.javaHolder) } else { fatalError("Enum value TIFINAGH was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .SYLOTI_NAGRI: if let SYLOTI_NAGRI = classObj.SYLOTI_NAGRI { - self = SYLOTI_NAGRI + self.init(javaHolder: SYLOTI_NAGRI.javaHolder) } else { fatalError("Enum value SYLOTI_NAGRI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .OLD_PERSIAN: if let OLD_PERSIAN = classObj.OLD_PERSIAN { - self = OLD_PERSIAN + self.init(javaHolder: OLD_PERSIAN.javaHolder) } else { fatalError("Enum value OLD_PERSIAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .KHAROSHTHI: if let KHAROSHTHI = classObj.KHAROSHTHI { - self = KHAROSHTHI + self.init(javaHolder: KHAROSHTHI.javaHolder) } else { fatalError("Enum value KHAROSHTHI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .BALINESE: if let BALINESE = classObj.BALINESE { - self = BALINESE + self.init(javaHolder: BALINESE.javaHolder) } else { fatalError("Enum value BALINESE was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .CUNEIFORM: if let CUNEIFORM = classObj.CUNEIFORM { - self = CUNEIFORM + self.init(javaHolder: CUNEIFORM.javaHolder) } else { fatalError("Enum value CUNEIFORM was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .PHOENICIAN: if let PHOENICIAN = classObj.PHOENICIAN { - self = PHOENICIAN + self.init(javaHolder: PHOENICIAN.javaHolder) } else { fatalError("Enum value PHOENICIAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .PHAGS_PA: if let PHAGS_PA = classObj.PHAGS_PA { - self = PHAGS_PA + self.init(javaHolder: PHAGS_PA.javaHolder) } else { fatalError("Enum value PHAGS_PA was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .NKO: if let NKO = classObj.NKO { - self = NKO + self.init(javaHolder: NKO.javaHolder) } else { fatalError("Enum value NKO was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .SUNDANESE: if let SUNDANESE = classObj.SUNDANESE { - self = SUNDANESE + self.init(javaHolder: SUNDANESE.javaHolder) } else { fatalError("Enum value SUNDANESE was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .BATAK: if let BATAK = classObj.BATAK { - self = BATAK + self.init(javaHolder: BATAK.javaHolder) } else { fatalError("Enum value BATAK was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .LEPCHA: if let LEPCHA = classObj.LEPCHA { - self = LEPCHA + self.init(javaHolder: LEPCHA.javaHolder) } else { fatalError("Enum value LEPCHA was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .OL_CHIKI: if let OL_CHIKI = classObj.OL_CHIKI { - self = OL_CHIKI + self.init(javaHolder: OL_CHIKI.javaHolder) } else { fatalError("Enum value OL_CHIKI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .VAI: if let VAI = classObj.VAI { - self = VAI + self.init(javaHolder: VAI.javaHolder) } else { fatalError("Enum value VAI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .SAURASHTRA: if let SAURASHTRA = classObj.SAURASHTRA { - self = SAURASHTRA + self.init(javaHolder: SAURASHTRA.javaHolder) } else { fatalError("Enum value SAURASHTRA was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .KAYAH_LI: if let KAYAH_LI = classObj.KAYAH_LI { - self = KAYAH_LI + self.init(javaHolder: KAYAH_LI.javaHolder) } else { fatalError("Enum value KAYAH_LI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .REJANG: if let REJANG = classObj.REJANG { - self = REJANG + self.init(javaHolder: REJANG.javaHolder) } else { fatalError("Enum value REJANG was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .LYCIAN: if let LYCIAN = classObj.LYCIAN { - self = LYCIAN + self.init(javaHolder: LYCIAN.javaHolder) } else { fatalError("Enum value LYCIAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .CARIAN: if let CARIAN = classObj.CARIAN { - self = CARIAN + self.init(javaHolder: CARIAN.javaHolder) } else { fatalError("Enum value CARIAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .LYDIAN: if let LYDIAN = classObj.LYDIAN { - self = LYDIAN + self.init(javaHolder: LYDIAN.javaHolder) } else { fatalError("Enum value LYDIAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .CHAM: if let CHAM = classObj.CHAM { - self = CHAM + self.init(javaHolder: CHAM.javaHolder) } else { fatalError("Enum value CHAM was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .TAI_THAM: if let TAI_THAM = classObj.TAI_THAM { - self = TAI_THAM + self.init(javaHolder: TAI_THAM.javaHolder) } else { fatalError("Enum value TAI_THAM was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .TAI_VIET: if let TAI_VIET = classObj.TAI_VIET { - self = TAI_VIET + self.init(javaHolder: TAI_VIET.javaHolder) } else { fatalError("Enum value TAI_VIET was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .AVESTAN: if let AVESTAN = classObj.AVESTAN { - self = AVESTAN + self.init(javaHolder: AVESTAN.javaHolder) } else { fatalError("Enum value AVESTAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .EGYPTIAN_HIEROGLYPHS: if let EGYPTIAN_HIEROGLYPHS = classObj.EGYPTIAN_HIEROGLYPHS { - self = EGYPTIAN_HIEROGLYPHS + self.init(javaHolder: EGYPTIAN_HIEROGLYPHS.javaHolder) } else { fatalError("Enum value EGYPTIAN_HIEROGLYPHS was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .SAMARITAN: if let SAMARITAN = classObj.SAMARITAN { - self = SAMARITAN + self.init(javaHolder: SAMARITAN.javaHolder) } else { fatalError("Enum value SAMARITAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .MANDAIC: if let MANDAIC = classObj.MANDAIC { - self = MANDAIC + self.init(javaHolder: MANDAIC.javaHolder) } else { fatalError("Enum value MANDAIC was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .LISU: if let LISU = classObj.LISU { - self = LISU + self.init(javaHolder: LISU.javaHolder) } else { fatalError("Enum value LISU was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .BAMUM: if let BAMUM = classObj.BAMUM { - self = BAMUM + self.init(javaHolder: BAMUM.javaHolder) } else { fatalError("Enum value BAMUM was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .JAVANESE: if let JAVANESE = classObj.JAVANESE { - self = JAVANESE + self.init(javaHolder: JAVANESE.javaHolder) } else { fatalError("Enum value JAVANESE was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .MEETEI_MAYEK: if let MEETEI_MAYEK = classObj.MEETEI_MAYEK { - self = MEETEI_MAYEK + self.init(javaHolder: MEETEI_MAYEK.javaHolder) } else { fatalError("Enum value MEETEI_MAYEK was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .IMPERIAL_ARAMAIC: if let IMPERIAL_ARAMAIC = classObj.IMPERIAL_ARAMAIC { - self = IMPERIAL_ARAMAIC + self.init(javaHolder: IMPERIAL_ARAMAIC.javaHolder) } else { fatalError("Enum value IMPERIAL_ARAMAIC was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .OLD_SOUTH_ARABIAN: if let OLD_SOUTH_ARABIAN = classObj.OLD_SOUTH_ARABIAN { - self = OLD_SOUTH_ARABIAN + self.init(javaHolder: OLD_SOUTH_ARABIAN.javaHolder) } else { fatalError("Enum value OLD_SOUTH_ARABIAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .INSCRIPTIONAL_PARTHIAN: if let INSCRIPTIONAL_PARTHIAN = classObj.INSCRIPTIONAL_PARTHIAN { - self = INSCRIPTIONAL_PARTHIAN + self.init(javaHolder: INSCRIPTIONAL_PARTHIAN.javaHolder) } else { fatalError("Enum value INSCRIPTIONAL_PARTHIAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .INSCRIPTIONAL_PAHLAVI: if let INSCRIPTIONAL_PAHLAVI = classObj.INSCRIPTIONAL_PAHLAVI { - self = INSCRIPTIONAL_PAHLAVI + self.init(javaHolder: INSCRIPTIONAL_PAHLAVI.javaHolder) } else { fatalError("Enum value INSCRIPTIONAL_PAHLAVI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .OLD_TURKIC: if let OLD_TURKIC = classObj.OLD_TURKIC { - self = OLD_TURKIC + self.init(javaHolder: OLD_TURKIC.javaHolder) } else { fatalError("Enum value OLD_TURKIC was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .BRAHMI: if let BRAHMI = classObj.BRAHMI { - self = BRAHMI + self.init(javaHolder: BRAHMI.javaHolder) } else { fatalError("Enum value BRAHMI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .KAITHI: if let KAITHI = classObj.KAITHI { - self = KAITHI + self.init(javaHolder: KAITHI.javaHolder) } else { fatalError("Enum value KAITHI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .MEROITIC_HIEROGLYPHS: if let MEROITIC_HIEROGLYPHS = classObj.MEROITIC_HIEROGLYPHS { - self = MEROITIC_HIEROGLYPHS + self.init(javaHolder: MEROITIC_HIEROGLYPHS.javaHolder) } else { fatalError("Enum value MEROITIC_HIEROGLYPHS was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .MEROITIC_CURSIVE: if let MEROITIC_CURSIVE = classObj.MEROITIC_CURSIVE { - self = MEROITIC_CURSIVE + self.init(javaHolder: MEROITIC_CURSIVE.javaHolder) } else { fatalError("Enum value MEROITIC_CURSIVE was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .SORA_SOMPENG: if let SORA_SOMPENG = classObj.SORA_SOMPENG { - self = SORA_SOMPENG + self.init(javaHolder: SORA_SOMPENG.javaHolder) } else { fatalError("Enum value SORA_SOMPENG was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .CHAKMA: if let CHAKMA = classObj.CHAKMA { - self = CHAKMA + self.init(javaHolder: CHAKMA.javaHolder) } else { fatalError("Enum value CHAKMA was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .SHARADA: if let SHARADA = classObj.SHARADA { - self = SHARADA + self.init(javaHolder: SHARADA.javaHolder) } else { fatalError("Enum value SHARADA was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .TAKRI: if let TAKRI = classObj.TAKRI { - self = TAKRI + self.init(javaHolder: TAKRI.javaHolder) } else { fatalError("Enum value TAKRI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .MIAO: if let MIAO = classObj.MIAO { - self = MIAO + self.init(javaHolder: MIAO.javaHolder) } else { fatalError("Enum value MIAO was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .CAUCASIAN_ALBANIAN: if let CAUCASIAN_ALBANIAN = classObj.CAUCASIAN_ALBANIAN { - self = CAUCASIAN_ALBANIAN + self.init(javaHolder: CAUCASIAN_ALBANIAN.javaHolder) } else { fatalError("Enum value CAUCASIAN_ALBANIAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .BASSA_VAH: if let BASSA_VAH = classObj.BASSA_VAH { - self = BASSA_VAH + self.init(javaHolder: BASSA_VAH.javaHolder) } else { fatalError("Enum value BASSA_VAH was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .DUPLOYAN: if let DUPLOYAN = classObj.DUPLOYAN { - self = DUPLOYAN + self.init(javaHolder: DUPLOYAN.javaHolder) } else { fatalError("Enum value DUPLOYAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .ELBASAN: if let ELBASAN = classObj.ELBASAN { - self = ELBASAN + self.init(javaHolder: ELBASAN.javaHolder) } else { fatalError("Enum value ELBASAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .GRANTHA: if let GRANTHA = classObj.GRANTHA { - self = GRANTHA + self.init(javaHolder: GRANTHA.javaHolder) } else { fatalError("Enum value GRANTHA was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .PAHAWH_HMONG: if let PAHAWH_HMONG = classObj.PAHAWH_HMONG { - self = PAHAWH_HMONG + self.init(javaHolder: PAHAWH_HMONG.javaHolder) } else { fatalError("Enum value PAHAWH_HMONG was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .KHOJKI: if let KHOJKI = classObj.KHOJKI { - self = KHOJKI + self.init(javaHolder: KHOJKI.javaHolder) } else { fatalError("Enum value KHOJKI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .LINEAR_A: if let LINEAR_A = classObj.LINEAR_A { - self = LINEAR_A + self.init(javaHolder: LINEAR_A.javaHolder) } else { fatalError("Enum value LINEAR_A was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .MAHAJANI: if let MAHAJANI = classObj.MAHAJANI { - self = MAHAJANI + self.init(javaHolder: MAHAJANI.javaHolder) } else { fatalError("Enum value MAHAJANI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .MANICHAEAN: if let MANICHAEAN = classObj.MANICHAEAN { - self = MANICHAEAN + self.init(javaHolder: MANICHAEAN.javaHolder) } else { fatalError("Enum value MANICHAEAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .MENDE_KIKAKUI: if let MENDE_KIKAKUI = classObj.MENDE_KIKAKUI { - self = MENDE_KIKAKUI + self.init(javaHolder: MENDE_KIKAKUI.javaHolder) } else { fatalError("Enum value MENDE_KIKAKUI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .MODI: if let MODI = classObj.MODI { - self = MODI + self.init(javaHolder: MODI.javaHolder) } else { fatalError("Enum value MODI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .MRO: if let MRO = classObj.MRO { - self = MRO + self.init(javaHolder: MRO.javaHolder) } else { fatalError("Enum value MRO was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .OLD_NORTH_ARABIAN: if let OLD_NORTH_ARABIAN = classObj.OLD_NORTH_ARABIAN { - self = OLD_NORTH_ARABIAN + self.init(javaHolder: OLD_NORTH_ARABIAN.javaHolder) } else { fatalError("Enum value OLD_NORTH_ARABIAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .NABATAEAN: if let NABATAEAN = classObj.NABATAEAN { - self = NABATAEAN + self.init(javaHolder: NABATAEAN.javaHolder) } else { fatalError("Enum value NABATAEAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .PALMYRENE: if let PALMYRENE = classObj.PALMYRENE { - self = PALMYRENE + self.init(javaHolder: PALMYRENE.javaHolder) } else { fatalError("Enum value PALMYRENE was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .PAU_CIN_HAU: if let PAU_CIN_HAU = classObj.PAU_CIN_HAU { - self = PAU_CIN_HAU + self.init(javaHolder: PAU_CIN_HAU.javaHolder) } else { fatalError("Enum value PAU_CIN_HAU was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .OLD_PERMIC: if let OLD_PERMIC = classObj.OLD_PERMIC { - self = OLD_PERMIC + self.init(javaHolder: OLD_PERMIC.javaHolder) } else { fatalError("Enum value OLD_PERMIC was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .PSALTER_PAHLAVI: if let PSALTER_PAHLAVI = classObj.PSALTER_PAHLAVI { - self = PSALTER_PAHLAVI + self.init(javaHolder: PSALTER_PAHLAVI.javaHolder) } else { fatalError("Enum value PSALTER_PAHLAVI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .SIDDHAM: if let SIDDHAM = classObj.SIDDHAM { - self = SIDDHAM + self.init(javaHolder: SIDDHAM.javaHolder) } else { fatalError("Enum value SIDDHAM was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .KHUDAWADI: if let KHUDAWADI = classObj.KHUDAWADI { - self = KHUDAWADI + self.init(javaHolder: KHUDAWADI.javaHolder) } else { fatalError("Enum value KHUDAWADI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .TIRHUTA: if let TIRHUTA = classObj.TIRHUTA { - self = TIRHUTA + self.init(javaHolder: TIRHUTA.javaHolder) } else { fatalError("Enum value TIRHUTA was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .WARANG_CITI: if let WARANG_CITI = classObj.WARANG_CITI { - self = WARANG_CITI + self.init(javaHolder: WARANG_CITI.javaHolder) } else { fatalError("Enum value WARANG_CITI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .AHOM: if let AHOM = classObj.AHOM { - self = AHOM + self.init(javaHolder: AHOM.javaHolder) } else { fatalError("Enum value AHOM was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .ANATOLIAN_HIEROGLYPHS: if let ANATOLIAN_HIEROGLYPHS = classObj.ANATOLIAN_HIEROGLYPHS { - self = ANATOLIAN_HIEROGLYPHS + self.init(javaHolder: ANATOLIAN_HIEROGLYPHS.javaHolder) } else { fatalError("Enum value ANATOLIAN_HIEROGLYPHS was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .HATRAN: if let HATRAN = classObj.HATRAN { - self = HATRAN + self.init(javaHolder: HATRAN.javaHolder) } else { fatalError("Enum value HATRAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .MULTANI: if let MULTANI = classObj.MULTANI { - self = MULTANI + self.init(javaHolder: MULTANI.javaHolder) } else { fatalError("Enum value MULTANI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .OLD_HUNGARIAN: if let OLD_HUNGARIAN = classObj.OLD_HUNGARIAN { - self = OLD_HUNGARIAN + self.init(javaHolder: OLD_HUNGARIAN.javaHolder) } else { fatalError("Enum value OLD_HUNGARIAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .SIGNWRITING: if let SIGNWRITING = classObj.SIGNWRITING { - self = SIGNWRITING + self.init(javaHolder: SIGNWRITING.javaHolder) } else { fatalError("Enum value SIGNWRITING was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .ADLAM: if let ADLAM = classObj.ADLAM { - self = ADLAM + self.init(javaHolder: ADLAM.javaHolder) } else { fatalError("Enum value ADLAM was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .BHAIKSUKI: if let BHAIKSUKI = classObj.BHAIKSUKI { - self = BHAIKSUKI + self.init(javaHolder: BHAIKSUKI.javaHolder) } else { fatalError("Enum value BHAIKSUKI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .MARCHEN: if let MARCHEN = classObj.MARCHEN { - self = MARCHEN + self.init(javaHolder: MARCHEN.javaHolder) } else { fatalError("Enum value MARCHEN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .NEWA: if let NEWA = classObj.NEWA { - self = NEWA + self.init(javaHolder: NEWA.javaHolder) } else { fatalError("Enum value NEWA was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .OSAGE: if let OSAGE = classObj.OSAGE { - self = OSAGE + self.init(javaHolder: OSAGE.javaHolder) } else { fatalError("Enum value OSAGE was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .TANGUT: if let TANGUT = classObj.TANGUT { - self = TANGUT + self.init(javaHolder: TANGUT.javaHolder) } else { fatalError("Enum value TANGUT was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .MASARAM_GONDI: if let MASARAM_GONDI = classObj.MASARAM_GONDI { - self = MASARAM_GONDI + self.init(javaHolder: MASARAM_GONDI.javaHolder) } else { fatalError("Enum value MASARAM_GONDI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .NUSHU: if let NUSHU = classObj.NUSHU { - self = NUSHU + self.init(javaHolder: NUSHU.javaHolder) } else { fatalError("Enum value NUSHU was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .SOYOMBO: if let SOYOMBO = classObj.SOYOMBO { - self = SOYOMBO + self.init(javaHolder: SOYOMBO.javaHolder) } else { fatalError("Enum value SOYOMBO was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .ZANABAZAR_SQUARE: if let ZANABAZAR_SQUARE = classObj.ZANABAZAR_SQUARE { - self = ZANABAZAR_SQUARE + self.init(javaHolder: ZANABAZAR_SQUARE.javaHolder) } else { fatalError("Enum value ZANABAZAR_SQUARE was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .HANIFI_ROHINGYA: if let HANIFI_ROHINGYA = classObj.HANIFI_ROHINGYA { - self = HANIFI_ROHINGYA + self.init(javaHolder: HANIFI_ROHINGYA.javaHolder) } else { fatalError("Enum value HANIFI_ROHINGYA was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .OLD_SOGDIAN: if let OLD_SOGDIAN = classObj.OLD_SOGDIAN { - self = OLD_SOGDIAN + self.init(javaHolder: OLD_SOGDIAN.javaHolder) } else { fatalError("Enum value OLD_SOGDIAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .SOGDIAN: if let SOGDIAN = classObj.SOGDIAN { - self = SOGDIAN + self.init(javaHolder: SOGDIAN.javaHolder) } else { fatalError("Enum value SOGDIAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .DOGRA: if let DOGRA = classObj.DOGRA { - self = DOGRA + self.init(javaHolder: DOGRA.javaHolder) } else { fatalError("Enum value DOGRA was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .GUNJALA_GONDI: if let GUNJALA_GONDI = classObj.GUNJALA_GONDI { - self = GUNJALA_GONDI + self.init(javaHolder: GUNJALA_GONDI.javaHolder) } else { fatalError("Enum value GUNJALA_GONDI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .MAKASAR: if let MAKASAR = classObj.MAKASAR { - self = MAKASAR + self.init(javaHolder: MAKASAR.javaHolder) } else { fatalError("Enum value MAKASAR was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .MEDEFAIDRIN: if let MEDEFAIDRIN = classObj.MEDEFAIDRIN { - self = MEDEFAIDRIN + self.init(javaHolder: MEDEFAIDRIN.javaHolder) } else { fatalError("Enum value MEDEFAIDRIN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .ELYMAIC: if let ELYMAIC = classObj.ELYMAIC { - self = ELYMAIC + self.init(javaHolder: ELYMAIC.javaHolder) } else { fatalError("Enum value ELYMAIC was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .NANDINAGARI: if let NANDINAGARI = classObj.NANDINAGARI { - self = NANDINAGARI + self.init(javaHolder: NANDINAGARI.javaHolder) } else { fatalError("Enum value NANDINAGARI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .NYIAKENG_PUACHUE_HMONG: if let NYIAKENG_PUACHUE_HMONG = classObj.NYIAKENG_PUACHUE_HMONG { - self = NYIAKENG_PUACHUE_HMONG + self.init(javaHolder: NYIAKENG_PUACHUE_HMONG.javaHolder) } else { fatalError("Enum value NYIAKENG_PUACHUE_HMONG was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .WANCHO: if let WANCHO = classObj.WANCHO { - self = WANCHO + self.init(javaHolder: WANCHO.javaHolder) } else { fatalError("Enum value WANCHO was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .YEZIDI: if let YEZIDI = classObj.YEZIDI { - self = YEZIDI + self.init(javaHolder: YEZIDI.javaHolder) } else { fatalError("Enum value YEZIDI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .CHORASMIAN: if let CHORASMIAN = classObj.CHORASMIAN { - self = CHORASMIAN + self.init(javaHolder: CHORASMIAN.javaHolder) } else { fatalError("Enum value CHORASMIAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .DIVES_AKURU: if let DIVES_AKURU = classObj.DIVES_AKURU { - self = DIVES_AKURU + self.init(javaHolder: DIVES_AKURU.javaHolder) } else { fatalError("Enum value DIVES_AKURU was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .KHITAN_SMALL_SCRIPT: if let KHITAN_SMALL_SCRIPT = classObj.KHITAN_SMALL_SCRIPT { - self = KHITAN_SMALL_SCRIPT + self.init(javaHolder: KHITAN_SMALL_SCRIPT.javaHolder) } else { fatalError("Enum value KHITAN_SMALL_SCRIPT was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .VITHKUQI: if let VITHKUQI = classObj.VITHKUQI { - self = VITHKUQI + self.init(javaHolder: VITHKUQI.javaHolder) } else { fatalError("Enum value VITHKUQI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .OLD_UYGHUR: if let OLD_UYGHUR = classObj.OLD_UYGHUR { - self = OLD_UYGHUR + self.init(javaHolder: OLD_UYGHUR.javaHolder) } else { fatalError("Enum value OLD_UYGHUR was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .CYPRO_MINOAN: if let CYPRO_MINOAN = classObj.CYPRO_MINOAN { - self = CYPRO_MINOAN + self.init(javaHolder: CYPRO_MINOAN.javaHolder) } else { fatalError("Enum value CYPRO_MINOAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .TANGSA: if let TANGSA = classObj.TANGSA { - self = TANGSA + self.init(javaHolder: TANGSA.javaHolder) } else { fatalError("Enum value TANGSA was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .TOTO: if let TOTO = classObj.TOTO { - self = TOTO + self.init(javaHolder: TOTO.javaHolder) } else { fatalError("Enum value TOTO was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .KAWI: if let KAWI = classObj.KAWI { - self = KAWI + self.init(javaHolder: KAWI.javaHolder) } else { fatalError("Enum value KAWI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .NAG_MUNDARI: if let NAG_MUNDARI = classObj.NAG_MUNDARI { - self = NAG_MUNDARI + self.init(javaHolder: NAG_MUNDARI.javaHolder) } else { fatalError("Enum value NAG_MUNDARI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } case .UNKNOWN: if let UNKNOWN = classObj.UNKNOWN { - self = UNKNOWN + self.init(javaHolder: UNKNOWN.javaHolder) } else { fatalError("Enum value UNKNOWN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") } } } - - @JavaMethod - public func name() -> String - - @JavaMethod - public func equals(_ arg0: JavaObject?) -> Bool - - @JavaMethod - public func toString() -> String - - @JavaMethod - public func hashCode() -> Int32 - - @JavaMethod - public func compareTo(_ arg0: JavaObject?) -> Int32 - - @JavaMethod - public func ordinal() -> Int32 - - @JavaMethod - public func getClass() -> JavaClass! - - @JavaMethod - public func notify() - - @JavaMethod - public func notifyAll() - - @JavaMethod - public func wait(_ arg0: Int64) throws - - @JavaMethod - public func wait(_ arg0: Int64, _ arg1: Int32) throws - - @JavaMethod - public func wait() throws } } extension JavaCharacter.UnicodeScript { - @JavaClass("java.lang.Enum$EnumDesc", extends: JavaObject.self) - public struct EnumDesc { - @JavaMethod - public func toString() -> String - - @JavaMethod - public func constantName() -> String - - @JavaMethod - public func equals(_ arg0: JavaObject?) -> Bool - - @JavaMethod - public func hashCode() -> Int32 - - @JavaMethod - public func getClass() -> JavaClass! - - @JavaMethod - public func notify() - - @JavaMethod - public func notifyAll() - - @JavaMethod - public func wait(_ arg0: Int64) throws - - @JavaMethod - public func wait(_ arg0: Int64, _ arg1: Int32) throws - + @JavaClass("java.lang.Enum$EnumDesc") + open class EnumDesc: JavaObject { @JavaMethod - public func wait() throws + open override func toString() -> String } } extension JavaClass { diff --git a/Sources/JavaKit/generated/JavaClass.swift b/Sources/JavaKit/generated/JavaClass.swift index a3d52d21..b66835aa 100644 --- a/Sources/JavaKit/generated/JavaClass.swift +++ b/Sources/JavaKit/generated/JavaClass.swift @@ -1,157 +1,133 @@ // Auto-generated by Java-to-Swift wrapper generator. import JavaRuntime -@JavaClass("java.lang.Class", extends: JavaObject.self) -public struct JavaClass { +@JavaClass("java.lang.Class") +open class JavaClass: JavaObject { @JavaMethod - public func getName() -> String + open func getName() -> String @JavaMethod - public func toString() -> String + open override func toString() -> String @JavaMethod - public func isAssignableFrom(_ arg0: JavaClass?) -> Bool + open func isAssignableFrom(_ arg0: JavaClass?) -> Bool @JavaMethod - public func isInstance(_ arg0: JavaObject?) -> Bool + open func isInstance(_ arg0: JavaObject?) -> Bool @JavaMethod - public func getModifiers() -> Int32 + open func getModifiers() -> Int32 @JavaMethod - public func isInterface() -> Bool + open func isInterface() -> Bool @JavaMethod - public func isArray() -> Bool + open func isArray() -> Bool @JavaMethod - public func isPrimitive() -> Bool + open func isPrimitive() -> Bool @JavaMethod - public func isHidden() -> Bool + open func isHidden() -> Bool @JavaMethod - public func getSuperclass() -> JavaClass! + open func getSuperclass() -> JavaClass! @JavaMethod - public func cast(_ arg0: JavaObject?) -> JavaObject! + open func cast(_ arg0: JavaObject?) -> JavaObject! @JavaMethod - public func componentType() -> JavaClass! + open func componentType() -> JavaClass! @JavaMethod - public func getComponentType() -> JavaClass! + open func getComponentType() -> JavaClass! @JavaMethod - public func isAnnotation() -> Bool + open func isAnnotation() -> Bool @JavaMethod - public func isEnum() -> Bool + open func isEnum() -> Bool @JavaMethod - public func isRecord() -> Bool + open func isRecord() -> Bool @JavaMethod - public func newInstance() throws -> JavaObject! + open func newInstance() throws -> JavaObject! @JavaMethod - public func getInterfaces() -> [JavaClass?] + open func getInterfaces() -> [JavaClass?] @JavaMethod - public func isMemberClass() -> Bool + open func isMemberClass() -> Bool @JavaMethod - public func isLocalClass() -> Bool + open func isLocalClass() -> Bool @JavaMethod - public func isAnonymousClass() -> Bool + open func isAnonymousClass() -> Bool @JavaMethod - public func getEnclosingClass() throws -> JavaClass! + open func getEnclosingClass() throws -> JavaClass! @JavaMethod - public func arrayType() -> JavaClass! + open func arrayType() -> JavaClass! @JavaMethod - public func getSimpleName() -> String + open func getSimpleName() -> String @JavaMethod - public func getCanonicalName() -> String + open func getCanonicalName() -> String @JavaMethod - public func getPackageName() -> String + open func getPackageName() -> String @JavaMethod - public func desiredAssertionStatus() -> Bool + open func desiredAssertionStatus() -> Bool @JavaMethod - public func getNestHost() -> JavaClass! + open func getNestHost() -> JavaClass! @JavaMethod - public func descriptorString() -> String + open func descriptorString() -> String @JavaMethod - public func getPermittedSubclasses() -> [JavaClass?] + open func getPermittedSubclasses() -> [JavaClass?] @JavaMethod - public func toGenericString() -> String + open func toGenericString() -> String @JavaMethod - public func isSynthetic() -> Bool + open func isSynthetic() -> Bool @JavaMethod - public func getSigners() -> [JavaObject?] + open func getSigners() -> [JavaObject?] @JavaMethod - public func getDeclaringClass() throws -> JavaClass! + open func getDeclaringClass() throws -> JavaClass! @JavaMethod - public func getTypeName() -> String + open func getTypeName() -> String @JavaMethod - public func getClasses() -> [JavaClass?] + open func getClasses() -> [JavaClass?] @JavaMethod - public func getDeclaredClasses() throws -> [JavaClass?] + open func getDeclaredClasses() throws -> [JavaClass?] @JavaMethod - public func getEnumConstants() -> [JavaObject?] + open func getEnumConstants() -> [JavaObject?] @JavaMethod - public func asSubclass(_ arg0: JavaClass?) -> JavaClass! + open func asSubclass(_ arg0: JavaClass?) -> JavaClass! @JavaMethod - public func isNestmateOf(_ arg0: JavaClass?) -> Bool + open func isNestmateOf(_ arg0: JavaClass?) -> Bool @JavaMethod - public func getNestMembers() -> [JavaClass?] + open func getNestMembers() -> [JavaClass?] @JavaMethod - public func isSealed() -> Bool - - @JavaMethod - public func equals(_ arg0: JavaObject?) -> Bool - - @JavaMethod - public func hashCode() -> Int32 - - @JavaMethod - public func getClass() -> JavaClass! - - @JavaMethod - public func notify() - - @JavaMethod - public func notifyAll() - - @JavaMethod - public func wait(_ arg0: Int64) throws - - @JavaMethod - public func wait(_ arg0: Int64, _ arg1: Int32) throws - - @JavaMethod - public func wait() throws + open func isSealed() -> Bool } extension JavaClass { @JavaStaticMethod diff --git a/Sources/JavaKit/generated/JavaDouble.swift b/Sources/JavaKit/generated/JavaDouble.swift index da2eb571..4eaa425e 100644 --- a/Sources/JavaKit/generated/JavaDouble.swift +++ b/Sources/JavaKit/generated/JavaDouble.swift @@ -1,70 +1,52 @@ // Auto-generated by Java-to-Swift wrapper generator. import JavaRuntime -@JavaClass("java.lang.Double", extends: JavaNumber.self) -public struct JavaDouble { +@JavaClass("java.lang.Double") +open class JavaDouble: JavaNumber { @JavaMethod - public init(_ arg0: Double, environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(_ arg0: Double, environment: JNIEnvironment? = nil) @JavaMethod - public init(_ arg0: String, environment: JNIEnvironment? = nil) throws + @_nonoverride public convenience init(_ arg0: String, environment: JNIEnvironment? = nil) throws @JavaMethod - public func equals(_ arg0: JavaObject?) -> Bool + open override func equals(_ arg0: JavaObject?) -> Bool @JavaMethod - public func toString() -> String + open override func toString() -> String @JavaMethod - public func hashCode() -> Int32 + open override func hashCode() -> Int32 @JavaMethod - public func isInfinite() -> Bool + open func isInfinite() -> Bool @JavaMethod - public func compareTo(_ arg0: JavaDouble?) -> Int32 + open func compareTo(_ arg0: JavaDouble?) -> Int32 @JavaMethod - public func compareTo(_ arg0: JavaObject?) -> Int32 + open func compareTo(_ arg0: JavaObject?) -> Int32 @JavaMethod - public func byteValue() -> Int8 + open override func byteValue() -> Int8 @JavaMethod - public func shortValue() -> Int16 + open override func shortValue() -> Int16 @JavaMethod - public func intValue() -> Int32 + open override func intValue() -> Int32 @JavaMethod - public func longValue() -> Int64 + open override func longValue() -> Int64 @JavaMethod - public func floatValue() -> Float + open override func floatValue() -> Float @JavaMethod - public func doubleValue() -> Double + open override func doubleValue() -> Double @JavaMethod - public func isNaN() -> Bool - - @JavaMethod - public func getClass() -> JavaClass! - - @JavaMethod - public func notify() - - @JavaMethod - public func notifyAll() - - @JavaMethod - public func wait(_ arg0: Int64) throws - - @JavaMethod - public func wait(_ arg0: Int64, _ arg1: Int32) throws - - @JavaMethod - public func wait() throws + open func isNaN() -> Bool } extension JavaClass { @JavaStaticField(isFinal: true) diff --git a/Sources/JavaKit/generated/JavaError.swift b/Sources/JavaKit/generated/JavaError.swift index 86398c9b..97c2e555 100644 --- a/Sources/JavaKit/generated/JavaError.swift +++ b/Sources/JavaKit/generated/JavaError.swift @@ -1,68 +1,17 @@ // Auto-generated by Java-to-Swift wrapper generator. import JavaRuntime -@JavaClass("java.lang.Error", extends: Throwable.self) -public struct JavaError { +@JavaClass("java.lang.Error") +open class JavaError: Throwable { @JavaMethod - public init(_ arg0: Throwable?, environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(_ arg0: Throwable?, environment: JNIEnvironment? = nil) @JavaMethod - public init(_ arg0: String, _ arg1: Throwable?, environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(_ arg0: String, _ arg1: Throwable?, environment: JNIEnvironment? = nil) @JavaMethod - public init(_ arg0: String, environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(_ arg0: String, environment: JNIEnvironment? = nil) @JavaMethod - public init(environment: JNIEnvironment? = nil) - - @JavaMethod - public func printStackTrace() - - @JavaMethod - public func fillInStackTrace() -> Throwable! - - @JavaMethod - public func getCause() -> Throwable! - - @JavaMethod - public func initCause(_ arg0: Throwable?) -> Throwable! - - @JavaMethod - public func toString() -> String - - @JavaMethod - public func getMessage() -> String - - @JavaMethod - public func getSuppressed() -> [Throwable?] - - @JavaMethod - public func getLocalizedMessage() -> String - - @JavaMethod - public func addSuppressed(_ arg0: Throwable?) - - @JavaMethod - public func equals(_ arg0: JavaObject?) -> Bool - - @JavaMethod - public func hashCode() -> Int32 - - @JavaMethod - public func getClass() -> JavaClass! - - @JavaMethod - public func notify() - - @JavaMethod - public func notifyAll() - - @JavaMethod - public func wait(_ arg0: Int64) throws - - @JavaMethod - public func wait(_ arg0: Int64, _ arg1: Int32) throws - - @JavaMethod - public func wait() throws + @_nonoverride public convenience init(environment: JNIEnvironment? = nil) } diff --git a/Sources/JavaKit/generated/JavaFloat.swift b/Sources/JavaKit/generated/JavaFloat.swift index 4df63cbb..6ad0536e 100644 --- a/Sources/JavaKit/generated/JavaFloat.swift +++ b/Sources/JavaKit/generated/JavaFloat.swift @@ -1,73 +1,55 @@ // Auto-generated by Java-to-Swift wrapper generator. import JavaRuntime -@JavaClass("java.lang.Float", extends: JavaNumber.self) -public struct JavaFloat { +@JavaClass("java.lang.Float") +open class JavaFloat: JavaNumber { @JavaMethod - public init(_ arg0: String, environment: JNIEnvironment? = nil) throws + @_nonoverride public convenience init(_ arg0: String, environment: JNIEnvironment? = nil) throws @JavaMethod - public init(_ arg0: Double, environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(_ arg0: Double, environment: JNIEnvironment? = nil) @JavaMethod - public init(_ arg0: Float, environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(_ arg0: Float, environment: JNIEnvironment? = nil) @JavaMethod - public func equals(_ arg0: JavaObject?) -> Bool + open override func equals(_ arg0: JavaObject?) -> Bool @JavaMethod - public func toString() -> String + open override func toString() -> String @JavaMethod - public func hashCode() -> Int32 + open override func hashCode() -> Int32 @JavaMethod - public func isInfinite() -> Bool + open func isInfinite() -> Bool @JavaMethod - public func compareTo(_ arg0: JavaObject?) -> Int32 + open func compareTo(_ arg0: JavaObject?) -> Int32 @JavaMethod - public func compareTo(_ arg0: JavaFloat?) -> Int32 + open func compareTo(_ arg0: JavaFloat?) -> Int32 @JavaMethod - public func byteValue() -> Int8 + open override func byteValue() -> Int8 @JavaMethod - public func shortValue() -> Int16 + open override func shortValue() -> Int16 @JavaMethod - public func intValue() -> Int32 + open override func intValue() -> Int32 @JavaMethod - public func longValue() -> Int64 + open override func longValue() -> Int64 @JavaMethod - public func floatValue() -> Float + open override func floatValue() -> Float @JavaMethod - public func doubleValue() -> Double + open override func doubleValue() -> Double @JavaMethod - public func isNaN() -> Bool - - @JavaMethod - public func getClass() -> JavaClass! - - @JavaMethod - public func notify() - - @JavaMethod - public func notifyAll() - - @JavaMethod - public func wait(_ arg0: Int64) throws - - @JavaMethod - public func wait(_ arg0: Int64, _ arg1: Int32) throws - - @JavaMethod - public func wait() throws + open func isNaN() -> Bool } extension JavaClass { @JavaStaticField(isFinal: true) diff --git a/Sources/JavaKit/generated/JavaInteger.swift b/Sources/JavaKit/generated/JavaInteger.swift index 6e6a64fa..7aadd187 100644 --- a/Sources/JavaKit/generated/JavaInteger.swift +++ b/Sources/JavaKit/generated/JavaInteger.swift @@ -1,64 +1,46 @@ // Auto-generated by Java-to-Swift wrapper generator. import JavaRuntime -@JavaClass("java.lang.Integer", extends: JavaNumber.self) -public struct JavaInteger { +@JavaClass("java.lang.Integer") +open class JavaInteger: JavaNumber { @JavaMethod - public init(_ arg0: Int32, environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(_ arg0: Int32, environment: JNIEnvironment? = nil) @JavaMethod - public init(_ arg0: String, environment: JNIEnvironment? = nil) throws + @_nonoverride public convenience init(_ arg0: String, environment: JNIEnvironment? = nil) throws @JavaMethod - public func equals(_ arg0: JavaObject?) -> Bool + open override func equals(_ arg0: JavaObject?) -> Bool @JavaMethod - public func toString() -> String + open override func toString() -> String @JavaMethod - public func hashCode() -> Int32 + open override func hashCode() -> Int32 @JavaMethod - public func compareTo(_ arg0: JavaObject?) -> Int32 + open func compareTo(_ arg0: JavaObject?) -> Int32 @JavaMethod - public func compareTo(_ arg0: JavaInteger?) -> Int32 + open func compareTo(_ arg0: JavaInteger?) -> Int32 @JavaMethod - public func byteValue() -> Int8 + open override func byteValue() -> Int8 @JavaMethod - public func shortValue() -> Int16 + open override func shortValue() -> Int16 @JavaMethod - public func intValue() -> Int32 + open override func intValue() -> Int32 @JavaMethod - public func longValue() -> Int64 + open override func longValue() -> Int64 @JavaMethod - public func floatValue() -> Float + open override func floatValue() -> Float @JavaMethod - public func doubleValue() -> Double - - @JavaMethod - public func getClass() -> JavaClass! - - @JavaMethod - public func notify() - - @JavaMethod - public func notifyAll() - - @JavaMethod - public func wait(_ arg0: Int64) throws - - @JavaMethod - public func wait(_ arg0: Int64, _ arg1: Int32) throws - - @JavaMethod - public func wait() throws + open override func doubleValue() -> Double } extension JavaClass { @JavaStaticField(isFinal: true) diff --git a/Sources/JavaKit/generated/JavaLong.swift b/Sources/JavaKit/generated/JavaLong.swift index fa02f070..4cbe97ba 100644 --- a/Sources/JavaKit/generated/JavaLong.swift +++ b/Sources/JavaKit/generated/JavaLong.swift @@ -1,64 +1,46 @@ // Auto-generated by Java-to-Swift wrapper generator. import JavaRuntime -@JavaClass("java.lang.Long", extends: JavaNumber.self) -public struct JavaLong { +@JavaClass("java.lang.Long") +open class JavaLong: JavaNumber { @JavaMethod - public init(_ arg0: String, environment: JNIEnvironment? = nil) throws + @_nonoverride public convenience init(_ arg0: String, environment: JNIEnvironment? = nil) throws @JavaMethod - public init(_ arg0: Int64, environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(_ arg0: Int64, environment: JNIEnvironment? = nil) @JavaMethod - public func equals(_ arg0: JavaObject?) -> Bool + open override func equals(_ arg0: JavaObject?) -> Bool @JavaMethod - public func toString() -> String + open override func toString() -> String @JavaMethod - public func hashCode() -> Int32 + open override func hashCode() -> Int32 @JavaMethod - public func compareTo(_ arg0: JavaObject?) -> Int32 + open func compareTo(_ arg0: JavaObject?) -> Int32 @JavaMethod - public func compareTo(_ arg0: JavaLong?) -> Int32 + open func compareTo(_ arg0: JavaLong?) -> Int32 @JavaMethod - public func byteValue() -> Int8 + open override func byteValue() -> Int8 @JavaMethod - public func shortValue() -> Int16 + open override func shortValue() -> Int16 @JavaMethod - public func intValue() -> Int32 + open override func intValue() -> Int32 @JavaMethod - public func longValue() -> Int64 + open override func longValue() -> Int64 @JavaMethod - public func floatValue() -> Float + open override func floatValue() -> Float @JavaMethod - public func doubleValue() -> Double - - @JavaMethod - public func getClass() -> JavaClass! - - @JavaMethod - public func notify() - - @JavaMethod - public func notifyAll() - - @JavaMethod - public func wait(_ arg0: Int64) throws - - @JavaMethod - public func wait(_ arg0: Int64, _ arg1: Int32) throws - - @JavaMethod - public func wait() throws + open override func doubleValue() -> Double } extension JavaClass { @JavaStaticField(isFinal: true) diff --git a/Sources/JavaKit/generated/JavaNumber.swift b/Sources/JavaKit/generated/JavaNumber.swift index acd461fe..414cd89b 100644 --- a/Sources/JavaKit/generated/JavaNumber.swift +++ b/Sources/JavaKit/generated/JavaNumber.swift @@ -1,53 +1,26 @@ // Auto-generated by Java-to-Swift wrapper generator. import JavaRuntime -@JavaClass("java.lang.Number", extends: JavaObject.self) -public struct JavaNumber { +@JavaClass("java.lang.Number") +open class JavaNumber: JavaObject { @JavaMethod - public init(environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(environment: JNIEnvironment? = nil) @JavaMethod - public func byteValue() -> Int8 + open func byteValue() -> Int8 @JavaMethod - public func shortValue() -> Int16 + open func shortValue() -> Int16 @JavaMethod - public func intValue() -> Int32 + open func intValue() -> Int32 @JavaMethod - public func longValue() -> Int64 + open func longValue() -> Int64 @JavaMethod - public func floatValue() -> Float + open func floatValue() -> Float @JavaMethod - public func doubleValue() -> Double - - @JavaMethod - public func equals(_ arg0: JavaObject?) -> Bool - - @JavaMethod - public func toString() -> String - - @JavaMethod - public func hashCode() -> Int32 - - @JavaMethod - public func getClass() -> JavaClass! - - @JavaMethod - public func notify() - - @JavaMethod - public func notifyAll() - - @JavaMethod - public func wait(_ arg0: Int64) throws - - @JavaMethod - public func wait(_ arg0: Int64, _ arg1: Int32) throws - - @JavaMethod - public func wait() throws + open func doubleValue() -> Double } diff --git a/Sources/JavaKit/generated/JavaObject.swift b/Sources/JavaKit/generated/JavaObject.swift index 8e7a20fc..07a6eaff 100644 --- a/Sources/JavaKit/generated/JavaObject.swift +++ b/Sources/JavaKit/generated/JavaObject.swift @@ -2,34 +2,40 @@ import JavaRuntime @JavaClass("java.lang.Object") -public struct JavaObject { +open class JavaObject { @JavaMethod - public init(environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(environment: JNIEnvironment? = nil) @JavaMethod - public func equals(_ arg0: JavaObject?) -> Bool + open func finalize() throws @JavaMethod - public func toString() -> String + open func equals(_ arg0: JavaObject?) -> Bool @JavaMethod - public func hashCode() -> Int32 + open func toString() -> String @JavaMethod - public func getClass() -> JavaClass! + open func hashCode() -> Int32 @JavaMethod - public func notify() + open func getClass() -> JavaClass! @JavaMethod - public func notifyAll() + open func clone() throws -> JavaObject! @JavaMethod - public func wait(_ arg0: Int64) throws + open func notify() @JavaMethod - public func wait(_ arg0: Int64, _ arg1: Int32) throws + open func notifyAll() @JavaMethod - public func wait() throws + open func wait(_ arg0: Int64) throws + + @JavaMethod + open func wait(_ arg0: Int64, _ arg1: Int32) throws + + @JavaMethod + open func wait() throws } diff --git a/Sources/JavaKit/generated/JavaShort.swift b/Sources/JavaKit/generated/JavaShort.swift index 58cb4e26..f425ae18 100644 --- a/Sources/JavaKit/generated/JavaShort.swift +++ b/Sources/JavaKit/generated/JavaShort.swift @@ -1,64 +1,46 @@ // Auto-generated by Java-to-Swift wrapper generator. import JavaRuntime -@JavaClass("java.lang.Short", extends: JavaNumber.self) -public struct JavaShort { +@JavaClass("java.lang.Short") +open class JavaShort: JavaNumber { @JavaMethod - public init(_ arg0: Int16, environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(_ arg0: Int16, environment: JNIEnvironment? = nil) @JavaMethod - public init(_ arg0: String, environment: JNIEnvironment? = nil) throws + @_nonoverride public convenience init(_ arg0: String, environment: JNIEnvironment? = nil) throws @JavaMethod - public func equals(_ arg0: JavaObject?) -> Bool + open override func equals(_ arg0: JavaObject?) -> Bool @JavaMethod - public func toString() -> String + open override func toString() -> String @JavaMethod - public func hashCode() -> Int32 + open override func hashCode() -> Int32 @JavaMethod - public func compareTo(_ arg0: JavaShort?) -> Int32 + open func compareTo(_ arg0: JavaShort?) -> Int32 @JavaMethod - public func compareTo(_ arg0: JavaObject?) -> Int32 + open func compareTo(_ arg0: JavaObject?) -> Int32 @JavaMethod - public func byteValue() -> Int8 + open override func byteValue() -> Int8 @JavaMethod - public func shortValue() -> Int16 + open override func shortValue() -> Int16 @JavaMethod - public func intValue() -> Int32 + open override func intValue() -> Int32 @JavaMethod - public func longValue() -> Int64 + open override func longValue() -> Int64 @JavaMethod - public func floatValue() -> Float + open override func floatValue() -> Float @JavaMethod - public func doubleValue() -> Double - - @JavaMethod - public func getClass() -> JavaClass! - - @JavaMethod - public func notify() - - @JavaMethod - public func notifyAll() - - @JavaMethod - public func wait(_ arg0: Int64) throws - - @JavaMethod - public func wait(_ arg0: Int64, _ arg1: Int32) throws - - @JavaMethod - public func wait() throws + open override func doubleValue() -> Double } extension JavaClass { @JavaStaticField(isFinal: true) diff --git a/Sources/JavaKit/generated/JavaString.swift b/Sources/JavaKit/generated/JavaString.swift index c062dc0d..adf1993d 100644 --- a/Sources/JavaKit/generated/JavaString.swift +++ b/Sources/JavaKit/generated/JavaString.swift @@ -1,229 +1,211 @@ // Auto-generated by Java-to-Swift wrapper generator. import JavaRuntime -@JavaClass("java.lang.String", extends: JavaObject.self) -public struct JavaString { +@JavaClass("java.lang.String") +open class JavaString: JavaObject { @JavaMethod - public init(_ arg0: [Int8], _ arg1: String, environment: JNIEnvironment? = nil) throws + @_nonoverride public convenience init(_ arg0: [Int8], _ arg1: String, environment: JNIEnvironment? = nil) throws @JavaMethod - public init(_ arg0: [Int8], _ arg1: Int32, _ arg2: Int32, environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(_ arg0: [Int8], _ arg1: Int32, _ arg2: Int32, environment: JNIEnvironment? = nil) @JavaMethod - public init(_ arg0: [Int8], environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(_ arg0: [Int8], environment: JNIEnvironment? = nil) @JavaMethod - public init(_ arg0: [UInt16], _ arg1: Int32, _ arg2: Int32, environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(_ arg0: [UInt16], _ arg1: Int32, _ arg2: Int32, environment: JNIEnvironment? = nil) @JavaMethod - public init(_ arg0: [UInt16], environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(_ arg0: [UInt16], environment: JNIEnvironment? = nil) @JavaMethod - public init(_ arg0: String, environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(_ arg0: String, environment: JNIEnvironment? = nil) @JavaMethod - public init(environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(environment: JNIEnvironment? = nil) @JavaMethod - public init(_ arg0: [Int8], _ arg1: Int32, _ arg2: Int32, _ arg3: String, environment: JNIEnvironment? = nil) throws + @_nonoverride public convenience init(_ arg0: [Int8], _ arg1: Int32, _ arg2: Int32, _ arg3: String, environment: JNIEnvironment? = nil) throws @JavaMethod - public init(_ arg0: [Int8], _ arg1: Int32, environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(_ arg0: [Int8], _ arg1: Int32, environment: JNIEnvironment? = nil) @JavaMethod - public init(_ arg0: [Int8], _ arg1: Int32, _ arg2: Int32, _ arg3: Int32, environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(_ arg0: [Int8], _ arg1: Int32, _ arg2: Int32, _ arg3: Int32, environment: JNIEnvironment? = nil) @JavaMethod - public init(_ arg0: [Int32], _ arg1: Int32, _ arg2: Int32, environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(_ arg0: [Int32], _ arg1: Int32, _ arg2: Int32, environment: JNIEnvironment? = nil) @JavaMethod - public func equals(_ arg0: JavaObject?) -> Bool + open override func equals(_ arg0: JavaObject?) -> Bool @JavaMethod - public func length() -> Int32 + open func length() -> Int32 @JavaMethod - public func toString() -> String + open override func toString() -> String @JavaMethod - public func hashCode() -> Int32 + open override func hashCode() -> Int32 @JavaMethod - public func getChars(_ arg0: Int32, _ arg1: Int32, _ arg2: [UInt16], _ arg3: Int32) + open func getChars(_ arg0: Int32, _ arg1: Int32, _ arg2: [UInt16], _ arg3: Int32) @JavaMethod - public func compareTo(_ arg0: JavaObject?) -> Int32 + open func compareTo(_ arg0: JavaObject?) -> Int32 @JavaMethod - public func compareTo(_ arg0: String) -> Int32 + open func compareTo(_ arg0: String) -> Int32 @JavaMethod - public func indexOf(_ arg0: String, _ arg1: Int32, _ arg2: Int32) -> Int32 + open func indexOf(_ arg0: String, _ arg1: Int32, _ arg2: Int32) -> Int32 @JavaMethod - public func indexOf(_ arg0: String) -> Int32 + open func indexOf(_ arg0: String) -> Int32 @JavaMethod - public func indexOf(_ arg0: Int32) -> Int32 + open func indexOf(_ arg0: Int32) -> Int32 @JavaMethod - public func indexOf(_ arg0: Int32, _ arg1: Int32) -> Int32 + open func indexOf(_ arg0: Int32, _ arg1: Int32) -> Int32 @JavaMethod - public func indexOf(_ arg0: Int32, _ arg1: Int32, _ arg2: Int32) -> Int32 + open func indexOf(_ arg0: Int32, _ arg1: Int32, _ arg2: Int32) -> Int32 @JavaMethod - public func indexOf(_ arg0: String, _ arg1: Int32) -> Int32 + open func indexOf(_ arg0: String, _ arg1: Int32) -> Int32 @JavaMethod - public func charAt(_ arg0: Int32) -> UInt16 + open func charAt(_ arg0: Int32) -> UInt16 @JavaMethod - public func codePointAt(_ arg0: Int32) -> Int32 + open func codePointAt(_ arg0: Int32) -> Int32 @JavaMethod - public func codePointBefore(_ arg0: Int32) -> Int32 + open func codePointBefore(_ arg0: Int32) -> Int32 @JavaMethod - public func codePointCount(_ arg0: Int32, _ arg1: Int32) -> Int32 + open func codePointCount(_ arg0: Int32, _ arg1: Int32) -> Int32 @JavaMethod - public func offsetByCodePoints(_ arg0: Int32, _ arg1: Int32) -> Int32 + open func offsetByCodePoints(_ arg0: Int32, _ arg1: Int32) -> Int32 @JavaMethod - public func getBytes() -> [Int8] + open func getBytes() -> [Int8] @JavaMethod - public func getBytes(_ arg0: String) throws -> [Int8] + open func getBytes(_ arg0: String) throws -> [Int8] @JavaMethod - public func getBytes(_ arg0: Int32, _ arg1: Int32, _ arg2: [Int8], _ arg3: Int32) + open func getBytes(_ arg0: Int32, _ arg1: Int32, _ arg2: [Int8], _ arg3: Int32) @JavaMethod - public func regionMatches(_ arg0: Bool, _ arg1: Int32, _ arg2: String, _ arg3: Int32, _ arg4: Int32) -> Bool + open func regionMatches(_ arg0: Bool, _ arg1: Int32, _ arg2: String, _ arg3: Int32, _ arg4: Int32) -> Bool @JavaMethod - public func regionMatches(_ arg0: Int32, _ arg1: String, _ arg2: Int32, _ arg3: Int32) -> Bool + open func regionMatches(_ arg0: Int32, _ arg1: String, _ arg2: Int32, _ arg3: Int32) -> Bool @JavaMethod - public func startsWith(_ arg0: String) -> Bool + open func startsWith(_ arg0: String) -> Bool @JavaMethod - public func startsWith(_ arg0: String, _ arg1: Int32) -> Bool + open func startsWith(_ arg0: String, _ arg1: Int32) -> Bool @JavaMethod - public func lastIndexOf(_ arg0: String) -> Int32 + open func lastIndexOf(_ arg0: String) -> Int32 @JavaMethod - public func lastIndexOf(_ arg0: Int32, _ arg1: Int32) -> Int32 + open func lastIndexOf(_ arg0: Int32, _ arg1: Int32) -> Int32 @JavaMethod - public func lastIndexOf(_ arg0: String, _ arg1: Int32) -> Int32 + open func lastIndexOf(_ arg0: String, _ arg1: Int32) -> Int32 @JavaMethod - public func lastIndexOf(_ arg0: Int32) -> Int32 + open func lastIndexOf(_ arg0: Int32) -> Int32 @JavaMethod - public func substring(_ arg0: Int32) -> String + open func substring(_ arg0: Int32) -> String @JavaMethod - public func substring(_ arg0: Int32, _ arg1: Int32) -> String + open func substring(_ arg0: Int32, _ arg1: Int32) -> String @JavaMethod - public func isEmpty() -> Bool + open func isEmpty() -> Bool @JavaMethod - public func replace(_ arg0: UInt16, _ arg1: UInt16) -> String + open func replace(_ arg0: UInt16, _ arg1: UInt16) -> String @JavaMethod - public func matches(_ arg0: String) -> Bool + open func matches(_ arg0: String) -> Bool @JavaMethod - public func replaceFirst(_ arg0: String, _ arg1: String) -> String + open func replaceFirst(_ arg0: String, _ arg1: String) -> String @JavaMethod - public func replaceAll(_ arg0: String, _ arg1: String) -> String + open func replaceAll(_ arg0: String, _ arg1: String) -> String @JavaMethod - public func split(_ arg0: String) -> [String] + open func split(_ arg0: String) -> [String] @JavaMethod - public func split(_ arg0: String, _ arg1: Int32) -> [String] + open func split(_ arg0: String, _ arg1: Int32) -> [String] @JavaMethod - public func splitWithDelimiters(_ arg0: String, _ arg1: Int32) -> [String] + open func splitWithDelimiters(_ arg0: String, _ arg1: Int32) -> [String] @JavaMethod - public func toLowerCase() -> String + open func toLowerCase() -> String @JavaMethod - public func toUpperCase() -> String + open func toUpperCase() -> String @JavaMethod - public func trim() -> String + open func trim() -> String @JavaMethod - public func strip() -> String + open func strip() -> String @JavaMethod - public func stripLeading() -> String + open func stripLeading() -> String @JavaMethod - public func stripTrailing() -> String + open func stripTrailing() -> String @JavaMethod - public func `repeat`(_ arg0: Int32) -> String + open func `repeat`(_ arg0: Int32) -> String @JavaMethod - public func isBlank() -> Bool + open func isBlank() -> Bool @JavaMethod - public func toCharArray() -> [UInt16] + open func toCharArray() -> [UInt16] @JavaMethod - public func equalsIgnoreCase(_ arg0: String) -> Bool + open func equalsIgnoreCase(_ arg0: String) -> Bool @JavaMethod - public func compareToIgnoreCase(_ arg0: String) -> Int32 + open func compareToIgnoreCase(_ arg0: String) -> Int32 @JavaMethod - public func endsWith(_ arg0: String) -> Bool + open func endsWith(_ arg0: String) -> Bool @JavaMethod - public func concat(_ arg0: String) -> String + open func concat(_ arg0: String) -> String @JavaMethod - public func indent(_ arg0: Int32) -> String + open func indent(_ arg0: Int32) -> String @JavaMethod - public func stripIndent() -> String + open func stripIndent() -> String @JavaMethod - public func translateEscapes() -> String + open func translateEscapes() -> String @JavaMethod - public func formatted(_ arg0: [JavaObject?]) -> String + open func formatted(_ arg0: [JavaObject?]) -> String @JavaMethod - public func intern() -> String - - @JavaMethod - public func getClass() -> JavaClass! - - @JavaMethod - public func notify() - - @JavaMethod - public func notifyAll() - - @JavaMethod - public func wait(_ arg0: Int64) throws - - @JavaMethod - public func wait(_ arg0: Int64, _ arg1: Int32) throws - - @JavaMethod - public func wait() throws + open func intern() -> String } extension JavaClass { @JavaStaticMethod diff --git a/Sources/JavaKit/generated/JavaVoid.swift b/Sources/JavaKit/generated/JavaVoid.swift index f9a21828..76a7334a 100644 --- a/Sources/JavaKit/generated/JavaVoid.swift +++ b/Sources/JavaKit/generated/JavaVoid.swift @@ -1,34 +1,9 @@ // Auto-generated by Java-to-Swift wrapper generator. import JavaRuntime -@JavaClass("java.lang.Void", extends: JavaObject.self) -public struct JavaVoid { - @JavaMethod - public func equals(_ arg0: JavaObject?) -> Bool +@JavaClass("java.lang.Void") +open class JavaVoid: JavaObject { - @JavaMethod - public func toString() -> String - - @JavaMethod - public func hashCode() -> Int32 - - @JavaMethod - public func getClass() -> JavaClass! - - @JavaMethod - public func notify() - - @JavaMethod - public func notifyAll() - - @JavaMethod - public func wait(_ arg0: Int64) throws - - @JavaMethod - public func wait(_ arg0: Int64, _ arg1: Int32) throws - - @JavaMethod - public func wait() throws } extension JavaClass { @JavaStaticField(isFinal: true) diff --git a/Sources/JavaKit/generated/RuntimeException.swift b/Sources/JavaKit/generated/RuntimeException.swift index 6ef0988f..c3e32506 100644 --- a/Sources/JavaKit/generated/RuntimeException.swift +++ b/Sources/JavaKit/generated/RuntimeException.swift @@ -1,68 +1,17 @@ // Auto-generated by Java-to-Swift wrapper generator. import JavaRuntime -@JavaClass("java.lang.RuntimeException", extends: Exception.self) -public struct RuntimeException { +@JavaClass("java.lang.RuntimeException") +open class RuntimeException: Exception { @JavaMethod - public init(_ arg0: Throwable?, environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(_ arg0: Throwable?, environment: JNIEnvironment? = nil) @JavaMethod - public init(_ arg0: String, _ arg1: Throwable?, environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(_ arg0: String, _ arg1: Throwable?, environment: JNIEnvironment? = nil) @JavaMethod - public init(_ arg0: String, environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(_ arg0: String, environment: JNIEnvironment? = nil) @JavaMethod - public init(environment: JNIEnvironment? = nil) - - @JavaMethod - public func printStackTrace() - - @JavaMethod - public func fillInStackTrace() -> Throwable! - - @JavaMethod - public func getCause() -> Throwable! - - @JavaMethod - public func initCause(_ arg0: Throwable?) -> Throwable! - - @JavaMethod - public func toString() -> String - - @JavaMethod - public func getMessage() -> String - - @JavaMethod - public func getSuppressed() -> [Throwable?] - - @JavaMethod - public func getLocalizedMessage() -> String - - @JavaMethod - public func addSuppressed(_ arg0: Throwable?) - - @JavaMethod - public func equals(_ arg0: JavaObject?) -> Bool - - @JavaMethod - public func hashCode() -> Int32 - - @JavaMethod - public func getClass() -> JavaClass! - - @JavaMethod - public func notify() - - @JavaMethod - public func notifyAll() - - @JavaMethod - public func wait(_ arg0: Int64) throws - - @JavaMethod - public func wait(_ arg0: Int64, _ arg1: Int32) throws - - @JavaMethod - public func wait() throws + @_nonoverride public convenience init(environment: JNIEnvironment? = nil) } diff --git a/Sources/JavaKit/generated/Throwable.swift b/Sources/JavaKit/generated/Throwable.swift index 171835d8..574fedf5 100644 --- a/Sources/JavaKit/generated/Throwable.swift +++ b/Sources/JavaKit/generated/Throwable.swift @@ -1,68 +1,44 @@ // Auto-generated by Java-to-Swift wrapper generator. import JavaRuntime -@JavaClass("java.lang.Throwable", extends: JavaObject.self) -public struct Throwable { +@JavaClass("java.lang.Throwable") +open class Throwable: JavaObject { @JavaMethod - public init(_ arg0: Throwable?, environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(_ arg0: Throwable?, environment: JNIEnvironment? = nil) @JavaMethod - public init(_ arg0: String, _ arg1: Throwable?, environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(_ arg0: String, _ arg1: Throwable?, environment: JNIEnvironment? = nil) @JavaMethod - public init(_ arg0: String, environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(_ arg0: String, environment: JNIEnvironment? = nil) @JavaMethod - public init(environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(environment: JNIEnvironment? = nil) @JavaMethod - public func printStackTrace() + open func printStackTrace() @JavaMethod - public func fillInStackTrace() -> Throwable! + open func fillInStackTrace() -> Throwable! @JavaMethod - public func getCause() -> Throwable! + open func getCause() -> Throwable! @JavaMethod - public func initCause(_ arg0: Throwable?) -> Throwable! + open func initCause(_ arg0: Throwable?) -> Throwable! @JavaMethod - public func toString() -> String + open override func toString() -> String @JavaMethod - public func getMessage() -> String + open func getMessage() -> String @JavaMethod - public func getSuppressed() -> [Throwable?] + open func getSuppressed() -> [Throwable?] @JavaMethod - public func getLocalizedMessage() -> String + open func getLocalizedMessage() -> String @JavaMethod - public func addSuppressed(_ arg0: Throwable?) - - @JavaMethod - public func equals(_ arg0: JavaObject?) -> Bool - - @JavaMethod - public func hashCode() -> Int32 - - @JavaMethod - public func getClass() -> JavaClass! - - @JavaMethod - public func notify() - - @JavaMethod - public func notifyAll() - - @JavaMethod - public func wait(_ arg0: Int64) throws - - @JavaMethod - public func wait(_ arg0: Int64, _ arg1: Int32) throws - - @JavaMethod - public func wait() throws + open func addSuppressed(_ arg0: Throwable?) } diff --git a/Sources/JavaKitCollection/generated/ArrayDeque.swift b/Sources/JavaKitCollection/generated/ArrayDeque.swift index d0a1134a..79a1e20b 100644 --- a/Sources/JavaKitCollection/generated/ArrayDeque.swift +++ b/Sources/JavaKitCollection/generated/ArrayDeque.swift @@ -2,149 +2,119 @@ import JavaKit import JavaRuntime -@JavaClass("java.util.ArrayDeque", extends: JavaObject.self) -public struct ArrayDeque { +@JavaClass("java.util.ArrayDeque") +open class ArrayDeque: JavaObject { @JavaMethod - public init(_ arg0: Int32, environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(_ arg0: Int32, environment: JNIEnvironment? = nil) @JavaMethod - public init(environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(environment: JNIEnvironment? = nil) @JavaMethod - public init(_ arg0: JavaCollection?, environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(_ arg0: JavaCollection?, environment: JNIEnvironment? = nil) @JavaMethod - public func remove() -> JavaObject! + open func remove() -> JavaObject! @JavaMethod - public func remove(_ arg0: JavaObject?) -> Bool + open func remove(_ arg0: JavaObject?) -> Bool @JavaMethod - public func size() -> Int32 + open func size() -> Int32 @JavaMethod - public func clone() -> ArrayDeque! + open override func clone() -> ArrayDeque! @JavaMethod - public func clear() + open func clear() @JavaMethod - public func isEmpty() -> Bool + open func isEmpty() -> Bool @JavaMethod - public func add(_ arg0: JavaObject?) -> Bool + open func add(_ arg0: JavaObject?) -> Bool @JavaMethod - public func toArray(_ arg0: [JavaObject?]) -> [JavaObject?] + open func toArray(_ arg0: [JavaObject?]) -> [JavaObject?] @JavaMethod - public func toArray() -> [JavaObject?] + open func toArray() -> [JavaObject?] @JavaMethod - public func iterator() -> JavaIterator! + open func iterator() -> JavaIterator! @JavaMethod - public func contains(_ arg0: JavaObject?) -> Bool + open func contains(_ arg0: JavaObject?) -> Bool @JavaMethod - public func addAll(_ arg0: JavaCollection?) -> Bool + open func addAll(_ arg0: JavaCollection?) -> Bool @JavaMethod - public func peek() -> JavaObject! + open func peek() -> JavaObject! @JavaMethod - public func getFirst() -> JavaObject! + open func getFirst() -> JavaObject! @JavaMethod - public func getLast() -> JavaObject! + open func getLast() -> JavaObject! @JavaMethod - public func element() -> JavaObject! + open func element() -> JavaObject! @JavaMethod - public func addFirst(_ arg0: JavaObject?) + open func addFirst(_ arg0: JavaObject?) @JavaMethod - public func addLast(_ arg0: JavaObject?) + open func addLast(_ arg0: JavaObject?) @JavaMethod - public func removeFirst() -> JavaObject! + open func removeFirst() -> JavaObject! @JavaMethod - public func removeLast() -> JavaObject! + open func removeLast() -> JavaObject! @JavaMethod - public func removeAll(_ arg0: JavaCollection?) -> Bool + open func removeAll(_ arg0: JavaCollection?) -> Bool @JavaMethod - public func retainAll(_ arg0: JavaCollection?) -> Bool + open func retainAll(_ arg0: JavaCollection?) -> Bool @JavaMethod - public func poll() -> JavaObject! + open func poll() -> JavaObject! @JavaMethod - public func push(_ arg0: JavaObject?) + open func push(_ arg0: JavaObject?) @JavaMethod - public func pop() -> JavaObject! + open func pop() -> JavaObject! @JavaMethod - public func pollFirst() -> JavaObject! + open func pollFirst() -> JavaObject! @JavaMethod - public func pollLast() -> JavaObject! + open func pollLast() -> JavaObject! @JavaMethod - public func offerLast(_ arg0: JavaObject?) -> Bool + open func offerLast(_ arg0: JavaObject?) -> Bool @JavaMethod - public func peekFirst() -> JavaObject! + open func peekFirst() -> JavaObject! @JavaMethod - public func removeFirstOccurrence(_ arg0: JavaObject?) -> Bool + open func removeFirstOccurrence(_ arg0: JavaObject?) -> Bool @JavaMethod - public func offerFirst(_ arg0: JavaObject?) -> Bool + open func offerFirst(_ arg0: JavaObject?) -> Bool @JavaMethod - public func peekLast() -> JavaObject! + open func peekLast() -> JavaObject! @JavaMethod - public func removeLastOccurrence(_ arg0: JavaObject?) -> Bool + open func removeLastOccurrence(_ arg0: JavaObject?) -> Bool @JavaMethod - public func offer(_ arg0: JavaObject?) -> Bool + open func offer(_ arg0: JavaObject?) -> Bool @JavaMethod - public func descendingIterator() -> JavaIterator! - - @JavaMethod - public func toString() -> String - - @JavaMethod - public func containsAll(_ arg0: JavaCollection?) -> Bool - - @JavaMethod - public func equals(_ arg0: JavaObject?) -> Bool - - @JavaMethod - public func hashCode() -> Int32 - - @JavaMethod - public func getClass() -> JavaClass! - - @JavaMethod - public func notify() - - @JavaMethod - public func notifyAll() - - @JavaMethod - public func wait(_ arg0: Int64) throws - - @JavaMethod - public func wait(_ arg0: Int64, _ arg1: Int32) throws - - @JavaMethod - public func wait() throws + open func descendingIterator() -> JavaIterator! } diff --git a/Sources/JavaKitCollection/generated/ArrayList.swift b/Sources/JavaKitCollection/generated/ArrayList.swift index 7074b693..6748640b 100644 --- a/Sources/JavaKitCollection/generated/ArrayList.swift +++ b/Sources/JavaKitCollection/generated/ArrayList.swift @@ -2,140 +2,116 @@ import JavaKit import JavaRuntime -@JavaClass("java.util.ArrayList", extends: JavaObject.self, implements: List.self, RandomAccess.self) -public struct ArrayList { +@JavaClass("java.util.ArrayList", implements: List.self, RandomAccess.self) +open class ArrayList: JavaObject { @JavaMethod - public init(_ arg0: JavaCollection?, environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(_ arg0: JavaCollection?, environment: JNIEnvironment? = nil) @JavaMethod - public init(environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(environment: JNIEnvironment? = nil) @JavaMethod - public init(_ arg0: Int32, environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(_ arg0: Int32, environment: JNIEnvironment? = nil) @JavaMethod - public func remove(_ arg0: JavaObject?) -> Bool + open func remove(_ arg0: JavaObject?) -> Bool @JavaMethod - public func remove(_ arg0: Int32) -> JavaObject! + open func remove(_ arg0: Int32) -> JavaObject! @JavaMethod - public func size() -> Int32 + open func size() -> Int32 @JavaMethod - public func get(_ arg0: Int32) -> JavaObject! + open func get(_ arg0: Int32) -> JavaObject! @JavaMethod - public func equals(_ arg0: JavaObject?) -> Bool + open override func equals(_ arg0: JavaObject?) -> Bool @JavaMethod - public func hashCode() -> Int32 + open override func hashCode() -> Int32 @JavaMethod - public func clone() -> JavaObject! + open override func clone() -> JavaObject! @JavaMethod - public func indexOf(_ arg0: JavaObject?) -> Int32 + open func indexOf(_ arg0: JavaObject?) -> Int32 @JavaMethod - public func clear() + open func clear() @JavaMethod - public func lastIndexOf(_ arg0: JavaObject?) -> Int32 + open func lastIndexOf(_ arg0: JavaObject?) -> Int32 @JavaMethod - public func isEmpty() -> Bool + open func isEmpty() -> Bool @JavaMethod - public func add(_ arg0: JavaObject?) -> Bool + open func add(_ arg0: JavaObject?) -> Bool @JavaMethod - public func add(_ arg0: Int32, _ arg1: JavaObject?) + open func add(_ arg0: Int32, _ arg1: JavaObject?) @JavaMethod - public func subList(_ arg0: Int32, _ arg1: Int32) -> List! + open func subList(_ arg0: Int32, _ arg1: Int32) -> List! @JavaMethod - public func toArray() -> [JavaObject?] + open func toArray() -> [JavaObject?] @JavaMethod - public func toArray(_ arg0: [JavaObject?]) -> [JavaObject?] + open func toArray(_ arg0: [JavaObject?]) -> [JavaObject?] @JavaMethod - public func iterator() -> JavaIterator! + open func iterator() -> JavaIterator! @JavaMethod - public func contains(_ arg0: JavaObject?) -> Bool + open func contains(_ arg0: JavaObject?) -> Bool @JavaMethod - public func addAll(_ arg0: Int32, _ arg1: JavaCollection?) -> Bool + open func addAll(_ arg0: Int32, _ arg1: JavaCollection?) -> Bool @JavaMethod - public func addAll(_ arg0: JavaCollection?) -> Bool + open func addAll(_ arg0: JavaCollection?) -> Bool @JavaMethod - public func set(_ arg0: Int32, _ arg1: JavaObject?) -> JavaObject! + open func set(_ arg0: Int32, _ arg1: JavaObject?) -> JavaObject! @JavaMethod - public func ensureCapacity(_ arg0: Int32) + open func ensureCapacity(_ arg0: Int32) @JavaMethod - public func trimToSize() + open func trimToSize() @JavaMethod - public func getFirst() -> JavaObject! + open func getFirst() -> JavaObject! @JavaMethod - public func getLast() -> JavaObject! + open func getLast() -> JavaObject! @JavaMethod - public func addFirst(_ arg0: JavaObject?) + open func addFirst(_ arg0: JavaObject?) @JavaMethod - public func addLast(_ arg0: JavaObject?) + open func addLast(_ arg0: JavaObject?) @JavaMethod - public func removeFirst() -> JavaObject! + open func removeFirst() -> JavaObject! @JavaMethod - public func removeLast() -> JavaObject! + open func removeLast() -> JavaObject! @JavaMethod - public func removeAll(_ arg0: JavaCollection?) -> Bool + open func removeRange(_ arg0: Int32, _ arg1: Int32) @JavaMethod - public func retainAll(_ arg0: JavaCollection?) -> Bool + open func removeAll(_ arg0: JavaCollection?) -> Bool @JavaMethod - public func listIterator(_ arg0: Int32) -> ListIterator! + open func retainAll(_ arg0: JavaCollection?) -> Bool @JavaMethod - public func listIterator() -> ListIterator! + open func listIterator(_ arg0: Int32) -> ListIterator! @JavaMethod - public func toString() -> String - - @JavaMethod - public func containsAll(_ arg0: JavaCollection?) -> Bool - - @JavaMethod - public func getClass() -> JavaClass! - - @JavaMethod - public func notify() - - @JavaMethod - public func notifyAll() - - @JavaMethod - public func wait(_ arg0: Int64) throws - - @JavaMethod - public func wait(_ arg0: Int64, _ arg1: Int32) throws - - @JavaMethod - public func wait() throws - - @JavaMethod - public func reversed() -> List! + open func listIterator() -> ListIterator! } diff --git a/Sources/JavaKitCollection/generated/BitSet.swift b/Sources/JavaKitCollection/generated/BitSet.swift index d00f539d..c7e54b95 100644 --- a/Sources/JavaKitCollection/generated/BitSet.swift +++ b/Sources/JavaKitCollection/generated/BitSet.swift @@ -2,121 +2,103 @@ import JavaKit import JavaRuntime -@JavaClass("java.util.BitSet", extends: JavaObject.self) -public struct BitSet { +@JavaClass("java.util.BitSet") +open class BitSet: JavaObject { @JavaMethod - public init(environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(environment: JNIEnvironment? = nil) @JavaMethod - public init(_ arg0: Int32, environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(_ arg0: Int32, environment: JNIEnvironment? = nil) @JavaMethod - public func cardinality() -> Int32 + open func cardinality() -> Int32 @JavaMethod - public func nextSetBit(_ arg0: Int32) -> Int32 + open func nextSetBit(_ arg0: Int32) -> Int32 @JavaMethod - public func toLongArray() -> [Int64] + open func toLongArray() -> [Int64] @JavaMethod - public func previousSetBit(_ arg0: Int32) -> Int32 + open func previousSetBit(_ arg0: Int32) -> Int32 @JavaMethod - public func previousClearBit(_ arg0: Int32) -> Int32 + open func previousClearBit(_ arg0: Int32) -> Int32 @JavaMethod - public func intersects(_ arg0: BitSet?) -> Bool + open func intersects(_ arg0: BitSet?) -> Bool @JavaMethod - public func size() -> Int32 + open func size() -> Int32 @JavaMethod - public func get(_ arg0: Int32, _ arg1: Int32) -> BitSet! + open func get(_ arg0: Int32, _ arg1: Int32) -> BitSet! @JavaMethod - public func get(_ arg0: Int32) -> Bool + open func get(_ arg0: Int32) -> Bool @JavaMethod - public func equals(_ arg0: JavaObject?) -> Bool + open override func equals(_ arg0: JavaObject?) -> Bool @JavaMethod - public func length() -> Int32 + open func length() -> Int32 @JavaMethod - public func toString() -> String + open override func toString() -> String @JavaMethod - public func hashCode() -> Int32 + open override func hashCode() -> Int32 @JavaMethod - public func clone() -> JavaObject! + open override func clone() -> JavaObject! @JavaMethod - public func clear(_ arg0: Int32) + open func clear(_ arg0: Int32) @JavaMethod - public func clear(_ arg0: Int32, _ arg1: Int32) + open func clear(_ arg0: Int32, _ arg1: Int32) @JavaMethod - public func clear() + open func clear() @JavaMethod - public func isEmpty() -> Bool + open func isEmpty() -> Bool @JavaMethod - public func set(_ arg0: Int32, _ arg1: Int32, _ arg2: Bool) + open func set(_ arg0: Int32, _ arg1: Int32, _ arg2: Bool) @JavaMethod - public func set(_ arg0: Int32, _ arg1: Int32) + open func set(_ arg0: Int32, _ arg1: Int32) @JavaMethod - public func set(_ arg0: Int32) + open func set(_ arg0: Int32) @JavaMethod - public func set(_ arg0: Int32, _ arg1: Bool) + open func set(_ arg0: Int32, _ arg1: Bool) @JavaMethod - public func flip(_ arg0: Int32, _ arg1: Int32) + open func flip(_ arg0: Int32, _ arg1: Int32) @JavaMethod - public func flip(_ arg0: Int32) + open func flip(_ arg0: Int32) @JavaMethod - public func nextClearBit(_ arg0: Int32) -> Int32 + open func nextClearBit(_ arg0: Int32) -> Int32 @JavaMethod - public func or(_ arg0: BitSet?) + open func or(_ arg0: BitSet?) @JavaMethod - public func toByteArray() -> [Int8] + open func toByteArray() -> [Int8] @JavaMethod - public func and(_ arg0: BitSet?) + open func and(_ arg0: BitSet?) @JavaMethod - public func xor(_ arg0: BitSet?) + open func xor(_ arg0: BitSet?) @JavaMethod - public func andNot(_ arg0: BitSet?) - - @JavaMethod - public func getClass() -> JavaClass! - - @JavaMethod - public func notify() - - @JavaMethod - public func notifyAll() - - @JavaMethod - public func wait(_ arg0: Int64) throws - - @JavaMethod - public func wait(_ arg0: Int64, _ arg1: Int32) throws - - @JavaMethod - public func wait() throws + open func andNot(_ arg0: BitSet?) } extension JavaClass { @JavaStaticMethod diff --git a/Sources/JavaKitCollection/generated/HashMap.swift b/Sources/JavaKitCollection/generated/HashMap.swift index 9f800c63..424dfbb9 100644 --- a/Sources/JavaKitCollection/generated/HashMap.swift +++ b/Sources/JavaKitCollection/generated/HashMap.swift @@ -2,91 +2,64 @@ import JavaKit import JavaRuntime -@JavaClass("java.util.HashMap", extends: JavaObject.self) -public struct HashMap { +@JavaClass("java.util.HashMap") +open class HashMap: JavaObject { @JavaMethod - public init(_ arg0: Int32, environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(_ arg0: Int32, environment: JNIEnvironment? = nil) @JavaMethod - public init(_ arg0: Int32, _ arg1: Float, environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(_ arg0: Int32, _ arg1: Float, environment: JNIEnvironment? = nil) @JavaMethod - public init(environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(environment: JNIEnvironment? = nil) @JavaMethod - public func remove(_ arg0: JavaObject?) -> JavaObject! + open func remove(_ arg0: JavaObject?) -> JavaObject! @JavaMethod - public func remove(_ arg0: JavaObject?, _ arg1: JavaObject?) -> Bool + open func remove(_ arg0: JavaObject?, _ arg1: JavaObject?) -> Bool @JavaMethod - public func size() -> Int32 + open func size() -> Int32 @JavaMethod - public func get(_ arg0: JavaObject?) -> JavaObject! + open func get(_ arg0: JavaObject?) -> JavaObject! @JavaMethod - public func put(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject! + open func put(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject! @JavaMethod - public func values() -> JavaCollection! + open func values() -> JavaCollection! @JavaMethod - public func clone() -> JavaObject! + open override func clone() -> JavaObject! @JavaMethod - public func clear() + open func clear() @JavaMethod - public func isEmpty() -> Bool + open func isEmpty() -> Bool @JavaMethod - public func replace(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject! + open func replace(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject! @JavaMethod - public func replace(_ arg0: JavaObject?, _ arg1: JavaObject?, _ arg2: JavaObject?) -> Bool + open func replace(_ arg0: JavaObject?, _ arg1: JavaObject?, _ arg2: JavaObject?) -> Bool @JavaMethod - public func putIfAbsent(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject! + open func putIfAbsent(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject! @JavaMethod - public func containsKey(_ arg0: JavaObject?) -> Bool + open func containsKey(_ arg0: JavaObject?) -> Bool @JavaMethod - public func keySet() -> JavaSet! + open func keySet() -> JavaSet! @JavaMethod - public func containsValue(_ arg0: JavaObject?) -> Bool + open func containsValue(_ arg0: JavaObject?) -> Bool @JavaMethod - public func getOrDefault(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject! - - @JavaMethod - public func equals(_ arg0: JavaObject?) -> Bool - - @JavaMethod - public func toString() -> String - - @JavaMethod - public func hashCode() -> Int32 - - @JavaMethod - public func getClass() -> JavaClass! - - @JavaMethod - public func notify() - - @JavaMethod - public func notifyAll() - - @JavaMethod - public func wait(_ arg0: Int64) throws - - @JavaMethod - public func wait(_ arg0: Int64, _ arg1: Int32) throws - - @JavaMethod - public func wait() throws + open func getOrDefault(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject! } extension JavaClass { @JavaStaticMethod diff --git a/Sources/JavaKitCollection/generated/HashSet.swift b/Sources/JavaKitCollection/generated/HashSet.swift index ab2da187..97b15dff 100644 --- a/Sources/JavaKitCollection/generated/HashSet.swift +++ b/Sources/JavaKitCollection/generated/HashSet.swift @@ -2,88 +2,49 @@ import JavaKit import JavaRuntime -@JavaClass("java.util.HashSet", extends: JavaObject.self, implements: JavaSet.self) -public struct HashSet { +@JavaClass("java.util.HashSet", implements: JavaSet.self) +open class HashSet: JavaObject { @JavaMethod - public init(_ arg0: Int32, environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(_ arg0: Int32, environment: JNIEnvironment? = nil) @JavaMethod - public init(_ arg0: Int32, _ arg1: Float, environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(_ arg0: Int32, _ arg1: Float, environment: JNIEnvironment? = nil) @JavaMethod - public init(_ arg0: JavaCollection?, environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(_ arg0: JavaCollection?, environment: JNIEnvironment? = nil) @JavaMethod - public init(environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(environment: JNIEnvironment? = nil) @JavaMethod - public func remove(_ arg0: JavaObject?) -> Bool + open func remove(_ arg0: JavaObject?) -> Bool @JavaMethod - public func size() -> Int32 + open func size() -> Int32 @JavaMethod - public func clone() -> JavaObject! + open override func clone() -> JavaObject! @JavaMethod - public func clear() + open func clear() @JavaMethod - public func isEmpty() -> Bool + open func isEmpty() -> Bool @JavaMethod - public func add(_ arg0: JavaObject?) -> Bool + open func add(_ arg0: JavaObject?) -> Bool @JavaMethod - public func toArray(_ arg0: [JavaObject?]) -> [JavaObject?] + open func toArray(_ arg0: [JavaObject?]) -> [JavaObject?] @JavaMethod - public func toArray() -> [JavaObject?] + open func toArray() -> [JavaObject?] @JavaMethod - public func iterator() -> JavaIterator! + open func iterator() -> JavaIterator! @JavaMethod - public func contains(_ arg0: JavaObject?) -> Bool - - @JavaMethod - public func equals(_ arg0: JavaObject?) -> Bool - - @JavaMethod - public func hashCode() -> Int32 - - @JavaMethod - public func removeAll(_ arg0: JavaCollection?) -> Bool - - @JavaMethod - public func toString() -> String - - @JavaMethod - public func addAll(_ arg0: JavaCollection?) -> Bool - - @JavaMethod - public func retainAll(_ arg0: JavaCollection?) -> Bool - - @JavaMethod - public func containsAll(_ arg0: JavaCollection?) -> Bool - - @JavaMethod - public func getClass() -> JavaClass! - - @JavaMethod - public func notify() - - @JavaMethod - public func notifyAll() - - @JavaMethod - public func wait(_ arg0: Int64) throws - - @JavaMethod - public func wait(_ arg0: Int64, _ arg1: Int32) throws - - @JavaMethod - public func wait() throws + open func contains(_ arg0: JavaObject?) -> Bool } extension JavaClass { @JavaStaticMethod diff --git a/Sources/JavaKitCollection/generated/JavaDictionary.swift b/Sources/JavaKitCollection/generated/JavaDictionary.swift index df1bdc87..43ded915 100644 --- a/Sources/JavaKitCollection/generated/JavaDictionary.swift +++ b/Sources/JavaKitCollection/generated/JavaDictionary.swift @@ -2,56 +2,29 @@ import JavaKit import JavaRuntime -@JavaClass("java.util.Dictionary", extends: JavaObject.self) -public struct JavaDictionary { +@JavaClass("java.util.Dictionary") +open class JavaDictionary: JavaObject { @JavaMethod - public init(environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(environment: JNIEnvironment? = nil) @JavaMethod - public func remove(_ arg0: JavaObject?) -> JavaObject! + open func remove(_ arg0: JavaObject?) -> JavaObject! @JavaMethod - public func size() -> Int32 + open func size() -> Int32 @JavaMethod - public func get(_ arg0: JavaObject?) -> JavaObject! + open func get(_ arg0: JavaObject?) -> JavaObject! @JavaMethod - public func put(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject! + open func put(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject! @JavaMethod - public func isEmpty() -> Bool + open func isEmpty() -> Bool @JavaMethod - public func elements() -> Enumeration! + open func elements() -> Enumeration! @JavaMethod - public func keys() -> Enumeration! - - @JavaMethod - public func equals(_ arg0: JavaObject?) -> Bool - - @JavaMethod - public func toString() -> String - - @JavaMethod - public func hashCode() -> Int32 - - @JavaMethod - public func getClass() -> JavaClass! - - @JavaMethod - public func notify() - - @JavaMethod - public func notifyAll() - - @JavaMethod - public func wait(_ arg0: Int64) throws - - @JavaMethod - public func wait(_ arg0: Int64, _ arg1: Int32) throws - - @JavaMethod - public func wait() throws + open func keys() -> Enumeration! } diff --git a/Sources/JavaKitCollection/generated/PriorityQueue.swift b/Sources/JavaKitCollection/generated/PriorityQueue.swift index 5704db8a..14e50f31 100644 --- a/Sources/JavaKitCollection/generated/PriorityQueue.swift +++ b/Sources/JavaKitCollection/generated/PriorityQueue.swift @@ -2,98 +2,56 @@ import JavaKit import JavaRuntime -@JavaClass("java.util.PriorityQueue", extends: JavaObject.self) -public struct PriorityQueue { +@JavaClass("java.util.PriorityQueue") +open class PriorityQueue: JavaObject { @JavaMethod - public init(_ arg0: PriorityQueue?, environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(_ arg0: PriorityQueue?, environment: JNIEnvironment? = nil) @JavaMethod - public init(_ arg0: JavaCollection?, environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(_ arg0: JavaCollection?, environment: JNIEnvironment? = nil) @JavaMethod - public init(_ arg0: Int32, environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(_ arg0: Int32, environment: JNIEnvironment? = nil) @JavaMethod - public init(environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(environment: JNIEnvironment? = nil) @JavaMethod - public func remove(_ arg0: JavaObject?) -> Bool + open func remove(_ arg0: JavaObject?) -> Bool @JavaMethod - public func size() -> Int32 + open func size() -> Int32 @JavaMethod - public func clear() + open func clear() @JavaMethod - public func add(_ arg0: JavaObject?) -> Bool + open func add(_ arg0: JavaObject?) -> Bool @JavaMethod - public func toArray(_ arg0: [JavaObject?]) -> [JavaObject?] + open func toArray(_ arg0: [JavaObject?]) -> [JavaObject?] @JavaMethod - public func toArray() -> [JavaObject?] + open func toArray() -> [JavaObject?] @JavaMethod - public func iterator() -> JavaIterator! + open func iterator() -> JavaIterator! @JavaMethod - public func contains(_ arg0: JavaObject?) -> Bool + open func contains(_ arg0: JavaObject?) -> Bool @JavaMethod - public func peek() -> JavaObject! + open func peek() -> JavaObject! @JavaMethod - public func removeAll(_ arg0: JavaCollection?) -> Bool + open func removeAll(_ arg0: JavaCollection?) -> Bool @JavaMethod - public func retainAll(_ arg0: JavaCollection?) -> Bool + open func retainAll(_ arg0: JavaCollection?) -> Bool @JavaMethod - public func poll() -> JavaObject! + open func poll() -> JavaObject! @JavaMethod - public func offer(_ arg0: JavaObject?) -> Bool - - @JavaMethod - public func remove() -> JavaObject! - - @JavaMethod - public func addAll(_ arg0: JavaCollection?) -> Bool - - @JavaMethod - public func element() -> JavaObject! - - @JavaMethod - public func toString() -> String - - @JavaMethod - public func isEmpty() -> Bool - - @JavaMethod - public func containsAll(_ arg0: JavaCollection?) -> Bool - - @JavaMethod - public func equals(_ arg0: JavaObject?) -> Bool - - @JavaMethod - public func hashCode() -> Int32 - - @JavaMethod - public func getClass() -> JavaClass! - - @JavaMethod - public func notify() - - @JavaMethod - public func notifyAll() - - @JavaMethod - public func wait(_ arg0: Int64) throws - - @JavaMethod - public func wait(_ arg0: Int64, _ arg1: Int32) throws - - @JavaMethod - public func wait() throws + open func offer(_ arg0: JavaObject?) -> Bool } diff --git a/Sources/JavaKitCollection/generated/Stack.swift b/Sources/JavaKitCollection/generated/Stack.swift index e79e7e07..867e9d44 100644 --- a/Sources/JavaKitCollection/generated/Stack.swift +++ b/Sources/JavaKitCollection/generated/Stack.swift @@ -2,194 +2,23 @@ import JavaKit import JavaRuntime -@JavaClass("java.util.Stack", extends: JavaObject.self) -public struct Stack { +@JavaClass("java.util.Stack") +open class Stack: JavaObject { @JavaMethod - public init(environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(environment: JNIEnvironment? = nil) @JavaMethod - public func empty() -> Bool + open func empty() -> Bool @JavaMethod - public func peek() -> JavaObject! + open func peek() -> JavaObject! @JavaMethod - public func search(_ arg0: JavaObject?) -> Int32 + open func search(_ arg0: JavaObject?) -> Int32 @JavaMethod - public func push(_ arg0: JavaObject?) -> JavaObject! + open func push(_ arg0: JavaObject?) -> JavaObject! @JavaMethod - public func pop() -> JavaObject! - - @JavaMethod - public func addElement(_ arg0: JavaObject?) - - @JavaMethod - public func removeElementAt(_ arg0: Int32) - - @JavaMethod - public func removeElement(_ arg0: JavaObject?) -> Bool - - @JavaMethod - public func insertElementAt(_ arg0: JavaObject?, _ arg1: Int32) - - @JavaMethod - public func removeAllElements() - - @JavaMethod - public func firstElement() -> JavaObject! - - @JavaMethod - public func lastElement() -> JavaObject! - - @JavaMethod - public func setElementAt(_ arg0: JavaObject?, _ arg1: Int32) - - @JavaMethod - public func remove(_ arg0: Int32) -> JavaObject! - - @JavaMethod - public func remove(_ arg0: JavaObject?) -> Bool - - @JavaMethod - public func size() -> Int32 - - @JavaMethod - public func get(_ arg0: Int32) -> JavaObject! - - @JavaMethod - public func equals(_ arg0: JavaObject?) -> Bool - - @JavaMethod - public func toString() -> String - - @JavaMethod - public func hashCode() -> Int32 - - @JavaMethod - public func clone() -> JavaObject! - - @JavaMethod - public func indexOf(_ arg0: JavaObject?, _ arg1: Int32) -> Int32 - - @JavaMethod - public func indexOf(_ arg0: JavaObject?) -> Int32 - - @JavaMethod - public func clear() - - @JavaMethod - public func lastIndexOf(_ arg0: JavaObject?, _ arg1: Int32) -> Int32 - - @JavaMethod - public func lastIndexOf(_ arg0: JavaObject?) -> Int32 - - @JavaMethod - public func isEmpty() -> Bool - - @JavaMethod - public func add(_ arg0: Int32, _ arg1: JavaObject?) - - @JavaMethod - public func add(_ arg0: JavaObject?) -> Bool - - @JavaMethod - public func subList(_ arg0: Int32, _ arg1: Int32) -> List! - - @JavaMethod - public func toArray(_ arg0: [JavaObject?]) -> [JavaObject?] - - @JavaMethod - public func toArray() -> [JavaObject?] - - @JavaMethod - public func iterator() -> JavaIterator! - - @JavaMethod - public func contains(_ arg0: JavaObject?) -> Bool - - @JavaMethod - public func elements() -> Enumeration! - - @JavaMethod - public func addAll(_ arg0: Int32, _ arg1: JavaCollection?) -> Bool - - @JavaMethod - public func addAll(_ arg0: JavaCollection?) -> Bool - - @JavaMethod - public func set(_ arg0: Int32, _ arg1: JavaObject?) -> JavaObject! - - @JavaMethod - public func capacity() -> Int32 - - @JavaMethod - public func ensureCapacity(_ arg0: Int32) - - @JavaMethod - public func trimToSize() - - @JavaMethod - public func elementAt(_ arg0: Int32) -> JavaObject! - - @JavaMethod - public func removeAll(_ arg0: JavaCollection?) -> Bool - - @JavaMethod - public func retainAll(_ arg0: JavaCollection?) -> Bool - - @JavaMethod - public func listIterator() -> ListIterator! - - @JavaMethod - public func listIterator(_ arg0: Int32) -> ListIterator! - - @JavaMethod - public func containsAll(_ arg0: JavaCollection?) -> Bool - - @JavaMethod - public func setSize(_ arg0: Int32) - - @JavaMethod - public func copyInto(_ arg0: [JavaObject?]) - - @JavaMethod - public func getClass() -> JavaClass! - - @JavaMethod - public func notify() - - @JavaMethod - public func notifyAll() - - @JavaMethod - public func wait(_ arg0: Int64) throws - - @JavaMethod - public func wait(_ arg0: Int64, _ arg1: Int32) throws - - @JavaMethod - public func wait() throws - - @JavaMethod - public func getFirst() -> JavaObject! - - @JavaMethod - public func getLast() -> JavaObject! - - @JavaMethod - public func addFirst(_ arg0: JavaObject?) - - @JavaMethod - public func addLast(_ arg0: JavaObject?) - - @JavaMethod - public func removeFirst() -> JavaObject! - - @JavaMethod - public func removeLast() -> JavaObject! - - @JavaMethod - public func reversed() -> List! + open func pop() -> JavaObject! } diff --git a/Sources/JavaKitCollection/generated/TreeMap.swift b/Sources/JavaKitCollection/generated/TreeMap.swift index 3d7d858a..7796d555 100644 --- a/Sources/JavaKitCollection/generated/TreeMap.swift +++ b/Sources/JavaKitCollection/generated/TreeMap.swift @@ -2,193 +2,121 @@ import JavaKit import JavaRuntime -@JavaClass("java.util.TreeMap", extends: JavaObject.self) -public struct TreeMap { +@JavaClass("java.util.TreeMap") +open class TreeMap: JavaObject { @JavaMethod - public init(environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(environment: JNIEnvironment? = nil) @JavaMethod - public func remove(_ arg0: JavaObject?) -> JavaObject! + open func remove(_ arg0: JavaObject?) -> JavaObject! @JavaMethod - public func size() -> Int32 + open func size() -> Int32 @JavaMethod - public func get(_ arg0: JavaObject?) -> JavaObject! + open func get(_ arg0: JavaObject?) -> JavaObject! @JavaMethod - public func put(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject! + open func put(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject! @JavaMethod - public func values() -> JavaCollection! + open func values() -> JavaCollection! @JavaMethod - public func clone() -> JavaObject! + open override func clone() -> JavaObject! @JavaMethod - public func clear() + open func clear() @JavaMethod - public func replace(_ arg0: JavaObject?, _ arg1: JavaObject?, _ arg2: JavaObject?) -> Bool + open func replace(_ arg0: JavaObject?, _ arg1: JavaObject?, _ arg2: JavaObject?) -> Bool @JavaMethod - public func replace(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject! + open func replace(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject! @JavaMethod - public func putIfAbsent(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject! + open func putIfAbsent(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject! @JavaMethod - public func containsKey(_ arg0: JavaObject?) -> Bool + open func containsKey(_ arg0: JavaObject?) -> Bool @JavaMethod - public func keySet() -> JavaSet! + open func keySet() -> JavaSet! @JavaMethod - public func containsValue(_ arg0: JavaObject?) -> Bool + open func containsValue(_ arg0: JavaObject?) -> Bool @JavaMethod - public func firstKey() -> JavaObject! + open func firstKey() -> JavaObject! @JavaMethod - public func putFirst(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject! + open func putFirst(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject! @JavaMethod - public func putLast(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject! + open func putLast(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject! @JavaMethod - public func lowerKey(_ arg0: JavaObject?) -> JavaObject! + open func lowerKey(_ arg0: JavaObject?) -> JavaObject! @JavaMethod - public func floorKey(_ arg0: JavaObject?) -> JavaObject! + open func floorKey(_ arg0: JavaObject?) -> JavaObject! @JavaMethod - public func ceilingKey(_ arg0: JavaObject?) -> JavaObject! + open func ceilingKey(_ arg0: JavaObject?) -> JavaObject! @JavaMethod - public func higherKey(_ arg0: JavaObject?) -> JavaObject! + open func higherKey(_ arg0: JavaObject?) -> JavaObject! @JavaMethod - public func lastKey() -> JavaObject! - - @JavaMethod - public func equals(_ arg0: JavaObject?) -> Bool - - @JavaMethod - public func toString() -> String - - @JavaMethod - public func hashCode() -> Int32 - - @JavaMethod - public func isEmpty() -> Bool - - @JavaMethod - public func getClass() -> JavaClass! - - @JavaMethod - public func notify() - - @JavaMethod - public func notifyAll() - - @JavaMethod - public func wait(_ arg0: Int64) throws - - @JavaMethod - public func wait(_ arg0: Int64, _ arg1: Int32) throws - - @JavaMethod - public func wait() throws - - @JavaMethod - public func remove(_ arg0: JavaObject?, _ arg1: JavaObject?) -> Bool - - @JavaMethod - public func getOrDefault(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject! + open func lastKey() -> JavaObject! } extension TreeMap { - @JavaClass("java.util.AbstractMap$SimpleEntry", extends: JavaObject.self) - public struct SimpleEntry { + @JavaClass("java.util.AbstractMap$SimpleEntry") + open class SimpleEntry: JavaObject { @JavaMethod - public init(_ arg0: JavaObject?, _ arg1: JavaObject?, environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(_ arg0: JavaObject?, _ arg1: JavaObject?, environment: JNIEnvironment? = nil) @JavaMethod - public func equals(_ arg0: JavaObject?) -> Bool + open override func equals(_ arg0: JavaObject?) -> Bool @JavaMethod - public func toString() -> String + open override func toString() -> String @JavaMethod - public func hashCode() -> Int32 + open override func hashCode() -> Int32 @JavaMethod - public func getValue() -> JavaObject! + open func getValue() -> JavaObject! @JavaMethod - public func getKey() -> JavaObject! + open func getKey() -> JavaObject! @JavaMethod - public func setValue(_ arg0: JavaObject?) -> JavaObject! - - @JavaMethod - public func getClass() -> JavaClass! - - @JavaMethod - public func notify() - - @JavaMethod - public func notifyAll() - - @JavaMethod - public func wait(_ arg0: Int64) throws - - @JavaMethod - public func wait(_ arg0: Int64, _ arg1: Int32) throws - - @JavaMethod - public func wait() throws + open func setValue(_ arg0: JavaObject?) -> JavaObject! } } extension TreeMap { - @JavaClass("java.util.AbstractMap$SimpleImmutableEntry", extends: JavaObject.self) - public struct SimpleImmutableEntry { - @JavaMethod - public init(_ arg0: JavaObject?, _ arg1: JavaObject?, environment: JNIEnvironment? = nil) - - @JavaMethod - public func equals(_ arg0: JavaObject?) -> Bool - - @JavaMethod - public func toString() -> String - - @JavaMethod - public func hashCode() -> Int32 - - @JavaMethod - public func getValue() -> JavaObject! - - @JavaMethod - public func getKey() -> JavaObject! - + @JavaClass("java.util.AbstractMap$SimpleImmutableEntry") + open class SimpleImmutableEntry: JavaObject { @JavaMethod - public func setValue(_ arg0: JavaObject?) -> JavaObject! + @_nonoverride public convenience init(_ arg0: JavaObject?, _ arg1: JavaObject?, environment: JNIEnvironment? = nil) @JavaMethod - public func getClass() -> JavaClass! + open override func equals(_ arg0: JavaObject?) -> Bool @JavaMethod - public func notify() + open override func toString() -> String @JavaMethod - public func notifyAll() + open override func hashCode() -> Int32 @JavaMethod - public func wait(_ arg0: Int64) throws + open func getValue() -> JavaObject! @JavaMethod - public func wait(_ arg0: Int64, _ arg1: Int32) throws + open func getKey() -> JavaObject! @JavaMethod - public func wait() throws + open func setValue(_ arg0: JavaObject?) -> JavaObject! } } diff --git a/Sources/JavaKitCollection/generated/TreeSet.swift b/Sources/JavaKitCollection/generated/TreeSet.swift index e78d6ada..7e1807ab 100644 --- a/Sources/JavaKitCollection/generated/TreeSet.swift +++ b/Sources/JavaKitCollection/generated/TreeSet.swift @@ -2,125 +2,71 @@ import JavaKit import JavaRuntime -@JavaClass("java.util.TreeSet", extends: JavaObject.self) -public struct TreeSet { +@JavaClass("java.util.TreeSet") +open class TreeSet: JavaObject { @JavaMethod - public init(_ arg0: JavaCollection?, environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(_ arg0: JavaCollection?, environment: JNIEnvironment? = nil) @JavaMethod - public init(environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(environment: JNIEnvironment? = nil) @JavaMethod - public func remove(_ arg0: JavaObject?) -> Bool + open func remove(_ arg0: JavaObject?) -> Bool @JavaMethod - public func size() -> Int32 + open func size() -> Int32 @JavaMethod - public func clone() -> JavaObject! + open override func clone() -> JavaObject! @JavaMethod - public func floor(_ arg0: JavaObject?) -> JavaObject! + open func floor(_ arg0: JavaObject?) -> JavaObject! @JavaMethod - public func clear() + open func clear() @JavaMethod - public func isEmpty() -> Bool + open func isEmpty() -> Bool @JavaMethod - public func add(_ arg0: JavaObject?) -> Bool + open func add(_ arg0: JavaObject?) -> Bool @JavaMethod - public func iterator() -> JavaIterator! + open func iterator() -> JavaIterator! @JavaMethod - public func contains(_ arg0: JavaObject?) -> Bool + open func contains(_ arg0: JavaObject?) -> Bool @JavaMethod - public func last() -> JavaObject! + open func last() -> JavaObject! @JavaMethod - public func addAll(_ arg0: JavaCollection?) -> Bool + open func addAll(_ arg0: JavaCollection?) -> Bool @JavaMethod - public func first() -> JavaObject! + open func first() -> JavaObject! @JavaMethod - public func addFirst(_ arg0: JavaObject?) + open func addFirst(_ arg0: JavaObject?) @JavaMethod - public func addLast(_ arg0: JavaObject?) + open func addLast(_ arg0: JavaObject?) @JavaMethod - public func lower(_ arg0: JavaObject?) -> JavaObject! + open func lower(_ arg0: JavaObject?) -> JavaObject! @JavaMethod - public func pollFirst() -> JavaObject! + open func pollFirst() -> JavaObject! @JavaMethod - public func pollLast() -> JavaObject! + open func pollLast() -> JavaObject! @JavaMethod - public func descendingIterator() -> JavaIterator! + open func descendingIterator() -> JavaIterator! @JavaMethod - public func ceiling(_ arg0: JavaObject?) -> JavaObject! + open func ceiling(_ arg0: JavaObject?) -> JavaObject! @JavaMethod - public func higher(_ arg0: JavaObject?) -> JavaObject! - - @JavaMethod - public func equals(_ arg0: JavaObject?) -> Bool - - @JavaMethod - public func hashCode() -> Int32 - - @JavaMethod - public func removeAll(_ arg0: JavaCollection?) -> Bool - - @JavaMethod - public func toString() -> String - - @JavaMethod - public func toArray(_ arg0: [JavaObject?]) -> [JavaObject?] - - @JavaMethod - public func toArray() -> [JavaObject?] - - @JavaMethod - public func retainAll(_ arg0: JavaCollection?) -> Bool - - @JavaMethod - public func containsAll(_ arg0: JavaCollection?) -> Bool - - @JavaMethod - public func getClass() -> JavaClass! - - @JavaMethod - public func notify() - - @JavaMethod - public func notifyAll() - - @JavaMethod - public func wait(_ arg0: Int64) throws - - @JavaMethod - public func wait(_ arg0: Int64, _ arg1: Int32) throws - - @JavaMethod - public func wait() throws - - @JavaMethod - public func removeFirst() -> JavaObject! - - @JavaMethod - public func removeLast() -> JavaObject! - - @JavaMethod - public func getFirst() -> JavaObject! - - @JavaMethod - public func getLast() -> JavaObject! + open func higher(_ arg0: JavaObject?) -> JavaObject! } diff --git a/Sources/JavaKitJar/generated/Attributes.swift b/Sources/JavaKitJar/generated/Attributes.swift index 1ecde6f7..f173c98d 100644 --- a/Sources/JavaKitJar/generated/Attributes.swift +++ b/Sources/JavaKitJar/generated/Attributes.swift @@ -3,133 +3,79 @@ import JavaKit import JavaKitCollection import JavaRuntime -@JavaClass("java.util.jar.Attributes", extends: JavaObject.self) -public struct Attributes { +@JavaClass("java.util.jar.Attributes") +open class Attributes: JavaObject { @JavaMethod - public init(_ arg0: Attributes?, environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(_ arg0: Attributes?, environment: JNIEnvironment? = nil) @JavaMethod - public init(_ arg0: Int32, environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(_ arg0: Int32, environment: JNIEnvironment? = nil) @JavaMethod - public init(environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(environment: JNIEnvironment? = nil) @JavaMethod - public func remove(_ arg0: JavaObject?) -> JavaObject! + open func remove(_ arg0: JavaObject?) -> JavaObject! @JavaMethod - public func size() -> Int32 + open func size() -> Int32 @JavaMethod - public func get(_ arg0: JavaObject?) -> JavaObject! + open func get(_ arg0: JavaObject?) -> JavaObject! @JavaMethod - public func put(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject! + open func put(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject! @JavaMethod - public func equals(_ arg0: JavaObject?) -> Bool + open override func equals(_ arg0: JavaObject?) -> Bool @JavaMethod - public func values() -> JavaCollection! + open func values() -> JavaCollection! @JavaMethod - public func hashCode() -> Int32 + open override func hashCode() -> Int32 @JavaMethod - public func clone() -> JavaObject! + open override func clone() -> JavaObject! @JavaMethod - public func clear() + open func clear() @JavaMethod - public func getValue(_ arg0: String) -> String + open func getValue(_ arg0: String) -> String @JavaMethod - public func getValue(_ arg0: Attributes.Name?) -> String + open func getValue(_ arg0: Attributes.Name?) -> String @JavaMethod - public func isEmpty() -> Bool + open func isEmpty() -> Bool @JavaMethod - public func containsKey(_ arg0: JavaObject?) -> Bool + open func containsKey(_ arg0: JavaObject?) -> Bool @JavaMethod - public func keySet() -> JavaSet! + open func keySet() -> JavaSet! @JavaMethod - public func containsValue(_ arg0: JavaObject?) -> Bool + open func containsValue(_ arg0: JavaObject?) -> Bool @JavaMethod - public func putValue(_ arg0: String, _ arg1: String) -> String - - @JavaMethod - public func toString() -> String - - @JavaMethod - public func getClass() -> JavaClass! - - @JavaMethod - public func notify() - - @JavaMethod - public func notifyAll() - - @JavaMethod - public func wait(_ arg0: Int64) throws - - @JavaMethod - public func wait(_ arg0: Int64, _ arg1: Int32) throws - - @JavaMethod - public func wait() throws - - @JavaMethod - public func remove(_ arg0: JavaObject?, _ arg1: JavaObject?) -> Bool - - @JavaMethod - public func replace(_ arg0: JavaObject?, _ arg1: JavaObject?, _ arg2: JavaObject?) -> Bool - - @JavaMethod - public func replace(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject! - - @JavaMethod - public func putIfAbsent(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject! - - @JavaMethod - public func getOrDefault(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject! + open func putValue(_ arg0: String, _ arg1: String) -> String } extension Attributes { - @JavaClass("java.util.jar.Attributes$Name", extends: JavaObject.self) - public struct Name { - @JavaMethod - public init(_ arg0: String, environment: JNIEnvironment? = nil) - - @JavaMethod - public func equals(_ arg0: JavaObject?) -> Bool - - @JavaMethod - public func toString() -> String - - @JavaMethod - public func hashCode() -> Int32 - - @JavaMethod - public func getClass() -> JavaClass! - - @JavaMethod - public func notify() - + @JavaClass("java.util.jar.Attributes$Name") + open class Name: JavaObject { @JavaMethod - public func notifyAll() + @_nonoverride public convenience init(_ arg0: String, environment: JNIEnvironment? = nil) @JavaMethod - public func wait(_ arg0: Int64) throws + open override func equals(_ arg0: JavaObject?) -> Bool @JavaMethod - public func wait(_ arg0: Int64, _ arg1: Int32) throws + open override func toString() -> String @JavaMethod - public func wait() throws + open override func hashCode() -> Int32 } } extension JavaClass { diff --git a/Sources/JavaKitJar/generated/JarEntry.swift b/Sources/JavaKitJar/generated/JarEntry.swift index 85f5afe7..3a90d6a8 100644 --- a/Sources/JavaKitJar/generated/JarEntry.swift +++ b/Sources/JavaKitJar/generated/JarEntry.swift @@ -2,100 +2,22 @@ import JavaKit import JavaRuntime -@JavaClass("java.util.jar.JarEntry", extends: ZipEntry.self) -public struct JarEntry { +@JavaClass("java.util.jar.JarEntry") +open class JarEntry: ZipEntry { @JavaMethod - public init(_ arg0: JarEntry?, environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(_ arg0: JarEntry?, environment: JNIEnvironment? = nil) @JavaMethod - public init(_ arg0: ZipEntry?, environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(_ arg0: ZipEntry?, environment: JNIEnvironment? = nil) @JavaMethod - public init(_ arg0: String, environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(_ arg0: String, environment: JNIEnvironment? = nil) @JavaMethod - public func getRealName() -> String + open func getRealName() -> String @JavaMethod - public func getAttributes() throws -> Attributes! - - @JavaMethod - public func getName() -> String - - @JavaMethod - public func toString() -> String - - @JavaMethod - public func hashCode() -> Int32 - - @JavaMethod - public func clone() -> JavaObject! - - @JavaMethod - public func getMethod() -> Int32 - - @JavaMethod - public func getSize() -> Int64 - - @JavaMethod - public func isDirectory() -> Bool - - @JavaMethod - public func getTime() -> Int64 - - @JavaMethod - public func setTime(_ arg0: Int64) - - @JavaMethod - public func setSize(_ arg0: Int64) - - @JavaMethod - public func getCompressedSize() -> Int64 - - @JavaMethod - public func setCompressedSize(_ arg0: Int64) - - @JavaMethod - public func setCrc(_ arg0: Int64) - - @JavaMethod - public func getCrc() -> Int64 - - @JavaMethod - public func setMethod(_ arg0: Int32) - - @JavaMethod - public func setExtra(_ arg0: [Int8]) - - @JavaMethod - public func getExtra() -> [Int8] - - @JavaMethod - public func setComment(_ arg0: String) - - @JavaMethod - public func getComment() -> String - - @JavaMethod - public func equals(_ arg0: JavaObject?) -> Bool - - @JavaMethod - public func getClass() -> JavaClass! - - @JavaMethod - public func notify() - - @JavaMethod - public func notifyAll() - - @JavaMethod - public func wait(_ arg0: Int64) throws - - @JavaMethod - public func wait(_ arg0: Int64, _ arg1: Int32) throws - - @JavaMethod - public func wait() throws + open func getAttributes() throws -> Attributes! } extension JavaClass { @JavaStaticField(isFinal: true) diff --git a/Sources/JavaKitJar/generated/JarFile.swift b/Sources/JavaKitJar/generated/JarFile.swift index a76d645e..d5ea9969 100644 --- a/Sources/JavaKitJar/generated/JarFile.swift +++ b/Sources/JavaKitJar/generated/JarFile.swift @@ -3,67 +3,28 @@ import JavaKit import JavaKitCollection import JavaRuntime -@JavaClass("java.util.jar.JarFile", extends: JavaObject.self) -public struct JarFile { +@JavaClass("java.util.jar.JarFile") +open class JarFile: JavaObject { @JavaMethod - public init(_ arg0: String, _ arg1: Bool, environment: JNIEnvironment? = nil) throws + @_nonoverride public convenience init(_ arg0: String, _ arg1: Bool, environment: JNIEnvironment? = nil) throws @JavaMethod - public init(_ arg0: String, environment: JNIEnvironment? = nil) throws + @_nonoverride public convenience init(_ arg0: String, environment: JNIEnvironment? = nil) throws @JavaMethod - public func entries() -> Enumeration! + open func entries() -> Enumeration! @JavaMethod - public func getManifest() throws -> Manifest! + open func getManifest() throws -> Manifest! @JavaMethod - public func getEntry(_ arg0: String) -> ZipEntry! + open func getEntry(_ arg0: String) -> ZipEntry! @JavaMethod - public func getJarEntry(_ arg0: String) -> JarEntry! + open func getJarEntry(_ arg0: String) -> JarEntry! @JavaMethod - public func isMultiRelease() -> Bool - - @JavaMethod - public func getName() -> String - - @JavaMethod - public func size() -> Int32 - - @JavaMethod - public func close() throws - - @JavaMethod - public func getComment() -> String - - @JavaMethod - public func equals(_ arg0: JavaObject?) -> Bool - - @JavaMethod - public func toString() -> String - - @JavaMethod - public func hashCode() -> Int32 - - @JavaMethod - public func getClass() -> JavaClass! - - @JavaMethod - public func notify() - - @JavaMethod - public func notifyAll() - - @JavaMethod - public func wait(_ arg0: Int64) throws - - @JavaMethod - public func wait(_ arg0: Int64, _ arg1: Int32) throws - - @JavaMethod - public func wait() throws + open func isMultiRelease() -> Bool } extension JavaClass { @JavaStaticField(isFinal: true) diff --git a/Sources/JavaKitJar/generated/JarInputStream.swift b/Sources/JavaKitJar/generated/JarInputStream.swift index ac6ade3b..f6d121d9 100644 --- a/Sources/JavaKitJar/generated/JarInputStream.swift +++ b/Sources/JavaKitJar/generated/JarInputStream.swift @@ -2,85 +2,22 @@ import JavaKit import JavaRuntime -@JavaClass("java.util.jar.JarInputStream", extends: JavaObject.self) -public struct JarInputStream { +@JavaClass("java.util.jar.JarInputStream") +open class JarInputStream: JavaObject { @JavaMethod - public func getNextEntry() throws -> ZipEntry! + open func getNextEntry() throws -> ZipEntry! @JavaMethod - public func getNextJarEntry() throws -> JarEntry! + open func getNextJarEntry() throws -> JarEntry! @JavaMethod - public func read(_ arg0: [Int8], _ arg1: Int32, _ arg2: Int32) throws -> Int32 + open func createZipEntry(_ arg0: String) -> ZipEntry! @JavaMethod - public func getManifest() -> Manifest! + open func read(_ arg0: [Int8], _ arg1: Int32, _ arg2: Int32) throws -> Int32 @JavaMethod - public func closeEntry() throws - - @JavaMethod - public func read() throws -> Int32 - - @JavaMethod - public func close() throws - - @JavaMethod - public func readAllBytes() throws -> [Int8] - - @JavaMethod - public func readNBytes(_ arg0: [Int8], _ arg1: Int32, _ arg2: Int32) throws -> Int32 - - @JavaMethod - public func readNBytes(_ arg0: Int32) throws -> [Int8] - - @JavaMethod - public func skip(_ arg0: Int64) throws -> Int64 - - @JavaMethod - public func available() throws -> Int32 - - @JavaMethod - public func skipNBytes(_ arg0: Int64) throws - - @JavaMethod - public func reset() throws - - @JavaMethod - public func mark(_ arg0: Int32) - - @JavaMethod - public func markSupported() -> Bool - - @JavaMethod - public func read(_ arg0: [Int8]) throws -> Int32 - - @JavaMethod - public func equals(_ arg0: JavaObject?) -> Bool - - @JavaMethod - public func toString() -> String - - @JavaMethod - public func hashCode() -> Int32 - - @JavaMethod - public func getClass() -> JavaClass! - - @JavaMethod - public func notify() - - @JavaMethod - public func notifyAll() - - @JavaMethod - public func wait(_ arg0: Int64) throws - - @JavaMethod - public func wait(_ arg0: Int64, _ arg1: Int32) throws - - @JavaMethod - public func wait() throws + open func getManifest() -> Manifest! } extension JavaClass { @JavaStaticField(isFinal: true) diff --git a/Sources/JavaKitJar/generated/JarOutputStream.swift b/Sources/JavaKitJar/generated/JarOutputStream.swift index 04b544c8..e13dc973 100644 --- a/Sources/JavaKitJar/generated/JarOutputStream.swift +++ b/Sources/JavaKitJar/generated/JarOutputStream.swift @@ -2,67 +2,10 @@ import JavaKit import JavaRuntime -@JavaClass("java.util.jar.JarOutputStream", extends: JavaObject.self) -public struct JarOutputStream { +@JavaClass("java.util.jar.JarOutputStream") +open class JarOutputStream: JavaObject { @JavaMethod - public func putNextEntry(_ arg0: ZipEntry?) throws - - @JavaMethod - public func closeEntry() throws - - @JavaMethod - public func write(_ arg0: [Int8], _ arg1: Int32, _ arg2: Int32) throws - - @JavaMethod - public func close() throws - - @JavaMethod - public func finish() throws - - @JavaMethod - public func setMethod(_ arg0: Int32) - - @JavaMethod - public func setComment(_ arg0: String) - - @JavaMethod - public func setLevel(_ arg0: Int32) - - @JavaMethod - public func flush() throws - - @JavaMethod - public func write(_ arg0: Int32) throws - - @JavaMethod - public func write(_ arg0: [Int8]) throws - - @JavaMethod - public func equals(_ arg0: JavaObject?) -> Bool - - @JavaMethod - public func toString() -> String - - @JavaMethod - public func hashCode() -> Int32 - - @JavaMethod - public func getClass() -> JavaClass! - - @JavaMethod - public func notify() - - @JavaMethod - public func notifyAll() - - @JavaMethod - public func wait(_ arg0: Int64) throws - - @JavaMethod - public func wait(_ arg0: Int64, _ arg1: Int32) throws - - @JavaMethod - public func wait() throws + open func putNextEntry(_ arg0: ZipEntry?) throws } extension JavaClass { @JavaStaticField(isFinal: true) diff --git a/Sources/JavaKitJar/generated/Manifest.swift b/Sources/JavaKitJar/generated/Manifest.swift index 6400f33c..101af57c 100644 --- a/Sources/JavaKitJar/generated/Manifest.swift +++ b/Sources/JavaKitJar/generated/Manifest.swift @@ -2,50 +2,29 @@ import JavaKit import JavaRuntime -@JavaClass("java.util.jar.Manifest", extends: JavaObject.self) -public struct Manifest { +@JavaClass("java.util.jar.Manifest") +open class Manifest: JavaObject { @JavaMethod - public init(_ arg0: Manifest?, environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(_ arg0: Manifest?, environment: JNIEnvironment? = nil) @JavaMethod - public init(environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(environment: JNIEnvironment? = nil) @JavaMethod - public func equals(_ arg0: JavaObject?) -> Bool + open override func equals(_ arg0: JavaObject?) -> Bool @JavaMethod - public func hashCode() -> Int32 + open override func hashCode() -> Int32 @JavaMethod - public func clone() -> JavaObject! + open override func clone() -> JavaObject! @JavaMethod - public func clear() + open func clear() @JavaMethod - public func getMainAttributes() -> Attributes! + open func getMainAttributes() -> Attributes! @JavaMethod - public func getAttributes(_ arg0: String) -> Attributes! - - @JavaMethod - public func toString() -> String - - @JavaMethod - public func getClass() -> JavaClass! - - @JavaMethod - public func notify() - - @JavaMethod - public func notifyAll() - - @JavaMethod - public func wait(_ arg0: Int64) throws - - @JavaMethod - public func wait(_ arg0: Int64, _ arg1: Int32) throws - - @JavaMethod - public func wait() throws + open func getAttributes(_ arg0: String) -> Attributes! } diff --git a/Sources/JavaKitJar/generated/ZipEntry.swift b/Sources/JavaKitJar/generated/ZipEntry.swift index 2f2e16a5..6a0fbd20 100644 --- a/Sources/JavaKitJar/generated/ZipEntry.swift +++ b/Sources/JavaKitJar/generated/ZipEntry.swift @@ -2,91 +2,70 @@ import JavaKit import JavaRuntime -@JavaClass("java.util.zip.ZipEntry", extends: JavaObject.self) -public struct ZipEntry { +@JavaClass("java.util.zip.ZipEntry") +open class ZipEntry: JavaObject { @JavaMethod - public init(_ arg0: String, environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(_ arg0: String, environment: JNIEnvironment? = nil) @JavaMethod - public init(_ arg0: ZipEntry?, environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(_ arg0: ZipEntry?, environment: JNIEnvironment? = nil) @JavaMethod - public func getName() -> String + open func getName() -> String @JavaMethod - public func toString() -> String + open override func toString() -> String @JavaMethod - public func hashCode() -> Int32 + open override func hashCode() -> Int32 @JavaMethod - public func clone() -> JavaObject! + open override func clone() -> JavaObject! @JavaMethod - public func getMethod() -> Int32 + open func getMethod() -> Int32 @JavaMethod - public func getSize() -> Int64 + open func getSize() -> Int64 @JavaMethod - public func isDirectory() -> Bool + open func isDirectory() -> Bool @JavaMethod - public func getTime() -> Int64 + open func getTime() -> Int64 @JavaMethod - public func setTime(_ arg0: Int64) + open func setTime(_ arg0: Int64) @JavaMethod - public func setSize(_ arg0: Int64) + open func setSize(_ arg0: Int64) @JavaMethod - public func getCompressedSize() -> Int64 + open func getCompressedSize() -> Int64 @JavaMethod - public func setCompressedSize(_ arg0: Int64) + open func setCompressedSize(_ arg0: Int64) @JavaMethod - public func setCrc(_ arg0: Int64) + open func setCrc(_ arg0: Int64) @JavaMethod - public func getCrc() -> Int64 + open func getCrc() -> Int64 @JavaMethod - public func setMethod(_ arg0: Int32) + open func setMethod(_ arg0: Int32) @JavaMethod - public func setExtra(_ arg0: [Int8]) + open func setExtra(_ arg0: [Int8]) @JavaMethod - public func getExtra() -> [Int8] + open func getExtra() -> [Int8] @JavaMethod - public func setComment(_ arg0: String) + open func setComment(_ arg0: String) @JavaMethod - public func getComment() -> String - - @JavaMethod - public func equals(_ arg0: JavaObject?) -> Bool - - @JavaMethod - public func getClass() -> JavaClass! - - @JavaMethod - public func notify() - - @JavaMethod - public func notifyAll() - - @JavaMethod - public func wait(_ arg0: Int64) throws - - @JavaMethod - public func wait(_ arg0: Int64, _ arg1: Int32) throws - - @JavaMethod - public func wait() throws + open func getComment() -> String } extension JavaClass { @JavaStaticField(isFinal: true) diff --git a/Sources/JavaKitNetwork/generated/URI.swift b/Sources/JavaKitNetwork/generated/URI.swift index a8b35bcb..000e29ca 100644 --- a/Sources/JavaKitNetwork/generated/URI.swift +++ b/Sources/JavaKitNetwork/generated/URI.swift @@ -2,127 +2,109 @@ import JavaKit import JavaRuntime -@JavaClass("java.net.URI", extends: JavaObject.self) -public struct URI { +@JavaClass("java.net.URI") +open class URI: JavaObject { @JavaMethod - public init(_ arg0: String, _ arg1: String, _ arg2: String, _ arg3: String, _ arg4: String, environment: JNIEnvironment? = nil) throws + @_nonoverride public convenience init(_ arg0: String, _ arg1: String, _ arg2: String, _ arg3: String, _ arg4: String, environment: JNIEnvironment? = nil) throws @JavaMethod - public init(_ arg0: String, _ arg1: String, _ arg2: String, _ arg3: String, environment: JNIEnvironment? = nil) throws + @_nonoverride public convenience init(_ arg0: String, _ arg1: String, _ arg2: String, _ arg3: String, environment: JNIEnvironment? = nil) throws @JavaMethod - public init(_ arg0: String, _ arg1: String, _ arg2: String, environment: JNIEnvironment? = nil) throws + @_nonoverride public convenience init(_ arg0: String, _ arg1: String, _ arg2: String, environment: JNIEnvironment? = nil) throws @JavaMethod - public init(_ arg0: String, environment: JNIEnvironment? = nil) throws + @_nonoverride public convenience init(_ arg0: String, environment: JNIEnvironment? = nil) throws @JavaMethod - public init(_ arg0: String, _ arg1: String, _ arg2: String, _ arg3: Int32, _ arg4: String, _ arg5: String, _ arg6: String, environment: JNIEnvironment? = nil) throws + @_nonoverride public convenience init(_ arg0: String, _ arg1: String, _ arg2: String, _ arg3: Int32, _ arg4: String, _ arg5: String, _ arg6: String, environment: JNIEnvironment? = nil) throws @JavaMethod - public func equals(_ arg0: JavaObject?) -> Bool + open override func equals(_ arg0: JavaObject?) -> Bool @JavaMethod - public func toString() -> String + open override func toString() -> String @JavaMethod - public func hashCode() -> Int32 + open override func hashCode() -> Int32 @JavaMethod - public func compareTo(_ arg0: JavaObject?) -> Int32 + open func compareTo(_ arg0: JavaObject?) -> Int32 @JavaMethod - public func compareTo(_ arg0: URI?) -> Int32 + open func compareTo(_ arg0: URI?) -> Int32 @JavaMethod - public func isAbsolute() -> Bool + open func isAbsolute() -> Bool @JavaMethod - public func resolve(_ arg0: String) -> URI! + open func resolve(_ arg0: String) -> URI! @JavaMethod - public func resolve(_ arg0: URI?) -> URI! + open func resolve(_ arg0: URI?) -> URI! @JavaMethod - public func getScheme() -> String + open func getScheme() -> String @JavaMethod - public func isOpaque() -> Bool + open func isOpaque() -> Bool @JavaMethod - public func getRawAuthority() -> String + open func getRawAuthority() -> String @JavaMethod - public func getRawFragment() -> String + open func getRawFragment() -> String @JavaMethod - public func getRawQuery() -> String + open func getRawQuery() -> String @JavaMethod - public func getRawPath() -> String + open func getRawPath() -> String @JavaMethod - public func getHost() -> String + open func getHost() -> String @JavaMethod - public func getPort() -> Int32 + open func getPort() -> Int32 @JavaMethod - public func getAuthority() -> String + open func getAuthority() -> String @JavaMethod - public func getQuery() -> String + open func getQuery() -> String @JavaMethod - public func getPath() -> String + open func getPath() -> String @JavaMethod - public func getUserInfo() -> String + open func getUserInfo() -> String @JavaMethod - public func toURL() throws -> URL! + open func toURL() throws -> URL! @JavaMethod - public func normalize() -> URI! + open func normalize() -> URI! @JavaMethod - public func relativize(_ arg0: URI?) -> URI! + open func relativize(_ arg0: URI?) -> URI! @JavaMethod - public func getRawSchemeSpecificPart() -> String + open func getRawSchemeSpecificPart() -> String @JavaMethod - public func parseServerAuthority() throws -> URI! + open func parseServerAuthority() throws -> URI! @JavaMethod - public func getSchemeSpecificPart() -> String + open func getSchemeSpecificPart() -> String @JavaMethod - public func getRawUserInfo() -> String + open func getRawUserInfo() -> String @JavaMethod - public func getFragment() -> String + open func getFragment() -> String @JavaMethod - public func toASCIIString() -> String - - @JavaMethod - public func getClass() -> JavaClass! - - @JavaMethod - public func notify() - - @JavaMethod - public func notifyAll() - - @JavaMethod - public func wait(_ arg0: Int64) throws - - @JavaMethod - public func wait(_ arg0: Int64, _ arg1: Int32) throws - - @JavaMethod - public func wait() throws + open func toASCIIString() -> String } extension JavaClass { @JavaStaticMethod diff --git a/Sources/JavaKitNetwork/generated/URL.swift b/Sources/JavaKitNetwork/generated/URL.swift index c9fb0832..ed0dee38 100644 --- a/Sources/JavaKitNetwork/generated/URL.swift +++ b/Sources/JavaKitNetwork/generated/URL.swift @@ -2,89 +2,71 @@ import JavaKit import JavaRuntime -@JavaClass("java.net.URL", extends: JavaObject.self) -public struct URL { +@JavaClass("java.net.URL") +open class URL: JavaObject { @JavaMethod - public init(_ arg0: URL?, _ arg1: String, environment: JNIEnvironment? = nil) throws + @_nonoverride public convenience init(_ arg0: URL?, _ arg1: String, environment: JNIEnvironment? = nil) throws @JavaMethod - public init(_ arg0: String, environment: JNIEnvironment? = nil) throws + @_nonoverride public convenience init(_ arg0: String, environment: JNIEnvironment? = nil) throws @JavaMethod - public init(_ arg0: String, _ arg1: String, _ arg2: Int32, _ arg3: String, environment: JNIEnvironment? = nil) throws + @_nonoverride public convenience init(_ arg0: String, _ arg1: String, _ arg2: Int32, _ arg3: String, environment: JNIEnvironment? = nil) throws @JavaMethod - public init(_ arg0: String, _ arg1: String, _ arg2: String, environment: JNIEnvironment? = nil) throws + @_nonoverride public convenience init(_ arg0: String, _ arg1: String, _ arg2: String, environment: JNIEnvironment? = nil) throws @JavaMethod - public func equals(_ arg0: JavaObject?) -> Bool + open override func equals(_ arg0: JavaObject?) -> Bool @JavaMethod - public func toString() -> String + open override func toString() -> String @JavaMethod - public func hashCode() -> Int32 + open override func hashCode() -> Int32 @JavaMethod - public func getHost() -> String + open func getHost() -> String @JavaMethod - public func getPort() -> Int32 + open func getPort() -> Int32 @JavaMethod - public func getDefaultPort() -> Int32 + open func getDefaultPort() -> Int32 @JavaMethod - public func sameFile(_ arg0: URL?) -> Bool + open func sameFile(_ arg0: URL?) -> Bool @JavaMethod - public func toExternalForm() -> String + open func toExternalForm() -> String @JavaMethod - public func getContent() throws -> JavaObject! + open func getContent() throws -> JavaObject! @JavaMethod - public func getContent(_ arg0: [JavaClass?]) throws -> JavaObject! + open func getContent(_ arg0: [JavaClass?]) throws -> JavaObject! @JavaMethod - public func getProtocol() -> String + open func getProtocol() -> String @JavaMethod - public func getAuthority() -> String + open func getAuthority() -> String @JavaMethod - public func getFile() -> String + open func getFile() -> String @JavaMethod - public func getRef() -> String + open func getRef() -> String @JavaMethod - public func getQuery() -> String + open func getQuery() -> String @JavaMethod - public func getPath() -> String + open func getPath() -> String @JavaMethod - public func getUserInfo() -> String + open func getUserInfo() -> String @JavaMethod - public func toURI() throws -> URI! - - @JavaMethod - public func getClass() -> JavaClass! - - @JavaMethod - public func notify() - - @JavaMethod - public func notifyAll() - - @JavaMethod - public func wait(_ arg0: Int64) throws - - @JavaMethod - public func wait(_ arg0: Int64, _ arg1: Int32) throws - - @JavaMethod - public func wait() throws + open func toURI() throws -> URI! } diff --git a/Sources/JavaKitNetwork/generated/URLClassLoader.swift b/Sources/JavaKitNetwork/generated/URLClassLoader.swift index b8e1f54f..ba977e07 100644 --- a/Sources/JavaKitNetwork/generated/URLClassLoader.swift +++ b/Sources/JavaKitNetwork/generated/URLClassLoader.swift @@ -3,84 +3,30 @@ import JavaKit import JavaKitCollection import JavaRuntime -@JavaClass("java.net.URLClassLoader", extends: JavaObject.self) -public struct URLClassLoader { +@JavaClass("java.net.URLClassLoader") +open class URLClassLoader: JavaObject { @JavaMethod - public init(_ arg0: [URL?], environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(_ arg0: [URL?], environment: JNIEnvironment? = nil) @JavaMethod - public func findResource(_ arg0: String) -> URL! + open func findResource(_ arg0: String) -> URL! @JavaMethod - public func findResources(_ arg0: String) throws -> Enumeration! + open func findClass(_ arg0: String) throws -> JavaClass! @JavaMethod - public func close() throws + open func findResources(_ arg0: String) throws -> Enumeration! @JavaMethod - public func getURLs() -> [URL?] + open func close() throws @JavaMethod - public func getName() -> String + open func addURL(_ arg0: URL?) @JavaMethod - public func loadClass(_ arg0: String) throws -> JavaClass! - - @JavaMethod - public func getResource(_ arg0: String) -> URL! - - @JavaMethod - public func getResources(_ arg0: String) throws -> Enumeration! - - @JavaMethod - public func isRegisteredAsParallelCapable() -> Bool - - @JavaMethod - public func setDefaultAssertionStatus(_ arg0: Bool) - - @JavaMethod - public func setPackageAssertionStatus(_ arg0: String, _ arg1: Bool) - - @JavaMethod - public func setClassAssertionStatus(_ arg0: String, _ arg1: Bool) - - @JavaMethod - public func clearAssertionStatus() - - @JavaMethod - public func equals(_ arg0: JavaObject?) -> Bool - - @JavaMethod - public func toString() -> String - - @JavaMethod - public func hashCode() -> Int32 - - @JavaMethod - public func getClass() -> JavaClass! - - @JavaMethod - public func notify() - - @JavaMethod - public func notifyAll() - - @JavaMethod - public func wait(_ arg0: Int64) throws - - @JavaMethod - public func wait(_ arg0: Int64, _ arg1: Int32) throws - - @JavaMethod - public func wait() throws + open func getURLs() -> [URL?] } extension JavaClass { @JavaStaticMethod public func newInstance(_ arg0: [URL?]) -> URLClassLoader! - - @JavaStaticMethod - public func getSystemResource(_ arg0: String) -> URL! - - @JavaStaticMethod - public func getSystemResources(_ arg0: String) throws -> Enumeration! } diff --git a/Sources/JavaKitReflection/Constructor+Utilities.swift b/Sources/JavaKitReflection/Constructor+Utilities.swift index 676a6283..8f57ffa5 100644 --- a/Sources/JavaKitReflection/Constructor+Utilities.swift +++ b/Sources/JavaKitReflection/Constructor+Utilities.swift @@ -22,9 +22,4 @@ extension Constructor { public var isNative: Bool { return (getModifiers() & 256) != 0 } - - /// Whether this executable throws any checked exception. - public var throwsCheckedException: Bool { - return self.as(Executable.self)!.throwsCheckedException - } } diff --git a/Sources/JavaKitReflection/Method+Utilities.swift b/Sources/JavaKitReflection/Method+Utilities.swift index 6c8e4a66..71ee864c 100644 --- a/Sources/JavaKitReflection/Method+Utilities.swift +++ b/Sources/JavaKitReflection/Method+Utilities.swift @@ -32,9 +32,4 @@ extension Method { public var isNative: Bool { return (getModifiers() & 256) != 0 } - - /// Whether this executable throws any checked exception. - public var throwsCheckedException: Bool { - return self.as(Executable.self)!.throwsCheckedException - } } diff --git a/Sources/JavaKitReflection/generated/AccessibleObject.swift b/Sources/JavaKitReflection/generated/AccessibleObject.swift index 1c474fb4..84dcc4c2 100644 --- a/Sources/JavaKitReflection/generated/AccessibleObject.swift +++ b/Sources/JavaKitReflection/generated/AccessibleObject.swift @@ -2,67 +2,40 @@ import JavaKit import JavaRuntime -@JavaClass("java.lang.reflect.AccessibleObject", extends: JavaObject.self) -public struct AccessibleObject { +@JavaClass("java.lang.reflect.AccessibleObject") +open class AccessibleObject: JavaObject { @JavaMethod - public func isAnnotationPresent(_ arg0: JavaClass?) -> Bool + open func isAnnotationPresent(_ arg0: JavaClass?) -> Bool @JavaMethod - public func getAnnotation(_ arg0: JavaClass?) -> Annotation! + open func getAnnotation(_ arg0: JavaClass?) -> Annotation! @JavaMethod - public func getAnnotationsByType(_ arg0: JavaClass?) -> [Annotation?] + open func getAnnotationsByType(_ arg0: JavaClass?) -> [Annotation?] @JavaMethod - public func getAnnotations() -> [Annotation?] + open func getAnnotations() -> [Annotation?] @JavaMethod - public func getDeclaredAnnotation(_ arg0: JavaClass?) -> Annotation! + open func getDeclaredAnnotation(_ arg0: JavaClass?) -> Annotation! @JavaMethod - public func getDeclaredAnnotationsByType(_ arg0: JavaClass?) -> [Annotation?] + open func getDeclaredAnnotationsByType(_ arg0: JavaClass?) -> [Annotation?] @JavaMethod - public func getDeclaredAnnotations() -> [Annotation?] + open func getDeclaredAnnotations() -> [Annotation?] @JavaMethod - public func setAccessible(_ arg0: Bool) + open func setAccessible(_ arg0: Bool) @JavaMethod - public func trySetAccessible() -> Bool + open func trySetAccessible() -> Bool @JavaMethod - public func canAccess(_ arg0: JavaObject?) -> Bool + open func canAccess(_ arg0: JavaObject?) -> Bool @JavaMethod - public func isAccessible() -> Bool - - @JavaMethod - public func equals(_ arg0: JavaObject?) -> Bool - - @JavaMethod - public func toString() -> String - - @JavaMethod - public func hashCode() -> Int32 - - @JavaMethod - public func getClass() -> JavaClass! - - @JavaMethod - public func notify() - - @JavaMethod - public func notifyAll() - - @JavaMethod - public func wait(_ arg0: Int64) throws - - @JavaMethod - public func wait(_ arg0: Int64, _ arg1: Int32) throws - - @JavaMethod - public func wait() throws + open func isAccessible() -> Bool } extension JavaClass { @JavaStaticMethod diff --git a/Sources/JavaKitReflection/generated/Constructor.swift b/Sources/JavaKitReflection/generated/Constructor.swift index c3e48a15..263d767d 100644 --- a/Sources/JavaKitReflection/generated/Constructor.swift +++ b/Sources/JavaKitReflection/generated/Constructor.swift @@ -1,126 +1,74 @@ // Auto-generated by Java-to-Swift wrapper generator. import JavaKit -import JavaKitCollection import JavaRuntime -@JavaClass("java.lang.reflect.Constructor", extends: Executable.self) -public struct Constructor { +@JavaClass("java.lang.reflect.Constructor") +open class Constructor: Executable { @JavaMethod - public func getName() -> String + open override func getName() -> String @JavaMethod - public func equals(_ arg0: JavaObject?) -> Bool + open override func equals(_ arg0: JavaObject?) -> Bool @JavaMethod - public func toString() -> String + open override func toString() -> String @JavaMethod - public func hashCode() -> Int32 + open override func hashCode() -> Int32 @JavaMethod - public func getModifiers() -> Int32 + open override func getModifiers() -> Int32 @JavaMethod - public func getTypeParameters() -> [TypeVariable>?] + open func getTypeParameters() -> [TypeVariable>?] @JavaMethod - public func newInstance(_ arg0: [JavaObject?]) throws -> JavaObject! + open func newInstance(_ arg0: [JavaObject?]) throws -> JavaObject! @JavaMethod - public func getParameterTypes() -> [JavaClass?] + open override func getParameterTypes() -> [JavaClass?] @JavaMethod - public func toGenericString() -> String + open override func toGenericString() -> String @JavaMethod - public func isSynthetic() -> Bool + open override func isSynthetic() -> Bool @JavaMethod - public func getDeclaringClass() -> JavaClass! + open override func getDeclaringClass() -> JavaClass! @JavaMethod - public func getAnnotation(_ arg0: JavaClass?) -> Annotation! + open override func getAnnotation(_ arg0: JavaClass?) -> Annotation! @JavaMethod - public func getDeclaredAnnotations() -> [Annotation?] + open override func getDeclaredAnnotations() -> [Annotation?] @JavaMethod - public func setAccessible(_ arg0: Bool) + open override func setAccessible(_ arg0: Bool) @JavaMethod - public func isVarArgs() -> Bool + open override func isVarArgs() -> Bool @JavaMethod - public func getParameterCount() -> Int32 + open override func getParameterCount() -> Int32 @JavaMethod - public func getParameterAnnotations() -> [[Annotation?]] + open override func getParameterAnnotations() -> [[Annotation?]] @JavaMethod - public func getGenericParameterTypes() -> [Type?] + open override func getGenericParameterTypes() -> [Type?] @JavaMethod - public func getGenericExceptionTypes() -> [Type?] + open override func getGenericExceptionTypes() -> [Type?] @JavaMethod - public func getExceptionTypes() -> [JavaClass?] + open override func getExceptionTypes() -> [JavaClass?] @JavaMethod - public func getAnnotatedReturnType() -> AnnotatedType! + open override func getAnnotatedReturnType() -> AnnotatedType! @JavaMethod - public func getAnnotatedReceiverType() -> AnnotatedType! - - @JavaMethod - public func getAnnotationsByType(_ arg0: JavaClass?) -> [Annotation?] - - @JavaMethod - public func getAnnotatedParameterTypes() -> [AnnotatedType?] - - @JavaMethod - public func getParameters() -> [Parameter?] - - @JavaMethod - public func getAnnotatedExceptionTypes() -> [AnnotatedType?] - - @JavaMethod - public func isAnnotationPresent(_ arg0: JavaClass?) -> Bool - - @JavaMethod - public func getAnnotations() -> [Annotation?] - - @JavaMethod - public func getDeclaredAnnotation(_ arg0: JavaClass?) -> Annotation! - - @JavaMethod - public func getDeclaredAnnotationsByType(_ arg0: JavaClass?) -> [Annotation?] - - @JavaMethod - public func trySetAccessible() -> Bool - - @JavaMethod - public func canAccess(_ arg0: JavaObject?) -> Bool - - @JavaMethod - public func isAccessible() -> Bool - - @JavaMethod - public func getClass() -> JavaClass! - - @JavaMethod - public func notify() - - @JavaMethod - public func notifyAll() - - @JavaMethod - public func wait(_ arg0: Int64) throws - - @JavaMethod - public func wait(_ arg0: Int64, _ arg1: Int32) throws - - @JavaMethod - public func wait() throws + open override func getAnnotatedReceiverType() -> AnnotatedType! } extension JavaClass { @JavaStaticField(isFinal: true) @@ -128,7 +76,4 @@ extension JavaClass { @JavaStaticField(isFinal: true) public var DECLARED: Int32 - - @JavaStaticMethod - public func setAccessible(_ arg0: [AccessibleObject?], _ arg1: Bool) where ObjectType == Constructor } diff --git a/Sources/JavaKitReflection/generated/Executable.swift b/Sources/JavaKitReflection/generated/Executable.swift index da1635f6..6a1f5b75 100644 --- a/Sources/JavaKitReflection/generated/Executable.swift +++ b/Sources/JavaKitReflection/generated/Executable.swift @@ -3,121 +3,70 @@ import JavaKit import JavaKitCollection import JavaRuntime -@JavaClass("java.lang.reflect.Executable", extends: AccessibleObject.self, implements: GenericDeclaration.self) -public struct Executable { +@JavaClass("java.lang.reflect.Executable", implements: GenericDeclaration.self) +open class Executable: AccessibleObject { @JavaMethod - public func getName() -> String + open func getName() -> String @JavaMethod - public func getModifiers() -> Int32 + open func getModifiers() -> Int32 @JavaMethod - public func getTypeParameters() -> [TypeVariable?] + open func getTypeParameters() -> [TypeVariable?] @JavaMethod - public func getParameterTypes() -> [JavaClass?] + open func getParameterTypes() -> [JavaClass?] @JavaMethod - public func toGenericString() -> String + open func toGenericString() -> String @JavaMethod - public func isSynthetic() -> Bool + open func isSynthetic() -> Bool @JavaMethod - public func getDeclaringClass() -> JavaClass! + open func getDeclaringClass() -> JavaClass! @JavaMethod - public func getAnnotation(_ arg0: JavaClass?) -> Annotation! + open override func getAnnotation(_ arg0: JavaClass?) -> Annotation! @JavaMethod - public func getAnnotationsByType(_ arg0: JavaClass?) -> [Annotation?] + open override func getAnnotationsByType(_ arg0: JavaClass?) -> [Annotation?] @JavaMethod - public func getDeclaredAnnotations() -> [Annotation?] + open override func getDeclaredAnnotations() -> [Annotation?] @JavaMethod - public func isVarArgs() -> Bool + open func isVarArgs() -> Bool @JavaMethod - public func getAnnotatedParameterTypes() -> [AnnotatedType?] + open func getAnnotatedParameterTypes() -> [AnnotatedType?] @JavaMethod - public func getParameterCount() -> Int32 + open func getParameterCount() -> Int32 @JavaMethod - public func getParameterAnnotations() -> [[Annotation?]] + open func getParameterAnnotations() -> [[Annotation?]] @JavaMethod - public func getGenericParameterTypes() -> [Type?] + open func getGenericParameterTypes() -> [Type?] @JavaMethod - public func getGenericExceptionTypes() -> [Type?] + open func getGenericExceptionTypes() -> [Type?] @JavaMethod - public func getExceptionTypes() -> [JavaClass?] + open func getExceptionTypes() -> [JavaClass?] @JavaMethod - public func getAnnotatedReturnType() -> AnnotatedType! + open func getAnnotatedReturnType() -> AnnotatedType! @JavaMethod - public func getParameters() -> [Parameter?] + open func getParameters() -> [Parameter?] @JavaMethod - public func getAnnotatedReceiverType() -> AnnotatedType! + open func getAnnotatedReceiverType() -> AnnotatedType! @JavaMethod - public func getAnnotatedExceptionTypes() -> [AnnotatedType?] - - @JavaMethod - public func isAnnotationPresent(_ arg0: JavaClass?) -> Bool - - @JavaMethod - public func getAnnotations() -> [Annotation?] - - @JavaMethod - public func getDeclaredAnnotation(_ arg0: JavaClass?) -> Annotation! - - @JavaMethod - public func getDeclaredAnnotationsByType(_ arg0: JavaClass?) -> [Annotation?] - - @JavaMethod - public func setAccessible(_ arg0: Bool) - - @JavaMethod - public func trySetAccessible() -> Bool - - @JavaMethod - public func canAccess(_ arg0: JavaObject?) -> Bool - - @JavaMethod - public func isAccessible() -> Bool - - @JavaMethod - public func equals(_ arg0: JavaObject?) -> Bool - - @JavaMethod - public func toString() -> String - - @JavaMethod - public func hashCode() -> Int32 - - @JavaMethod - public func getClass() -> JavaClass! - - @JavaMethod - public func notify() - - @JavaMethod - public func notifyAll() - - @JavaMethod - public func wait(_ arg0: Int64) throws - - @JavaMethod - public func wait(_ arg0: Int64, _ arg1: Int32) throws - - @JavaMethod - public func wait() throws + open func getAnnotatedExceptionTypes() -> [AnnotatedType?] } extension JavaClass { @JavaStaticField(isFinal: true) @@ -125,7 +74,4 @@ extension JavaClass { @JavaStaticField(isFinal: true) public var DECLARED: Int32 - - @JavaStaticMethod - public func setAccessible(_ arg0: [AccessibleObject?], _ arg1: Bool) } diff --git a/Sources/JavaKitReflection/generated/Field.swift b/Sources/JavaKitReflection/generated/Field.swift index 41e71afb..c67e56ff 100644 --- a/Sources/JavaKitReflection/generated/Field.swift +++ b/Sources/JavaKitReflection/generated/Field.swift @@ -3,148 +3,109 @@ import JavaKit import JavaKitCollection import JavaRuntime -@JavaClass("java.lang.reflect.Field", extends: AccessibleObject.self) -public struct Field { +@JavaClass("java.lang.reflect.Field") +open class Field: AccessibleObject { @JavaMethod - public func getName() -> String + open func getName() -> String @JavaMethod - public func get(_ arg0: JavaObject?) throws -> JavaObject! + open func get(_ arg0: JavaObject?) throws -> JavaObject! @JavaMethod - public func equals(_ arg0: JavaObject?) -> Bool + open override func equals(_ arg0: JavaObject?) -> Bool @JavaMethod - public func toString() -> String + open override func toString() -> String @JavaMethod - public func hashCode() -> Int32 + open override func hashCode() -> Int32 @JavaMethod - public func getModifiers() -> Int32 + open func getModifiers() -> Int32 @JavaMethod - public func getBoolean(_ arg0: JavaObject?) throws -> Bool + open func getBoolean(_ arg0: JavaObject?) throws -> Bool @JavaMethod - public func getByte(_ arg0: JavaObject?) throws -> Int8 + open func getByte(_ arg0: JavaObject?) throws -> Int8 @JavaMethod - public func getShort(_ arg0: JavaObject?) throws -> Int16 + open func getShort(_ arg0: JavaObject?) throws -> Int16 @JavaMethod - public func getChar(_ arg0: JavaObject?) throws -> UInt16 + open func getChar(_ arg0: JavaObject?) throws -> UInt16 @JavaMethod - public func getInt(_ arg0: JavaObject?) throws -> Int32 + open func getInt(_ arg0: JavaObject?) throws -> Int32 @JavaMethod - public func getLong(_ arg0: JavaObject?) throws -> Int64 + open func getLong(_ arg0: JavaObject?) throws -> Int64 @JavaMethod - public func getFloat(_ arg0: JavaObject?) throws -> Float + open func getFloat(_ arg0: JavaObject?) throws -> Float @JavaMethod - public func getDouble(_ arg0: JavaObject?) throws -> Double + open func getDouble(_ arg0: JavaObject?) throws -> Double @JavaMethod - public func toGenericString() -> String + open func toGenericString() -> String @JavaMethod - public func isSynthetic() -> Bool + open func isSynthetic() -> Bool @JavaMethod - public func getDeclaringClass() -> JavaClass! + open func getDeclaringClass() -> JavaClass! @JavaMethod - public func getAnnotation(_ arg0: JavaClass?) -> Annotation! + open override func getAnnotation(_ arg0: JavaClass?) -> Annotation! @JavaMethod - public func getAnnotationsByType(_ arg0: JavaClass?) -> [Annotation?] + open override func getAnnotationsByType(_ arg0: JavaClass?) -> [Annotation?] @JavaMethod - public func getDeclaredAnnotations() -> [Annotation?] + open override func getDeclaredAnnotations() -> [Annotation?] @JavaMethod - public func set(_ arg0: JavaObject?, _ arg1: JavaObject?) throws + open func set(_ arg0: JavaObject?, _ arg1: JavaObject?) throws @JavaMethod - public func setAccessible(_ arg0: Bool) + open override func setAccessible(_ arg0: Bool) @JavaMethod - public func getGenericType() -> Type! + open func getGenericType() -> Type! @JavaMethod - public func getType() -> JavaClass! + open func getType() -> JavaClass! @JavaMethod - public func setBoolean(_ arg0: JavaObject?, _ arg1: Bool) throws + open func setBoolean(_ arg0: JavaObject?, _ arg1: Bool) throws @JavaMethod - public func setByte(_ arg0: JavaObject?, _ arg1: Int8) throws + open func setByte(_ arg0: JavaObject?, _ arg1: Int8) throws @JavaMethod - public func setChar(_ arg0: JavaObject?, _ arg1: UInt16) throws + open func setChar(_ arg0: JavaObject?, _ arg1: UInt16) throws @JavaMethod - public func setShort(_ arg0: JavaObject?, _ arg1: Int16) throws + open func setShort(_ arg0: JavaObject?, _ arg1: Int16) throws @JavaMethod - public func setInt(_ arg0: JavaObject?, _ arg1: Int32) throws + open func setInt(_ arg0: JavaObject?, _ arg1: Int32) throws @JavaMethod - public func setLong(_ arg0: JavaObject?, _ arg1: Int64) throws + open func setLong(_ arg0: JavaObject?, _ arg1: Int64) throws @JavaMethod - public func setFloat(_ arg0: JavaObject?, _ arg1: Float) throws + open func setFloat(_ arg0: JavaObject?, _ arg1: Float) throws @JavaMethod - public func setDouble(_ arg0: JavaObject?, _ arg1: Double) throws + open func setDouble(_ arg0: JavaObject?, _ arg1: Double) throws @JavaMethod - public func isEnumConstant() -> Bool + open func isEnumConstant() -> Bool @JavaMethod - public func getAnnotatedType() -> AnnotatedType! - - @JavaMethod - public func isAnnotationPresent(_ arg0: JavaClass?) -> Bool - - @JavaMethod - public func getAnnotations() -> [Annotation?] - - @JavaMethod - public func getDeclaredAnnotation(_ arg0: JavaClass?) -> Annotation! - - @JavaMethod - public func getDeclaredAnnotationsByType(_ arg0: JavaClass?) -> [Annotation?] - - @JavaMethod - public func trySetAccessible() -> Bool - - @JavaMethod - public func canAccess(_ arg0: JavaObject?) -> Bool - - @JavaMethod - public func isAccessible() -> Bool - - @JavaMethod - public func getClass() -> JavaClass! - - @JavaMethod - public func notify() - - @JavaMethod - public func notifyAll() - - @JavaMethod - public func wait(_ arg0: Int64) throws - - @JavaMethod - public func wait(_ arg0: Int64, _ arg1: Int32) throws - - @JavaMethod - public func wait() throws + open func getAnnotatedType() -> AnnotatedType! } extension JavaClass { @JavaStaticField(isFinal: true) @@ -152,7 +113,4 @@ extension JavaClass { @JavaStaticField(isFinal: true) public var DECLARED: Int32 - - @JavaStaticMethod - public func setAccessible(_ arg0: [AccessibleObject?], _ arg1: Bool) } diff --git a/Sources/JavaKitReflection/generated/Method.swift b/Sources/JavaKitReflection/generated/Method.swift index 3a67073c..46183f4f 100644 --- a/Sources/JavaKitReflection/generated/Method.swift +++ b/Sources/JavaKitReflection/generated/Method.swift @@ -1,141 +1,86 @@ // Auto-generated by Java-to-Swift wrapper generator. import JavaKit -import JavaKitCollection import JavaRuntime -@JavaClass("java.lang.reflect.Method", extends: Executable.self) -public struct Method { +@JavaClass("java.lang.reflect.Method") +open class Method: Executable { @JavaMethod - public func invoke(_ arg0: JavaObject?, _ arg1: [JavaObject?]) throws -> JavaObject! + open func invoke(_ arg0: JavaObject?, _ arg1: [JavaObject?]) throws -> JavaObject! @JavaMethod - public func getName() -> String + open override func getName() -> String @JavaMethod - public func equals(_ arg0: JavaObject?) -> Bool + open override func equals(_ arg0: JavaObject?) -> Bool @JavaMethod - public func toString() -> String + open override func toString() -> String @JavaMethod - public func hashCode() -> Int32 + open override func hashCode() -> Int32 @JavaMethod - public func getModifiers() -> Int32 + open override func getModifiers() -> Int32 @JavaMethod - public func getTypeParameters() -> [TypeVariable?] + open func getTypeParameters() -> [TypeVariable?] @JavaMethod - public func getReturnType() -> JavaClass! + open func getReturnType() -> JavaClass! @JavaMethod - public func getParameterTypes() -> [JavaClass?] + open override func getParameterTypes() -> [JavaClass?] @JavaMethod - public func toGenericString() -> String + open override func toGenericString() -> String @JavaMethod - public func isSynthetic() -> Bool + open override func isSynthetic() -> Bool @JavaMethod - public func getDeclaringClass() -> JavaClass! + open override func getDeclaringClass() -> JavaClass! @JavaMethod - public func getAnnotation(_ arg0: JavaClass?) -> Annotation! + open override func getAnnotation(_ arg0: JavaClass?) -> Annotation! @JavaMethod - public func getDeclaredAnnotations() -> [Annotation?] + open override func getDeclaredAnnotations() -> [Annotation?] @JavaMethod - public func setAccessible(_ arg0: Bool) + open override func setAccessible(_ arg0: Bool) @JavaMethod - public func isVarArgs() -> Bool + open override func isVarArgs() -> Bool @JavaMethod - public func getParameterCount() -> Int32 + open override func getParameterCount() -> Int32 @JavaMethod - public func getParameterAnnotations() -> [[Annotation?]] + open override func getParameterAnnotations() -> [[Annotation?]] @JavaMethod - public func getGenericParameterTypes() -> [Type?] + open override func getGenericParameterTypes() -> [Type?] @JavaMethod - public func getGenericExceptionTypes() -> [Type?] + open override func getGenericExceptionTypes() -> [Type?] @JavaMethod - public func isDefault() -> Bool + open func isDefault() -> Bool @JavaMethod - public func getGenericReturnType() -> Type! + open func getGenericReturnType() -> Type! @JavaMethod - public func getExceptionTypes() -> [JavaClass?] + open override func getExceptionTypes() -> [JavaClass?] @JavaMethod - public func isBridge() -> Bool + open func isBridge() -> Bool @JavaMethod - public func getDefaultValue() -> JavaObject! + open func getDefaultValue() -> JavaObject! @JavaMethod - public func getAnnotatedReturnType() -> AnnotatedType! - - @JavaMethod - public func getAnnotationsByType(_ arg0: JavaClass?) -> [Annotation?] - - @JavaMethod - public func getAnnotatedParameterTypes() -> [AnnotatedType?] - - @JavaMethod - public func getParameters() -> [Parameter?] - - @JavaMethod - public func getAnnotatedReceiverType() -> AnnotatedType! - - @JavaMethod - public func getAnnotatedExceptionTypes() -> [AnnotatedType?] - - @JavaMethod - public func isAnnotationPresent(_ arg0: JavaClass?) -> Bool - - @JavaMethod - public func getAnnotations() -> [Annotation?] - - @JavaMethod - public func getDeclaredAnnotation(_ arg0: JavaClass?) -> Annotation! - - @JavaMethod - public func getDeclaredAnnotationsByType(_ arg0: JavaClass?) -> [Annotation?] - - @JavaMethod - public func trySetAccessible() -> Bool - - @JavaMethod - public func canAccess(_ arg0: JavaObject?) -> Bool - - @JavaMethod - public func isAccessible() -> Bool - - @JavaMethod - public func getClass() -> JavaClass! - - @JavaMethod - public func notify() - - @JavaMethod - public func notifyAll() - - @JavaMethod - public func wait(_ arg0: Int64) throws - - @JavaMethod - public func wait(_ arg0: Int64, _ arg1: Int32) throws - - @JavaMethod - public func wait() throws + open override func getAnnotatedReturnType() -> AnnotatedType! } extension JavaClass { @JavaStaticField(isFinal: true) @@ -143,7 +88,4 @@ extension JavaClass { @JavaStaticField(isFinal: true) public var DECLARED: Int32 - - @JavaStaticMethod - public func setAccessible(_ arg0: [AccessibleObject?], _ arg1: Bool) } diff --git a/Sources/JavaKitReflection/generated/Parameter.swift b/Sources/JavaKitReflection/generated/Parameter.swift index 5788f089..30f2d628 100644 --- a/Sources/JavaKitReflection/generated/Parameter.swift +++ b/Sources/JavaKitReflection/generated/Parameter.swift @@ -3,83 +3,62 @@ import JavaKit import JavaKitCollection import JavaRuntime -@JavaClass("java.lang.reflect.Parameter", extends: JavaObject.self) -public struct Parameter { +@JavaClass("java.lang.reflect.Parameter") +open class Parameter: JavaObject { @JavaMethod - public func getName() -> String + open func getName() -> String @JavaMethod - public func equals(_ arg0: JavaObject?) -> Bool + open override func equals(_ arg0: JavaObject?) -> Bool @JavaMethod - public func toString() -> String + open override func toString() -> String @JavaMethod - public func hashCode() -> Int32 + open override func hashCode() -> Int32 @JavaMethod - public func getModifiers() -> Int32 + open func getModifiers() -> Int32 @JavaMethod - public func isSynthetic() -> Bool + open func isSynthetic() -> Bool @JavaMethod - public func getAnnotation(_ arg0: JavaClass?) -> Annotation! + open func getAnnotation(_ arg0: JavaClass?) -> Annotation! @JavaMethod - public func getAnnotationsByType(_ arg0: JavaClass?) -> [Annotation?] + open func getAnnotationsByType(_ arg0: JavaClass?) -> [Annotation?] @JavaMethod - public func getAnnotations() -> [Annotation?] + open func getAnnotations() -> [Annotation?] @JavaMethod - public func getDeclaredAnnotation(_ arg0: JavaClass?) -> Annotation! + open func getDeclaredAnnotation(_ arg0: JavaClass?) -> Annotation! @JavaMethod - public func getDeclaredAnnotationsByType(_ arg0: JavaClass?) -> [Annotation?] + open func getDeclaredAnnotationsByType(_ arg0: JavaClass?) -> [Annotation?] @JavaMethod - public func getDeclaredAnnotations() -> [Annotation?] + open func getDeclaredAnnotations() -> [Annotation?] @JavaMethod - public func getType() -> JavaClass! + open func getType() -> JavaClass! @JavaMethod - public func getAnnotatedType() -> AnnotatedType! + open func getAnnotatedType() -> AnnotatedType! @JavaMethod - public func getParameterizedType() -> Type! + open func getParameterizedType() -> Type! @JavaMethod - public func isVarArgs() -> Bool + open func isVarArgs() -> Bool @JavaMethod - public func isNamePresent() -> Bool + open func isNamePresent() -> Bool @JavaMethod - public func getDeclaringExecutable() -> Executable! + open func getDeclaringExecutable() -> Executable! @JavaMethod - public func isImplicit() -> Bool - - @JavaMethod - public func getClass() -> JavaClass! - - @JavaMethod - public func notify() - - @JavaMethod - public func notifyAll() - - @JavaMethod - public func wait(_ arg0: Int64) throws - - @JavaMethod - public func wait(_ arg0: Int64, _ arg1: Int32) throws - - @JavaMethod - public func wait() throws - - @JavaMethod - public func isAnnotationPresent(_ arg0: JavaClass?) -> Bool + open func isImplicit() -> Bool } diff --git a/Tests/JavaKitTests/BasicRuntimeTests.swift b/Tests/JavaKitTests/BasicRuntimeTests.swift index 5185294e..e417cd6d 100644 --- a/Tests/JavaKitTests/BasicRuntimeTests.swift +++ b/Tests/JavaKitTests/BasicRuntimeTests.swift @@ -44,7 +44,7 @@ class BasicRuntimeTests: XCTestCase { // 'super' and 'as' don't require allocating a new holder. let url = try URL("http://swift.org", environment: environment) - let superURL = url.super + let superURL: JavaObject = url XCTAssert(url.javaHolder === superURL.javaHolder) let urlAgain = superURL.as(URL.self)! XCTAssert(url.javaHolder === urlAgain.javaHolder) From d1b71c33fb6f76672c9ad5c8a4842b1093046b5d Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Thu, 31 Oct 2024 09:38:19 -0700 Subject: [PATCH 165/426] JavaKit: Update user guide for the move to Swift classes --- USER_GUIDE.md | 44 +++++++++++++++++++++++++++++--------------- 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/USER_GUIDE.md b/USER_GUIDE.md index a85fa94e..e352670e 100644 --- a/USER_GUIDE.md +++ b/USER_GUIDE.md @@ -45,15 +45,15 @@ If you build the project, there will be a generated file `BigInteger.swift` that ```swift @JavaClass("java.math.BigInteger") -public struct BigInteger { +open class BigInteger: JavaNumber { @JavaMethod public init(_ arg0: String, environment: JNIEnvironment? = nil) @JavaMethod - public func toString() -> String + open func toString() -> String @JavaMethod - public func isProbablePrime(_ arg0: Int32) -> Bool + open func isProbablePrime(_ arg0: Int32) -> Bool // many more methods } @@ -219,7 +219,7 @@ do { Note that we are passing the Jar file in the `classPath` argument when initializing the `JavaVirtualMachine` instance. Otherwise, the program will fail with an error because it cannot find the Java class `com.gazman.quadratic_sieve.primes.SieveOfEratosthenes`. -### Up and downcasting +### Downcasting All Java classes available in Swift provide `is` and `as` methods to check whether an object dynamically matches another type. The `is` operation is the equivalent of Java's `instanceof` and Swift's `is` operator, and will checkin whether a given object is of the specified type, e.g., @@ -288,31 +288,31 @@ This section describes how Java libraries and mapped into Swift and their use fr ### Translation from Java classes into Swift -Each Java class that can be used from Swift is translated to a Swift `struct` that provides information about the Java class itself and is populated with the Swift projection of each of its constructors, methods, and fields. For example, here is an excerpt of the Swift projection of [`java.util.jar.JarFile`](https://docs.oracle.com/javase/8/docs/api/java/util/jar/JarFile.html): +Each Java class that can be used from Swift is translated to a Swift `class` that provides information about the Java class itself and is populated with the Swift projection of each of its constructors, methods, and fields. For example, here is an excerpt of the Swift projection of [`java.util.jar.JarFile`](https://docs.oracle.com/javase/8/docs/api/java/util/jar/JarFile.html): ```swift -@JavaClass("java.util.jar.JarFile", extends: ZipFile.self, implements: AutoCloseable.self) -public struct JarFile { +@JavaClass("java.util.jar.JarFile", extends: AutoCloseable.self) +open class JarFile: ZipFile { @JavaMethod - public init(_ arg0: String, _ arg1: Bool, environment: JNIEnvironment? = nil) + @_nonoverride public convenience init(_ arg0: String, _ arg1: Bool, environment: JNIEnvironment? = nil) throws @JavaMethod - public func entries() -> Enumeration? + @_nonoverride public convenience init(_ arg0: String, environment: JNIEnvironment? = nil) throws @JavaMethod - public func getManifest() -> Manifest? + open func entries() -> Enumeration! @JavaMethod - public func getJarEntry(_ arg0: String) -> JarEntry? + open func getManifest() throws -> Manifest! @JavaMethod - public func isMultiRelease() -> Bool + open func getEntry(_ arg0: String) -> ZipEntry! @JavaMethod - public func getName() -> String + open func getJarEntry(_ arg0: String) -> JarEntry! @JavaMethod - public func size() -> Int32 + open func isMultiRelease() -> Bool } ``` @@ -328,7 +328,7 @@ Each of the public Java constructors, methods, and fields in the Java class will ```swift @JavaMethod - public init(_ arg0: String, _ arg1: Bool, environment: JNIEnvironment? = nil) + public convenience init(_ arg0: String, _ arg1: Bool, environment: JNIEnvironment? = nil) ``` corresponds to the Java constructor: @@ -424,6 +424,20 @@ extension JavaClass { Java interfaces are similar to classes, and are projected into Swift in much the same way, but with the macro `JavaInterface`. The `JavaInterface` macro takes the Java interface name as well as any Java interfaces that this interface extends. As an example, here is the Swift projection of the [`java.util.Enumeration`](https://docs.oracle.com/javase/8/docs/api/java/util/Enumeration.html) generic interface: +```swift +@JavaInterface("java.util.Enumeration") +public struct Enumeration { + @JavaMethod + public func asIterator() -> JavaIterator! + + @JavaMethod + public func hasMoreElements() -> Bool + + @JavaMethod + public func nextElement() -> JavaObject! +} +``` + ## Translating Java classes with `Java2Swift` The `Java2Swift` is a Swift program that uses Java's runtime reflection facilities to translate the requested Java classes into their Swift projections. The output is a number of Swift source files, each of which corresponds to a From 38b39c157fb7be6b93c2b0600b74a3f4ff69fffd Mon Sep 17 00:00:00 2001 From: Luke Howard Date: Fri, 1 Nov 2024 10:36:04 +1100 Subject: [PATCH 166/426] JavaKit: clear exception before initializing Throwable Initializing Throwable with an exception calls the JNI method NewGlobalRef, which on Android cannot be called while an exception is pending. [1] Clear the exception first before initializing the Throwable. [1] https://developer.android.com/training/articles/perf-jni.html#exceptions_1 --- Sources/JavaKit/Exceptions/ExceptionHandling.swift | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Sources/JavaKit/Exceptions/ExceptionHandling.swift b/Sources/JavaKit/Exceptions/ExceptionHandling.swift index efd98e94..cf063d0a 100644 --- a/Sources/JavaKit/Exceptions/ExceptionHandling.swift +++ b/Sources/JavaKit/Exceptions/ExceptionHandling.swift @@ -20,9 +20,8 @@ extension JNIEnvironment { // Check whether a Java exception occurred. if let exception = interface.ExceptionOccurred(self) { - let throwable = Throwable(javaThis: exception, environment: self) interface.ExceptionClear(self) - throw throwable + throw Throwable(javaThis: exception, environment: self) } return result From c586056278b93d4344f10ec4dcc474128527275f Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Fri, 1 Nov 2024 14:41:36 -0700 Subject: [PATCH 167/426] Fixes for importing Java classes as Swift classes --- .../Sources/JavaKitExample/JavaKitExample.swift | 2 +- Sources/JavaKitMacros/JavaFieldMacro.swift | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Samples/JavaKitSampleApp/Sources/JavaKitExample/JavaKitExample.swift b/Samples/JavaKitSampleApp/Sources/JavaKitExample/JavaKitExample.swift index 140c0604..42a5b789 100644 --- a/Samples/JavaKitSampleApp/Sources/JavaKitExample/JavaKitExample.swift +++ b/Samples/JavaKitSampleApp/Sources/JavaKitExample/JavaKitExample.swift @@ -57,7 +57,7 @@ extension HelloSwift: HelloSwiftNativeMethods { print("Hello from the subclass!") helloSub.greetMe() - assert(helloSub.super.value == 2.71828) + assert(helloSub.value == 2.71828) } else { fatalError("Expected subclass here") } diff --git a/Sources/JavaKitMacros/JavaFieldMacro.swift b/Sources/JavaKitMacros/JavaFieldMacro.swift index 40bf7113..7f60f26d 100644 --- a/Sources/JavaKitMacros/JavaFieldMacro.swift +++ b/Sources/JavaKitMacros/JavaFieldMacro.swift @@ -65,7 +65,8 @@ extension JavaFieldMacro: AccessorMacro { ] let nonmutatingModifier = - (context.lexicalContext.first?.is(ClassDeclSyntax.self) ?? false) + (context.lexicalContext.first?.is(ClassDeclSyntax.self) ?? false || + context.lexicalContext.first?.is(ExtensionDeclSyntax.self) ?? false) ? "" : "nonmutating " From f1923425a1a9ca75c548ec2a28b527e9794c6dfc Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Fri, 1 Nov 2024 21:58:45 -0700 Subject: [PATCH 168/426] Java2Swift: Swift does not support overriding with covariant array result types --- .../Java2SwiftLib/JavaClassTranslator.swift | 6 +++ Tests/Java2SwiftTests/Java2SwiftTests.swift | 39 +++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/Sources/Java2SwiftLib/JavaClassTranslator.swift b/Sources/Java2SwiftLib/JavaClassTranslator.swift index afcac639..b90a538a 100644 --- a/Sources/Java2SwiftLib/JavaClassTranslator.swift +++ b/Sources/Java2SwiftLib/JavaClassTranslator.swift @@ -819,6 +819,12 @@ extension Type { // If both are classes, check for subclassing. if let selfClass = self.as(JavaClass.self), let otherClass = other.as(JavaClass.self) { + // If either is a Java array, then this cannot be a subtype relationship + // in Swift. + if selfClass.isArray() || otherClass.isArray() { + return false + } + return selfClass.isSubclass(of: otherClass) } diff --git a/Tests/Java2SwiftTests/Java2SwiftTests.swift b/Tests/Java2SwiftTests/Java2SwiftTests.swift index 445c501c..259193b1 100644 --- a/Tests/Java2SwiftTests/Java2SwiftTests.swift +++ b/Tests/Java2SwiftTests/Java2SwiftTests.swift @@ -547,6 +547,35 @@ class Java2SwiftTests: XCTestCase { ] ) } + + func testCovariantInJavaNotInSwiftOverride3() throws { + try assertTranslatedClass( + NIOByteBuffer.self, + swiftTypeName: "NIOByteBuffer", + asClass: true, + translatedClasses: [ + "java.lang.Object" : ("JavaObject", "JavaKit"), + "java.lang.Class" : ("JavaClass", "JavaKit"), + "java.nio.Buffer": ("NIOBuffer", "JavaKitNIO"), + "java.nio.ByteBuffer": ("NIOByteBuffer", "JavaKitNIO"), + ], + expectedChunks: [ + "import JavaKitNIO", + """ + @JavaClass("java.nio.ByteBuffer") + open class NIOByteBuffer: NIOBuffer { + """, + """ + @JavaMethod + open func array() -> [Int8] + """, + """ + @JavaMethod + open override func arrayOffset() -> Int32 + """, + ] + ) + } } @JavaClass("java.lang.ClassLoader") @@ -597,6 +626,16 @@ public struct Executable { public struct TypeVariable { } +@JavaClass("java.nio.Buffer") +open class NIOBuffer: JavaObject { + +} + +@JavaClass("java.nio.ByteBuffer") +open class NIOByteBuffer: NIOBuffer { + +} + /// Translate a Java class and assert that the translated output contains /// each of the expected "chunks" of text. func assertTranslatedClass( From 1bc80c1ef40db08fbdf5922e537dd30d4791861a Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Mon, 4 Nov 2024 12:00:52 -0800 Subject: [PATCH 169/426] Drop dependency on swift-collections We only used it in one place where we don't really need it. --- Package.swift | 2 -- Sources/JExtractSwift/ImportedDecls.swift | 3 +-- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/Package.swift b/Package.swift index ac1d6842..0ea37b36 100644 --- a/Package.swift +++ b/Package.swift @@ -139,7 +139,6 @@ let package = Package( dependencies: [ .package(url: "https://github.com/swiftlang/swift-syntax.git", branch: "main"), .package(url: "https://github.com/apple/swift-argument-parser", from: "1.5.0"), - .package(url: "https://github.com/apple/swift-collections.git", .upToNextMinor(from: "1.1.0")), .package(url: "https://github.com/ordo-one/package-benchmark", .upToNextMajor(from: "1.4.0")), ], targets: [ @@ -309,7 +308,6 @@ let package = Package( .product(name: "SwiftSyntax", package: "swift-syntax"), .product(name: "SwiftSyntaxBuilder", package: "swift-syntax"), .product(name: "ArgumentParser", package: "swift-argument-parser"), - .product(name: "Collections", package: "swift-collections"), "JavaTypes", ], swiftSettings: [ diff --git a/Sources/JExtractSwift/ImportedDecls.swift b/Sources/JExtractSwift/ImportedDecls.swift index 3999a0c9..56c3bd6b 100644 --- a/Sources/JExtractSwift/ImportedDecls.swift +++ b/Sources/JExtractSwift/ImportedDecls.swift @@ -15,7 +15,6 @@ import Foundation import JavaTypes import SwiftSyntax -import OrderedCollections /// Any imported (Swift) declaration protocol ImportedDecl { @@ -254,7 +253,7 @@ public struct ImportedVariable: ImportedDecl, CustomStringConvertible { /// Usually this will be all the accessors the variable declares, /// however if the getter is async or throwing we may not be able to import it /// (yet), and therefore would skip it from the supported set. - public var supportedAccessorKinds: OrderedSet = [.get, .set] + public var supportedAccessorKinds: [VariableAccessorKind] = [.get, .set] /// This is the base identifier for the function, e.g., "init" for an /// initializer or "f" for "f(a:b:)". From ddd578c68f970156c87fb21876b44eca2e5c6356 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Mon, 4 Nov 2024 13:58:02 -0800 Subject: [PATCH 170/426] Remove unneeded import of OrderedCollections --- Sources/JExtractSwift/ImportedDecls+Printing.swift | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Sources/JExtractSwift/ImportedDecls+Printing.swift b/Sources/JExtractSwift/ImportedDecls+Printing.swift index 76422d09..966b5a3d 100644 --- a/Sources/JExtractSwift/ImportedDecls+Printing.swift +++ b/Sources/JExtractSwift/ImportedDecls+Printing.swift @@ -15,7 +15,6 @@ import Foundation import JavaTypes import SwiftSyntax -import OrderedCollections extension ImportedFunc { /// Render a `@{@snippet ... }` comment section that can be put inside a JavaDoc comment @@ -99,4 +98,4 @@ extension Optional where Wrapped == VariableAccessorKind { func renderMethodName(_ decl: ImportedFunc) -> String { self?.renderMethodName(decl) ?? decl.baseIdentifier } -} \ No newline at end of file +} From b08446a5dfc2925d3e8921b519de5a9312350255 Mon Sep 17 00:00:00 2001 From: Luke Howard Date: Mon, 4 Nov 2024 08:15:55 +1100 Subject: [PATCH 171/426] JavaKit: check each classPath element exists before starting VM Fixes #136. --- .../JavaKit/JavaKitVM/JavaVirtualMachine.swift | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/Sources/JavaKit/JavaKitVM/JavaVirtualMachine.swift b/Sources/JavaKit/JavaKitVM/JavaVirtualMachine.swift index 52882a41..9fb4db55 100644 --- a/Sources/JavaKit/JavaKitVM/JavaVirtualMachine.swift +++ b/Sources/JavaKit/JavaKitVM/JavaVirtualMachine.swift @@ -12,6 +12,12 @@ // //===----------------------------------------------------------------------===// +#if canImport(FoundationEssentials) +import FoundationEssentials +#else +import Foundation +#endif + typealias JavaVMPointer = UnsafeMutablePointer public final class JavaVirtualMachine: @unchecked Sendable { @@ -54,6 +60,12 @@ public final class JavaVirtualMachine: @unchecked Sendable { // Construct the complete list of VM options. var allVMOptions: [String] = [] if !classPath.isEmpty { + let fileManager = FileManager.default + for path in classPath { + if !fileManager.fileExists(atPath: path) { + throw JavaKitError.classPathEntryNotFound(entry: path, classPath: classPath) + } + } let colonSeparatedClassPath = classPath.joined(separator: ":") allVMOptions.append("-Djava.class.path=\(colonSeparatedClassPath)") } @@ -268,4 +280,8 @@ extension JavaVirtualMachine { } } } + + enum JavaKitError: Error { + case classPathEntryNotFound(entry: String, classPath: [String]) + } } From 4fa32a1971d204d30b5fe805d0805367b45a2fe8 Mon Sep 17 00:00:00 2001 From: Luke Howard Date: Thu, 7 Nov 2024 15:57:16 +1100 Subject: [PATCH 172/426] JavaKit: map NULL jstring to the empty string There's an impedance mismatch here between the JNIType (which is optional) and the Swift type. Assuming this is intentional than init(fromJNI:in) should check for a NULL value and map it to the empty string. Fixes: #155 --- Sources/JavaKit/BridgedValues/JavaValue+String.swift | 4 ++++ Tests/JavaKitTests/BasicRuntimeTests.swift | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/Sources/JavaKit/BridgedValues/JavaValue+String.swift b/Sources/JavaKit/BridgedValues/JavaValue+String.swift index e9c11e64..5e98634d 100644 --- a/Sources/JavaKit/BridgedValues/JavaValue+String.swift +++ b/Sources/JavaKit/BridgedValues/JavaValue+String.swift @@ -24,6 +24,10 @@ extension String: JavaValue { } public init(fromJNI value: JNIType, in environment: JNIEnvironment) { + guard let value else { + self.init() + return + } let cString = environment.interface.GetStringUTFChars(environment, value, nil)! defer { environment.interface.ReleaseStringUTFChars(environment, value, cString) } self = String(cString: cString) diff --git a/Tests/JavaKitTests/BasicRuntimeTests.swift b/Tests/JavaKitTests/BasicRuntimeTests.swift index e417cd6d..1cb0e787 100644 --- a/Tests/JavaKitTests/BasicRuntimeTests.swift +++ b/Tests/JavaKitTests/BasicRuntimeTests.swift @@ -76,6 +76,12 @@ class BasicRuntimeTests: XCTestCase { XCTAssertEqual(String(describing: error), "org/swift/javakit/Nonexistent") } } + + func testNullJavaStringConversion() throws { + let environment = try jvm.environment() + let nullString = String(fromJNI: nil, in: environment) + XCTAssertEqual(nullString, "") + } } @JavaClass("org.swift.javakit.Nonexistent") From abdd950ba8e347f88df6e4242e6b188835fff28e Mon Sep 17 00:00:00 2001 From: Luke Howard Date: Thu, 7 Nov 2024 09:42:42 +1100 Subject: [PATCH 173/426] JavaKit: make JavaVirtualMachine(adoptingJVM:) public This is useful for a shared object to wrap a VM passed in JNI_OnLoad() --- Sources/JavaKit/JavaKitVM/JavaVirtualMachine.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/JavaKit/JavaKitVM/JavaVirtualMachine.swift b/Sources/JavaKit/JavaKitVM/JavaVirtualMachine.swift index 9fb4db55..7769fa17 100644 --- a/Sources/JavaKit/JavaKitVM/JavaVirtualMachine.swift +++ b/Sources/JavaKit/JavaKitVM/JavaVirtualMachine.swift @@ -18,7 +18,7 @@ import FoundationEssentials import Foundation #endif -typealias JavaVMPointer = UnsafeMutablePointer +public typealias JavaVMPointer = UnsafeMutablePointer public final class JavaVirtualMachine: @unchecked Sendable { /// The JNI version that we depend on. @@ -31,7 +31,7 @@ public final class JavaVirtualMachine: @unchecked Sendable { private let destroyOnDeinit: Bool /// Adopt an existing JVM pointer. - private init(adoptingJVM jvm: JavaVMPointer) { + public init(adoptingJVM jvm: JavaVMPointer) { self.jvm = jvm self.destroyOnDeinit = false } From cd87fb4e83235bc816da642c2f0ae8f66d5b8592 Mon Sep 17 00:00:00 2001 From: Luke Howard Date: Thu, 7 Nov 2024 10:18:55 +1100 Subject: [PATCH 174/426] JavaKit: add CustomJavaClassLoader protocol Swift projections of Java classes can conform to CustomJavaClassLoader, to provide a custom class loader to be used when initializing new instances. This is useful for platforms such as Android which modify class and class loader visibility depending on the call stack. Fixes: #154 --- Sources/JavaKit/AnyJavaObject.swift | 47 +++++++++++- .../Exceptions/ExceptionHandling.swift | 8 +-- Sources/JavaKit/Java2Swift.config | 1 + .../JavaKit/JavaClass+Initialization.swift | 10 +-- Sources/JavaKit/JavaObject+Inheritance.swift | 20 +++--- Sources/JavaKit/JavaObject+MethodCalls.swift | 32 ++++----- Sources/JavaKit/Optional+JavaObject.swift | 5 +- .../JavaKit/generated/JavaClassLoader.swift | 72 +++++++++++++++++++ Tests/Java2SwiftTests/Java2SwiftTests.swift | 36 +++++----- 9 files changed, 174 insertions(+), 57 deletions(-) create mode 100644 Sources/JavaKit/generated/JavaClassLoader.swift diff --git a/Sources/JavaKit/AnyJavaObject.swift b/Sources/JavaKit/AnyJavaObject.swift index 6e39766a..27c3e06d 100644 --- a/Sources/JavaKit/AnyJavaObject.swift +++ b/Sources/JavaKit/AnyJavaObject.swift @@ -49,6 +49,19 @@ public protocol AnyJavaObject { var javaHolder: JavaObjectHolder { get } } +/// Protocol that allows Swift types to specify a custom Java class loader on +/// initialization. This is useful for platforms (e.g. Android) where the default +/// class loader does not make all application classes visible. +public protocol CustomJavaClassLoader: AnyJavaObject { + static func getJavaClassLoader(in environment: JNIEnvironment) throws -> JavaClassLoader! +} + +/// Add getClassLoader() to JavaObject as it is otherwise recursively defined +extension JavaObject { + @JavaMethod + public func getClassLoader() throws -> JavaClassLoader! +} + extension AnyJavaObject { /// Retrieve the underlying Java object. public var javaThis: jobject { @@ -81,13 +94,41 @@ extension AnyJavaObject { JavaClass(javaThis: jniClass!, environment: javaEnvironment) } - /// Retrieve the Java class for this type. - public static func getJNIClass(in environment: JNIEnvironment) throws -> jclass { - try environment.translatingJNIExceptions { + /// Retrieve the Java class for this type using the default class loader. + private static func _withJNIClassFromDefaultClassLoader( + in environment: JNIEnvironment, + _ body: (jclass) throws -> Result + ) throws -> Result { + let resolvedClass = try environment.translatingJNIExceptions { environment.interface.FindClass( environment, fullJavaClassNameWithSlashes ) }! + return try body(resolvedClass) + } + + /// Retrieve the Java class for this type using a specific class loader. + private static func _withJNIClassFromCustomClassLoader( + _ classLoader: JavaClassLoader, + in environment: JNIEnvironment, + _ body: (jclass) throws -> Result + ) throws -> Result { + let resolvedClass = try classLoader.findClass(fullJavaClassName) + return try body(resolvedClass!.javaThis) + } + + /// Retrieve the Java class for this type and execute body(). + @_spi(Testing) + public static func withJNIClass( + in environment: JNIEnvironment, + _ body: (jclass) throws -> Result + ) throws -> Result { + if let customJavaClassLoader = self as? CustomJavaClassLoader.Type, + let customClassLoader = try customJavaClassLoader.getJavaClassLoader(in: environment) { + try _withJNIClassFromCustomClassLoader(customClassLoader, in: environment, body) + } else { + try _withJNIClassFromDefaultClassLoader(in: environment, body) + } } } diff --git a/Sources/JavaKit/Exceptions/ExceptionHandling.swift b/Sources/JavaKit/Exceptions/ExceptionHandling.swift index cf063d0a..02537281 100644 --- a/Sources/JavaKit/Exceptions/ExceptionHandling.swift +++ b/Sources/JavaKit/Exceptions/ExceptionHandling.swift @@ -39,10 +39,8 @@ extension JNIEnvironment { } // Otherwise, create a exception with a message. - _ = interface.ThrowNew( - self, - try! JavaClass.getJNIClass(in: self), - String(describing: error) - ) + _ = try! JavaClass.withJNIClass(in: self) { exceptionClass in + interface.ThrowNew(self, exceptionClass, String(describing: error)) + } } } diff --git a/Sources/JavaKit/Java2Swift.config b/Sources/JavaKit/Java2Swift.config index ed284d31..d02a10ed 100644 --- a/Sources/JavaKit/Java2Swift.config +++ b/Sources/JavaKit/Java2Swift.config @@ -5,6 +5,7 @@ "java.lang.Byte" : "JavaByte", "java.lang.Character" : "JavaCharacter", "java.lang.Class" : "JavaClass", + "java.lang.ClassLoader" : "JavaClassLoader", "java.lang.Double" : "JavaDouble", "java.lang.Error" : "JavaError", "java.lang.Exception" : "Exception", diff --git a/Sources/JavaKit/JavaClass+Initialization.swift b/Sources/JavaKit/JavaClass+Initialization.swift index 9881e0dc..d443120f 100644 --- a/Sources/JavaKit/JavaClass+Initialization.swift +++ b/Sources/JavaKit/JavaClass+Initialization.swift @@ -21,9 +21,11 @@ extension JavaClass { @_nonoverride public convenience init(environment: JNIEnvironment? = nil) throws { let environment = try environment ?? JavaVirtualMachine.shared().environment() - self.init( - javaThis: try ObjectType.getJNIClass(in: environment), - environment: environment - ) + var javaClassHolder: JavaObjectHolder! + + javaClassHolder = try ObjectType.withJNIClass(in: environment) { javaClass in + JavaObjectHolder(object: javaClass, environment: environment) + } + self.init(javaHolder: javaClassHolder) } } diff --git a/Sources/JavaKit/JavaObject+Inheritance.swift b/Sources/JavaKit/JavaObject+Inheritance.swift index a8557b97..43d86c2a 100644 --- a/Sources/JavaKit/JavaObject+Inheritance.swift +++ b/Sources/JavaKit/JavaObject+Inheritance.swift @@ -22,19 +22,17 @@ extension AnyJavaObject { private func isInstanceOf( _ otherClass: OtherClass.Type ) -> jclass? { - guard let otherJavaClass = try? otherClass.getJNIClass(in: javaEnvironment) else { - return nil - } + try? otherClass.withJNIClass(in: javaEnvironment) { otherJavaClass in + if javaEnvironment.interface.IsInstanceOf( + javaEnvironment, + javaThis, + otherJavaClass + ) == 0 { + return nil + } - if javaEnvironment.interface.IsInstanceOf( - javaEnvironment, - javaThis, - otherJavaClass - ) == 0 { - return nil + return otherJavaClass } - - return otherJavaClass } /// Determine whether this object is an instance of a specific diff --git a/Sources/JavaKit/JavaObject+MethodCalls.swift b/Sources/JavaKit/JavaObject+MethodCalls.swift index 28558d49..9f02a58d 100644 --- a/Sources/JavaKit/JavaObject+MethodCalls.swift +++ b/Sources/JavaKit/JavaObject+MethodCalls.swift @@ -253,23 +253,23 @@ extension AnyJavaObject { in environment: JNIEnvironment, arguments: repeat each Param ) throws -> jobject { - let thisClass = try Self.getJNIClass(in: environment) - - // Compute the method signature so we can find the right method, then look up the - // method within the class. - let methodID = try Self.javaMethodLookup( - thisClass: thisClass, - methodName: javaConstructorName, - parameterTypes: repeat (each Param).self, - resultType: .void, - in: environment - ) + try Self.withJNIClass(in: environment) { thisClass in + // Compute the method signature so we can find the right method, then look up the + // method within the class. + let methodID = try Self.javaMethodLookup( + thisClass: thisClass, + methodName: javaConstructorName, + parameterTypes: repeat (each Param).self, + resultType: .void, + in: environment + ) - // Retrieve the constructor, then map the arguments and call it. - let jniArgs = getJValues(repeat each arguments, in: environment) - return try environment.translatingJNIExceptions { - environment.interface.NewObjectA!(environment, thisClass, methodID, jniArgs) - }! + // Retrieve the constructor, then map the arguments and call it. + let jniArgs = getJValues(repeat each arguments, in: environment) + return try environment.translatingJNIExceptions { + environment.interface.NewObjectA!(environment, thisClass, methodID, jniArgs) + }! + } } /// Retrieve the JNI field ID for a field with the given name and type. diff --git a/Sources/JavaKit/Optional+JavaObject.swift b/Sources/JavaKit/Optional+JavaObject.swift index b2f115db..7aff4294 100644 --- a/Sources/JavaKit/Optional+JavaObject.swift +++ b/Sources/JavaKit/Optional+JavaObject.swift @@ -70,8 +70,9 @@ extension Optional: JavaValue where Wrapped: AnyJavaObject { public static func jniNewArray(in environment: JNIEnvironment) -> JNINewArray { return { environment, size in - let jniClass = try! Wrapped.getJNIClass(in: environment) - return environment.interface.NewObjectArray(environment, size, jniClass, nil) + try! Wrapped.withJNIClass(in: environment) { jniClass in + environment.interface.NewObjectArray(environment, size, jniClass, nil) + } } } diff --git a/Sources/JavaKit/generated/JavaClassLoader.swift b/Sources/JavaKit/generated/JavaClassLoader.swift new file mode 100644 index 00000000..43eaeb4e --- /dev/null +++ b/Sources/JavaKit/generated/JavaClassLoader.swift @@ -0,0 +1,72 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaRuntime + +@JavaClass("java.lang.ClassLoader") +open class JavaClassLoader: JavaObject { + @JavaMethod + open func getName() -> String + + @JavaMethod + open func loadClass(_ arg0: String, _ arg1: Bool) throws -> JavaClass! + + @JavaMethod + open func loadClass(_ arg0: String) throws -> JavaClass! + + @JavaMethod + open func setSigners(_ arg0: JavaClass?, _ arg1: [JavaObject?]) + + @JavaMethod + open func getClassLoadingLock(_ arg0: String) -> JavaObject! + + @JavaMethod + open func findLoadedClass(_ arg0: String) -> JavaClass! + + @JavaMethod + open func findClass(_ arg0: String) throws -> JavaClass! + + @JavaMethod + open func findClass(_ arg0: String, _ arg1: String) -> JavaClass! + + @JavaMethod + open func resolveClass(_ arg0: JavaClass?) + + @JavaMethod + open func defineClass(_ arg0: [Int8], _ arg1: Int32, _ arg2: Int32) throws -> JavaClass! + + @JavaMethod + open func defineClass(_ arg0: String, _ arg1: [Int8], _ arg2: Int32, _ arg3: Int32) throws -> JavaClass! + + @JavaMethod + open func findLibrary(_ arg0: String) -> String + + @JavaMethod + open func findSystemClass(_ arg0: String) throws -> JavaClass! + + @JavaMethod + open func isRegisteredAsParallelCapable() -> Bool + + @JavaMethod + open func getParent() -> JavaClassLoader! + + @JavaMethod + open func setDefaultAssertionStatus(_ arg0: Bool) + + @JavaMethod + open func setPackageAssertionStatus(_ arg0: String, _ arg1: Bool) + + @JavaMethod + open func setClassAssertionStatus(_ arg0: String, _ arg1: Bool) + + @JavaMethod + open func clearAssertionStatus() +} +extension JavaClass { + @JavaStaticMethod + public func getPlatformClassLoader() -> JavaClassLoader! + + @JavaStaticMethod + public func getSystemClassLoader() -> JavaClassLoader! + + @JavaStaticMethod + public func registerAsParallelCapable() -> Bool +} diff --git a/Tests/Java2SwiftTests/Java2SwiftTests.swift b/Tests/Java2SwiftTests/Java2SwiftTests.swift index 259193b1..48440522 100644 --- a/Tests/Java2SwiftTests/Java2SwiftTests.swift +++ b/Tests/Java2SwiftTests/Java2SwiftTests.swift @@ -12,6 +12,7 @@ // //===----------------------------------------------------------------------===// +@_spi(Testing) import JavaKit import Java2SwiftLib import XCTest // NOTE: Workaround for https://github.com/swiftlang/swift-java/issues/43 @@ -661,24 +662,27 @@ func assertTranslatedClass( translator.translatedClasses[javaType.fullJavaClassName] = (swiftTypeName, nil) translator.nestedClasses = nestedClasses translator.startNewFile() - let translatedDecls = try translator.translateClass( - JavaClass( - javaThis: javaType.getJNIClass(in: environment), - environment: environment) - ) - let importDecls = translator.getImportDecls() - let swiftFileText = """ - // Auto-generated by Java-to-Swift wrapper generator. - \(importDecls.map { $0.description }.joined()) - \(translatedDecls.map { $0.description }.joined(separator: "\n")) - """ + try javaType.withJNIClass(in: environment) { javaClass in + let translatedDecls = try translator.translateClass( + JavaClass( + javaThis: javaClass, + environment: environment) + ) + let importDecls = translator.getImportDecls() - for expectedChunk in expectedChunks { - if swiftFileText.contains(expectedChunk) { - continue - } + let swiftFileText = """ + // Auto-generated by Java-to-Swift wrapper generator. + \(importDecls.map { $0.description }.joined()) + \(translatedDecls.map { $0.description }.joined(separator: "\n")) + """ - XCTFail("Expected chunk '\(expectedChunk)' not found in '\(swiftFileText)'", file: file, line: line) + for expectedChunk in expectedChunks { + if swiftFileText.contains(expectedChunk) { + continue + } + + XCTFail("Expected chunk '\(expectedChunk)' not found in '\(swiftFileText)'", file: file, line: line) + } } } From 24062a2e0ad1e1ca306ab65d7ab80d6731e7decb Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Thu, 7 Nov 2024 16:20:24 -0800 Subject: [PATCH 175/426] ExampleSwiftLibrary: adjust imports for Windows Guard the `Darwin` import to when the module is available rather than assuming it to be the default. Add a case for Windows. --- Sources/ExampleSwiftLibrary/MySwiftLibrary.swift | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Sources/ExampleSwiftLibrary/MySwiftLibrary.swift b/Sources/ExampleSwiftLibrary/MySwiftLibrary.swift index b5c8f5fd..36e09b14 100644 --- a/Sources/ExampleSwiftLibrary/MySwiftLibrary.swift +++ b/Sources/ExampleSwiftLibrary/MySwiftLibrary.swift @@ -19,7 +19,9 @@ #if os(Linux) import Glibc -#else +#elseif os(Windows) +import CRT +#elseif canImport(Darwin) import Darwin.C #endif From abc6af1629b225aea509d8809c206cb845a29212 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Thu, 7 Nov 2024 16:22:26 -0800 Subject: [PATCH 176/426] build: add proper search path for Windows The Windows includes are under `win32` at least with the Oracle JDK. This is required to be able to build on Windows. --- Package.swift | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Package.swift b/Package.swift index 0ea37b36..fc8e344f 100644 --- a/Package.swift +++ b/Package.swift @@ -35,9 +35,8 @@ let javaIncludePath = "\(javaHome)/include" let javaPlatformIncludePath = "\(javaIncludePath)/linux" #elseif os(macOS) let javaPlatformIncludePath = "\(javaIncludePath)/darwin" -#else - // TODO: Handle windows as well - #error("Currently only macOS and Linux platforms are supported, this may change in the future.") +#elseif os(Windows) + let javaPlatformIncludePath = "\(javaIncludePath)/win32" #endif let package = Package( From 25df0ecb0b044763edb015a6cbe556f6e064769c Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Thu, 7 Nov 2024 16:23:27 -0800 Subject: [PATCH 177/426] build: adjust the linker flags for JavaKit `-rpath` is not a universally valid flag for the linker. Adjust the linker flags to add the library search path on Windows and elide the `-rpath` flag. It is unclear why there is no `server` subdirectory under `lib` when using the Oracle JDK 23, but this allows us to find the necessary library. --- Package.swift | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Package.swift b/Package.swift index 0ea37b36..c944f41d 100644 --- a/Package.swift +++ b/Package.swift @@ -174,8 +174,10 @@ let package = Package( "-rpath", "-Xlinker", "\(javaHome)/lib/server", - ] + ], + .when(platforms: [.linux, .macOS]) ), + .unsafeFlags(["-L\(javaHome)/lib"], .when(platforms: [.windows])), .linkedLibrary("jvm"), ] ), From cc760e1db89be83ba5c5bc60fbcef691a72732e1 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Fri, 8 Nov 2024 16:43:57 +0900 Subject: [PATCH 178/426] Update Package.swift --- Package.swift | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Package.swift b/Package.swift index c944f41d..44d59bf8 100644 --- a/Package.swift +++ b/Package.swift @@ -177,7 +177,11 @@ let package = Package( ], .when(platforms: [.linux, .macOS]) ), - .unsafeFlags(["-L\(javaHome)/lib"], .when(platforms: [.windows])), + .unsafeFlags( + [ + "-L\(javaHome)/lib" + ], + .when(platforms: [.windows])), .linkedLibrary("jvm"), ] ), From 0f4002d1893befe7ecc79b038a31ac2911c94f28 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Fri, 8 Nov 2024 09:23:47 -0800 Subject: [PATCH 179/426] Adapt to swift-syntax changes in generic argument handling --- Sources/JExtractSwift/TranslatedType.swift | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/Sources/JExtractSwift/TranslatedType.swift b/Sources/JExtractSwift/TranslatedType.swift index 367c92cc..ca1ecf73 100644 --- a/Sources/JExtractSwift/TranslatedType.swift +++ b/Sources/JExtractSwift/TranslatedType.swift @@ -55,7 +55,12 @@ extension Swift2JavaVisitor { // Translate the generic arguments to the C-compatible types. let genericArgs = try memberType.genericArgumentClause.map { genericArgumentClause in try genericArgumentClause.arguments.map { argument in - try cCompatibleType(for: argument.argument) + switch argument.argument { + case .type(let argumentType): + try cCompatibleType(for: argumentType) + @unknown default: + throw TypeTranslationError.unimplementedType(TypeSyntax(memberType)) + } } } @@ -71,7 +76,12 @@ extension Swift2JavaVisitor { // Translate the generic arguments to the C-compatible types. let genericArgs = try identifierType.genericArgumentClause.map { genericArgumentClause in try genericArgumentClause.arguments.map { argument in - try cCompatibleType(for: argument.argument) + switch argument.argument { + case .type(let argumentType): + try cCompatibleType(for: argumentType) + @unknown default: + throw TypeTranslationError.unimplementedType(TypeSyntax(identifierType)) + } } } From 023323629b3a55d21dcafa2d9e2ade683c9e23d3 Mon Sep 17 00:00:00 2001 From: Luke Howard Date: Fri, 8 Nov 2024 22:31:17 +1100 Subject: [PATCH 180/426] JavaKit: add source/target versions to Java2Swift.config Fixes: #152 --- Plugins/Java2SwiftPlugin/Configuration.swift | 8 +++ .../JavaCompilerPlugin/Configuration.swift | 51 +++++++++++++++++++ .../JavaCompilerPlugin.swift | 13 ++++- Sources/Java2SwiftLib/Configuration.swift | 14 ++++- 4 files changed, 84 insertions(+), 2 deletions(-) create mode 100644 Plugins/JavaCompilerPlugin/Configuration.swift diff --git a/Plugins/Java2SwiftPlugin/Configuration.swift b/Plugins/Java2SwiftPlugin/Configuration.swift index 6b9b4076..c9b17d06 100644 --- a/Plugins/Java2SwiftPlugin/Configuration.swift +++ b/Plugins/Java2SwiftPlugin/Configuration.swift @@ -12,6 +12,8 @@ // //===----------------------------------------------------------------------===// +typealias JavaVersion = Int + /// Configuration for the Java2Swift translation tool, provided on a per-target /// basis. /// @@ -25,4 +27,10 @@ struct Configuration: Codable { /// canonical Java class names (e.g., java.util.Vector) and the values are /// the corresponding Swift names (e.g., JavaVector). var classes: [String: String] = [:] + + // Compile for the specified Java SE release. + var sourceCompatibility: JavaVersion? + + // Generate class files suitable for the specified Java SE release. + var targetCompatibility: JavaVersion? } diff --git a/Plugins/JavaCompilerPlugin/Configuration.swift b/Plugins/JavaCompilerPlugin/Configuration.swift new file mode 100644 index 00000000..96180760 --- /dev/null +++ b/Plugins/JavaCompilerPlugin/Configuration.swift @@ -0,0 +1,51 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +typealias JavaVersion = Int + +/// Configuration for the Java2Swift translation tool, provided on a per-target +/// basis. +/// +/// Note: there is a copy of this struct in the Java2Swift library. They +/// must be kept in sync. +struct Configuration: Codable { + /// The Java class path that should be passed along to the Java2Swift tool. + var classPath: String? = nil + + /// The Java classes that should be translated to Swift. The keys are + /// canonical Java class names (e.g., java.util.Vector) and the values are + /// the corresponding Swift names (e.g., JavaVector). + var classes: [String: String] = [:] + + // Compile for the specified Java SE release. + var sourceCompatibility: JavaVersion? + + // Generate class files suitable for the specified Java SE release. + var targetCompatibility: JavaVersion? +} + +extension Configuration { + var compilerVersionArgs: [String] { + var compilerVersionArgs = [String]() + + if let sourceCompatibility { + compilerVersionArgs += ["--source", String(sourceCompatibility)] + } + if let targetCompatibility { + compilerVersionArgs += ["--target", String(targetCompatibility)] + } + + return compilerVersionArgs + } +} diff --git a/Plugins/JavaCompilerPlugin/JavaCompilerPlugin.swift b/Plugins/JavaCompilerPlugin/JavaCompilerPlugin.swift index 64e1d2a7..518073a2 100644 --- a/Plugins/JavaCompilerPlugin/JavaCompilerPlugin.swift +++ b/Plugins/JavaCompilerPlugin/JavaCompilerPlugin.swift @@ -32,6 +32,17 @@ struct JavaCompilerBuildToolPlugin: BuildToolPlugin { // so we cannot eliminate this deprecation warning. let sourceDir = target.directory.string + // The name of the configuration file JavaKit.config from the target for + // which we are generating Swift wrappers for Java classes. + let configFile = URL(filePath: sourceDir).appending(path: "Java2Swift.config") + let config: Configuration? + + if let configData = try? Data(contentsOf: configFile) { + config = try? JSONDecoder().decode(Configuration.self, from: configData) + } else { + config = nil + } + // The class files themselves will be generated into the build directory // for this target. let classFiles = javaFiles.map { sourceFileURL in @@ -60,7 +71,7 @@ struct JavaCompilerBuildToolPlugin: BuildToolPlugin { arguments: javaFiles.map { $0.path(percentEncoded: false) } + [ "-d", javaClassFileURL.path(), "-parameters", // keep parameter names, which allows us to emit them in generated Swift decls - ], + ] + (config?.compilerVersionArgs ?? []), inputFiles: javaFiles, outputFiles: classFiles ) diff --git a/Sources/Java2SwiftLib/Configuration.swift b/Sources/Java2SwiftLib/Configuration.swift index 6617b4d0..be92dd84 100644 --- a/Sources/Java2SwiftLib/Configuration.swift +++ b/Sources/Java2SwiftLib/Configuration.swift @@ -12,6 +12,8 @@ // //===----------------------------------------------------------------------===// +package typealias JavaVersion = Int + /// Configuration for the Java2Swift translation tool, provided on a per-target /// basis. /// @@ -26,8 +28,18 @@ package struct Configuration: Codable { /// the corresponding Swift names (e.g., JavaVector). package var classes: [String: String] = [:] - package init(classPath: String? = nil, classes: [String : String] = [:]) { + package var sourceCompatibility: JavaVersion? + package var targetCompatibility: JavaVersion? + + package init( + classPath: String? = nil, + classes: [String : String] = [:], + sourceCompatibility: JavaVersion? = nil, + targetCompatibility: JavaVersion? = nil + ) { self.classPath = classPath self.classes = classes + self.sourceCompatibility = sourceCompatibility + self.targetCompatibility = targetCompatibility } } From 0c57644d2cef1f82c8907cd706ec13c1ef7d84da Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Thu, 14 Nov 2024 23:13:11 +0900 Subject: [PATCH 181/426] Redesign jextract-swift: plugins and avoid custom swift features (#170) --- .github/actions/prepare_env/action.yml | 44 ++ .github/scripts/validate_samples.sh | 37 ++ .github/workflows/pull_request.yml | 135 ++---- .gitignore | 6 + .licenseignore | 3 + ...d-logic.java-common-conventions.gradle.kts | 35 +- Makefile | 42 +- Package.swift | 35 +- .../JExtractSwiftCommandPlugin.swift | 161 +++++++ .../PluginsShared/Configuration.swift | 36 ++ .../PluginsShared/PluginUtils.swift | 48 ++ .../JExtractSwiftPlugin.swift | 63 +++ .../PluginsShared/Configuration.swift | 36 ++ .../PluginsShared/PluginUtils.swift | 37 ++ Samples/JavaProbablyPrime/ci-validate.sh | 3 + .../JavaSieve/Sources/JavaSieve/main.swift | 3 + Samples/JavaSieve/ci-validate.sh | 3 + Samples/SwiftKitSampleApp/Package.swift | 77 +++ .../MySwiftLibrary/MySwiftLibrary.swift | 101 ++++ .../Sources/MySwiftLibrary/swift-java.config | 3 + Samples/SwiftKitSampleApp/build.gradle | 94 +++- Samples/SwiftKitSampleApp/gradlew | 1 + Samples/SwiftKitSampleApp/gradlew.bat | 1 + .../swift/swiftkit/JavaToSwiftBenchmark.java | 3 +- .../com/example/swift/HelloJava2Swift.java | 27 +- .../{generated => }/MySwiftClassTest.java | 38 +- ...oduleTest.java => MySwiftLibraryTest.java} | 30 +- .../org/swift/swiftkit/MySwiftClassTest.java | 10 +- .../org/swift/swiftkit/SwiftArenaTest.java | 11 +- .../ExampleSwiftLibrary/MySwiftLibrary.swift | 9 + Sources/JExtractSwift/CodePrinter.swift | 75 ++- .../Convenience/Collection+Extensions.swift | 10 + Sources/JExtractSwift/ImportedDecls.swift | 131 +++-- Sources/JExtractSwift/Logger.swift | 18 +- Sources/JExtractSwift/Swift2Java.swift | 71 ++- .../Swift2JavaTranslator+MemoryLayouts.swift | 10 +- .../Swift2JavaTranslator+Printing.swift | 453 +++++++++++------- .../JExtractSwift/Swift2JavaTranslator.swift | 31 +- Sources/JExtractSwift/Swift2JavaVisitor.swift | 50 +- Sources/JExtractSwift/SwiftKit+Printing.swift | 44 ++ .../JExtractSwift/SwiftThunkTranslator.swift | 136 ++++++ Sources/JExtractSwift/TerminalColors.swift | 17 + Sources/JExtractSwift/ThunkNameRegistry.swift | 65 +++ Sources/JExtractSwift/TranslatedType.swift | 18 +- .../Java2SwiftLib/JavaClassTranslator.swift | 4 +- Sources/SwiftKitSwift/SwiftKit.swift | 34 +- SwiftKit/build.gradle | 29 ++ .../java/org/swift/swiftkit/SwiftAnyType.java | 8 +- .../java/org/swift/swiftkit/SwiftKit.java | 145 ++++-- .../swiftkit/SwiftRuntimeMetadataTest.java | 1 + .../Asserts/TextAssertions.swift | 118 ++++- .../FuncCallbackImportTests.swift | 8 +- .../FunctionDescriptorImportTests.swift | 20 +- .../MethodImportTests.swift | 64 +-- .../JExtractSwiftTests/MethodThunkTests.swift | 56 +++ .../VariableImportTests.swift | 268 ++++++----- WIP.md | 47 -- buildSrc/build.gradle | 9 + .../swift/swiftkit/gradle/BuildUtils.groovy | 21 +- docker/Dockerfile | 4 +- docker/install_jdk.sh | 3 - settings.gradle | 1 - 62 files changed, 2263 insertions(+), 838 deletions(-) create mode 100644 .github/actions/prepare_env/action.yml create mode 100755 .github/scripts/validate_samples.sh create mode 100644 Plugins/JExtractSwiftCommandPlugin/JExtractSwiftCommandPlugin.swift create mode 100644 Plugins/JExtractSwiftCommandPlugin/PluginsShared/Configuration.swift create mode 100644 Plugins/JExtractSwiftCommandPlugin/PluginsShared/PluginUtils.swift create mode 100644 Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift create mode 100644 Plugins/JExtractSwiftPlugin/PluginsShared/Configuration.swift create mode 100644 Plugins/JExtractSwiftPlugin/PluginsShared/PluginUtils.swift create mode 100755 Samples/JavaProbablyPrime/ci-validate.sh create mode 100755 Samples/JavaSieve/ci-validate.sh create mode 100644 Samples/SwiftKitSampleApp/Package.swift create mode 100644 Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift create mode 100644 Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/swift-java.config create mode 120000 Samples/SwiftKitSampleApp/gradlew create mode 120000 Samples/SwiftKitSampleApp/gradlew.bat rename Samples/SwiftKitSampleApp/src/test/java/com/example/swift/{generated => }/MySwiftClassTest.java (56%) rename Samples/SwiftKitSampleApp/src/test/java/com/example/swift/{generated/GeneratedJavaKitExampleModuleTest.java => MySwiftLibraryTest.java} (59%) create mode 100644 Sources/JExtractSwift/SwiftKit+Printing.swift create mode 100644 Sources/JExtractSwift/SwiftThunkTranslator.swift create mode 100644 Sources/JExtractSwift/ThunkNameRegistry.swift create mode 100644 Tests/JExtractSwiftTests/MethodThunkTests.swift diff --git a/.github/actions/prepare_env/action.yml b/.github/actions/prepare_env/action.yml new file mode 100644 index 00000000..ebcc8aed --- /dev/null +++ b/.github/actions/prepare_env/action.yml @@ -0,0 +1,44 @@ +name: 'Swift Java CI Env' +description: 'Prepare the CI environment by installing Swift and selected JDK etc.' + +runs: + using: composite + steps: + - name: Install System Dependencies + run: apt-get -qq update && apt-get -qq install -y make curl wget libjemalloc2 libjemalloc-dev + shell: bash + - name: Cache JDK + id: cache-jdk + uses: actions/cache@v4 + continue-on-error: true + with: + path: /usr/lib/jvm/default-jdk/ + key: ${{ runner.os }}-jdk-${{ matrix.jdk_vendor }}-${{ hashFiles('/usr/lib/jvm/default-jdk/*') }} + restore-keys: | + ${{ runner.os }}-jdk- + - name: Install JDK + if: steps.cache-jdk.outputs.cache-hit != 'true' + run: "bash -xc 'JDK_VENDOR=${{ matrix.jdk_vendor }} ./docker/install_jdk.sh'" + shell: bash + # TODO: not using setup-java since incompatible with the swiftlang/swift base image + # - name: Install Untested Nightly Swift + # run: "bash -xc './docker/install_untested_nightly_swift.sh'" + - name: Cache local Gradle repository + uses: actions/cache@v4 + continue-on-error: true + with: + path: | + /root/.gradle/caches + /root/.gradle/wrapper + key: ${{ runner.os }}-gradle-${{ hashFiles('*/*.gradle*', 'settings.gradle') }} + restore-keys: | + ${{ runner.os }}-gradle- + - name: Cache local SwiftPM repository + uses: actions/cache@v4 + continue-on-error: true + with: + path: /__w/swift-java/swift-java/.build/checkouts + key: ${{ runner.os }}-swiftpm-cache-${{ hashFiles('Package.swift') }} + restore-keys: | + ${{ runner.os }}-swiftpm-cache + ${{ runner.os }}-swiftpm- diff --git a/.github/scripts/validate_samples.sh b/.github/scripts/validate_samples.sh new file mode 100755 index 00000000..26273575 --- /dev/null +++ b/.github/scripts/validate_samples.sh @@ -0,0 +1,37 @@ +#!/bin/bash + +# shellcheck disable=SC2034 +declare -r GREEN='\033[0;32m' +declare -r BOLD='\033[1m' +declare -r RESET='\033[0m' + +# shellcheck disable=SC2155 +declare -r SAMPLE_PACKAGES=$(find Samples -name Package.swift -maxdepth 2) +declare -r CI_VALIDATE_SCRIPT='ci-validate.sh' + +for samplePackage in ${SAMPLE_PACKAGES} ; do + sampleDir=$(dirname "$samplePackage") + + echo "" + echo "" + echo "========================================================================" + printf "Validate sample '${BOLD}%s${RESET}' using: " "$sampleDir" + cd "$sampleDir" || exit + if [[ $(find . -name ${CI_VALIDATE_SCRIPT} -maxdepth 1) ]]; then + echo -e "Custom ${BOLD}${CI_VALIDATE_SCRIPT}${RESET} script..." + ./${CI_VALIDATE_SCRIPT} || exit + elif [[ $(find . -name 'build.gradle*' -maxdepth 1) ]]; then + echo -e "${BOLD}Gradle${RESET} build..." + ./gradlew build || ./gradlew build --info # re-run to get better failure output + else + echo -e "${BOLD}SwiftPM${RESET} build..." + swift build || exit + fi + + echo -e "Validated sample '${BOLD}${sampleDir}${RESET}': ${BOLD}passed${RESET}." + cd - || exit +done + +echo +printf "Done validating samples: " +echo -e "${GREEN}done${RESET}." diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index eea13444..8039b572 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -8,6 +8,7 @@ jobs: soundness: uses: swiftlang/github-workflows/.github/workflows/soundness.yml@main with: + # Not API stable package (yet) api_breakage_check_enabled: false # FIXME: Something is off with the format task and it gets "stuck", need to investigate format_check_enabled: false @@ -19,7 +20,8 @@ jobs: strategy: fail-fast: true matrix: - swift_version: ['nightly-main'] + # swift_version: ['nightly-main'] + swift_version: ['6.0.2'] os_version: ['jammy'] jdk_vendor: ['Corretto'] container: @@ -28,50 +30,14 @@ jobs: JAVA_HOME: "/usr/lib/jvm/default-jdk" steps: - uses: actions/checkout@v4 - - name: Install System Dependencies - run: apt-get -qq update && apt-get -qq install -y make curl wget libjemalloc2 libjemalloc-dev - - name: Cache JDK - id: cache-jdk - uses: actions/cache@v4 - continue-on-error: true - with: - path: /usr/lib/jvm/default-jdk/ - key: ${{ runner.os }}-jdk-${{ matrix.jdk_vendor }}-${{ hashFiles('/usr/lib/jvm/default-jdk/*') }} - restore-keys: | - ${{ runner.os }}-jdk- - - name: Install JDK - if: steps.cache-jdk.outputs.cache-hit != 'true' - run: "bash -xc 'JDK_VENDOR=${{ matrix.jdk_vendor }} ./docker/install_jdk.sh'" - # TODO: not using setup-java since incompatible with the swiftlang/swift base image - - name: Install Untested Nightly Swift - run: "bash -xc './docker/install_untested_nightly_swift.sh'" - - name: Cache local Gradle repository - uses: actions/cache@v4 - continue-on-error: true - with: - path: | - /root/.gradle/caches - /root/.gradle/wrapper - key: ${{ runner.os }}-gradle-${{ hashFiles('*/*.gradle*', 'settings.gradle') }} - restore-keys: | - ${{ runner.os }}-gradle- - - name: Cache local SwiftPM repository - uses: actions/cache@v4 - continue-on-error: true - with: - path: /__w/swift-java/swift-java/.build/checkouts - key: ${{ runner.os }}-swiftpm-cache-${{ hashFiles('Package.swift') }} - restore-keys: | - ${{ runner.os }}-swiftpm-cache - ${{ runner.os }}-swiftpm- - # run the actual build - - name: Gradle build - run: | - ./gradlew build -x test --no-daemon # just build - ./gradlew build --info --no-daemon - - name: Gradle build (benchmarks) - run: | - ./gradlew compileJmh --info --no-daemon + - name: Prepare CI Environment + uses: ./.github/actions/prepare_env + - name: Gradle :SwiftKit:build + run: ./gradlew build -x test + - name: Gradle :SwiftKit:check + run: ./gradlew :SwiftKit:check --info + - name: Gradle compile JMH benchmarks + run: ./gradlew compileJmh --info test-swift: name: Swift tests (swift:${{ matrix.swift_version }} jdk:${{matrix.jdk_vendor}} os:${{ matrix.os_version }}) @@ -79,7 +45,8 @@ jobs: strategy: fail-fast: false matrix: - swift_version: ['nightly-main'] + # swift_version: ['nightly-main'] + swift_version: ['6.0.2'] os_version: ['jammy'] jdk_vendor: ['Corretto'] container: @@ -88,51 +55,33 @@ jobs: JAVA_HOME: "/usr/lib/jvm/default-jdk" steps: - uses: actions/checkout@v4 - - name: Install System Dependencies - run: apt-get -qq update && apt-get -qq install -y make curl wget libjemalloc2 libjemalloc-dev - - name: Cache JDK - id: cache-jdk - uses: actions/cache@v4 - continue-on-error: true - with: - path: /usr/lib/jvm/default-jdk/ - key: ${{ runner.os }}-jdk-${{ matrix.jdk_vendor }}-${{ hashFiles('/usr/lib/jvm/default-jdk/*') }} - restore-keys: | - ${{ runner.os }}-jdk- - - name: Install JDK - if: steps.cache-jdk.outputs.cache-hit != 'true' - run: "bash -xc 'JDK_VENDOR=${{ matrix.jdk_vendor }} ./docker/install_jdk.sh'" - # TODO: not using setup-java since incompatible with the swiftlang/swift base image - - name: Install Untested Nightly Swift - run: "bash -xc './docker/install_untested_nightly_swift.sh'" - - name: Cache local Gradle repository - uses: actions/cache@v4 - continue-on-error: true - with: - path: | - /root/.gradle/caches - /root/.gradle/wrapper - key: ${{ runner.os }}-gradle-${{ hashFiles('*/*.gradle*', 'settings.gradle') }} - restore-keys: | - ${{ runner.os }}-gradle- - - name: Cache local SwiftPM repository - uses: actions/cache@v4 - continue-on-error: true - with: - path: /__w/swift-java/swift-java/.build/checkouts - key: ${{ runner.os }}-swiftpm-cache-${{ hashFiles('Package.swift') }} - restore-keys: | - ${{ runner.os }}-swiftpm-cache - ${{ runner.os }}-swiftpm- - # run the actual build - - name: Generate sources (make) (Temporary) - # TODO: this should be triggered by the respective builds - run: "make jextract-generate" - - name: Test Swift + - name: Prepare CI Environment + uses: ./.github/actions/prepare_env + - name: Swift Build + run: "swift build --build-tests" + - name: Swift Test run: "swift test" - - name: Build (Swift) Sample Apps - run: | - find Samples/ -name Package.swift -maxdepth 2 -exec swift build --package-path $(dirname {}) \;; - # TODO: Benchmark compile crashes in CI, enable when nightly toolchains in better shape. - # - name: Build (Swift) Benchmarks - # run: "swift package --package-path Benchmarks/ benchmark list" + + verify-samples: + name: Verify Samples (swift:${{ matrix.swift_version }} jdk:${{matrix.jdk_vendor}} os:${{ matrix.os_version }}) + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + # swift_version: ['nightly-main'] + swift_version: ['6.0.2'] + os_version: ['jammy'] + jdk_vendor: ['Corretto'] + container: + image: ${{ (contains(matrix.swift_version, 'nightly') && 'swiftlang/swift') || 'swift' }}:${{ matrix.swift_version }}-${{ matrix.os_version }} + env: + JAVA_HOME: "/usr/lib/jvm/default-jdk" + steps: + - uses: actions/checkout@v4 + - name: Prepare CI Environment + uses: ./.github/actions/prepare_env + - name: Verify Samples (All) + run: .github/scripts/validate_samples.sh + # TODO: Benchmark compile crashes in CI, enable when nightly toolchains in better shape. + # - name: Build (Swift) Benchmarks + # run: "swift package --package-path Benchmarks/ benchmark list" diff --git a/.gitignore b/.gitignore index 5055eec2..11bbeceb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ .DS_Store .build +.idea Packages xcuserdata/ DerivedData/ @@ -33,3 +34,8 @@ Package.resolved # Ignore files generated by jextract, we always can re-generate them */**/src/generated/java/**/* + +*/**/*.d +*/**/*.o +*/**/*.swiftdeps +*/**/*.swiftdeps~ diff --git a/.licenseignore b/.licenseignore index 02866b01..c5dfe3d2 100644 --- a/.licenseignore +++ b/.licenseignore @@ -37,3 +37,6 @@ Makefile gradle/wrapper/gradle-wrapper.properties gradlew gradlew.bat +**/gradlew +**/gradlew.bat +**/ci-validate.sh diff --git a/BuildLogic/src/main/kotlin/build-logic.java-common-conventions.gradle.kts b/BuildLogic/src/main/kotlin/build-logic.java-common-conventions.gradle.kts index e3fc499f..136da7d3 100644 --- a/BuildLogic/src/main/kotlin/build-logic.java-common-conventions.gradle.kts +++ b/BuildLogic/src/main/kotlin/build-logic.java-common-conventions.gradle.kts @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// import java.util.* +import java.io.* plugins { java @@ -44,7 +45,7 @@ tasks.withType(JavaCompile::class).forEach { // FIXME: cannot share definition with 'buildSrc' so we duplicated the impl here -fun javaLibraryPaths(): List { +fun javaLibraryPaths(dir: File): List { val osName = System.getProperty("os.name") val osArch = System.getProperty("os.arch") val isLinux = osName.lowercase(Locale.getDefault()).contains("linux") @@ -52,15 +53,15 @@ fun javaLibraryPaths(): List { return listOf( if (isLinux) { if (osArch.equals("x86_64") || osArch.equals("amd64")) { - "$rootDir/.build/x86_64-unknown-linux-gnu/debug/" + "$dir/.build/x86_64-unknown-linux-gnu/debug/" } else { - "$rootDir/.build/$osArch-unknown-linux-gnu/debug/" + "$dir/.build/$osArch-unknown-linux-gnu/debug/" } } else { if (osArch.equals("aarch64")) { - "$rootDir/.build/arm64-apple-macosx/debug/" + "$dir/.build/arm64-apple-macosx/debug/" } else { - "$rootDir/.build/$osArch-apple-macosx/debug/" + "$dir/.build/$osArch-apple-macosx/debug/" } }, if (isLinux) { @@ -68,6 +69,12 @@ fun javaLibraryPaths(): List { } else { // assume macOS "/usr/lib/swift/" + }, + if (isLinux) { + System.getProperty("user.home") + "/.local/share/swiftly/toolchains/6.0.2/usr/lib/swift/linux" + } else { + // assume macOS + "/usr/lib/swift/" } ) } @@ -79,7 +86,9 @@ tasks.test { "--enable-native-access=ALL-UNNAMED", // Include the library paths where our dylibs are that we want to load and call - "-Djava.library.path=" + javaLibraryPaths().joinToString(File.pathSeparator) + "-Djava.library.path=" + + (javaLibraryPaths(rootDir) + javaLibraryPaths(project.projectDir)) + .joinToString(File.pathSeparator) ) } @@ -88,17 +97,3 @@ tasks.withType { this.showStandardStreams = true } } - - -// TODO: This is a crude workaround, we'll remove 'make' soon and properly track build dependencies -// val buildSwiftJExtract = tasks.register("buildMake") { -// description = "Triggers 'make' build" -// -// workingDir(rootDir) -// commandLine("make") -// } -// -// tasks.build { -// dependsOn(buildSwiftJExtract) -// } - diff --git a/Makefile b/Makefile index aeb3eedd..d8f8717a 100644 --- a/Makefile +++ b/Makefile @@ -57,8 +57,6 @@ all: @echo "Welcome to swift-java! There are several makefile targets to choose from:" @echo " javakit-run: Run the JavaKit example program that uses Java libraries from Swift." @echo " javakit-generate: Regenerate the Swift wrapper code for the various JavaKit libraries from Java. This only has to be done when changing the Java2Swift tool." - @echo " jextract-run: Run the Java example code that uses the wrapped Swift library. NOTE: this requires development toolchain described in the README." - @echo " jextract-generate: Generate Java wrapper code for the example Swift library allowing Swift to be called from Java. NOTE: this requires development toolchain described in the README." $(BUILD_DIR)/debug/libJavaKit.$(LIB_SUFFIX) $(BUILD_DIR)/debug/Java2Swift: swift build @@ -96,6 +94,9 @@ javakit-generate: generate-JavaKit generate-JavaKitReflection generate-JavaKitJa clean: rm -rf .build; \ + rm -rf build; \ + rm -rf Samples/JExtractPluginSampleApp/.build; \ + rm -rf Samples/JExtractPluginSampleApp/build; \ rm -rf Samples/SwiftKitExampleApp/src/generated/java/* format: @@ -105,42 +106,5 @@ format: ### "SwiftKit" is the "call swift from java" ### ################################################# -JEXTRACT_BUILD_DIR="$(BUILD_DIR)/jextract" - -define make_swiftinterface - $(eval $@_MODULE = $(1)) - $(eval $@_FILENAME = $(2)) - eval ${SWIFTC} \ - -emit-module-interface-path ${JEXTRACT_BUILD_DIR}/${$@_MODULE}/${$@_FILENAME}.swiftinterface \ - -emit-module-path ${JEXTRACT_BUILD_DIR}/${$@_MODULE}/${$@_FILENAME}.swiftmodule \ - -enable-library-evolution \ - -Xfrontend -abi-comments-in-module-interface \ - -module-name ${$@_MODULE} \ - -Xfrontend -abi-comments-in-module-interface \ - Sources/${$@_MODULE}/${$@_FILENAME}.swift - echo "Generated: ${JEXTRACT_BUILD_DIR}/${$@_MODULE}/${$@_FILENAME}.swiftinterface" -endef - -jextract-swift: generate-JExtract-interface-files - swift build - -generate-JExtract-interface-files: $(BUILD_DIR)/debug/libJavaKit.$(LIB_SUFFIX) - @echo "Generate .swiftinterface files..." - @$(call make_swiftinterface, "ExampleSwiftLibrary", "MySwiftLibrary") - @$(call make_swiftinterface, "SwiftKitSwift", "SwiftKit") - -jextract-generate: jextract-swift generate-JExtract-interface-files - swift run jextract-swift \ - --package-name com.example.swift.generated \ - --swift-module ExampleSwiftLibrary \ - --output-directory ${SAMPLES_DIR}/SwiftKitSampleApp/build/generated/sources/jextract/main \ - $(BUILD_DIR)/jextract/ExampleSwiftLibrary/MySwiftLibrary.swiftinterface; \ - swift run jextract-swift \ - --package-name org.swift.swiftkit.generated \ - --swift-module SwiftKitSwift \ - --output-directory ${SAMPLES_DIR}/SwiftKitSampleApp/build/generated/sources/jextract/main \ - $(BUILD_DIR)/jextract/SwiftKitSwift/SwiftKit.swiftinterface - - jextract-run: jextract-generate ./gradlew Samples:SwiftKitSampleApp:run diff --git a/Package.swift b/Package.swift index cd456d76..0d5a5dab 100644 --- a/Package.swift +++ b/Package.swift @@ -126,6 +126,20 @@ let package = Package( targets: ["JExtractSwift"] ), + // ==== Plugin for wrapping Java classes in Swift + .plugin( + name: "JExtractSwiftPlugin", + targets: [ + "JExtractSwiftPlugin" + ] + ), + .plugin( + name: "JExtractSwiftCommandPlugin", + targets: [ + "JExtractSwiftCommandPlugin" + ] + ), + // ==== Examples .library( @@ -136,7 +150,7 @@ let package = Package( ], dependencies: [ - .package(url: "https://github.com/swiftlang/swift-syntax.git", branch: "main"), + .package(url: "https://github.com/swiftlang/swift-syntax", from: "600.0.1"), .package(url: "https://github.com/apple/swift-argument-parser", from: "1.5.0"), .package(url: "https://github.com/ordo-one/package-benchmark", .upToNextMajor(from: "1.4.0")), ], @@ -229,6 +243,7 @@ let package = Package( .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) ] ), + .plugin( name: "JavaCompilerPlugin", capability: .buildTool() @@ -331,6 +346,24 @@ let package = Package( ] ), + .plugin( + name: "JExtractSwiftPlugin", + capability: .buildTool(), + dependencies: [ + "JExtractSwiftTool" + ] + ), + .plugin( + name: "JExtractSwiftCommandPlugin", + capability: .command( + intent: .custom(verb: "jextract", description: "Extract Java accessors from Swift module"), + permissions: [ + ]), + dependencies: [ + "JExtractSwiftTool" + ] + ), + .testTarget( name: "JavaKitTests", dependencies: ["JavaKit", "JavaKitNetwork"], diff --git a/Plugins/JExtractSwiftCommandPlugin/JExtractSwiftCommandPlugin.swift b/Plugins/JExtractSwiftCommandPlugin/JExtractSwiftCommandPlugin.swift new file mode 100644 index 00000000..008bc7d7 --- /dev/null +++ b/Plugins/JExtractSwiftCommandPlugin/JExtractSwiftCommandPlugin.swift @@ -0,0 +1,161 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import Foundation +import PackagePlugin + +@main +final class JExtractSwiftCommandPlugin: BuildToolPlugin, CommandPlugin { + + var verbose: Bool = false + + /// Build the target before attempting to extract from it. + /// This avoids trying to extract from broken sources. + /// + /// You may disable this if confident that input targets sources are correct and there's no need to kick off a pre-build for some reason. + var buildInputs: Bool = true + + /// Build the target once swift-java sources have been generated. + /// This helps verify that the generated output is correct, and won't miscompile on the next build. + var buildOutputs: Bool = true + + func createBuildCommands(context: PluginContext, target: any Target) async throws -> [Command] { + // FIXME: This is not a build plugin but SwiftPM forces us to impleme the protocol anyway? rdar://139556637 + return [] + } + + func performCommand(context: PluginContext, arguments: [String]) throws { + // Plugin can't have dependencies, so we have some naive argument parsing instead: + self.verbose = arguments.contains("-v") || arguments.contains("--verbose") + + let selectedTargets: [String] = + if let last = arguments.lastIndex(where: { $0.starts(with: "-")}), + last < arguments.endIndex { + Array(arguments[.. [String] { + guard let sourceModule = target.sourceModule else { return [] } + + // Note: Target doesn't have a directoryURL counterpart to directory, + // so we cannot eliminate this deprecation warning. + let sourceDir = target.directory.string + + let configuration = try readConfiguration(sourceDir: "\(sourceDir)") + + // We use the the usual maven-style structure of "src/[generated|main|test]/java/..." + // that is common in JVM ecosystem + let outputDirectoryJava = context.pluginWorkDirectoryURL + .appending(path: "src") + .appending(path: "generated") + .appending(path: "java") + let outputDirectorySwift = context.pluginWorkDirectoryURL + .appending(path: "Sources") + + var arguments: [String] = [ + "--swift-module", sourceModule.name, + "--package-name", configuration.javaPackage, + "--output-directory-java", outputDirectoryJava.path(percentEncoded: false), + "--output-directory-swift", outputDirectorySwift.path(percentEncoded: false), + // TODO: "--build-cache-directory", ... + // Since plugins cannot depend on libraries we cannot detect what the output files will be, + // as it depends on the contents of the input files. Therefore we have to implement this as a prebuild plugin. + // We'll have to make up some caching inside the tool so we don't re-parse files which have not changed etc. + ] + arguments.append(sourceDir) + + return arguments + } + + /// Perform the command on a specific target. + func performCommand(context: PluginContext, target: Target, extraArguments _: [String]) throws { + // Make sure the target can builds properly + try self.packageManager.build(.target(target.name), parameters: .init()) + + guard let sourceModule = target.sourceModule else { return } + + if self.buildInputs { + log("Pre-building target '\(target.name)' before extracting sources...") + try self.packageManager.build(.target(target.name), parameters: .init()) + } + + let arguments = try prepareJExtractArguments(context: context, target: target) + + try runExtract(context: context, target: target, arguments: arguments) + + if self.buildOutputs { + // Building the *products* since we need to build the dylib that contains our newly generated sources, + // so just building the target again would not be enough. We build all products which we affected using + // our source generation, which usually would be just a product dylib with our library. + // + // In practice, we'll always want to build after generating; either here, + // or via some other task before we run any Java code, calling into Swift. + log("Post-extract building products with target '\(target.name)'...") + for product in context.package.products where product.targets.contains(where: { $0.id == target.id }) { + log("Post-extract building product '\(product.name)'...") + try self.packageManager.build(.product(product.name), parameters: .init()) + } + } + } + + func runExtract(context: PluginContext, target: Target, arguments: [String]) throws { + let process = Process() + process.executableURL = try context.tool(named: "JExtractSwiftTool").url + process.arguments = arguments + + do { + log("Execute: \(process.executableURL!.absoluteURL.relativePath) \(arguments.joined(separator: " "))") + + try process.run() + process.waitUntilExit() + + assert(process.terminationStatus == 0, "Process failed with exit code: \(process.terminationStatus)") + } catch { + print("[swift-java-command] Failed to extract Java sources for target: '\(target.name); Error: \(error)") + } + } + + func log(_ message: @autoclosure () -> String, terminator: String = "\n") { + if self.verbose { + print("[swift-java-command] \(message())", terminator: terminator) + } + } +} + +// Mini coloring helper, since we cannot have dependencies we keep it minimal here +extension String { + var green: String { + "\u{001B}[0;32m" + "\(self)" + "\u{001B}[0;0m" + } +} \ No newline at end of file diff --git a/Plugins/JExtractSwiftCommandPlugin/PluginsShared/Configuration.swift b/Plugins/JExtractSwiftCommandPlugin/PluginsShared/Configuration.swift new file mode 100644 index 00000000..f917290c --- /dev/null +++ b/Plugins/JExtractSwiftCommandPlugin/PluginsShared/Configuration.swift @@ -0,0 +1,36 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import Foundation + +/// Configuration for the JExtractSwift translation tool, provided on a per-target +/// basis. +struct Configuration: Codable { + var javaPackage: String +} + +func readConfiguration(sourceDir: String) throws -> Configuration { + let configFile = URL(filePath: sourceDir).appending(path: "swift-java.config") + do { + let configData = try Data(contentsOf: configFile) + return try JSONDecoder().decode(Configuration.self, from: configData) + } catch { + throw ConfigurationError(message: "Failed to parse JExtractSwift configuration at '\(configFile)!'", error: error) + } +} + +struct ConfigurationError: Error { + let message: String + let error: any Error +} diff --git a/Plugins/JExtractSwiftCommandPlugin/PluginsShared/PluginUtils.swift b/Plugins/JExtractSwiftCommandPlugin/PluginsShared/PluginUtils.swift new file mode 100644 index 00000000..320dfc19 --- /dev/null +++ b/Plugins/JExtractSwiftCommandPlugin/PluginsShared/PluginUtils.swift @@ -0,0 +1,48 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import Foundation +import PackagePlugin + +// Note: the JAVA_HOME environment variable must be set to point to where +// Java is installed, e.g., +// Library/Java/JavaVirtualMachines/openjdk-21.jdk/Contents/Home. +func findJavaHome() -> String { + if let home = ProcessInfo.processInfo.environment["JAVA_HOME"] { + return home + } + + // This is a workaround for envs (some IDEs) which have trouble with + // picking up env variables during the build process + let path = "\(FileManager.default.homeDirectoryForCurrentUser.path()).java_home" + if let home = try? String(contentsOfFile: path, encoding: .utf8) { + if let lastChar = home.last, lastChar.isNewline { + return String(home.dropLast()) + } + + return home + } + + fatalError("Please set the JAVA_HOME environment variable to point to where Java is installed.") +} + +func getSwiftJavaConfig(target: Target) -> String? { + let configPath = URL(fileURLWithPath: target.directory.string).appending(component: "swift-java.config").path() + + if FileManager.default.fileExists(atPath: configPath) { + return configPath + } else { + return nil + } +} diff --git a/Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift b/Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift new file mode 100644 index 00000000..f23a1dbf --- /dev/null +++ b/Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift @@ -0,0 +1,63 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import Foundation +import PackagePlugin + +@main +struct JExtractSwiftBuildToolPlugin: BuildToolPlugin { + func createBuildCommands(context: PluginContext, target: Target) throws -> [Command] { + guard let sourceModule = target.sourceModule else { return [] } + + // Note: Target doesn't have a directoryURL counterpart to directory, + // so we cannot eliminate this deprecation warning. + let sourceDir = target.directory.string + + let toolURL = try context.tool(named: "JExtractSwiftTool").url + let configuration = try readConfiguration(sourceDir: "\(sourceDir)") + + // We use the the usual maven-style structure of "src/[generated|main|test]/java/..." + // that is common in JVM ecosystem + let outputDirectoryJava = context.pluginWorkDirectoryURL + .appending(path: "src") + .appending(path: "generated") + .appending(path: "java") + let outputDirectorySwift = context.pluginWorkDirectoryURL + .appending(path: "Sources") + + var arguments: [String] = [ + "--swift-module", sourceModule.name, + "--package-name", configuration.javaPackage, + "--output-directory-java", outputDirectoryJava.path(percentEncoded: false), + "--output-directory-swift", outputDirectorySwift.path(percentEncoded: false), + // TODO: "--build-cache-directory", ... + // Since plugins cannot depend on libraries we cannot detect what the output files will be, + // as it depends on the contents of the input files. Therefore we have to implement this as a prebuild plugin. + // We'll have to make up some caching inside the tool so we don't re-parse files which have not changed etc. + ] + arguments.append(sourceDir) + + return [ + .prebuildCommand( + displayName: "Generate Java wrappers for Swift types", + executable: toolURL, + arguments: arguments, + // inputFiles: [ configFile ] + swiftFiles, + // outputFiles: outputJavaFiles + outputFilesDirectory: outputDirectorySwift + ) + ] + } +} + diff --git a/Plugins/JExtractSwiftPlugin/PluginsShared/Configuration.swift b/Plugins/JExtractSwiftPlugin/PluginsShared/Configuration.swift new file mode 100644 index 00000000..f917290c --- /dev/null +++ b/Plugins/JExtractSwiftPlugin/PluginsShared/Configuration.swift @@ -0,0 +1,36 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import Foundation + +/// Configuration for the JExtractSwift translation tool, provided on a per-target +/// basis. +struct Configuration: Codable { + var javaPackage: String +} + +func readConfiguration(sourceDir: String) throws -> Configuration { + let configFile = URL(filePath: sourceDir).appending(path: "swift-java.config") + do { + let configData = try Data(contentsOf: configFile) + return try JSONDecoder().decode(Configuration.self, from: configData) + } catch { + throw ConfigurationError(message: "Failed to parse JExtractSwift configuration at '\(configFile)!'", error: error) + } +} + +struct ConfigurationError: Error { + let message: String + let error: any Error +} diff --git a/Plugins/JExtractSwiftPlugin/PluginsShared/PluginUtils.swift b/Plugins/JExtractSwiftPlugin/PluginsShared/PluginUtils.swift new file mode 100644 index 00000000..6ec58147 --- /dev/null +++ b/Plugins/JExtractSwiftPlugin/PluginsShared/PluginUtils.swift @@ -0,0 +1,37 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import Foundation + +// Note: the JAVA_HOME environment variable must be set to point to where +// Java is installed, e.g., +// Library/Java/JavaVirtualMachines/openjdk-21.jdk/Contents/Home. +func findJavaHome() -> String { + if let home = ProcessInfo.processInfo.environment["JAVA_HOME"] { + return home + } + + // This is a workaround for envs (some IDEs) which have trouble with + // picking up env variables during the build process + let path = "\(FileManager.default.homeDirectoryForCurrentUser.path()).java_home" + if let home = try? String(contentsOfFile: path, encoding: .utf8) { + if let lastChar = home.last, lastChar.isNewline { + return String(home.dropLast()) + } + + return home + } + + fatalError("Please set the JAVA_HOME environment variable to point to where Java is installed.") +} diff --git a/Samples/JavaProbablyPrime/ci-validate.sh b/Samples/JavaProbablyPrime/ci-validate.sh new file mode 100755 index 00000000..948a390c --- /dev/null +++ b/Samples/JavaProbablyPrime/ci-validate.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +swift run JavaProbablyPrime 1337 \ No newline at end of file diff --git a/Samples/JavaSieve/Sources/JavaSieve/main.swift b/Samples/JavaSieve/Sources/JavaSieve/main.swift index c075a8a1..b06cc6bb 100644 --- a/Samples/JavaSieve/Sources/JavaSieve/main.swift +++ b/Samples/JavaSieve/Sources/JavaSieve/main.swift @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// import JavaKit +import JavaMath let jvm = try JavaVirtualMachine.shared(classPath: ["QuadraticSieve-1.0.jar"]) do { @@ -20,6 +21,8 @@ do { for prime in sieveClass.findPrimes(100)! { print("Found prime: \(prime.intValue())") } + + try JavaClass().HALF_UP } catch { print("Failure: \(error)") } diff --git a/Samples/JavaSieve/ci-validate.sh b/Samples/JavaSieve/ci-validate.sh new file mode 100755 index 00000000..3eebd3ca --- /dev/null +++ b/Samples/JavaSieve/ci-validate.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +echo "Not validated in CI..." diff --git a/Samples/SwiftKitSampleApp/Package.swift b/Samples/SwiftKitSampleApp/Package.swift new file mode 100644 index 00000000..f12ecfd6 --- /dev/null +++ b/Samples/SwiftKitSampleApp/Package.swift @@ -0,0 +1,77 @@ +// swift-tools-version: 6.0 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import CompilerPluginSupport +import PackageDescription + +import class Foundation.FileManager +import class Foundation.ProcessInfo + +// Note: the JAVA_HOME environment variable must be set to point to where +// Java is installed, e.g., +// Library/Java/JavaVirtualMachines/openjdk-21.jdk/Contents/Home. +func findJavaHome() -> String { + if let home = ProcessInfo.processInfo.environment["JAVA_HOME"] { + return home + } + + // This is a workaround for envs (some IDEs) which have trouble with + // picking up env variables during the build process + let path = "\(FileManager.default.homeDirectoryForCurrentUser.path()).java_home" + if let home = try? String(contentsOfFile: path, encoding: .utf8) { + if let lastChar = home.last, lastChar.isNewline { + return String(home.dropLast()) + } + + return home + } + + fatalError("Please set the JAVA_HOME environment variable to point to where Java is installed.") +} +let javaHome = findJavaHome() + +let javaIncludePath = "\(javaHome)/include" +#if os(Linux) + let javaPlatformIncludePath = "\(javaIncludePath)/linux" +#elseif os(macOS) + let javaPlatformIncludePath = "\(javaIncludePath)/darwin" +#else + // TODO: Handle windows as well + #error("Currently only macOS and Linux platforms are supported, this may change in the future.") +#endif + +let package = Package( + name: "SwiftKitSampleApp", + platforms: [ + .macOS(.v10_15) + ], + products: [ + .library( + name: "MySwiftLibrary", + type: .dynamic, + targets: ["MySwiftLibrary"] + ), + + ], + dependencies: [ + .package(name: "swift-java", path: "../../"), + ], + targets: [ + .target( + name: "MySwiftLibrary", + dependencies: [ + .product(name: "SwiftKitSwift", package: "swift-java"), + ], + exclude: [ + "swift-java.config", + ], + swiftSettings: [ + .swiftLanguageMode(.v5), + .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) + ], + plugins: [ + .plugin(name: "JExtractSwiftPlugin", package: "swift-java"), + ] + ), + ] +) diff --git a/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift b/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift new file mode 100644 index 00000000..84e4618f --- /dev/null +++ b/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift @@ -0,0 +1,101 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +// This is a "plain Swift" file containing various types of declarations, +// that is exported to Java by using the `jextract-swift` tool. +// +// No annotations are necessary on the Swift side to perform the export. + +#if os(Linux) +import Glibc +#else +import Darwin.C +#endif + +public func helloWorld() { + p("\(#function)") +} + +public func globalTakeInt(i: Int) { + p("i:\(i)") +} + +public func globalTakeIntInt(i: Int, j: Int) { + p("i:\(i), j:\(j)") +} + +public func globalCallMeRunnable(run: () -> ()) { + run() +} + +public class MySwiftClass { + + public var len: Int + public var cap: Int + + public init(len: Int, cap: Int) { + self.len = len + self.cap = cap + + p("\(MySwiftClass.self).len = \(self.len)") + p("\(MySwiftClass.self).cap = \(self.cap)") + let addr = unsafeBitCast(self, to: UInt64.self) + p("initializer done, self = 0x\(String(addr, radix: 16, uppercase: true))") + } + + deinit { + let addr = unsafeBitCast(self, to: UInt64.self) + p("Deinit, self = 0x\(String(addr, radix: 16, uppercase: true))") + } + + public var counter: Int32 = 0 + + public func voidMethod() { + p("") + } + + public func takeIntMethod(i: Int) { + p("i:\(i)") + } + + public func echoIntMethod(i: Int) -> Int { + p("i:\(i)") + return i + } + + public func makeIntMethod() -> Int { + p("make int -> 12") + return 12 + } + + public func makeRandomIntMethod() -> Int { + return Int.random(in: 1..<256) + } +} + +// ==== Internal helpers + +private func p(_ msg: String, file: String = #fileID, line: UInt = #line, function: String = #function) { + print("[swift][\(file):\(line)](\(function)) \(msg)") + fflush(stdout) +} + +#if os(Linux) +// FIXME: why do we need this workaround? +@_silgen_name("_objc_autoreleaseReturnValue") +public func _objc_autoreleaseReturnValue(a: Any) {} + +@_silgen_name("objc_autoreleaseReturnValue") +public func objc_autoreleaseReturnValue(a: Any) {} +#endif diff --git a/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/swift-java.config b/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/swift-java.config new file mode 100644 index 00000000..6e5bc2af --- /dev/null +++ b/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/swift-java.config @@ -0,0 +1,3 @@ +{ + "javaPackage": "com.example.swift" +} diff --git a/Samples/SwiftKitSampleApp/build.gradle b/Samples/SwiftKitSampleApp/build.gradle index 3b79bd72..ff9e1837 100644 --- a/Samples/SwiftKitSampleApp/build.gradle +++ b/Samples/SwiftKitSampleApp/build.gradle @@ -14,6 +14,8 @@ import org.swift.swiftkit.gradle.BuildUtils +import java.nio.file.* + plugins { id("build-logic.java-application-conventions") id("me.champeau.jmh") version "0.7.2" @@ -33,27 +35,86 @@ java { } +// This is for development, when we edit the Swift swift-java project, the outputs of the generated sources may change. +// Thus, we also need to watch and re-build the top level project. +def compileSwiftJExtractPlugin = tasks.register("compileSwiftJExtractPlugin", Exec) { + description = "Rebuild the swift-java root project" + + inputs.file(new File(rootDir, "Package.swift")) + inputs.dir(new File(rootDir, "Sources")) + outputs.dir(new File(rootDir, ".build")) + + workingDir = rootDir + commandLine "swift" + args("build", + "--product", "SwiftKitSwift", + "--product", "JExtractSwiftPlugin", + "--product", "JExtractSwiftCommandPlugin") +} + def jextract = tasks.register("jextract", Exec) { - description = "Extracts Java accessor sources using jextract" + description = "Builds swift sources, including swift-java source generation" + dependsOn compileSwiftJExtractPlugin - outputs.dir(layout.buildDirectory.dir("generated/sources/jextract/main")) - inputs.dir("$rootDir/Sources/ExampleSwiftLibrary") // monitored library + // only because we depend on "live developing" the plugin while using this project to test it + inputs.file(new File(rootDir, "Package.swift")) + inputs.dir(new File(rootDir, "Sources")) - // any changes in the source generator sources also mean the resulting output might change - inputs.dir("$rootDir/Sources/JExtractSwift") - inputs.dir("$rootDir/Sources/JExtractSwiftTool") + inputs.file(new File(projectDir, "Package.swift")) + inputs.dir(new File(projectDir, "Sources")) - workingDir = rootDir - commandLine "make" - args "jextract-generate" + // TODO: we can use package describe --type json to figure out which targets depend on JExtractSwiftPlugin and will produce outputs + // Avoid adding this directory, but create the expected one specifically for all targets + // which WILL produce sources because they have the plugin + outputs.dir(layout.buildDirectory.dir("../.build/plugins/outputs/${layout.projectDirectory.asFile.getName().toLowerCase()}")) + + File baseSwiftPluginOutputsDir = layout.buildDirectory.dir("../.build/plugins/outputs/").get().asFile + if (!baseSwiftPluginOutputsDir.exists()) { + baseSwiftPluginOutputsDir.mkdirs() + } + Files.walk(layout.buildDirectory.dir("../.build/plugins/outputs/").get().asFile.toPath()).each { + // Add any Java sources generated by the plugin to our sourceSet + if (it.endsWith("JExtractSwiftPlugin/src/generated/java")) { + outputs.dir(it) + } + } + + workingDir = layout.projectDirectory + commandLine "swift" + args("package", "jextract", "-v", "--log-level", "info") // TODO: pass log level from Gradle build } +// Add the java-swift generated Java sources sourceSets { main { java { srcDir(jextract) } } + test { + java { + srcDir(jextract) + } + } + jmh { + java { + srcDir(jextract) + } + } +} + +tasks.build { + dependsOn("jextract") +} + + +def cleanSwift = tasks.register("cleanSwift", Exec) { + workingDir = layout.projectDirectory + commandLine "swift" + args("package", "clean") +} +tasks.clean { + dependsOn("cleanSwift") } dependencies { @@ -70,17 +131,14 @@ tasks.named('test', Test) { application { mainClass = "com.example.swift.HelloJava2Swift" - // In order to silence: - // WARNING: A restricted method in java.lang.foreign.SymbolLookup has been called - // WARNING: java.lang.foreign.SymbolLookup::libraryLookup has been called by org.example.swift.JavaKitExample in an unnamed module - // WARNING: Use --enable-native-access=ALL-UNNAMED to avoid a warning for callers in this module - // WARNING: Restricted methods will be blocked in a future release unless native access is enabled - // FIXME: Find out the proper solution to this applicationDefaultJvmArgs = [ "--enable-native-access=ALL-UNNAMED", // Include the library paths where our dylibs are that we want to load and call - "-Djava.library.path=" + BuildUtils.javaLibraryPaths(rootDir).join(":"), + "-Djava.library.path=" + + (BuildUtils.javaLibraryPaths(rootDir) + + BuildUtils.javaLibraryPaths(project.projectDir)).join(":"), + // Enable tracing downcalls (to Swift) "-Djextract.trace.downcalls=true" @@ -89,6 +147,8 @@ application { jmh { jvmArgsAppend = [ - "-Djava.library.path=" + BuildUtils.javaLibraryPaths(rootDir).join(":"), + "-Djava.library.path=" + + (BuildUtils.javaLibraryPaths(rootDir) + + BuildUtils.javaLibraryPaths(project.projectDir)).join(":"), ] } diff --git a/Samples/SwiftKitSampleApp/gradlew b/Samples/SwiftKitSampleApp/gradlew new file mode 120000 index 00000000..343e0d2c --- /dev/null +++ b/Samples/SwiftKitSampleApp/gradlew @@ -0,0 +1 @@ +../../gradlew \ No newline at end of file diff --git a/Samples/SwiftKitSampleApp/gradlew.bat b/Samples/SwiftKitSampleApp/gradlew.bat new file mode 120000 index 00000000..cb5a9464 --- /dev/null +++ b/Samples/SwiftKitSampleApp/gradlew.bat @@ -0,0 +1 @@ +../../gradlew.bat \ No newline at end of file diff --git a/Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/JavaToSwiftBenchmark.java b/Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/JavaToSwiftBenchmark.java index 5ce9ee6b..614697a3 100644 --- a/Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/JavaToSwiftBenchmark.java +++ b/Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/JavaToSwiftBenchmark.java @@ -26,8 +26,9 @@ import org.openjdk.jmh.annotations.State; import org.openjdk.jmh.infra.Blackhole; -import com.example.swift.generated.MySwiftClass; +import com.example.swift.MySwiftClass; +@SuppressWarnings("unused") public class JavaToSwiftBenchmark { @State(Scope.Benchmark) diff --git a/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java b/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java index 51dd48b1..2a86e403 100644 --- a/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java +++ b/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java @@ -15,15 +15,16 @@ package com.example.swift; // Import swift-extract generated sources -import com.example.swift.generated.ExampleSwiftLibrary; -import com.example.swift.generated.MySwiftClass; + +import com.example.swift.MySwiftLibrary; +import com.example.swift.MySwiftClass; // Import javakit/swiftkit support libraries import org.swift.swiftkit.SwiftArena; import org.swift.swiftkit.SwiftKit; import org.swift.swiftkit.SwiftValueWitnessTable; -import java.lang.foreign.*; +import java.util.Arrays; public class HelloJava2Swift { @@ -31,23 +32,27 @@ public static void main(String[] args) { boolean traceDowncalls = Boolean.getBoolean("jextract.trace.downcalls"); System.out.println("Property: jextract.trace.downcalls = " + traceDowncalls); - System.out.printf("java.library.path = %s\n", System.getProperty("java.library.path")); + System.out.print("Property: java.library.path = " +SwiftKit.getJavaLibraryPath()); examples(); } static void examples() { - ExampleSwiftLibrary.helloWorld(); + MySwiftLibrary.helloWorld(); - ExampleSwiftLibrary.globalTakeInt(1337); + MySwiftLibrary.globalTakeInt(1337); - MySwiftClass obj = new MySwiftClass(2222, 7777); + // Example of using an arena; MyClass.deinit is run at end of scope + try (var arena = SwiftArena.ofConfined()) { + MySwiftClass obj = new MySwiftClass(arena, 2222, 7777); - SwiftKit.retain(obj.$memorySegment()); - System.out.println("[java] obj ref count = " + SwiftKit.retainCount(obj.$memorySegment())); + // just checking retains/releases work + SwiftKit.retain(obj.$memorySegment()); + SwiftKit.release(obj.$memorySegment()); - obj.voidMethod(); - obj.takeIntMethod(42); + obj.voidMethod(); + obj.takeIntMethod(42); + } System.out.println("DONE."); } diff --git a/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/generated/MySwiftClassTest.java b/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/MySwiftClassTest.java similarity index 56% rename from Samples/SwiftKitSampleApp/src/test/java/com/example/swift/generated/MySwiftClassTest.java rename to Samples/SwiftKitSampleApp/src/test/java/com/example/swift/MySwiftClassTest.java index 7495ff19..fa17ef1a 100644 --- a/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/generated/MySwiftClassTest.java +++ b/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/MySwiftClassTest.java @@ -12,33 +12,41 @@ // //===----------------------------------------------------------------------===// -package com.example.swift.generated; +package com.example.swift; -import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.condition.DisabledOnOs; -import org.junit.jupiter.api.condition.OS; +import org.swift.swiftkit.SwiftKit; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; +import java.io.File; +import java.util.stream.Stream; -public class MySwiftClassTest { +import static org.junit.jupiter.api.Assertions.*; - @BeforeAll - static void beforeAll() { - System.out.printf("java.library.path = %s\n", System.getProperty("java.library.path")); +public class MySwiftClassTest { - System.loadLibrary("swiftCore"); - System.loadLibrary("ExampleSwiftLibrary"); + void checkPaths(Throwable throwable) { + var paths = SwiftKit.getJavaLibraryPath().split(":"); + for (var path : paths) { + System.out.println("CHECKING PATH: " + path); + Stream.of(new File(path).listFiles()) + .filter(file -> !file.isDirectory()) + .forEach((file) -> { + System.out.println(" - " + file.getPath()); + }); + } - System.setProperty("jextract.trace.downcalls", "true"); + throw new RuntimeException(throwable); } @Test void test_MySwiftClass_voidMethod() { - MySwiftClass o = new MySwiftClass(12, 42); - o.voidMethod(); + try { + MySwiftClass o = new MySwiftClass(12, 42); + o.voidMethod(); + } catch (Throwable throwable) { + checkPaths(throwable); + } } @Test diff --git a/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/generated/GeneratedJavaKitExampleModuleTest.java b/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/MySwiftLibraryTest.java similarity index 59% rename from Samples/SwiftKitSampleApp/src/test/java/com/example/swift/generated/GeneratedJavaKitExampleModuleTest.java rename to Samples/SwiftKitSampleApp/src/test/java/com/example/swift/MySwiftLibraryTest.java index 9cceacf5..ffa90359 100644 --- a/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/generated/GeneratedJavaKitExampleModuleTest.java +++ b/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/MySwiftLibraryTest.java @@ -12,46 +12,42 @@ // //===----------------------------------------------------------------------===// -package com.example.swift.generated; +package com.example.swift; import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.condition.DisabledOnOs; -import org.junit.jupiter.api.condition.OS; import org.swift.swiftkit.SwiftKit; +import java.util.Arrays; import java.util.concurrent.CountDownLatch; +import java.util.stream.Collectors; import static org.junit.jupiter.api.Assertions.*; -public class GeneratedJavaKitExampleModuleTest { - - @BeforeAll - static void beforeAll() { - System.out.println("java.library.path = " + SwiftKit.getJavaLibraryPath()); - System.out.println("java.library.path = " + SwiftKit.getJextractTraceDowncalls()); - } +public class MySwiftLibraryTest { @Test void call_helloWorld() { - ExampleSwiftLibrary.helloWorld(); + MySwiftLibrary.helloWorld(); - assertNotNull(ExampleSwiftLibrary.helloWorld$address()); + assertNotNull(MySwiftLibrary.helloWorld$address()); } @Test void call_globalTakeInt() { - ExampleSwiftLibrary.globalTakeInt(12); + MySwiftLibrary.globalTakeInt(12); - assertNotNull(ExampleSwiftLibrary.globalTakeInt$address()); + assertNotNull(MySwiftLibrary.globalTakeInt$address()); } @Test + @Disabled("Upcalls not yet implemented in new scheme") @SuppressWarnings({"Convert2Lambda", "Convert2MethodRef"}) void call_globalCallMeRunnable() { CountDownLatch countDownLatch = new CountDownLatch(3); - ExampleSwiftLibrary.globalCallMeRunnable(new Runnable() { + MySwiftLibrary.globalCallMeRunnable(new Runnable() { @Override public void run() { countDownLatch.countDown(); @@ -59,10 +55,10 @@ public void run() { }); assertEquals(2, countDownLatch.getCount()); - ExampleSwiftLibrary.globalCallMeRunnable(() -> countDownLatch.countDown()); + MySwiftLibrary.globalCallMeRunnable(() -> countDownLatch.countDown()); assertEquals(1, countDownLatch.getCount()); - ExampleSwiftLibrary.globalCallMeRunnable(countDownLatch::countDown); + MySwiftLibrary.globalCallMeRunnable(countDownLatch::countDown); assertEquals(0, countDownLatch.getCount()); } diff --git a/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/MySwiftClassTest.java b/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/MySwiftClassTest.java index 069a4e41..633d5f1c 100644 --- a/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/MySwiftClassTest.java +++ b/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/MySwiftClassTest.java @@ -15,19 +15,13 @@ package org.swift.swiftkit; import static org.junit.jupiter.api.Assertions.assertEquals; -import org.junit.jupiter.api.BeforeAll; + import org.junit.jupiter.api.Test; -import com.example.swift.generated.MySwiftClass; +import com.example.swift.MySwiftClass; public class MySwiftClassTest { - @BeforeAll - static void beforeAll() { - System.out.printf("java.library.path = %s\n", SwiftKit.getJavaLibraryPath()); - System.out.printf("jextract.trace.downcalls = %s\n", SwiftKit.getJextractTraceDowncalls()); - } - @Test void call_retain_retainCount_release() { var arena = SwiftArena.ofConfined(); diff --git a/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/SwiftArenaTest.java b/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/SwiftArenaTest.java index 4f4ab9df..ad514e1b 100644 --- a/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/SwiftArenaTest.java +++ b/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/SwiftArenaTest.java @@ -14,24 +14,21 @@ package org.swift.swiftkit; -import com.example.swift.generated.MySwiftClass; +import com.example.swift.MySwiftClass; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.DisabledIf; import org.swift.swiftkit.util.PlatformUtils; +import java.util.Arrays; +import java.util.stream.Collectors; + import static org.junit.jupiter.api.Assertions.*; import static org.swift.swiftkit.SwiftKit.*; import static org.swift.swiftkit.SwiftKit.retainCount; public class SwiftArenaTest { - @BeforeAll - static void beforeAll() { - System.out.printf("java.library.path = %s\n", SwiftKit.getJavaLibraryPath()); - System.out.printf("jextract.trace.downcalls = %s\n", SwiftKit.getJextractTraceDowncalls()); - } - static boolean isAmd64() { return PlatformUtils.isAmd64(); } diff --git a/Sources/ExampleSwiftLibrary/MySwiftLibrary.swift b/Sources/ExampleSwiftLibrary/MySwiftLibrary.swift index 36e09b14..8376d9b6 100644 --- a/Sources/ExampleSwiftLibrary/MySwiftLibrary.swift +++ b/Sources/ExampleSwiftLibrary/MySwiftLibrary.swift @@ -101,3 +101,12 @@ private func p(_ msg: String, file: String = #fileID, line: UInt = #line, functi print("[swift][\(file):\(line)](\(function)) \(msg)") fflush(stdout) } + +#if os(Linux) +// FIXME: why do we need this workaround? +@_silgen_name("_objc_autoreleaseReturnValue") +public func _objc_autoreleaseReturnValue(a: Any) {} + +@_silgen_name("objc_autoreleaseReturnValue") +public func objc_autoreleaseReturnValue(a: Any) {} +#endif diff --git a/Sources/JExtractSwift/CodePrinter.swift b/Sources/JExtractSwift/CodePrinter.swift index 308db69e..6e26b960 100644 --- a/Sources/JExtractSwift/CodePrinter.swift +++ b/Sources/JExtractSwift/CodePrinter.swift @@ -34,14 +34,19 @@ public struct CodePrinter { } public var indentationText: String = "" - public static func toString(_ block: (inout CodePrinter) -> ()) -> String { + public static func toString(_ block: (inout CodePrinter) throws -> ()) rethrows -> String { var printer = CodePrinter() - block(&printer) + try block(&printer) return printer.finalize() } - public init() { - + var mode: PrintMode + public enum PrintMode { + case accumulateAll + case flushToFileOnWrite + } + public init(mode: PrintMode = .flushToFileOnWrite) { + self.mode = mode } internal mutating func append(_ text: String) { @@ -91,6 +96,16 @@ public struct CodePrinter { } } + /// Print a plain newline, e.g. to separate declarations. + public mutating func println( + _ terminator: PrinterTerminator = .newLine, + function: String = #function, + file: String = #fileID, + line: UInt = #line + ) { + print("") + } + public mutating func print( _ text: Any, _ terminator: PrinterTerminator = .newLine, @@ -159,6 +174,12 @@ public struct CodePrinter { public var isEmpty: Bool { self.contents.isEmpty } + + public mutating func dump(file: String = #fileID, line: UInt = #line) { + Swift.print("// CodePrinter.dump @ \(file):\(line)") + Swift.print(contents) + } + } public enum PrinterTerminator: String { @@ -185,3 +206,49 @@ public enum PrinterTerminator: String { } } } + +extension CodePrinter { + + /// - Returns: the output path of the generated file, if any (i.e. not in accumulate in memory mode) + package mutating func writeContents( + outputDirectory: String, + javaPackagePath: String?, + filename: String + ) throws -> URL? { + guard self.mode != .accumulateAll else { + // if we're accumulating everything, we don't want to finalize/flush any contents + // let's mark that this is where a write would have happened though: + print("// ^^^^ Contents of: \(outputDirectory)/\(filename)") + return nil + } + + let contents = finalize() + if outputDirectory == "-" { + print( + "// ==== ---------------------------------------------------------------------------------------------------" + ) + if let javaPackagePath { + print("// \(javaPackagePath)/\(filename)") + } else { + print("// \(filename)") + } + print(contents) + return nil + } + + let targetDirectory = [outputDirectory, javaPackagePath].compactMap { $0 }.joined(separator: PATH_SEPARATOR) + log.trace("Prepare target directory: \(targetDirectory)") + try FileManager.default.createDirectory( + atPath: targetDirectory, withIntermediateDirectories: true) + + let outputPath = Foundation.URL(fileURLWithPath: targetDirectory).appendingPathComponent(filename) + try contents.write( + to: outputPath, + atomically: true, + encoding: .utf8 + ) + + return outputPath + } + +} diff --git a/Sources/JExtractSwift/Convenience/Collection+Extensions.swift b/Sources/JExtractSwift/Convenience/Collection+Extensions.swift index 5df901d2..fcb817d7 100644 --- a/Sources/JExtractSwift/Convenience/Collection+Extensions.swift +++ b/Sources/JExtractSwift/Convenience/Collection+Extensions.swift @@ -39,3 +39,13 @@ extension Collection { } } } + +extension Collection where Element == Int { + var sum: Int { + var s = 0 + for i in self { + s += i + } + return s + } +} \ No newline at end of file diff --git a/Sources/JExtractSwift/ImportedDecls.swift b/Sources/JExtractSwift/ImportedDecls.swift index 56c3bd6b..cbff9969 100644 --- a/Sources/JExtractSwift/ImportedDecls.swift +++ b/Sources/JExtractSwift/ImportedDecls.swift @@ -28,17 +28,15 @@ public typealias JavaPackage = String public struct ImportedNominalType: ImportedDecl { public let swiftTypeName: String public let javaType: JavaType - public var swiftMangledName: String? public var kind: NominalTypeKind public var initializers: [ImportedFunc] = [] public var methods: [ImportedFunc] = [] public var variables: [ImportedVariable] = [] - public init(swiftTypeName: String, javaType: JavaType, swiftMangledName: String? = nil, kind: NominalTypeKind) { + public init(swiftTypeName: String, javaType: JavaType, kind: NominalTypeKind) { self.swiftTypeName = swiftTypeName self.javaType = javaType - self.swiftMangledName = swiftMangledName self.kind = kind } @@ -55,7 +53,7 @@ public struct ImportedNominalType: ImportedDecl { /// The Java class name without the package. public var javaClassName: String { switch javaType { - case .class(package: _, name: let name): name + case .class(package: _, let name): name default: javaType.description } } @@ -69,10 +67,10 @@ public enum NominalTypeKind { } public struct ImportedParam { - let param: FunctionParameterSyntax + let syntax: FunctionParameterSyntax var firstName: String? { - let text = param.firstName.trimmed.text + let text = syntax.firstName.trimmed.text guard text != "_" else { return nil } @@ -81,7 +79,7 @@ public struct ImportedParam { } var secondName: String? { - let text = param.secondName?.trimmed.text + let text = syntax.secondName?.trimmed.text guard text != "_" else { return nil } @@ -95,7 +93,7 @@ public struct ImportedParam { // The Swift type as-is from the swift interface var swiftType: String { - param.type.trimmed.description + syntax.type.trimmed.description } // The mapped-to Java type of the above Java type, collections and optionals may be replaced with Java ones etc. @@ -116,22 +114,33 @@ extension ImportedParam { } // TODO: this is used in different contexts and needs a cleanup +// Perhaps this is "which parameter passing style"? public enum SelfParameterVariant { + // ==== Java forwarding patterns + /// Make a method that accepts the raw memory pointer as a MemorySegment case memorySegment /// Make a method that accepts the the Java wrapper class of the type case wrapper /// Raw SWIFT_POINTER case pointer + + // ==== Swift forwarding patterns + + case swiftThunkSelf } public struct ImportedFunc: ImportedDecl, CustomStringConvertible { + + /// Swift module name (e.g. the target name where a type or function was declared) + public var module: String + /// If this function/method is member of a class/struct/protocol, /// this will contain that declaration's imported name. /// /// This is necessary when rendering accessor Java code we need the type that "self" is expecting to have. - public var parentName: TranslatedType? - public var hasParent: Bool { parentName != nil } + public var parent: TranslatedType? + public var hasParent: Bool { parent != nil } /// This is a full name such as init(cap:name:). public var identifier: String @@ -148,8 +157,8 @@ public struct ImportedFunc: ImportedDecl, CustomStringConvertible { /// A display name to use to refer to the Swift declaration with its /// enclosing type, if there is one. public var displayName: String { - if let parentName { - return "\(parentName.swiftTypeName).\(identifier)" + if let parent { + return "\(parent.swiftTypeName).\(identifier)" } return identifier @@ -158,36 +167,33 @@ public struct ImportedFunc: ImportedDecl, CustomStringConvertible { public var returnType: TranslatedType public var parameters: [ImportedParam] - public func effectiveParameters(selfVariant: SelfParameterVariant?) -> [ImportedParam] { - if let parentName { + public func effectiveParameters(paramPassingStyle: SelfParameterVariant?) -> [ImportedParam] { + if let parent { var params = parameters // Add `self: Self` for method calls on a member // // allocating initializer takes a Self.Type instead, but it's also a pointer - switch selfVariant { + switch paramPassingStyle { case nil, .wrapper: break case .pointer: let selfParam: FunctionParameterSyntax = "self$: $swift_pointer" params.append( - ImportedParam( - param: selfParam, - type: parentName - ) + ImportedParam(syntax: selfParam, type: parent) ) case .memorySegment: let selfParam: FunctionParameterSyntax = "self$: $java_lang_foreign_MemorySegment" - var parentForSelf = parentName + var parentForSelf = parent parentForSelf.javaType = .javaForeignMemorySegment params.append( - ImportedParam( - param: selfParam, - type: parentForSelf - ) + ImportedParam(syntax: selfParam, type: parentForSelf) ) + + case .swiftThunkSelf: + break } // TODO: add any metadata for generics and other things we may need to add here @@ -198,19 +204,25 @@ public struct ImportedFunc: ImportedDecl, CustomStringConvertible { } } - public var swiftMangledName: String = "" + public var swiftDecl: any DeclSyntaxProtocol - public var syntax: String? = nil + public var syntax: String? { + "\(self.swiftDecl)" + } public var isInit: Bool = false public init( - parentName: TranslatedType?, + module: String, + decl: any DeclSyntaxProtocol, + parent: TranslatedType?, identifier: String, returnType: TranslatedType, parameters: [ImportedParam] ) { - self.parentName = parentName + self.swiftDecl = decl + self.module = module + self.parent = parent self.identifier = identifier self.returnType = returnType self.parameters = parameters @@ -219,7 +231,6 @@ public struct ImportedFunc: ImportedDecl, CustomStringConvertible { public var description: String { """ ImportedFunc { - mangledName: \(swiftMangledName) identifier: \(identifier) returnType: \(returnType) parameters: \(parameters) @@ -232,12 +243,26 @@ public struct ImportedFunc: ImportedDecl, CustomStringConvertible { } } +extension ImportedFunc: Hashable { + public func hash(into hasher: inout Swift.Hasher) { + self.swiftDecl.id.hash(into: &hasher) + } + + public static func ==(lhs: ImportedFunc, rhs: ImportedFunc) -> Swift.Bool { + lhs.parent?.originalSwiftType.id == rhs.parent?.originalSwiftType.id && + lhs.swiftDecl.id == rhs.swiftDecl.id + } +} + public enum VariableAccessorKind { case get case set } public struct ImportedVariable: ImportedDecl, CustomStringConvertible { + + public var module: String + /// If this function/method is member of a class/struct/protocol, /// this will contain that declaration's imported name. /// @@ -249,7 +274,7 @@ public struct ImportedVariable: ImportedDecl, CustomStringConvertible { public var identifier: String /// Which accessors are we able to expose. - /// + /// /// Usually this will be all the accessors the variable declares, /// however if the getter is async or throwing we may not be able to import it /// (yet), and therefore would skip it from the supported set. @@ -284,51 +309,54 @@ public struct ImportedVariable: ImportedDecl, CustomStringConvertible { switch kind { case .set: - let newValueParam: FunctionParameterSyntax = "_ newValue: \(self.returnType.cCompatibleSwiftType)" - var funcDecl = ImportedFunc( - parentName: self.parentName, + let newValueParam: FunctionParameterSyntax = + "_ newValue: \(self.returnType.cCompatibleSwiftType)" + let funcDecl = ImportedFunc( + module: self.module, + decl: self.syntax!, + parent: self.parentName, identifier: self.identifier, returnType: TranslatedType.void, - parameters: [.init(param: newValueParam, type: self.returnType)]) - funcDecl.swiftMangledName = self.swiftMangledName + "s" // form mangled name of the getter by adding the suffix + parameters: [.init(syntax: newValueParam, type: self.returnType)]) return funcDecl case .get: - var funcDecl = ImportedFunc( - parentName: self.parentName, + let funcDecl = ImportedFunc( + module: self.module, + decl: self.syntax!, + parent: self.parentName, identifier: self.identifier, returnType: self.returnType, parameters: []) - funcDecl.swiftMangledName = self.swiftMangledName + "g" // form mangled name of the getter by adding the suffix return funcDecl } } - public func effectiveAccessorParameters(_ kind: VariableAccessorKind, selfVariant: SelfParameterVariant?) -> [ImportedParam] { + public func effectiveAccessorParameters( + _ kind: VariableAccessorKind, paramPassingStyle: SelfParameterVariant? + ) -> [ImportedParam] { var params: [ImportedParam] = [] if kind == .set { - let newValueParam: FunctionParameterSyntax = "_ newValue: \(raw: self.returnType.swiftTypeName)" + let newValueParam: FunctionParameterSyntax = + "_ newValue: \(raw: self.returnType.swiftTypeName)" params.append( ImportedParam( - param: newValueParam, + syntax: newValueParam, type: self.returnType) - ) + ) } if let parentName { // Add `self: Self` for method calls on a member // // allocating initializer takes a Self.Type instead, but it's also a pointer - switch selfVariant { - case nil, .wrapper: - break - + switch paramPassingStyle { case .pointer: let selfParam: FunctionParameterSyntax = "self$: $swift_pointer" params.append( ImportedParam( - param: selfParam, + syntax: selfParam, type: parentName ) ) @@ -339,10 +367,15 @@ public struct ImportedVariable: ImportedDecl, CustomStringConvertible { parentForSelf.javaType = .javaForeignMemorySegment params.append( ImportedParam( - param: selfParam, + syntax: selfParam, type: parentForSelf ) ) + + case nil, + .wrapper, + .swiftThunkSelf: + break } } @@ -354,10 +387,12 @@ public struct ImportedVariable: ImportedDecl, CustomStringConvertible { public var syntax: VariableDeclSyntax? = nil public init( + module: String, parentName: TranslatedType?, identifier: String, returnType: TranslatedType ) { + self.module = module self.parentName = parentName self.identifier = identifier self.returnType = returnType diff --git a/Sources/JExtractSwift/Logger.swift b/Sources/JExtractSwift/Logger.swift index 7309c3d7..9aceb201 100644 --- a/Sources/JExtractSwift/Logger.swift +++ b/Sources/JExtractSwift/Logger.swift @@ -88,21 +88,21 @@ public struct Logger { } let metadataString: String = - metadata.isEmpty ? "\(metadata)" : "" + metadata.isEmpty ? "" : "\(metadata)" print("[trace][\(file):\(line)](\(function)) \(message()) \(metadataString)") } } extension Logger { - public enum Level: Int, Hashable { - case trace = 0 - case debug = 1 - case info = 2 - case notice = 3 - case warning = 4 - case error = 5 - case critical = 6 + public enum Level: String, Hashable { + case trace = "trace" + case debug = "debug" + case info = "info" + case notice = "notice" + case warning = "warning" + case error = "error" + case critical = "critical" } } diff --git a/Sources/JExtractSwift/Swift2Java.swift b/Sources/JExtractSwift/Swift2Java.swift index e01143cc..2167c391 100644 --- a/Sources/JExtractSwift/Swift2Java.swift +++ b/Sources/JExtractSwift/Swift2Java.swift @@ -28,22 +28,27 @@ public struct SwiftToJava: ParsableCommand { @Option(help: "The package the generated Java code should be emitted into.") var packageName: String - @Option(name: .shortAndLong, help: "The directory in which to output the generated Swift files and manifest.") - var outputDirectory: String = ".build/jextract-swift/generated" + @Option( + name: .shortAndLong, + help: "The directory in which to output the generated Swift files and manifest.") + var outputDirectoryJava: String = ".build/jextract-swift/generated" - @Option(name: .long, help: "Name of the Swift module to import (and the swift interface files belong to)") + @Option(help: "Swift output directory") + var outputDirectorySwift: String + + @Option( + name: .long, + help: "Name of the Swift module to import (and the swift interface files belong to)") var swiftModule: String - // TODO: Once we ship this, make this `.warning` by default @Option(name: .shortAndLong, help: "Configure the level of lots that should be printed") - var logLevel: Logger.Level = .notice + var logLevel: Logger.Level = .info - @Argument(help: "The Swift interface files to export to Java.") - var swiftInterfaceFiles: [String] + @Argument(help: "The Swift files or directories to recursively export to Java.") + var input: [String] public func run() throws { - let interfaceFiles = self.swiftInterfaceFiles.dropFirst() - print("Interface files: \(interfaceFiles)") + let inputPaths = self.input.dropFirst().map { URL(string: $0)! } let translator = Swift2JavaTranslator( javaPackage: packageName, @@ -51,21 +56,41 @@ public struct SwiftToJava: ParsableCommand { ) translator.log.logLevel = logLevel - var fileNo = 1 - for interfaceFile in interfaceFiles { - print("[\(fileNo)/\(interfaceFiles.count)] Importing module '\(swiftModule)', interface file: \(interfaceFile)") - defer { fileNo += 1 } + var allFiles: [URL] = [] + let fileManager = FileManager.default + let log = translator.log + + for path in inputPaths { + log.debug("Input path: \(path)") + if isDirectory(url: path) { + if let enumerator = fileManager.enumerator(at: path, includingPropertiesForKeys: nil) { + for case let fileURL as URL in enumerator { + allFiles.append(fileURL) + } + } + } else if path.isFileURL { + allFiles.append(path) + } + } + + for file in allFiles where canExtract(from: file) { + translator.log.debug("Importing module '\(swiftModule)', file: \(file)") - try translator.analyze(swiftInterfacePath: interfaceFile) - try translator.writeImportedTypesTo(outputDirectory: outputDirectory) + try translator.analyze(file: file.path) + try translator.writeExportedJavaSources(outputDirectory: outputDirectoryJava) + try translator.writeSwiftThunkSources(outputDirectory: outputDirectorySwift) - print("[\(fileNo)/\(interfaceFiles.count)] Imported interface file: \(interfaceFile) " + "done.".green) + log.debug("[swift-java] Imported interface file: \(file.path)") } - try translator.writeModuleTo(outputDirectory: outputDirectory) - print("") - print("Generated Java sources in package '\(packageName)' in: \(outputDirectory)/") - print("Swift module '\(swiftModule)' import: " + "done.".green) + try translator.writeExportedJavaModule(outputDirectory: outputDirectoryJava) + print("[swift-java] Generated Java sources (\(packageName)) in: \(outputDirectoryJava)/") + print("[swift-java] Imported Swift module '\(swiftModule)': " + "done.".green) + } + + func canExtract(from file: URL) -> Bool { + file.lastPathComponent.hasSuffix(".swift") || + file.lastPathComponent.hasSuffix(".swiftinterface") } } @@ -79,3 +104,9 @@ extension Logger.Level: ExpressibleByArgument { public private(set) static var defaultCompletionKind: CompletionKind = .default } + +func isDirectory(url: URL) -> Bool { + var isDirectory: ObjCBool = false + _ = FileManager.default.fileExists(atPath: url.path, isDirectory: &isDirectory) + return isDirectory.boolValue +} diff --git a/Sources/JExtractSwift/Swift2JavaTranslator+MemoryLayouts.swift b/Sources/JExtractSwift/Swift2JavaTranslator+MemoryLayouts.swift index 4e8f6aa7..21d6946b 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator+MemoryLayouts.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator+MemoryLayouts.swift @@ -20,16 +20,20 @@ import SwiftSyntax extension Swift2JavaTranslator { public func javaMemoryLayoutDescriptors( forParametersOf decl: ImportedFunc, - selfVariant: SelfParameterVariant? + paramPassingStyle: SelfParameterVariant? ) -> [ForeignValueLayout] { var layouts: [ForeignValueLayout] = [] layouts.reserveCapacity(decl.parameters.count + 1) // // When the method is `init()` it does not accept a self (well, unless allocating init but we don't import those) - // let selfVariant: SelfParameterVariant? = + // let paramPassingStyle: SelfParameterVariant? = // decl.isInit ? nil : .wrapper - for param in decl.effectiveParameters(selfVariant: selfVariant) { + for param in decl.effectiveParameters(paramPassingStyle: paramPassingStyle) { + if param.type.cCompatibleJavaMemoryLayout == CCompatibleJavaMemoryLayout.primitive(.void) { + continue + } + layouts.append(param.type.foreignValueLayout) } diff --git a/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift b/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift index c8b9bf09..cb9fd7ed 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift @@ -25,64 +25,125 @@ let PATH_SEPARATOR = "/" // TODO: Windows extension Swift2JavaTranslator { /// Every imported public type becomes a public class in its own file in Java. - public func writeImportedTypesTo(outputDirectory: String) throws { + public func writeExportedJavaSources(outputDirectory: String) throws { var printer = CodePrinter() + try writeExportedJavaSources(outputDirectory: outputDirectory, printer: &printer) + } + public func writeExportedJavaSources(outputDirectory: String, printer: inout CodePrinter) throws { for (_, ty) in importedTypes.sorted(by: { (lhs, rhs) in lhs.key < rhs.key }) { let filename = "\(ty.javaClassName).java" log.info("Printing contents: \(filename)") printImportedClass(&printer, ty) - try writeContents( - printer.finalize(), + if let outputFile = try printer.writeContents( outputDirectory: outputDirectory, javaPackagePath: javaPackagePath, filename: filename - ) + ) { + print("[swift-java] Generated: \(ty.javaClassName.bold).java (at \(outputFile))") + } + } + } + + public func writeSwiftThunkSources(outputDirectory: String) throws { + var printer = CodePrinter() + + try writeSwiftThunkSources(outputDirectory: outputDirectory, printer: &printer) + } + + public func writeSwiftThunkSources(outputDirectory: String, printer: inout CodePrinter) throws { + let moduleFilenameBase = "\(self.swiftModuleName)Module+SwiftJava" + let moduleFilename = "\(moduleFilenameBase).swift" + do { + log.info("Printing contents: \(moduleFilename)") + + try printGlobalSwiftThunkSources(&printer) + + if let outputFile = try printer.writeContents( + outputDirectory: outputDirectory, + javaPackagePath: nil, + filename: moduleFilename) { + print("[swift-java] Generated: \(moduleFilenameBase.bold).swift (at \(outputFile)") + } + } catch { + log.warning("Failed to write to Swift thunks: \(moduleFilename)") + } + + // === All types + for (_, ty) in importedTypes.sorted(by: { (lhs, rhs) in lhs.key < rhs.key }) { + let fileNameBase = "\(ty.swiftTypeName)+SwiftJava" + let filename = "\(fileNameBase).swift" + log.info("Printing contents: \(filename)") + + do { + try printSwiftThunkSources(&printer, ty: ty) + + if let outputFile = try printer.writeContents( + outputDirectory: outputDirectory, + javaPackagePath: nil, + filename: filename) { + print("[swift-java] Generated: \(fileNameBase.bold).swift (at \(outputFile)") + } + } catch { + log.warning("Failed to write to Swift thunks: \(filename)") + } + } + } + + public func printGlobalSwiftThunkSources(_ printer: inout CodePrinter) throws { + let stt = SwiftThunkTranslator(self) + + for thunk in stt.renderGlobalThunks() { + printer.print(thunk) + printer.println() + } + } + + public func printSwiftThunkSources(_ printer: inout CodePrinter, decl: ImportedFunc) { + let stt = SwiftThunkTranslator(self) + + for thunk in stt.render(forFunc: decl) { + printer.print(thunk) + printer.println() + } + } + + public func printSwiftThunkSources(_ printer: inout CodePrinter, ty: ImportedNominalType) throws { + let stt = SwiftThunkTranslator(self) + + printer.print( + """ + // Generated by swift-java + + import SwiftKitSwift + + """ + ) + + for thunk in stt.renderThunks(forType: ty) { + printer.print("\(thunk)") + printer.print("") } } /// A module contains all static and global functions from the Swift module, /// potentially from across multiple swift interfaces. - public func writeModuleTo(outputDirectory: String) throws { + public func writeExportedJavaModule(outputDirectory: String) throws { var printer = CodePrinter() + try writeExportedJavaModule(outputDirectory: outputDirectory, printer: &printer) + } + + public func writeExportedJavaModule(outputDirectory: String, printer: inout CodePrinter) throws { printModule(&printer) - try writeContents( - printer.finalize(), + if let file = try printer.writeContents( outputDirectory: outputDirectory, javaPackagePath: javaPackagePath, filename: "\(swiftModuleName).java" - ) - } - - private func writeContents( - _ contents: String, - outputDirectory: String, - javaPackagePath: String, - filename: String - ) throws { - if outputDirectory == "-" { - print( - "// ==== ---------------------------------------------------------------------------------------------------" - ) - print("// \(javaPackagePath)/\(filename)") - print(contents) - return + ) { + self.log.info("Generated: \(file): \("done".green).") } - - let targetDirectory = [outputDirectory, javaPackagePath].joined(separator: PATH_SEPARATOR) - log.trace("Prepare target directory: \(targetDirectory)") - try FileManager.default.createDirectory(atPath: targetDirectory, withIntermediateDirectories: true) - - let targetFilePath = [javaPackagePath, filename].joined(separator: PATH_SEPARATOR) - print("Writing '\(targetFilePath)'...", terminator: "") - try contents.write( - to: Foundation.URL(fileURLWithPath: targetDirectory).appendingPathComponent(filename), - atomically: true, - encoding: .utf8 - ) - print(" done.".green) } } @@ -100,9 +161,6 @@ extension Swift2JavaTranslator { printImports(&printer) printModuleClass(&printer) { printer in - - printStaticLibraryLoad(&printer) - // TODO: print all "static" methods for decl in importedGlobalFuncs { printFunctionDowncallMethods(&printer, decl) @@ -116,14 +174,30 @@ extension Swift2JavaTranslator { printImports(&printer) printClass(&printer, decl) { printer in - // Ensure we have loaded the library where the Swift type was declared before we attempt to resolve types in Swift - printStaticLibraryLoad(&printer) - - // Prepare type metadata, we're going to need these when invoking e.g. initializers so cache them in a static - printer.print( + // Prepare type metadata, we're going to need these when invoking e.g. initializers so cache them in a static. + // We call into source swift-java source generated accessors which give us the type of the Swift object: + // TODO: seems we no longer need the mangled name per se, so avoiding such constant and downcall + // printer.printParts( + // "public static final String TYPE_MANGLED_NAME = ", + // SwiftKitPrinting.renderCallGetSwiftTypeMangledName(module: self.swiftModuleName, nominal: decl), + // ";" + // ) + + // We use a static field to abuse the initialization order such that by the time we get type metadata, + // we already have loaded the library where it will be obtained from. + printer.printParts( """ - public static final String TYPE_MANGLED_NAME = "\(decl.swiftMangledName ?? "")"; - public static final SwiftAnyType TYPE_METADATA = SwiftKit.getTypeByMangledNameInEnvironment(TYPE_MANGLED_NAME).get(); + @SuppressWarnings("unused") + private static final boolean INITIALIZED_LIBS = initializeLibs(); + static boolean initializeLibs() { + System.loadLibrary(SwiftKit.STDLIB_DYLIB_NAME); + System.loadLibrary("SwiftKitSwift"); + System.loadLibrary(LIB_NAME); + return true; + } + + public static final SwiftAnyType TYPE_METADATA = + new SwiftAnyType(\(SwiftKitPrinting.renderCallGetSwiftType(module: self.swiftModuleName, nominal: decl))); public final SwiftAnyType $swiftType() { return TYPE_METADATA; } @@ -178,8 +252,11 @@ extension Swift2JavaTranslator { printer.print("") } - public func printClass(_ printer: inout CodePrinter, _ decl: ImportedNominalType, body: (inout CodePrinter) -> Void) { - printer.printTypeDecl("public final class \(decl.javaClassName) implements SwiftHeapObject") { printer in + public func printClass( + _ printer: inout CodePrinter, _ decl: ImportedNominalType, body: (inout CodePrinter) -> Void + ) { + printer.printTypeDecl("public final class \(decl.javaClassName) implements SwiftHeapObject") { + printer in // ==== Storage of the class printClassSelfProperty(&printer, decl) @@ -190,9 +267,6 @@ extension Swift2JavaTranslator { // Layout of the class printClassMemoryLayout(&printer, decl) - // Render the 'trace' functions etc - printTraceFunctionDecls(&printer) - body(&printer) } } @@ -205,9 +279,6 @@ extension Swift2JavaTranslator { printClassConstants(printer: &printer) printTypeMappingDecls(&printer) - // Render the 'trace' functions etc - printTraceFunctionDecls(&printer) - printer.print( """ static MemorySegment findOrThrow(String symbol) { @@ -253,6 +324,11 @@ extension Swift2JavaTranslator { """ static final SymbolLookup SYMBOL_LOOKUP = getSymbolLookup(); private static SymbolLookup getSymbolLookup() { + // Ensure Swift and our Lib are loaded during static initialization of the class. + System.loadLibrary("swiftCore"); + System.loadLibrary("SwiftKitSwift"); + System.loadLibrary(LIB_NAME); + if (PlatformUtils.isMacOS()) { return SymbolLookup.libraryLookup(System.mapLibraryName(LIB_NAME), LIBRARY_ARENA) .or(SymbolLookup.loaderLookup()) @@ -284,6 +360,11 @@ extension Swift2JavaTranslator { private \(typeName)() { // Should not be called directly } + + // Static enum to force initialization + private static enum Initializer { + FORCE; // Refer to this to force outer Class initialization (and static{} blocks to trigger) + } """ ) } @@ -308,7 +389,7 @@ extension Swift2JavaTranslator { """ private static final GroupLayout $LAYOUT = MemoryLayout.structLayout( SWIFT_POINTER - ).withName("\(decl.swiftMangledName ?? decl.swiftTypeName)"); + ).withName("\(decl.swiftTypeName)"); public final GroupLayout $layout() { return $LAYOUT; @@ -356,42 +437,8 @@ extension Swift2JavaTranslator { ) } - public func printTraceFunctionDecls(_ printer: inout CodePrinter) { - printer.print( - """ - static final boolean TRACE_DOWNCALLS = Boolean.getBoolean("jextract.trace.downcalls"); - - static void traceDowncall(Object... args) { - var ex = new RuntimeException(); - - String traceArgs = Arrays.stream(args) - .map(Object::toString) - .collect(Collectors.joining(", ")); - System.out.printf("[java][%s:%d] Downcall: %s(%s)\\n", - ex.getStackTrace()[1].getFileName(), - ex.getStackTrace()[1].getLineNumber(), - ex.getStackTrace()[1].getMethodName(), - traceArgs); - } - - static void trace(Object... args) { - var ex = new RuntimeException(); - - String traceArgs = Arrays.stream(args) - .map(Object::toString) - .collect(Collectors.joining(", ")); - System.out.printf("[java][%s:%d] %s: %s\\n", - ex.getStackTrace()[1].getFileName(), - ex.getStackTrace()[1].getLineNumber(), - ex.getStackTrace()[1].getMethodName(), - traceArgs); - } - """ - ) - } - public func printClassConstructors(_ printer: inout CodePrinter, _ decl: ImportedFunc) { - guard let parentName = decl.parentName else { + guard let parentName = decl.parent else { fatalError("init must be inside a parent type! Was: \(decl)") } printer.printSeparator(decl.identifier) @@ -399,7 +446,7 @@ extension Swift2JavaTranslator { let descClassIdentifier = renderDescClassName(decl) printer.printTypeDecl("private static class \(descClassIdentifier)") { printer in printFunctionDescriptorValue(&printer, decl) - printFindMemorySegmentAddrByMangledName(&printer, decl) + printAccessorFunctionAddr(&printer, decl) printMethodDowncallHandleForAddrDesc(&printer) } @@ -420,8 +467,8 @@ extension Swift2JavaTranslator { * \(decl.renderCommentSnippet ?? " *") */ - public \(parentName.unqualifiedJavaTypeName)(\(renderJavaParamDecls(decl, selfVariant: .wrapper))) { - this(/*arena=*/null, \(renderForwardParams(decl, selfVariant: .wrapper))); + public \(parentName.unqualifiedJavaTypeName)(\(renderJavaParamDecls(decl, paramPassingStyle: .wrapper))) { + this(/*arena=*/null, \(renderForwardJavaParams(decl, paramPassingStyle: .wrapper))); } """ ) @@ -434,14 +481,14 @@ extension Swift2JavaTranslator { * \(decl.renderCommentSnippet ?? " *") */ - public \(parentName.unqualifiedJavaTypeName)(SwiftArena arena, \(renderJavaParamDecls(decl, selfVariant: .wrapper))) { + public \(parentName.unqualifiedJavaTypeName)(SwiftArena arena, \(renderJavaParamDecls(decl, paramPassingStyle: .wrapper))) { var mh$ = \(descClassIdentifier).HANDLE; try { - if (TRACE_DOWNCALLS) { - traceDowncall(\(renderForwardParams(decl, selfVariant: nil))); + if (SwiftKit.TRACE_DOWNCALLS) { + SwiftKit.traceDowncall(\(renderForwardJavaParams(decl, paramPassingStyle: nil))); } - this.selfMemorySegment = (MemorySegment) mh$.invokeExact(\(renderForwardParams(decl, selfVariant: nil)), TYPE_METADATA.$memorySegment()); + this.selfMemorySegment = (MemorySegment) mh$.invokeExact(\(renderForwardJavaParams(decl, paramPassingStyle: nil)), TYPE_METADATA.$memorySegment()); if (arena != null) { arena.register(this); } @@ -453,23 +500,12 @@ extension Swift2JavaTranslator { ) } - public func printStaticLibraryLoad(_ printer: inout CodePrinter) { - printer.print( - """ - static { - System.loadLibrary("swiftCore"); - System.loadLibrary(LIB_NAME); - } - """ - ) - } - public func printFunctionDowncallMethods(_ printer: inout CodePrinter, _ decl: ImportedFunc) { printer.printSeparator(decl.identifier) printer.printTypeDecl("private static class \(decl.baseIdentifier)") { printer in - printFunctionDescriptorValue(&printer, decl); - printFindMemorySegmentAddrByMangledName(&printer, decl) + printFunctionDescriptorValue(&printer, decl) + printAccessorFunctionAddr(&printer, decl) printMethodDowncallHandleForAddrDesc(&printer) } @@ -479,16 +515,18 @@ extension Swift2JavaTranslator { // Render the basic "make the downcall" function if decl.hasParent { - printFuncDowncallMethod(&printer, decl: decl, selfVariant: .memorySegment) - printFuncDowncallMethod(&printer, decl: decl, selfVariant: .wrapper) + printFuncDowncallMethod(&printer, decl: decl, paramPassingStyle: .memorySegment) + printFuncDowncallMethod(&printer, decl: decl, paramPassingStyle: .wrapper) } else { - printFuncDowncallMethod(&printer, decl: decl, selfVariant: nil) + printFuncDowncallMethod(&printer, decl: decl, paramPassingStyle: nil) } } - private func printFunctionAddressMethod(_ printer: inout CodePrinter, - decl: ImportedFunc, - accessorKind: VariableAccessorKind? = nil) { + private func printFunctionAddressMethod( + _ printer: inout CodePrinter, + decl: ImportedFunc, + accessorKind: VariableAccessorKind? = nil + ) { let addrName = accessorKind.renderAddrFieldName let methodNameSegment = accessorKind.renderMethodNameSegment @@ -507,9 +545,11 @@ extension Swift2JavaTranslator { ) } - private func printFunctionMethodHandleMethod(_ printer: inout CodePrinter, - decl: ImportedFunc, - accessorKind: VariableAccessorKind? = nil) { + private func printFunctionMethodHandleMethod( + _ printer: inout CodePrinter, + decl: ImportedFunc, + accessorKind: VariableAccessorKind? = nil + ) { let handleName = accessorKind.renderHandleFieldName let methodNameSegment = accessorKind.renderMethodNameSegment let snippet = decl.renderCommentSnippet ?? "* " @@ -527,9 +567,11 @@ extension Swift2JavaTranslator { ) } - private func printFunctionDescriptorMethod(_ printer: inout CodePrinter, - decl: ImportedFunc, - accessorKind: VariableAccessorKind? = nil) { + private func printFunctionDescriptorMethod( + _ printer: inout CodePrinter, + decl: ImportedFunc, + accessorKind: VariableAccessorKind? = nil + ) { let descName = accessorKind.renderDescFieldName let methodNameSegment = accessorKind.renderMethodNameSegment let snippet = decl.renderCommentSnippet ?? "* " @@ -557,8 +599,8 @@ extension Swift2JavaTranslator { continue } - printFunctionDescriptorValue(&printer, accessor, accessorKind: accessorKind); - printFindMemorySegmentAddrByMangledName(&printer, accessor, accessorKind: accessorKind) + printFunctionDescriptorValue(&printer, accessor, accessorKind: accessorKind) + printAccessorFunctionAddr(&printer, accessor, accessorKind: accessorKind) printMethodDowncallHandleForAddrDesc(&printer, accessorKind: accessorKind) } } @@ -583,24 +625,36 @@ extension Swift2JavaTranslator { // Render the basic "make the downcall" function if decl.hasParent { - printFuncDowncallMethod(&printer, decl: accessor, selfVariant: .memorySegment, accessorKind: accessorKind) - printFuncDowncallMethod(&printer, decl: accessor, selfVariant: .wrapper, accessorKind: accessorKind) + printFuncDowncallMethod( + &printer, decl: accessor, paramPassingStyle: .memorySegment, accessorKind: accessorKind) + printFuncDowncallMethod( + &printer, decl: accessor, paramPassingStyle: .wrapper, accessorKind: accessorKind) } else { - printFuncDowncallMethod(&printer, decl: accessor, selfVariant: nil, accessorKind: accessorKind) + printFuncDowncallMethod( + &printer, decl: accessor, paramPassingStyle: nil, accessorKind: accessorKind) } } } - func printFindMemorySegmentAddrByMangledName(_ printer: inout CodePrinter, _ decl: ImportedFunc, - accessorKind: VariableAccessorKind? = nil) { + func printAccessorFunctionAddr( + _ printer: inout CodePrinter, _ decl: ImportedFunc, + accessorKind: VariableAccessorKind? = nil + ) { +// var thunkName = SwiftKitPrinting.Names.functionThunk( +// thunkNameRegistry: &self.thunkNameRegistry, +// module: self.swiftModuleName, function: decl) + let thunkName = thunkNameRegistry.functionThunkName(module: self.swiftModuleName, decl: decl) printer.print( """ - public static final MemorySegment \(accessorKind.renderAddrFieldName) = \(swiftModuleName).findOrThrow("\(decl.swiftMangledName)"); + public static final MemorySegment \(accessorKind.renderAddrFieldName) = + \(self.swiftModuleName).findOrThrow("\(thunkName)"); """ - ); + ) } - func printMethodDowncallHandleForAddrDesc(_ printer: inout CodePrinter, accessorKind: VariableAccessorKind? = nil) { + func printMethodDowncallHandleForAddrDesc( + _ printer: inout CodePrinter, accessorKind: VariableAccessorKind? = nil + ) { printer.print( """ public static final MethodHandle \(accessorKind.renderHandleFieldName) = Linker.nativeLinker().downcallHandle(\(accessorKind.renderAddrFieldName), \(accessorKind.renderDescFieldName)); @@ -611,7 +665,7 @@ extension Swift2JavaTranslator { public func printFuncDowncallMethod( _ printer: inout CodePrinter, decl: ImportedFunc, - selfVariant: SelfParameterVariant?, + paramPassingStyle: SelfParameterVariant?, accessorKind: VariableAccessorKind? = nil ) { let returnTy = decl.returnType.javaType @@ -635,13 +689,13 @@ extension Swift2JavaTranslator { // An identifier may be "getX", "setX" or just the plain method name let identifier = accessorKind.renderMethodName(decl) - if selfVariant == SelfParameterVariant.wrapper { + if paramPassingStyle == SelfParameterVariant.wrapper { // delegate to the MemorySegment "self" accepting overload printer.print( """ \(javaDocComment) - public \(returnTy) \(identifier)(\(renderJavaParamDecls(decl, selfVariant: .wrapper))) { - \(maybeReturnCast) \(identifier)(\(renderForwardParams(decl, selfVariant: .wrapper))); + public \(returnTy) \(identifier)(\(renderJavaParamDecls(decl, paramPassingStyle: .wrapper))) { + \(maybeReturnCast) \(identifier)(\(renderForwardJavaParams(decl, paramPassingStyle: .wrapper))); } """ ) @@ -654,7 +708,7 @@ extension Swift2JavaTranslator { printer.printParts( """ \(javaDocComment) - public static \(returnTy) \(identifier)(\(renderJavaParamDecls(decl, selfVariant: selfVariant))) { + public static \(returnTy) \(identifier)(\(renderJavaParamDecls(decl, paramPassingStyle: paramPassingStyle))) { var mh$ = \(decl.baseIdentifier).\(handleName); \(renderTry(withArena: needsArena)) """, @@ -662,10 +716,10 @@ extension Swift2JavaTranslator { \(renderUpcallHandles(decl)) """, """ - if (TRACE_DOWNCALLS) { - traceDowncall(\(renderForwardParams(decl, selfVariant: .memorySegment))); + if (SwiftKit.TRACE_DOWNCALLS) { + SwiftKit.traceDowncall(\(renderForwardJavaParams(decl, paramPassingStyle: .memorySegment))); } - \(maybeReturnCast) mh$.invokeExact(\(renderForwardParams(decl, selfVariant: selfVariant))); + \(maybeReturnCast) mh$.invokeExact(\(renderForwardJavaParams(decl, paramPassingStyle: paramPassingStyle))); } catch (Throwable ex$) { throw new AssertionError("should not reach here", ex$); } @@ -677,7 +731,7 @@ extension Swift2JavaTranslator { public func printPropertyAccessorDowncallMethod( _ printer: inout CodePrinter, decl: ImportedFunc, - selfVariant: SelfParameterVariant? + paramPassingStyle: SelfParameterVariant? ) { let returnTy = decl.returnType.javaType @@ -688,7 +742,7 @@ extension Swift2JavaTranslator { maybeReturnCast = "return (\(returnTy))" } - if selfVariant == SelfParameterVariant.wrapper { + if paramPassingStyle == SelfParameterVariant.wrapper { // delegate to the MemorySegment "self" accepting overload printer.print( """ @@ -697,8 +751,8 @@ extension Swift2JavaTranslator { * \(/*TODO: make a printSnippet func*/decl.syntax ?? "") * } */ - public \(returnTy) \(decl.baseIdentifier)(\(renderJavaParamDecls(decl, selfVariant: .wrapper))) { - \(maybeReturnCast) \(decl.baseIdentifier)(\(renderForwardParams(decl, selfVariant: .wrapper))); + public \(returnTy) \(decl.baseIdentifier)(\(renderJavaParamDecls(decl, paramPassingStyle: .wrapper))) { + \(maybeReturnCast) \(decl.baseIdentifier)(\(renderForwardJavaParams(decl, paramPassingStyle: .wrapper))); } """ ) @@ -712,13 +766,13 @@ extension Swift2JavaTranslator { * \(/*TODO: make a printSnippet func*/decl.syntax ?? "") * } */ - public static \(returnTy) \(decl.baseIdentifier)(\(renderJavaParamDecls(decl, selfVariant: selfVariant))) { + public static \(returnTy) \(decl.baseIdentifier)(\(renderJavaParamDecls(decl, paramPassingStyle: paramPassingStyle))) { var mh$ = \(decl.baseIdentifier).HANDLE; try { - if (TRACE_DOWNCALLS) { - traceDowncall(\(renderForwardParams(decl, selfVariant: .memorySegment))); + if (SwiftKit.TRACE_DOWNCALLS) { + SwiftKit.traceDowncall(\(renderForwardJavaParams(decl, paramPassingStyle: .memorySegment))); } - \(maybeReturnCast) mh$.invokeExact(\(renderForwardParams(decl, selfVariant: selfVariant))); + \(maybeReturnCast) mh$.invokeExact(\(renderForwardJavaParams(decl, paramPassingStyle: paramPassingStyle))); } catch (Throwable ex$) { throw new AssertionError("should not reach here", ex$); } @@ -737,7 +791,7 @@ extension Swift2JavaTranslator { return "p\(pCounter)" } - for p in decl.effectiveParameters(selfVariant: nil) { + for p in decl.effectiveParameters(paramPassingStyle: nil) { let param = "\(p.effectiveName ?? nextUniqueParamName())" ps.append(param) } @@ -758,7 +812,7 @@ extension Swift2JavaTranslator { return false } - + public func renderTry(withArena: Bool) -> String { if withArena { "try (Arena arena = Arena.ofConfined()) {" @@ -767,7 +821,7 @@ extension Swift2JavaTranslator { } } - public func renderJavaParamDecls(_ decl: ImportedFunc, selfVariant: SelfParameterVariant?) -> String { + public func renderJavaParamDecls(_ decl: ImportedFunc, paramPassingStyle: SelfParameterVariant?) -> String { var ps: [String] = [] var pCounter = 0 @@ -776,7 +830,7 @@ extension Swift2JavaTranslator { return "p\(pCounter)" } - for p in decl.effectiveParameters(selfVariant: selfVariant) { + for p in decl.effectiveParameters(paramPassingStyle: paramPassingStyle) { let param = "\(p.type.javaType.description) \(p.effectiveName ?? nextUniqueParamName())" ps.append(param) } @@ -785,12 +839,53 @@ extension Swift2JavaTranslator { return res } + // TODO: these are stateless, find new place for them? + public func renderSwiftParamDecls(_ decl: ImportedFunc, paramPassingStyle: SelfParameterVariant?) -> String { + var ps: [String] = [] + var pCounter = 0 + + func nextUniqueParamName() -> String { + pCounter += 1 + return "p\(pCounter)" + } + + for p in decl.effectiveParameters(paramPassingStyle: paramPassingStyle) { + let firstName = p.firstName ?? "_" + let secondName = p.secondName ?? p.firstName ?? nextUniqueParamName() + + let paramTy: String = + if paramPassingStyle == .swiftThunkSelf { + "\(p.type.cCompatibleSwiftType)" + } else { + p.type.swiftTypeName.description + } + + let param = + if firstName == secondName { + // We have to do this to avoid a 'extraneous duplicate parameter name; 'number' already has an argument label' warning + "\(firstName): \(paramTy)" + } else { + "\(firstName) \(secondName): \(paramTy)" + } + ps.append(param) + } + + if paramPassingStyle == .swiftThunkSelf { + ps.append("_self: UnsafeMutableRawPointer") +// ps.append("_self: Any") + } + + let res = ps.joined(separator: ", ") + return res + } + public func renderUpcallHandles(_ decl: ImportedFunc) -> String { var printer = CodePrinter() for p in decl.parameters where p.type.javaType.isSwiftClosure { if p.type.javaType == .javaLangRunnable { let paramName = p.secondName ?? p.firstName ?? "_" - let handleDesc = p.type.javaType.prepareClosureDowncallHandle(decl: decl, parameter: paramName) + let handleDesc = p.type.javaType.prepareClosureDowncallHandle( + decl: decl, parameter: paramName) printer.print(handleDesc) } } @@ -798,7 +893,7 @@ extension Swift2JavaTranslator { return printer.contents } - public func renderForwardParams(_ decl: ImportedFunc, selfVariant: SelfParameterVariant?) -> String { + public func renderForwardJavaParams(_ decl: ImportedFunc, paramPassingStyle: SelfParameterVariant?) -> String { var ps: [String] = [] var pCounter = 0 @@ -807,12 +902,12 @@ extension Swift2JavaTranslator { return "p\(pCounter)" } - for p in decl.effectiveParameters(selfVariant: selfVariant) { + for p in decl.effectiveParameters(paramPassingStyle: paramPassingStyle) { // FIXME: fix the handling here we're already a memory segment let param: String if p.effectiveName == "self$" { - precondition(selfVariant == .memorySegment) - param = "self$"; + precondition(paramPassingStyle == .memorySegment) + param = "self$" } else { param = "\(p.renderParameterForwarding() ?? nextUniqueParamName())" } @@ -820,30 +915,52 @@ extension Swift2JavaTranslator { } // Add the forwarding "self" - if selfVariant == .wrapper && !decl.isInit { + if paramPassingStyle == .wrapper && !decl.isInit { ps.append("$memorySegment()") } return ps.joined(separator: ", ") } + // TODO: these are stateless, find new place for them? + public func renderForwardSwiftParams(_ decl: ImportedFunc, paramPassingStyle: SelfParameterVariant?) -> String { + var ps: [String] = [] + var pCounter = 0 + + func nextUniqueParamName() -> String { + pCounter += 1 + return "p\(pCounter)" + } + + for p in decl.effectiveParameters(paramPassingStyle: paramPassingStyle) { + if let firstName = p.firstName { + ps.append("\(firstName): \(p.effectiveName ?? nextUniqueParamName())") + } else { + ps.append("\(p.effectiveName ?? nextUniqueParamName())") + } + } + + return ps.joined(separator: ", ") + } + public func printFunctionDescriptorValue( _ printer: inout CodePrinter, _ decl: ImportedFunc, - accessorKind: VariableAccessorKind? = nil) { + accessorKind: VariableAccessorKind? = nil + ) { let fieldName = accessorKind.renderDescFieldName printer.start("public static final FunctionDescriptor \(fieldName) = ") let parameterLayoutDescriptors = javaMemoryLayoutDescriptors( forParametersOf: decl, - selfVariant: .pointer + paramPassingStyle: .pointer ) if decl.returnType.javaType == .void { - printer.print("FunctionDescriptor.ofVoid("); + printer.print("FunctionDescriptor.ofVoid(") printer.indent() } else { - printer.print("FunctionDescriptor.of("); + printer.print("FunctionDescriptor.of(") printer.indent() printer.print("", .continue) @@ -851,7 +968,9 @@ extension Swift2JavaTranslator { let returnTyIsLastTy = decl.parameters.isEmpty && !decl.hasParent if decl.isInit { // when initializing, we return a pointer to the newly created object - printer.print("/* -> */\(ForeignValueLayout.SwiftPointer)", .parameterNewlineSeparator(returnTyIsLastTy)) + printer.print( + "/* -> */\(ForeignValueLayout.SwiftPointer)", .parameterNewlineSeparator(returnTyIsLastTy) + ) } else { var returnDesc = decl.returnType.foreignValueLayout returnDesc.inlineComment = " -> " @@ -864,11 +983,13 @@ extension Swift2JavaTranslator { printer.print(desc, .parameterNewlineSeparator(isLast)) } - printer.outdent(); - printer.print(");"); + printer.outdent() + printer.print(");") } - public func printHeapObjectToStringMethod(_ printer: inout CodePrinter, _ decl: ImportedNominalType) { + public func printHeapObjectToStringMethod( + _ printer: inout CodePrinter, _ decl: ImportedNominalType + ) { printer.print( """ @Override diff --git a/Sources/JExtractSwift/Swift2JavaTranslator.swift b/Sources/JExtractSwift/Swift2JavaTranslator.swift index a954620b..9894244b 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator.swift @@ -36,15 +36,16 @@ public final class Swift2JavaTranslator { // ==== Output state - // TODO: consider how/if we need to store those etc - public var importedGlobalFuncs: [ImportedFunc] = [] + package var importedGlobalFuncs: [ImportedFunc] = [] /// A mapping from Swift type names (e.g., A.B) over to the imported nominal /// type representation. - public var importedTypes: [String: ImportedNominalType] = [:] + package var importedTypes: [String: ImportedNominalType] = [:] let nominalResolution: NominalTypeResolution = NominalTypeResolution() + var thunkNameRegistry: ThunkNameRegistry = ThunkNameRegistry() + public init( javaPackage: String, swiftModuleName: String @@ -68,31 +69,22 @@ extension Swift2JavaTranslator { var javaPrimitiveForSwiftInt: JavaType { .long } public func analyze( - swiftInterfacePath: String, + file: String, text: String? = nil ) throws { - if text == nil { - precondition( - swiftInterfacePath.hasSuffix(Self.SWIFT_INTERFACE_SUFFIX), - "Swift interface path must end with \(Self.SWIFT_INTERFACE_SUFFIX), was: \(swiftInterfacePath)" - ) - - if !FileManager.default.fileExists(atPath: swiftInterfacePath) { - throw Swift2JavaTranslatorError(message: "Missing input file: \(swiftInterfacePath)") - } + guard text != nil || FileManager.default.fileExists(atPath: file) else { + throw Swift2JavaTranslatorError(message: "Missing input file: \(file)") } - log.trace("Analyze: \(swiftInterfacePath)") - let text = try text ?? String(contentsOfFile: swiftInterfacePath) + log.trace("Analyze: \(file)") + let text = try text ?? String(contentsOfFile: file) - try analyzeSwiftInterface(interfaceFilePath: swiftInterfacePath, text: text) + try analyzeSwiftInterface(interfaceFilePath: file, text: text) - log.info("Done processing: \(swiftInterfacePath)") + log.debug("Done processing: \(file)") } package func analyzeSwiftInterface(interfaceFilePath: String, text: String) throws { - assert(interfaceFilePath.hasSuffix(Self.SWIFT_INTERFACE_SUFFIX)) - let sourceFileSyntax = Parser.parse(source: text) // Find all of the types and extensions, then bind the extensions. @@ -168,7 +160,6 @@ extension Swift2JavaTranslator { package: javaPackage, name: fullName ), - swiftMangledName: nominal.mangledNameFromComment, kind: kind ) diff --git a/Sources/JExtractSwift/Swift2JavaVisitor.swift b/Sources/JExtractSwift/Swift2JavaVisitor.swift index 8cf39eab..3feceec3 100644 --- a/Sources/JExtractSwift/Swift2JavaVisitor.swift +++ b/Sources/JExtractSwift/Swift2JavaVisitor.swift @@ -50,7 +50,7 @@ final class Swift2JavaVisitor: SyntaxVisitor { override func visitPost(_ node: ClassDeclSyntax) { if currentTypeName != nil { - log.info("Completed import: \(node.kind) \(node.name)") + log.debug("Completed import: \(node.kind) \(node.name)") currentTypeName = nil } } @@ -59,7 +59,8 @@ final class Swift2JavaVisitor: SyntaxVisitor { // Resolve the extended type of the extension as an imported nominal, and // recurse if we found it. guard let nominal = translator.nominalResolution.extendedType(of: node), - let importedNominalType = translator.importedNominalType(nominal) else { + let importedNominalType = translator.importedNominalType(nominal) + else { return .skipChildren } @@ -94,7 +95,7 @@ final class Swift2JavaVisitor: SyntaxVisitor { // TODO: more robust parameter handling // TODO: More robust type handling return ImportedParam( - param: param, + syntax: param, type: try cCompatibleType(for: param.type) ) } @@ -107,18 +108,14 @@ final class Swift2JavaVisitor: SyntaxVisitor { let fullName = "\(node.name.text)" - var funcDecl = ImportedFunc( - parentName: currentTypeName.map { translator.importedTypes[$0] }??.translatedType, + let funcDecl = ImportedFunc( + module: self.translator.swiftModuleName, + decl: node.trimmed, + parent: currentTypeName.map { translator.importedTypes[$0] }??.translatedType, identifier: fullName, returnType: javaResultType, parameters: params ) - funcDecl.syntax = "\(node.trimmed)" // TODO: rethink this, it's useful for comments in Java - - // Retrieve the mangled name, if available. - if let mangledName = node.mangledNameFromComment { - funcDecl.swiftMangledName = mangledName - } if let currentTypeName { log.debug("Record method in \(currentTypeName)") @@ -139,10 +136,10 @@ final class Swift2JavaVisitor: SyntaxVisitor { // TODO: filter out kinds of variables we cannot import - self.log.info("Import variable: \(node.kind) \(fullName)") + self.log.debug("Import variable: \(node.kind) \(fullName)") let returnTy: TypeSyntax - if let typeAnnotation = binding.typeAnnotation{ + if let typeAnnotation = binding.typeAnnotation { returnTy = typeAnnotation.type } else { returnTy = "Swift.Void" @@ -157,6 +154,7 @@ final class Swift2JavaVisitor: SyntaxVisitor { } var varDecl = ImportedVariable( + module: self.translator.swiftModuleName, parentName: currentTypeName.map { translator.importedTypes[$0] }??.translatedType, identifier: fullName, returnType: javaResultType @@ -169,7 +167,7 @@ final class Swift2JavaVisitor: SyntaxVisitor { } if let currentTypeName { - log.info("Record variable in \(currentTypeName)") + log.debug("Record variable in \(currentTypeName)") translator.importedTypes[currentTypeName]!.variables.append(varDecl) } else { fatalError("Global variables are not supported yet: \(node.debugDescription)") @@ -180,21 +178,22 @@ final class Swift2JavaVisitor: SyntaxVisitor { override func visit(_ node: InitializerDeclSyntax) -> SyntaxVisitorContinueKind { guard let currentTypeName, - let currentType = translator.importedTypes[currentTypeName] else { + let currentType = translator.importedTypes[currentTypeName] + else { fatalError("Initializer must be within a current type, was: \(node)") } guard node.shouldImport(log: log) else { return .skipChildren } - self.log.info("Import initializer: \(node.kind) \(currentType.javaType.description)") + self.log.debug("Import initializer: \(node.kind) \(currentType.javaType.description)") let params: [ImportedParam] do { params = try node.signature.parameterClause.parameters.map { param in // TODO: more robust parameter handling // TODO: More robust type handling return ImportedParam( - param: param, + syntax: param, type: try cCompatibleType(for: param.type) ) } @@ -207,24 +206,25 @@ final class Swift2JavaVisitor: SyntaxVisitor { "init(\(String(params.flatMap { "\($0.effectiveName ?? "_"):" })))" var funcDecl = ImportedFunc( - parentName: currentType.translatedType, + module: self.translator.swiftModuleName, + decl: node.trimmed, + parent: currentType.translatedType, identifier: initIdentifier, returnType: currentType.translatedType, parameters: params ) funcDecl.isInit = true - funcDecl.syntax = "\(node.trimmed)" // TODO: rethink this, it's useful for comments in Java - // Retrieve the mangled name, if available. - if let mangledName = node.mangledNameFromComment { - funcDecl.swiftMangledName = mangledName - } - - log.info("Record initializer method in \(currentType.javaType.description): \(funcDecl.identifier)") + log.debug( + "Record initializer method in \(currentType.javaType.description): \(funcDecl.identifier)") translator.importedTypes[currentTypeName]!.initializers.append(funcDecl) return .skipChildren } + + override func visit(_ node: DeinitializerDeclSyntax) -> SyntaxVisitorContinueKind { + return .skipChildren + } } extension DeclGroupSyntax where Self: NamedDeclSyntax { diff --git a/Sources/JExtractSwift/SwiftKit+Printing.swift b/Sources/JExtractSwift/SwiftKit+Printing.swift new file mode 100644 index 00000000..ed7d05d6 --- /dev/null +++ b/Sources/JExtractSwift/SwiftKit+Printing.swift @@ -0,0 +1,44 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import Foundation +import SwiftBasicFormat +import SwiftParser +import SwiftSyntax + +/// Helper for printing calls into SwiftKit generated code from generated sources. +package struct SwiftKitPrinting { + + /// Forms syntax for a Java call to a swiftkit exposed function. + static func renderCallGetSwiftType(module: String, nominal: ImportedNominalType) -> String { + """ + SwiftKit.swiftjava.getType("\(module)", "\(nominal.swiftTypeName)") + """ + } +} + +// ==== ------------------------------------------------------------------------ +// Helpers to form names of "well known" SwiftKit generated functions + +extension SwiftKitPrinting { + enum Names { + } +} + +extension SwiftKitPrinting.Names { + static func getType(module: String, nominal: ImportedNominalType) -> String { + "swiftjava_getType_\(module)_\(nominal.swiftTypeName)" + } + +} diff --git a/Sources/JExtractSwift/SwiftThunkTranslator.swift b/Sources/JExtractSwift/SwiftThunkTranslator.swift new file mode 100644 index 00000000..5fc01279 --- /dev/null +++ b/Sources/JExtractSwift/SwiftThunkTranslator.swift @@ -0,0 +1,136 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import Foundation +import SwiftBasicFormat +import SwiftParser +import SwiftSyntax + +struct SwiftThunkTranslator { + + let st: Swift2JavaTranslator + + init(_ st: Swift2JavaTranslator) { + self.st = st + } + + func renderGlobalThunks() -> [DeclSyntax] { + var decls: [DeclSyntax] = [] + + for decl in st.importedGlobalFuncs { + decls.append(contentsOf: render(forFunc: decl)) + } + + return decls + } + + /// Render all the thunks that make Swift methods accessible to Java. + func renderThunks(forType nominal: ImportedNominalType) -> [DeclSyntax] { + var decls: [DeclSyntax] = [] + decls.reserveCapacity(nominal.initializers.count + nominal.methods.count) + + decls.append(renderSwiftTypeAccessor(nominal)) + + for decl in nominal.initializers { + decls.append(contentsOf: renderSwiftInitAccessor(decl)) + } + + for decl in nominal.methods { + decls.append(contentsOf: render(forFunc: decl)) + } + +// for v in nominal.variables { +// if let acc = v.accessorFunc(kind: .get) { +// decls.append(contentsOf: render(forFunc: acc)) +// } +// if let acc = v.accessorFunc(kind: .set) { +// decls.append(contentsOf: render(forFunc: acc)) +// } +// } + + return decls + } + + /// Accessor to get the `T.self` of the Swift type, without having to rely on mangled name lookups. + func renderSwiftTypeAccessor(_ nominal: ImportedNominalType) -> DeclSyntax { + let funcName = SwiftKitPrinting.Names.getType( + module: st.swiftModuleName, + nominal: nominal) + + return + """ + @_cdecl("\(raw: funcName)") + public func \(raw: funcName)() -> UnsafeMutableRawPointer /* Any.Type */ { + return unsafeBitCast(\(raw: nominal.swiftTypeName).self, to: UnsafeMutableRawPointer.self) + } + """ + } + + func renderSwiftInitAccessor(_ function: ImportedFunc) -> [DeclSyntax] { + guard let parent = function.parent else { + fatalError("Cannot render initializer accessor if init function has no parent! Was: \(function)") + } + + let thunkName = self.st.thunkNameRegistry.functionThunkName( + module: st.swiftModuleName, decl: function) + + return + [ + """ + @_cdecl("\(raw: thunkName)") + public func \(raw: thunkName)(\(raw: st.renderSwiftParamDecls(function, paramPassingStyle: nil))) -> UnsafeMutableRawPointer /* \(raw: parent.swiftTypeName) */ { + let _self = \(raw: parent.swiftTypeName)(\(raw: st.renderForwardSwiftParams(function, paramPassingStyle: nil))) + let self$ = unsafeBitCast(_self, to: UnsafeMutableRawPointer.self) + return _swiftjava_swift_retain(object: self$) + } + """ + ] + } + + func render(forFunc decl: ImportedFunc) -> [DeclSyntax] { + st.log.trace("Rendering thunks for: \(decl.baseIdentifier)") + let thunkName = st.thunkNameRegistry.functionThunkName(module: st.swiftModuleName, decl: decl) + + // Do we need to pass a self parameter? + let paramPassingStyle: SelfParameterVariant? + let callBaseDot: String + if let parent = decl.parent { + paramPassingStyle = .swiftThunkSelf + callBaseDot = "unsafeBitCast(_self, to: \(parent.originalSwiftType).self)." + // callBaseDot = "(_self as! \(parent.originalSwiftType))." + } else { + paramPassingStyle = nil + callBaseDot = "" + } + + let returnArrowTy = + if decl.returnType.cCompatibleJavaMemoryLayout == .primitive(.void) { + "/* \(decl.returnType.swiftTypeName) */" + } else { + "-> \(decl.returnType.cCompatibleSwiftType) /* \(decl.returnType.swiftTypeName) */" + } + + // FIXME: handle in thunk: errors + + return + [ + """ + @_cdecl("\(raw: thunkName)") + public func \(raw: thunkName)(\(raw: st.renderSwiftParamDecls(decl, paramPassingStyle: paramPassingStyle))) \(raw: returnArrowTy) { + return \(raw: callBaseDot)\(raw: decl.baseIdentifier)(\(raw: st.renderForwardSwiftParams(decl, paramPassingStyle: paramPassingStyle))) + } + """ + ] + } +} diff --git a/Sources/JExtractSwift/TerminalColors.swift b/Sources/JExtractSwift/TerminalColors.swift index fcef5a3c..6170e2bc 100644 --- a/Sources/JExtractSwift/TerminalColors.swift +++ b/Sources/JExtractSwift/TerminalColors.swift @@ -21,6 +21,7 @@ package enum Rainbow: String { case magenta = "\u{001B}[0;35m" case cyan = "\u{001B}[0;36m" case white = "\u{001B}[0;37m" + case bold = "\u{001B}[1m" case `default` = "\u{001B}[0;0m" func name() -> String { @@ -33,6 +34,7 @@ package enum Rainbow: String { case .magenta: return "Magenta" case .cyan: return "Cyan" case .white: return "White" + case .bold: return "Bold" case .default: return "Default" } } @@ -127,6 +129,17 @@ package extension String { } } + var bold: String { + self.colored(as: .bold) + } + func bold(if condition: Bool) -> String { + if condition { + self.colored(as: .bold) + } else { + self + } + } + var `default`: String { self.colored(as: .default) } @@ -169,6 +182,10 @@ package extension Substring { self.colored(as: .white) } + var bold: String { + self.colored(as: .bold) + } + var `default`: String { self.colored(as: .default) } diff --git a/Sources/JExtractSwift/ThunkNameRegistry.swift b/Sources/JExtractSwift/ThunkNameRegistry.swift new file mode 100644 index 00000000..92f1397d --- /dev/null +++ b/Sources/JExtractSwift/ThunkNameRegistry.swift @@ -0,0 +1,65 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import SwiftSyntax + +/// Registry of names we've already emitted as @_cdecl and must be kept unique. +/// In order to avoid duplicate symbols, the registry can append some unique identifier to duplicated names +package struct ThunkNameRegistry { + /// Maps base names such as "swiftjava_Module_Type_method_a_b_c" to the number of times we've seen them. + /// This is used to de-duplicate symbols as we emit them. + private var registry: [ImportedFunc: String] = [:] + private var duplicateNames: [String: Int] = [:] + + package init() {} + + package mutating func functionThunkName( + module: String, decl: ImportedFunc, + file: String = #fileID, line: UInt = #line) -> String { + if let existingName = self.registry[decl] { + return existingName + } + + let params = decl.effectiveParameters(paramPassingStyle: .swiftThunkSelf) + var paramsPart = "" + if !params.isEmpty { + paramsPart = "_" + params.map { param in + param.firstName ?? "_" + }.joined(separator: "_") + } + + + + let name = + if let parent = decl.parent { + "swiftjava_\(module)_\(parent.swiftTypeName)_\(decl.baseIdentifier)\(paramsPart)" + } else { + "swiftjava_\(module)_\(decl.baseIdentifier)\(paramsPart)" + } + + let emittedCount = self.duplicateNames[name, default: 0] + defer { self.duplicateNames[name] = emittedCount + 1 } + + let deduplicatedName = + if emittedCount == 0 { + name // first occurrence of a name we keep as-is + } else { + "\(name)$\(emittedCount)" + } + + // Store the name we assigned to this specific decl. + self.registry[decl] = deduplicatedName + return deduplicatedName + } +} diff --git a/Sources/JExtractSwift/TranslatedType.swift b/Sources/JExtractSwift/TranslatedType.swift index ca1ecf73..9dc12e07 100644 --- a/Sources/JExtractSwift/TranslatedType.swift +++ b/Sources/JExtractSwift/TranslatedType.swift @@ -55,12 +55,7 @@ extension Swift2JavaVisitor { // Translate the generic arguments to the C-compatible types. let genericArgs = try memberType.genericArgumentClause.map { genericArgumentClause in try genericArgumentClause.arguments.map { argument in - switch argument.argument { - case .type(let argumentType): - try cCompatibleType(for: argumentType) - @unknown default: - throw TypeTranslationError.unimplementedType(TypeSyntax(memberType)) - } + try cCompatibleType(for: argument.argument) } } @@ -76,12 +71,7 @@ extension Swift2JavaVisitor { // Translate the generic arguments to the C-compatible types. let genericArgs = try identifierType.genericArgumentClause.map { genericArgumentClause in try genericArgumentClause.arguments.map { argument in - switch argument.argument { - case .type(let argumentType): - try cCompatibleType(for: argumentType) - @unknown default: - throw TypeTranslationError.unimplementedType(TypeSyntax(identifierType)) - } + try cCompatibleType(for: argument.argument) } } @@ -256,7 +246,7 @@ extension TranslatedType { } /// Describes the C-compatible layout as it should be referenced from Java. -enum CCompatibleJavaMemoryLayout { +enum CCompatibleJavaMemoryLayout: Hashable { /// A primitive Java type that has a direct counterpart in C. case primitive(JavaType) @@ -288,7 +278,7 @@ extension TranslatedType { case .long: return .SwiftInt64 case .float: return .SwiftFloat case .double: return .SwiftDouble - case .array, .class, .void: fatalError("Not a primitive type") + case .array, .class, .void: fatalError("Not a primitive type: \(cCompatibleJavaMemoryLayout) in \(self)") } case .int: diff --git a/Sources/Java2SwiftLib/JavaClassTranslator.swift b/Sources/Java2SwiftLib/JavaClassTranslator.swift index b90a538a..b0b0628f 100644 --- a/Sources/Java2SwiftLib/JavaClassTranslator.swift +++ b/Sources/Java2SwiftLib/JavaClassTranslator.swift @@ -518,7 +518,9 @@ extension JavaClassTranslator { preferValueTypes: true, outerOptional: .implicitlyUnwrappedOptional ) - if resultType != "Void" { + + // FIXME: cleanup the checking here + if resultType != "Void" && resultType != "Swift.Void" { resultTypeStr = " -> \(resultType)" } else { resultTypeStr = "" diff --git a/Sources/SwiftKitSwift/SwiftKit.swift b/Sources/SwiftKitSwift/SwiftKit.swift index 9fdcdd80..38b3c1c8 100644 --- a/Sources/SwiftKitSwift/SwiftKit.swift +++ b/Sources/SwiftKitSwift/SwiftKit.swift @@ -12,12 +12,6 @@ // //===----------------------------------------------------------------------===// -// This is a "plain Swift" file containing various types of declarations, -// that is exported to Java by using the `jextract-swift` tool. -// -// No annotations are necessary on the Swift side to perform the export. - -// FIXME: this is a workaround until we can pass String to Swift directly @_silgen_name("getTypeByStringByteArray") public func getTypeByStringByteArray(_ name: UnsafePointer) -> Any.Type? { let string = String(cString: name) @@ -26,9 +20,25 @@ public func getTypeByStringByteArray(_ name: UnsafePointer) -> Any.Type? return type } -//// FIXME: this is internal in stdlib, it would make things easier here -//@_silgen_name("swift_stdlib_getTypeByMangledNameUntrusted") -//public func _getTypeByMangledNameUntrusted( -// _ name: UnsafePointer, -// _ nameLength: UInt) -// -> Any.Type? +@_silgen_name("swift_retain") +public func _swiftjava_swift_retain(object: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer + +@_silgen_name("swift_release") +public func _swiftjava_swift_release(object: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer + +@_silgen_name("swift_retainCount") +public func _swiftjava_swift_retainCount(object: UnsafeMutableRawPointer) -> Int + +@_silgen_name("swift_isUniquelyReferenced") +public func _swiftjava_swift_isUniquelyReferenced(object: UnsafeMutableRawPointer) -> Bool + + + @_alwaysEmitIntoClient @_transparent + internal func _swiftjava_withHeapObject( + of object: AnyObject, + _ body: (UnsafeMutableRawPointer) -> R + ) -> R { + defer { _fixLifetime(object) } + let unmanaged = Unmanaged.passUnretained(object) + return body(unmanaged.toOpaque()) + } diff --git a/SwiftKit/build.gradle b/SwiftKit/build.gradle index 3479e6c8..e0896e66 100644 --- a/SwiftKit/build.gradle +++ b/SwiftKit/build.gradle @@ -40,3 +40,32 @@ tasks.test { events("passed", "skipped", "failed") } } + +// SwiftKit depends on SwiftKitSwift (Swift library that this Java library calls into) + +def compileSwift = tasks.register("compileSwift", Exec) { + description "Compile the swift-java SwiftKitSwift dynamic library that SwiftKit (Java) calls into" + + inputs.file(new File(rootDir, "Package.swift")) + inputs.dir(new File(rootDir, "Sources/")) // a bit generous, but better safe than sorry, and include all Swift source changes + outputs.dir(new File(rootDir, ".build")) + + workingDir = rootDir + commandLine "swift" + args("build", "--target", "SwiftKitSwift") +} +tasks.build { + dependsOn("compileSwift") +} + + + +def cleanSwift = tasks.register("cleanSwift", Exec) { + workingDir = rootDir + commandLine "swift" + args("package", "clean") +} +tasks.clean { + dependsOn("cleanSwift") +} + diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftAnyType.java b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftAnyType.java index 6dcd1f6b..cf7cc238 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftAnyType.java +++ b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftAnyType.java @@ -27,11 +27,11 @@ public final class SwiftAnyType { private final MemorySegment memorySegment; public SwiftAnyType(MemorySegment memorySegment) { - if (memorySegment.byteSize() == 0) { - throw new IllegalArgumentException("A Swift Any.Type cannot be null!"); - } +// if (SwiftKit.getSwiftInt(memorySegment, 0) > 0) { +// throw new IllegalArgumentException("A Swift Any.Type cannot be null!"); +// } - this.memorySegment = memorySegment; + this.memorySegment = memorySegment.asReadOnly(); } public SwiftAnyType(SwiftHeapObject object) { diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftKit.java b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftKit.java index 064be4ec..1951c23e 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftKit.java +++ b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftKit.java @@ -27,15 +27,23 @@ public class SwiftKit { - private static final String STDLIB_DYLIB_NAME = "swiftCore"; + public static final String STDLIB_DYLIB_NAME = "swiftCore"; + public static final String SWIFTKITSWIFT_DYLIB_NAME = "SwiftKitSwift"; + public static final boolean TRACE_DOWNCALLS = Boolean.getBoolean("jextract.trace.downcalls"); + private static final String STDLIB_MACOS_DYLIB_PATH = "/usr/lib/swift/libswiftCore.dylib"; private static final Arena LIBRARY_ARENA = Arena.ofAuto(); - static final boolean TRACE_DOWNCALLS = Boolean.getBoolean("jextract.trace.downcalls"); - static { + @SuppressWarnings("unused") + private static final boolean INITIALIZED_LIBS = loadLibraries(false); + + public static boolean loadLibraries(boolean loadSwiftKit) { System.loadLibrary(STDLIB_DYLIB_NAME); - System.loadLibrary("SwiftKitSwift"); + if (loadSwiftKit) { + System.loadLibrary(SWIFTKITSWIFT_DYLIB_NAME); + } + return true; } static final SymbolLookup SYMBOL_LOOKUP = getSymbolLookup(); @@ -55,12 +63,31 @@ private static SymbolLookup getSymbolLookup() { public SwiftKit() { } - static void traceDowncall(String name, Object... args) { - String traceArgs = Arrays.stream(args) - .map(Object::toString) - .collect(Collectors.joining(", ")); - System.out.printf("[java] Downcall: %s(%s)\n", name, traceArgs); - } + public static void traceDowncall(Object... args) { + var ex = new RuntimeException(); + + String traceArgs = Arrays.stream(args) + .map(Object::toString) + .collect(Collectors.joining(", ")); + System.out.printf("[java][%s:%d] Downcall: %s(%s)\n", + ex.getStackTrace()[1].getFileName(), + ex.getStackTrace()[1].getLineNumber(), + ex.getStackTrace()[1].getMethodName(), + traceArgs); + } + + public static void trace(Object... args) { + var ex = new RuntimeException(); + + String traceArgs = Arrays.stream(args) + .map(Object::toString) + .collect(Collectors.joining(", ")); + System.out.printf("[java][%s:%d] %s: %s\n", + ex.getStackTrace()[1].getFileName(), + ex.getStackTrace()[1].getLineNumber(), + ex.getStackTrace()[1].getMethodName(), + traceArgs); + } static MemorySegment findOrThrow(String symbol) { return SYMBOL_LOOKUP.find(symbol) @@ -260,17 +287,6 @@ private static class swift_getTypeByMangledNameInEnvironment { public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } - private static class getTypeByStringByteArray { - public static final FunctionDescriptor DESC = FunctionDescriptor.of( - /*returns=*/SwiftValueLayout.SWIFT_POINTER, - ValueLayout.ADDRESS - ); - - public static final MemorySegment ADDR = findOrThrow("getTypeByStringByteArray"); - - public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); - } - /** * Get a Swift {@code Any.Type} wrapped by {@link SwiftAnyType} which represents the type metadata available at runtime. * @@ -308,6 +324,64 @@ public static Optional getTypeByMangledNameInEnvironment(String ma } } + /** + * Produce the name of the Swift type given its Swift type metadata. + *

+ * If 'qualified' is true, leave all the qualification in place to + * disambiguate the type, producing a more complete (but longer) type name. + * + * @param typeMetadata the memory segment must point to a Swift metadata, + * e.g. the result of a {@link swift_getTypeByMangledNameInEnvironment} call + */ + public static String nameOfSwiftType(MemorySegment typeMetadata, boolean qualified) { + MethodHandle mh = swift_getTypeName.HANDLE; + + try (Arena arena = Arena.ofConfined()) { + MemorySegment charsAndLength = (MemorySegment) mh.invokeExact((SegmentAllocator) arena, typeMetadata, qualified); + MemorySegment utf8Chars = charsAndLength.get(SwiftValueLayout.SWIFT_POINTER, 0); + String typeName = utf8Chars.getString(0); + + // FIXME: this free is not always correct: + // java(80175,0x17008f000) malloc: *** error for object 0x600000362610: pointer being freed was not allocated + // cFree(utf8Chars); + + return typeName; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + + /*** + * Namespace for calls down into swift-java generated thunks and accessors, such as {@code swiftjava_getType_...} etc. + *

Not intended to be used by end-user code directly, but used by swift-java generated Java code. + */ + @SuppressWarnings("unused") // used by source generated Java code + public static final class swiftjava { + private swiftjava() { /* just a namespace */ } + + private static class getType { + public static final FunctionDescriptor DESC = FunctionDescriptor.of( + /* -> */ValueLayout.ADDRESS); + } + + public static MemorySegment getType(String moduleName, String nominalName) { + // We cannot cache this statically since it depends on the type names we're looking up + // TODO: we could cache the handles per type once we have them, to speed up subsequent calls + String symbol = "swiftjava_getType_" + moduleName + "_" + nominalName; + + try { + var addr = findOrThrow(symbol); + var mh$ = Linker.nativeLinker().downcallHandle(addr, getType.DESC); + return (MemorySegment) mh$.invokeExact(); + } catch (Throwable e) { + throw new AssertionError("Failed to call: " + symbol, e); + } + } + } + + // ==== ------------------------------------------------------------------------------------------------------------ + // Get Swift values out of native memory segments + /** * Read a Swift.Int value from memory at the given offset and translate it into a Java long. *

@@ -329,7 +403,7 @@ private static class swift_getTypeName { * Descriptor for the swift_getTypeName runtime function. */ public static final FunctionDescriptor DESC = FunctionDescriptor.of( - /*returns=*/MemoryLayout.structLayout( + /* -> */MemoryLayout.structLayout( SwiftValueLayout.SWIFT_POINTER.withName("utf8Chars"), SwiftValueLayout.SWIFT_INT.withName("length") ), @@ -348,31 +422,4 @@ private static class swift_getTypeName { public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } - /** - * Produce the name of the Swift type given its Swift type metadata. - *

- * If 'qualified' is true, leave all the qualification in place to - * disambiguate the type, producing a more complete (but longer) type name. - * - * @param typeMetadata the memory segment must point to a Swift metadata, - * e.g. the result of a {@link swift_getTypeByMangledNameInEnvironment} call - */ - public static String nameOfSwiftType(MemorySegment typeMetadata, boolean qualified) { - MethodHandle mh = swift_getTypeName.HANDLE; - - try (Arena arena = Arena.ofConfined()) { - MemorySegment charsAndLength = (MemorySegment) mh.invokeExact((SegmentAllocator) arena, typeMetadata, qualified); - MemorySegment utf8Chars = charsAndLength.get(SwiftValueLayout.SWIFT_POINTER, 0); - String typeName = utf8Chars.getString(0); - - // FIXME: this free is not always correct: - // java(80175,0x17008f000) malloc: *** error for object 0x600000362610: pointer being freed was not allocated - // cFree(utf8Chars); - - return typeName; - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - } - } diff --git a/SwiftKit/src/test/java/org/swift/swiftkit/SwiftRuntimeMetadataTest.java b/SwiftKit/src/test/java/org/swift/swiftkit/SwiftRuntimeMetadataTest.java index 5354cc4f..ffefe72e 100644 --- a/SwiftKit/src/test/java/org/swift/swiftkit/SwiftRuntimeMetadataTest.java +++ b/SwiftKit/src/test/java/org/swift/swiftkit/SwiftRuntimeMetadataTest.java @@ -15,6 +15,7 @@ package org.swift.swiftkit; import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; public class SwiftRuntimeMetadataTest { diff --git a/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift b/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift index 84c4b2ec..0efff0c7 100644 --- a/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift +++ b/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift @@ -16,6 +16,112 @@ import JExtractSwift import Testing import struct Foundation.CharacterSet +enum RenderKind { + case swift + case java +} + +func assertOutput( + dump: Bool = false, + _ translator: Swift2JavaTranslator, + input: String, + _ renderKind: RenderKind, + detectChunkByInitialLines: Int = 4, + expectedChunks: [String], + fileID: String = #fileID, + filePath: String = #filePath, + line: Int = #line, + column: Int = #column +) throws { + try! translator.analyze(file: "/fake/Fake.swiftinterface", text: input) + + let output: String + var printer: CodePrinter = CodePrinter(mode: .accumulateAll) + switch renderKind { + case .swift: + try translator.writeSwiftThunkSources(outputDirectory: "/fake", printer: &printer) + case .java: + try translator.writeExportedJavaSources(outputDirectory: "/fake", printer: &printer) + } + output = printer.finalize() + + let gotLines = output.split(separator: "\n") + for expected in expectedChunks { + let expectedLines = expected.split(separator: "\n") + + var matchingOutputOffset: Int? = nil + let expectedInitialMatchingLines = expectedLines[0.. (offset+detectChunkByInitialLines) { + let textLinesAtOffset = gotLines[offset.. 0 + if hasDiff || dump { + print("") + if hasDiff { + print("error: Number of not matching lines: \(diffLineNumbers.count)!".red) + + print("==== ---------------------------------------------------------------") + print("Expected output:") + for (n, e) in expectedLines.enumerated() { + print("\(n): \(e)".yellow(if: diffLineNumbers.map({$0 - matchingOutputOffset}).contains(n))) + } + } + + print("==== ---------------------------------------------------------------") + print("Got output:") + let printFromLineNo = matchingOutputOffset + let printToLineNo = matchingOutputOffset + expectedLines.count + for (n, g) in gotLines.enumerated() where n >= printFromLineNo && n <= printToLineNo { + print("\(n): \(g)".red(if: diffLineNumbers.contains(n))) + } + print("==== ---------------------------------------------------------------\n") + } + } +} + func assertOutput( dump: Bool = false, _ got: String, @@ -32,21 +138,13 @@ func assertOutput( for (no, (g, e)) in zip(gotLines, expectedLines).enumerated() { if g.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines).count == 0 - || e.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines).count == 0 - { + || e.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines).count == 0 { continue } let ge = g.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines) let ee = e.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines) if ge.commonPrefix(with: ee) != ee { - // print("") - // print("[\(file):\(line)] " + "Difference found on line: \(no + 1)!".red) - // print("Expected @ \(file):\(Int(line) + no + 3 /*formatting*/ + 1):") - // print(e.yellow) - // print("Got instead:") - // print(g.red) - diffLineNumbers.append(no) let sourceLocation = SourceLocation( @@ -57,7 +155,7 @@ func assertOutput( } let hasDiff = diffLineNumbers.count > 0 - if hasDiff || dump{ + if hasDiff || dump { print("") if hasDiff { print("error: Number of not matching lines: \(diffLineNumbers.count)!".red) diff --git a/Tests/JExtractSwiftTests/FuncCallbackImportTests.swift b/Tests/JExtractSwiftTests/FuncCallbackImportTests.swift index 90541263..2f2c8c8c 100644 --- a/Tests/JExtractSwiftTests/FuncCallbackImportTests.swift +++ b/Tests/JExtractSwiftTests/FuncCallbackImportTests.swift @@ -41,12 +41,12 @@ final class FuncCallbackImportTests { ) st.log.logLevel = .error - try st.analyze(swiftInterfacePath: "/fake/Fake.swiftinterface", text: Self.class_interfaceFile) + try st.analyze(file: "Fake.swift", text: Self.class_interfaceFile) let funcDecl = st.importedGlobalFuncs.first { $0.baseIdentifier == "callMe" }! let output = CodePrinter.toString { printer in - st.printFuncDowncallMethod(&printer, decl: funcDecl, selfVariant: nil) + st.printFuncDowncallMethod(&printer, decl: funcDecl, paramPassingStyle: nil) } assertOutput( @@ -69,8 +69,8 @@ final class FuncCallbackImportTests { callMe_callback_handle$ = callMe_callback_handle$.bindTo(callback); Linker linker = Linker.nativeLinker(); MemorySegment callback$ = linker.upcallStub(callMe_callback_handle$, callMe_callback_desc$, arena); - if (TRACE_DOWNCALLS) { - traceDowncall(callback$); + if (SwiftKit.TRACE_DOWNCALLS) { + SwiftKit.traceDowncall(callback$); } mh$.invokeExact(callback$); } catch (Throwable ex$) { diff --git a/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift b/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift index 2f3bccb1..3160d55f 100644 --- a/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift +++ b/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift @@ -53,7 +53,6 @@ final class FunctionDescriptorTests { } """ - @Test func FunctionDescriptor_globalTakeInt() throws { try functionDescriptorTest("globalTakeInt") { output in @@ -141,7 +140,7 @@ extension FunctionDescriptorTests { javaPackage: String = "com.example.swift", swiftModuleName: String = "SwiftModule", logLevel: Logger.Level = .trace, - body: (String) throws -> () + body: (String) throws -> Void ) throws { let st = Swift2JavaTranslator( javaPackage: javaPackage, @@ -149,7 +148,7 @@ extension FunctionDescriptorTests { ) st.log.logLevel = logLevel - try st.analyze(swiftInterfacePath: "/fake/Sample.swiftinterface", text: interfaceFile) + try st.analyze(file: "/fake/Sample.swiftinterface", text: interfaceFile) let funcDecl = st.importedGlobalFuncs.first { $0.baseIdentifier == methodIdentifier @@ -168,7 +167,7 @@ extension FunctionDescriptorTests { javaPackage: String = "com.example.swift", swiftModuleName: String = "SwiftModule", logLevel: Logger.Level = .trace, - body: (String) throws -> () + body: (String) throws -> Void ) throws { let st = Swift2JavaTranslator( javaPackage: javaPackage, @@ -176,20 +175,21 @@ extension FunctionDescriptorTests { ) st.log.logLevel = logLevel - try st.analyze(swiftInterfacePath: "/fake/Sample.swiftinterface", text: interfaceFile) + try st.analyze(file: "/fake/Sample.swiftinterface", text: interfaceFile) let varDecl: ImportedVariable? = st.importedTypes.values.compactMap { - $0.variables.first { - $0.identifier == identifier - } - }.first + $0.variables.first { + $0.identifier == identifier + } + }.first guard let varDecl else { fatalError("Cannot find descriptor of: \(identifier)") } let getOutput = CodePrinter.toString { printer in - st.printFunctionDescriptorValue(&printer, varDecl.accessorFunc(kind: accessorKind)!, accessorKind: accessorKind) + st.printFunctionDescriptorValue( + &printer, varDecl.accessorFunc(kind: accessorKind)!, accessorKind: accessorKind) } try body(getOutput) diff --git a/Tests/JExtractSwiftTests/MethodImportTests.swift b/Tests/JExtractSwiftTests/MethodImportTests.swift index 3b2ef4f4..c866cb60 100644 --- a/Tests/JExtractSwiftTests/MethodImportTests.swift +++ b/Tests/JExtractSwiftTests/MethodImportTests.swift @@ -70,12 +70,12 @@ final class MethodImportTests { ) st.log.logLevel = .error - try st.analyze(swiftInterfacePath: "/fake/Fake.swiftinterface", text: class_interfaceFile) + try st.analyze(file: "Fake.swift", text: class_interfaceFile) let funcDecl = st.importedGlobalFuncs.first { $0.baseIdentifier == "helloWorld" }! let output = CodePrinter.toString { printer in - st.printFuncDowncallMethod(&printer, decl: funcDecl, selfVariant: nil) + st.printFuncDowncallMethod(&printer, decl: funcDecl, paramPassingStyle: nil) } assertOutput( @@ -91,8 +91,8 @@ final class MethodImportTests { public static void helloWorld() { var mh$ = helloWorld.HANDLE; try { - if (TRACE_DOWNCALLS) { - traceDowncall(); + if (SwiftKit.TRACE_DOWNCALLS) { + SwiftKit.traceDowncall(); } mh$.invokeExact(); } catch (Throwable ex$) { @@ -111,14 +111,14 @@ final class MethodImportTests { ) st.log.logLevel = .error - try st.analyze(swiftInterfacePath: "/fake/__FakeModule/SwiftFile.swiftinterface", text: class_interfaceFile) + try st.analyze(file: "Fake.swift", text: class_interfaceFile) let funcDecl = st.importedGlobalFuncs.first { $0.baseIdentifier == "globalTakeInt" }! let output = CodePrinter.toString { printer in - st.printFuncDowncallMethod(&printer, decl: funcDecl, selfVariant: nil) + st.printFuncDowncallMethod(&printer, decl: funcDecl, paramPassingStyle: nil) } assertOutput( @@ -134,8 +134,8 @@ final class MethodImportTests { public static void globalTakeInt(long i) { var mh$ = globalTakeInt.HANDLE; try { - if (TRACE_DOWNCALLS) { - traceDowncall(i); + if (SwiftKit.TRACE_DOWNCALLS) { + SwiftKit.traceDowncall(i); } mh$.invokeExact(i); } catch (Throwable ex$) { @@ -154,14 +154,14 @@ final class MethodImportTests { ) st.log.logLevel = .error - try st.analyze(swiftInterfacePath: "/fake/__FakeModule/SwiftFile.swiftinterface", text: class_interfaceFile) + try st.analyze(file: "Fake.swift", text: class_interfaceFile) let funcDecl = st.importedGlobalFuncs.first { $0.baseIdentifier == "globalTakeIntLongString" }! let output = CodePrinter.toString { printer in - st.printFuncDowncallMethod(&printer, decl: funcDecl, selfVariant: .memorySegment) + st.printFuncDowncallMethod(&printer, decl: funcDecl, paramPassingStyle: .memorySegment) } assertOutput( @@ -177,8 +177,8 @@ final class MethodImportTests { public static void globalTakeIntLongString(int i32, long l, com.example.swift.String s) { var mh$ = globalTakeIntLongString.HANDLE; try { - if (TRACE_DOWNCALLS) { - traceDowncall(i32, l, s.$memorySegment()); + if (SwiftKit.TRACE_DOWNCALLS) { + SwiftKit.traceDowncall(i32, l, s.$memorySegment()); } mh$.invokeExact(i32, l, s.$memorySegment()); } catch (Throwable ex$) { @@ -197,14 +197,14 @@ final class MethodImportTests { ) st.log.logLevel = .error - try st.analyze(swiftInterfacePath: "/fake/__FakeModule/SwiftFile.swiftinterface", text: class_interfaceFile) + try st.analyze(file: "Fake.swift", text: class_interfaceFile) let funcDecl: ImportedFunc = st.importedTypes["MySwiftClass"]!.methods.first { $0.baseIdentifier == "helloMemberFunction" }! let output = CodePrinter.toString { printer in - st.printFuncDowncallMethod(&printer, decl: funcDecl, selfVariant: .memorySegment) + st.printFuncDowncallMethod(&printer, decl: funcDecl, paramPassingStyle: .memorySegment) } assertOutput( @@ -220,8 +220,8 @@ final class MethodImportTests { public static void helloMemberFunction(java.lang.foreign.MemorySegment self$) { var mh$ = helloMemberFunction.HANDLE; try { - if (TRACE_DOWNCALLS) { - traceDowncall(self$); + if (SwiftKit.TRACE_DOWNCALLS) { + SwiftKit.traceDowncall(self$); } mh$.invokeExact(self$); } catch (Throwable ex$) { @@ -240,14 +240,14 @@ final class MethodImportTests { ) st.log.logLevel = .error - try st.analyze(swiftInterfacePath: "/fake/__FakeModule/SwiftFile.swiftinterface", text: class_interfaceFile) + try st.analyze(file: "Fake.swift", text: class_interfaceFile) let funcDecl: ImportedFunc = st.importedTypes["MySwiftClass"]!.methods.first { $0.baseIdentifier == "helloMemberInExtension" }! let output = CodePrinter.toString { printer in - st.printFuncDowncallMethod(&printer, decl: funcDecl, selfVariant: .memorySegment) + st.printFuncDowncallMethod(&printer, decl: funcDecl, paramPassingStyle: .memorySegment) } assertOutput( @@ -263,8 +263,8 @@ final class MethodImportTests { public static void helloMemberInExtension(java.lang.foreign.MemorySegment self$) { var mh$ = helloMemberInExtension.HANDLE; try { - if (TRACE_DOWNCALLS) { - traceDowncall(self$); + if (SwiftKit.TRACE_DOWNCALLS) { + SwiftKit.traceDowncall(self$); } mh$.invokeExact(self$); } catch (Throwable ex$) { @@ -283,14 +283,14 @@ final class MethodImportTests { ) st.log.logLevel = .info - try st.analyze(swiftInterfacePath: "/fake/__FakeModule/SwiftFile.swiftinterface", text: class_interfaceFile) + try st.analyze(file: "Fake.swift", text: class_interfaceFile) let funcDecl: ImportedFunc = st.importedTypes["MySwiftClass"]!.methods.first { $0.baseIdentifier == "helloMemberFunction" }! let output = CodePrinter.toString { printer in - st.printFuncDowncallMethod(&printer, decl: funcDecl, selfVariant: .memorySegment) + st.printFuncDowncallMethod(&printer, decl: funcDecl, paramPassingStyle: .memorySegment) } assertOutput( @@ -306,8 +306,8 @@ final class MethodImportTests { public static void helloMemberFunction(java.lang.foreign.MemorySegment self$) { var mh$ = helloMemberFunction.HANDLE; try { - if (TRACE_DOWNCALLS) { - traceDowncall(self$); + if (SwiftKit.TRACE_DOWNCALLS) { + SwiftKit.traceDowncall(self$); } mh$.invokeExact(self$); } catch (Throwable ex$) { @@ -326,14 +326,14 @@ final class MethodImportTests { ) st.log.logLevel = .info - try st.analyze(swiftInterfacePath: "/fake/__FakeModule/SwiftFile.swiftinterface", text: class_interfaceFile) + try st.analyze(file: "Fake.swift", text: class_interfaceFile) let funcDecl: ImportedFunc = st.importedTypes["MySwiftClass"]!.methods.first { $0.baseIdentifier == "helloMemberFunction" }! let output = CodePrinter.toString { printer in - st.printFuncDowncallMethod(&printer, decl: funcDecl, selfVariant: .wrapper) + st.printFuncDowncallMethod(&printer, decl: funcDecl, paramPassingStyle: .wrapper) } assertOutput( @@ -361,14 +361,14 @@ final class MethodImportTests { ) st.log.logLevel = .info - try st.analyze(swiftInterfacePath: "/fake/__FakeModule/SwiftFile.swiftinterface", text: class_interfaceFile) + try st.analyze(file: "Fake.swift", text: class_interfaceFile) let funcDecl: ImportedFunc = st.importedTypes["MySwiftClass"]!.methods.first { $0.baseIdentifier == "makeInt" }! let output = CodePrinter.toString { printer in - st.printFuncDowncallMethod(&printer, decl: funcDecl, selfVariant: .wrapper) + st.printFuncDowncallMethod(&printer, decl: funcDecl, paramPassingStyle: .wrapper) } assertOutput( @@ -396,14 +396,14 @@ final class MethodImportTests { ) st.log.logLevel = .info - try st.analyze(swiftInterfacePath: "/fake/__FakeModule/SwiftFile.swiftinterface", text: class_interfaceFile) + try st.analyze(file: "Fake.swift", text: class_interfaceFile) let initDecl: ImportedFunc = st.importedTypes["MySwiftClass"]!.initializers.first { $0.identifier == "init(len:cap:)" }! let output = CodePrinter.toString { printer in - st.printClassInitializerConstructors(&printer, initDecl, parentName: initDecl.parentName!) + st.printClassInitializerConstructors(&printer, initDecl, parentName: initDecl.parent!) } assertOutput( @@ -431,8 +431,8 @@ final class MethodImportTests { public MySwiftClass(SwiftArena arena, long len, long cap) { var mh$ = init_len_cap.HANDLE; try { - if (TRACE_DOWNCALLS) { - traceDowncall(len, cap); + if (SwiftKit.TRACE_DOWNCALLS) { + SwiftKit.traceDowncall(len, cap); } this.selfMemorySegment = (MemorySegment) mh$.invokeExact(len, cap, TYPE_METADATA.$memorySegment()); if (arena != null) { diff --git a/Tests/JExtractSwiftTests/MethodThunkTests.swift b/Tests/JExtractSwiftTests/MethodThunkTests.swift new file mode 100644 index 00000000..56eedfa5 --- /dev/null +++ b/Tests/JExtractSwiftTests/MethodThunkTests.swift @@ -0,0 +1,56 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import JExtractSwift +import Testing + +final class MethodThunkTests { + let input = + """ + import Swift + + public func globalFunc(a: Int32, b: Int64) {} + public func globalFunc(a: Double, b: Int64) {} + """ + + @Test("Thunk overloads: globalFunc(a: Int32, b: Int64) & globalFunc(i32: Int32, l: Int64)") + func thunk_overloads() throws { + let st = Swift2JavaTranslator( + javaPackage: "com.example.swift", + swiftModuleName: "FakeModule" + ) + st.log.logLevel = .error + + try assertOutput( + st, input: input, .swift, + detectChunkByInitialLines: 1, + expectedChunks: + [ + """ + @_cdecl("swiftjava_FakeModule_globalFunc_a_b") + public func swiftjava_FakeModule_globalFunc_a_b(a: Int32, b: Int64) /* Void */ { + return globalFunc(a: a, b: b) + } + """, + """ + @_cdecl("swiftjava_FakeModule_globalFunc_a_b$1") + public func swiftjava_FakeModule_globalFunc_a_b$1(a: Double, b: Int64) /* Void */ { + return globalFunc(a: a, b: b) + } + """ + ] + ) + } + +} diff --git a/Tests/JExtractSwiftTests/VariableImportTests.swift b/Tests/JExtractSwiftTests/VariableImportTests.swift index d776b42a..ee562cbd 100644 --- a/Tests/JExtractSwiftTests/VariableImportTests.swift +++ b/Tests/JExtractSwiftTests/VariableImportTests.swift @@ -34,138 +34,166 @@ final class VariableImportTests { """ @Test("Import: var counter: Int") - func variable_() throws { + func variable_int() throws { let st = Swift2JavaTranslator( javaPackage: "com.example.swift", - swiftModuleName: "__FakeModule" + swiftModuleName: "FakeModule" ) st.log.logLevel = .error - try st.analyze(swiftInterfacePath: "/fake/Fake.swiftinterface", text: class_interfaceFile) - - let identifier = "counterInt" - let varDecl: ImportedVariable? = - st.importedTypes.values.compactMap { - $0.variables.first { - $0.identifier == identifier - } - }.first - guard let varDecl else { - fatalError("Cannot find: \(identifier)") - } - - let output = CodePrinter.toString { printer in - st.printVariableDowncallMethods(&printer, varDecl) - } - - assertOutput( - dump: true, - output, - expected: - """ - // ==== -------------------------------------------------- - // counterInt - private static class counterInt { - public static final FunctionDescriptor DESC_GET = FunctionDescriptor.of( + try assertOutput( + st, input: class_interfaceFile, .java, + detectChunkByInitialLines: 7, + expectedChunks: + [ + """ + private static class counterInt { + public static final FunctionDescriptor DESC_GET = FunctionDescriptor.of( /* -> */SWIFT_INT, - SWIFT_POINTER + SWIFT_POINTER ); - public static final MemorySegment ADDR_GET = __FakeModule.findOrThrow("g"); - public static final MethodHandle HANDLE_GET = Linker.nativeLinker().downcallHandle(ADDR_GET, DESC_GET); - public static final FunctionDescriptor DESC_SET = FunctionDescriptor.ofVoid( - SWIFT_INT, - SWIFT_POINTER + public static final MemorySegment ADDR_GET = + FakeModule.findOrThrow("swiftjava_FakeModule_MySwiftClass_counterInt"); + + public static final MethodHandle HANDLE_GET = Linker.nativeLinker().downcallHandle(ADDR_GET, DESC_GET); + public static final FunctionDescriptor DESC_SET = FunctionDescriptor.ofVoid( + SWIFT_INT, + SWIFT_POINTER ); - public static final MemorySegment ADDR_SET = __FakeModule.findOrThrow("s"); - public static final MethodHandle HANDLE_SET = Linker.nativeLinker().downcallHandle(ADDR_SET, DESC_SET); - } - /** - * Function descriptor for: - * - */ - public static FunctionDescriptor counterInt$get$descriptor() { - return counterInt.DESC_GET; - } - /** - * Downcall method handle for: - * - */ - public static MethodHandle counterInt$get$handle() { - return counterInt.HANDLE_GET; - } - /** - * Address for: - * - */ - public static MemorySegment counterInt$get$address() { - return counterInt.ADDR_GET; - } - /** - * Function descriptor for: - * - */ - public static FunctionDescriptor counterInt$set$descriptor() { - return counterInt.DESC_SET; - } - /** - * Downcall method handle for: - * - */ - public static MethodHandle counterInt$set$handle() { - return counterInt.HANDLE_SET; - } - /** - * Address for: - * - */ - public static MemorySegment counterInt$set$address() { - return counterInt.ADDR_SET; - } - /** - * Downcall to Swift: - * - */ - public static long getCounterInt(java.lang.foreign.MemorySegment self$) { - var mh$ = counterInt.HANDLE_GET; + public static final MemorySegment ADDR_SET = + FakeModule.findOrThrow("swiftjava_FakeModule_MySwiftClass_counterInt"); + + public static final MethodHandle HANDLE_SET = Linker.nativeLinker().downcallHandle(ADDR_SET, DESC_SET); + } + """, + """ + /** + * Function descriptor for: + * {@snippet lang=swift : + * public var counterInt: Int + * } + */ + public static FunctionDescriptor counterInt$get$descriptor() { + return counterInt.DESC_GET; + } + """, + """ + /** + * Downcall method handle for: + * {@snippet lang=swift : + * public var counterInt: Int + * } + */ + public static MethodHandle counterInt$get$handle() { + return counterInt.HANDLE_GET; + } + """, + """ + /** + * Address for: + * {@snippet lang=swift : + * public var counterInt: Int + * } + */ + public static MemorySegment counterInt$get$address() { + return counterInt.ADDR_GET; + } + """, + """ + /** + * Function descriptor for: + * {@snippet lang=swift : + * public var counterInt: Int + * } + */ + public static FunctionDescriptor counterInt$set$descriptor() { + return counterInt.DESC_SET; + } + """ + , + """ + /** + * Downcall method handle for: + * {@snippet lang=swift : + * public var counterInt: Int + * } + */ + public static MethodHandle counterInt$set$handle() { + return counterInt.HANDLE_SET; + } + """, + """ + /** + * Address for: + * {@snippet lang=swift : + * public var counterInt: Int + * } + */ + public static MemorySegment counterInt$set$address() { + return counterInt.ADDR_SET; + } + """, + """ + /** + * Downcall to Swift: + * {@snippet lang=swift : + * public var counterInt: Int + * } + */ + public static long getCounterInt(java.lang.foreign.MemorySegment self$) { + var mh$ = counterInt.HANDLE_GET; + try { + if (SwiftKit.TRACE_DOWNCALLS) { + SwiftKit.traceDowncall(self$); + } + return (long) mh$.invokeExact(self$); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + """, + """ + /** + * Downcall to Swift: + * {@snippet lang=swift : + * public var counterInt: Int + * } + */ + public long getCounterInt() { + return (long) getCounterInt($memorySegment()); + } + """, + """ + /** + * Downcall to Swift: + * {@snippet lang=swift : + * public var counterInt: Int + * } + */ + public static void setCounterInt(long newValue, java.lang.foreign.MemorySegment self$) { + var mh$ = counterInt.HANDLE_SET; try { - if (TRACE_DOWNCALLS) { - traceDowncall(self$); - } - return (long) mh$.invokeExact(self$); + if (SwiftKit.TRACE_DOWNCALLS) { + SwiftKit.traceDowncall(newValue, self$); + } + mh$.invokeExact(newValue, self$); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } - } - /** - * Downcall to Swift: - * - */ - public long getCounterInt() { - return (long) getCounterInt($memorySegment()); - } - /** - * Downcall to Swift: - * - */ - public static void setCounterInt(long newValue, java.lang.foreign.MemorySegment self$) { - var mh$ = counterInt.HANDLE_SET; - try { - if (TRACE_DOWNCALLS) { - traceDowncall(newValue, self$); - } - mh$.invokeExact(newValue, self$); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); } - } - /** - * Downcall to Swift: - * - */ - public void setCounterInt(long newValue) { - setCounterInt(newValue, $memorySegment()); - } - """ + """, + """ + /** + * Downcall to Swift: + * {@snippet lang=swift : + * public var counterInt: Int + * } + */ + public void setCounterInt(long newValue) { + setCounterInt(newValue, $memorySegment()); + } + """ + ] ) } } diff --git a/WIP.md b/WIP.md index c8a6255d..e1f58612 100644 --- a/WIP.md +++ b/WIP.md @@ -32,50 +32,3 @@ improve: - [ ] Investigate "unbridged" variants of String, Array, etc. - [ ] Investigate the new [Foreign Function & Memory API](https://bugs.openjdk.org/browse/JDK-8312523) (aka Project Panama) for exposing Swift APIs to Java. - -### jextract-swift - -Separate todo list for the jextract / panama side of the project: - -Calling convention: -- [x] Call swift methods, take parameters, return values -- [ ] How to call a **throwing** Swift function from Java -- [ ] How to call a **generic** Swift function from Java - - [ ] How to pass "call me back" (Callable, Runnable) to Swift, and make an **up-call** -- [ ] How to support passing a struct **inout** `SwiftValue` to Swift so that Java side sees change - -Bridges: -- [ ] Java **Optional** / Swift Optional - depends on generics (!) -- [ ] Efficient **String** / SwiftString wrappers and converters -- [ ] Handle byte buffers and pointers properly -- [ ] Converters for **Array** -- [ ] Converters for **List** and common collections? -- [ ] expose Swift collections as some bridged type implementing java.util.Collection? -- [ ] Import Swift **enums** - -Importer: -- [x] import global functions into the `Module.theFunction` on Java side -- [x] import functions with parameters -- [x] import functions return values -- [ ] import instance member functions using "wrapper" pattern -- [ ] handle types like `[any Thing]?`, we can't parse them right now even -- [ ] support nested types in Swift -- [ ] handle types like `any Thing`, importer does not understand `any` or `some` - -Programming model: -- [ ] Which style of ownership for Java class wrapping a Swift Class - - [x] __allocating_init, how to release/destroy from Java - - [x] Offer explicit swift_**release** / swift_**retain** functions - - [ ] Offer some way to make Immortal class instance - - [ ] **SwiftArena** which retains/destroys underlying Swift class? -- [ ] How to create a Swift struct - -Swift Compiler work: -- [x] Expose **mangled names** of types and methods in .swiftinterface -- [ ] Expose **@layout** of class, struct etc. types in .swiftinterface -- [ ] Expose `demangle` function to human-readable text; it'd be good for usability - -Build: -- [x] Gradle build for Java parts of samples and "SwiftKit" utilities -- [x] Build Swift dependencies when building Java samples automatically -- [ ] JMH benchmarks diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle index a61e5793..c18f30c1 100644 --- a/buildSrc/build.gradle +++ b/buildSrc/build.gradle @@ -15,3 +15,12 @@ repositories { mavenCentral() } + +def cleanSwift = tasks.register("cleanSwift", Exec) { + workingDir = layout.projectDirectory + commandLine "swift" + args("package", "clean") +} +tasks.clean { + dependsOn("cleanSwift") +} diff --git a/buildSrc/src/main/groovy/org/swift/swiftkit/gradle/BuildUtils.groovy b/buildSrc/src/main/groovy/org/swift/swiftkit/gradle/BuildUtils.groovy index 2e09d11b..4fcddbee 100644 --- a/buildSrc/src/main/groovy/org/swift/swiftkit/gradle/BuildUtils.groovy +++ b/buildSrc/src/main/groovy/org/swift/swiftkit/gradle/BuildUtils.groovy @@ -23,7 +23,7 @@ final class BuildUtils { def isLinux = osName.toLowerCase(Locale.getDefault()).contains("linux") def base = rootDir == null ? "" : "${rootDir}/" - return [ + def debugPaths = [ isLinux ? /* Linux */ (osArch == "amd64" || osArch == "x86_64" ? "${base}.build/x86_64-unknown-linux-gnu/debug/" : @@ -38,10 +38,21 @@ final class BuildUtils { /* macOS */ (osArch == "aarch64" ? "${base}../../.build/arm64-apple-macosx/debug/" : "${base}../../.build/${osArch}-apple-macosx/debug/"), - isLinux ? - "/usr/lib/swift/linux" : - // assume macOS - "/usr/lib/swift/" ] + def releasePaths = debugPaths.collect { it.replaceAll("debug", "release") } + def systemPaths = + // system paths + isLinux ? + [ + "/usr/lib/swift/linux", + // TODO: should we be Swiftly aware and then use the currently used path? + System.getProperty("user.home") + "/.local/share/swiftly/toolchains/6.0.2/usr/lib/swift/linux" + ] : + [ + // assume macOS + "/usr/lib/swift/" + ] + + return releasePaths + debugPaths + systemPaths } } diff --git a/docker/Dockerfile b/docker/Dockerfile index c4711253..c68ccc3c 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -26,5 +26,5 @@ ENV PATH="$PATH:/usr/lib/jvm/default-jdk/bin" # Install "untested" nightly 'main' Swift # TODO: Only do this if the released Swift is older than what we require -COPY install_untested_nightly_swift.sh . -RUN bash -xc './install_untested_nightly_swift.sh' +#COPY install_untested_nightly_swift.sh . +RUN #bash -xc './install_untested_nightly_swift.sh' diff --git a/docker/install_jdk.sh b/docker/install_jdk.sh index 0d63eaf9..8aa295ce 100755 --- a/docker/install_jdk.sh +++ b/docker/install_jdk.sh @@ -76,10 +76,7 @@ fi mkdir -p /usr/lib/jvm/ mv jdk.tar.gz /usr/lib/jvm/ cd /usr/lib/jvm/ -ls tar xzvf jdk.tar.gz && rm jdk.tar.gz -ls -find . -depth -maxdepth 1 -type d mv "$(find . -depth -maxdepth 1 -type d | head -n1)" default-jdk echo "JAVA_HOME = /usr/lib/jvm/default-jdk" diff --git a/settings.gradle b/settings.gradle index 3a0bd106..fa0fa5bd 100644 --- a/settings.gradle +++ b/settings.gradle @@ -26,4 +26,3 @@ new File(rootDir, "Samples").listFiles().each { include ":Samples:${it.name}" } } - From 867128b1b74ab54c9b6f2944d861c148490655eb Mon Sep 17 00:00:00 2001 From: Jack Rosen Date: Thu, 14 Nov 2024 23:25:08 -0500 Subject: [PATCH 182/426] Fail Macro Expansion if JavaStaticField is used in non-class (#174) --- Sources/JavaKitMacros/JavaFieldMacro.swift | 15 +++++ .../JavaClassMacroTests.swift | 57 ++++++++++++++++++- 2 files changed, 71 insertions(+), 1 deletion(-) diff --git a/Sources/JavaKitMacros/JavaFieldMacro.swift b/Sources/JavaKitMacros/JavaFieldMacro.swift index 7f60f26d..29eb966c 100644 --- a/Sources/JavaKitMacros/JavaFieldMacro.swift +++ b/Sources/JavaKitMacros/JavaFieldMacro.swift @@ -33,6 +33,11 @@ extension JavaFieldMacro: AccessorMacro { return [] } + let isStatic = node.attributeName.trimmedDescription == "JavaStaticField" + guard !isStatic || isInJavaClassContext(context: context) else { + throw MacroExpansionErrorMessage("Cannot use @JavaStaticField outside of a JavaClass instance") + } + // Dig out the Java field name, if provided. Otherwise, use the name as written. let fieldName = if case .argumentList(let arguments) = node.arguments, @@ -79,4 +84,14 @@ extension JavaFieldMacro: AccessorMacro { return accessors } + + private static func isInJavaClassContext(context: some MacroExpansionContext) -> Bool { + for lexicalContext in context.lexicalContext { + if let classSyntax = lexicalContext.as(ExtensionDeclSyntax.self) { + return classSyntax.extendedType.trimmedDescription.starts(with: "JavaClass") + } + } + + return false + } } diff --git a/Tests/JavaKitMacroTests/JavaClassMacroTests.swift b/Tests/JavaKitMacroTests/JavaClassMacroTests.swift index e639800b..1dc08ba8 100644 --- a/Tests/JavaKitMacroTests/JavaClassMacroTests.swift +++ b/Tests/JavaKitMacroTests/JavaClassMacroTests.swift @@ -23,9 +23,64 @@ class JavaKitMacroTests: XCTestCase { static let javaKitMacros: [String: any Macro.Type] = [ "JavaClass": JavaClassMacro.self, "JavaMethod": JavaMethodMacro.self, - "JavaField": JavaFieldMacro.self + "JavaField": JavaFieldMacro.self, + "JavaStaticField": JavaFieldMacro.self ] + func testJavaStaticMethodFailure() throws { + assertMacroExpansion( + """ + @JavaClass("org.swift.example.HelloWorld") + public class HelloWorld { + @JavaStaticField + public var test: String + } + """, + expandedSource: """ + + public class HelloWorld { + public var test: String + + /// The full Java class name for this Swift type. + open override class var fullJavaClassName: String { + "org.swift.example.HelloWorld" + } + + public required init(javaHolder: JavaObjectHolder) { + super.init(javaHolder: javaHolder) + } + } + """, + diagnostics: [DiagnosticSpec(message: "Cannot use @JavaStaticField outside of a JavaClass instance", line: 3, column: 5)], + macros: Self.javaKitMacros + ) + } + + func testJavaStaticMethodSuccess() throws { + assertMacroExpansion( + """ + extension JavaClass { + @JavaStaticField + public var test: String + } + """, + expandedSource: """ + + extension JavaClass { + public var test: String { + get { + self[javaFieldName: "test", fieldType: String.self] + } + set { + self[javaFieldName: "test", fieldType: String.self] = newValue + } + } + } + """, + macros: Self.javaKitMacros + ) + } + func testJavaClass() throws { assertMacroExpansion(""" @JavaClass("org.swift.example.HelloWorld") From 3ceb6efaca177493e3403669399ab4cd740c192f Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Fri, 15 Nov 2024 17:04:01 +0900 Subject: [PATCH 183/426] use -print-target-info to get swift library paths reliably (#178) --- .licenseignore | 1 + BuildLogic/build.gradle.kts | 5 ++ ...d-logic.java-common-conventions.gradle.kts | 77 ++++++++++++------- buildSrc/build.gradle | 4 + .../swift/swiftkit/gradle/BuildUtils.groovy | 30 ++++---- 5 files changed, 75 insertions(+), 42 deletions(-) diff --git a/.licenseignore b/.licenseignore index c5dfe3d2..04a64766 100644 --- a/.licenseignore +++ b/.licenseignore @@ -40,3 +40,4 @@ gradlew.bat **/gradlew **/gradlew.bat **/ci-validate.sh +**/DO_NOT_EDIT.txt diff --git a/BuildLogic/build.gradle.kts b/BuildLogic/build.gradle.kts index 142b7f7c..f64d3e94 100644 --- a/BuildLogic/build.gradle.kts +++ b/BuildLogic/build.gradle.kts @@ -14,6 +14,11 @@ repositories { gradlePluginPortal() + mavenCentral() +} + +dependencies { + implementation("org.jetbrains.kotlinx:kotlinx-serialization-json-jvm:1.7.3") } plugins { diff --git a/BuildLogic/src/main/kotlin/build-logic.java-common-conventions.gradle.kts b/BuildLogic/src/main/kotlin/build-logic.java-common-conventions.gradle.kts index 136da7d3..ef88ce15 100644 --- a/BuildLogic/src/main/kotlin/build-logic.java-common-conventions.gradle.kts +++ b/BuildLogic/src/main/kotlin/build-logic.java-common-conventions.gradle.kts @@ -14,6 +14,8 @@ import java.util.* import java.io.* +import kotlin.system.exitProcess +import kotlinx.serialization.json.* plugins { java @@ -44,41 +46,60 @@ tasks.withType(JavaCompile::class).forEach { } -// FIXME: cannot share definition with 'buildSrc' so we duplicated the impl here -fun javaLibraryPaths(dir: File): List { - val osName = System.getProperty("os.name") +fun getSwiftRuntimeLibraryPaths(): List { + val process = ProcessBuilder("swiftc", "-print-target-info") + .redirectError(ProcessBuilder.Redirect.INHERIT) + .start() + + val output = process.inputStream.bufferedReader().use { it.readText() } + val exitCode = process.waitFor() + if (exitCode != 0) { + System.err.println("Error executing swiftc -print-target-info") + exitProcess(exitCode) + } + + val json = Json.parseToJsonElement(output) + val runtimeLibraryPaths = json.jsonObject["paths"]?.jsonObject?.get("runtimeLibraryPaths")?.jsonArray + return runtimeLibraryPaths?.map { it.jsonPrimitive.content } ?: emptyList() +} + +/** + * Find library paths for 'java.library.path' when running or testing projects inside this build. + */ +// TODO: can't figure out how to share this code between BuildLogic/ and buildSrc/ +fun javaLibraryPaths(rootDir: File): List { + val osName = System.getProperty("os.name").lowercase(Locale.getDefault()) val osArch = System.getProperty("os.arch") - val isLinux = osName.lowercase(Locale.getDefault()).contains("linux") + val isLinux = osName.contains("linux") + val base = rootDir.path.let { "$it/" } - return listOf( - if (isLinux) { - if (osArch.equals("x86_64") || osArch.equals("amd64")) { - "$dir/.build/x86_64-unknown-linux-gnu/debug/" - } else { - "$dir/.build/$osArch-unknown-linux-gnu/debug/" - } - } else { - if (osArch.equals("aarch64")) { - "$dir/.build/arm64-apple-macosx/debug/" - } else { - "$dir/.build/$osArch-apple-macosx/debug/" - } - }, + val projectBuildOutputPath = if (isLinux) { - "/usr/lib/swift/linux" + if (osArch == "amd64" || osArch == "x86_64") + "$base.build/x86_64-unknown-linux-gnu" + else + "$base.build/${osArch}-unknown-linux-gnu" } else { - // assume macOS - "/usr/lib/swift/" - }, - if (isLinux) { - System.getProperty("user.home") + "/.local/share/swiftly/toolchains/6.0.2/usr/lib/swift/linux" - } else { - // assume macOS - "/usr/lib/swift/" + if (osArch == "aarch64") + "$base.build/arm64-apple-macosx" + else + "$base.build/${osArch}-apple-macosx" } + val parentParentBuildOutputPath = + "../../$projectBuildOutputPath" + + + val swiftBuildOutputPaths = listOf( + projectBuildOutputPath, + parentParentBuildOutputPath ) -} + val debugBuildOutputPaths = swiftBuildOutputPaths.map { "$it/debug" } + val releaseBuildOutputPaths = swiftBuildOutputPaths.map { "$it/release" } + val swiftRuntimePaths = getSwiftRuntimeLibraryPaths() + + return debugBuildOutputPaths + releaseBuildOutputPaths + swiftRuntimePaths +} // Configure paths for native (Swift) libraries tasks.test { diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle index c18f30c1..925db83f 100644 --- a/buildSrc/build.gradle +++ b/buildSrc/build.gradle @@ -16,6 +16,10 @@ repositories { mavenCentral() } +dependencies { + implementation("org.jetbrains.kotlinx:kotlinx-serialization-json-jvm:1.7.3") +} + def cleanSwift = tasks.register("cleanSwift", Exec) { workingDir = layout.projectDirectory commandLine "swift" diff --git a/buildSrc/src/main/groovy/org/swift/swiftkit/gradle/BuildUtils.groovy b/buildSrc/src/main/groovy/org/swift/swiftkit/gradle/BuildUtils.groovy index 4fcddbee..9512307f 100644 --- a/buildSrc/src/main/groovy/org/swift/swiftkit/gradle/BuildUtils.groovy +++ b/buildSrc/src/main/groovy/org/swift/swiftkit/gradle/BuildUtils.groovy @@ -14,8 +14,21 @@ package org.swift.swiftkit.gradle +import groovy.json.JsonSlurper + final class BuildUtils { + static List getSwiftRuntimeLibraryPaths() { + def process = ['swiftc', '-print-target-info'].execute() + def output = new StringWriter() + process.consumeProcessOutput(output, System.err) + process.waitFor() + + def json = new JsonSlurper().parseText(output.toString()) + def runtimeLibraryPaths = json.paths.runtimeLibraryPaths + return runtimeLibraryPaths + } + /// Find library paths for 'java.library.path' when running or testing projects inside this build. static def javaLibraryPaths(File rootDir) { def osName = System.getProperty("os.name") @@ -40,19 +53,8 @@ final class BuildUtils { "${base}../../.build/${osArch}-apple-macosx/debug/"), ] def releasePaths = debugPaths.collect { it.replaceAll("debug", "release") } - def systemPaths = - // system paths - isLinux ? - [ - "/usr/lib/swift/linux", - // TODO: should we be Swiftly aware and then use the currently used path? - System.getProperty("user.home") + "/.local/share/swiftly/toolchains/6.0.2/usr/lib/swift/linux" - ] : - [ - // assume macOS - "/usr/lib/swift/" - ] - - return releasePaths + debugPaths + systemPaths + def swiftRuntimePaths = getSwiftRuntimeLibraryPaths() + + return releasePaths + debugPaths + swiftRuntimePaths } } From 82b5e601ab945b2fe17dfc9e237fbc484639f4dc Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Tue, 19 Nov 2024 10:47:20 +0900 Subject: [PATCH 184/426] Sample for making jars with dylibs (#180) --- .../JExtractSwiftPlugin.swift | 10 + Samples/SwiftAndJavaJarSampleLib/Example.java | 23 +++ .../SwiftAndJavaJarSampleLib/Package.swift | 77 ++++++++ .../MySwiftLibrary/MySwiftLibrary.swift | 101 ++++++++++ .../Sources/MySwiftLibrary/swift-java.config | 3 + Samples/SwiftAndJavaJarSampleLib/build.gradle | 184 ++++++++++++++++++ Samples/SwiftAndJavaJarSampleLib/gradlew | 1 + Samples/SwiftAndJavaJarSampleLib/gradlew.bat | 1 + .../swift/swiftkit/JavaToSwiftBenchmark.java | 54 +++++ .../com/example/swift/HelloJava2Swift.java | 59 ++++++ .../com/example/swift/MySwiftClassTest.java | 67 +++++++ .../com/example/swift/MySwiftLibraryTest.java | 65 +++++++ .../org/swift/swiftkit/MySwiftClassTest.java | 39 ++++ .../org/swift/swiftkit/SwiftArenaTest.java | 75 +++++++ .../Swift2JavaTranslator+Printing.swift | 6 +- .../java/org/swift/swiftkit/SwiftKit.java | 93 ++++++--- .../swift/swiftkit/util/PlatformUtils.java | 15 ++ 17 files changed, 844 insertions(+), 29 deletions(-) create mode 100644 Samples/SwiftAndJavaJarSampleLib/Example.java create mode 100644 Samples/SwiftAndJavaJarSampleLib/Package.swift create mode 100644 Samples/SwiftAndJavaJarSampleLib/Sources/MySwiftLibrary/MySwiftLibrary.swift create mode 100644 Samples/SwiftAndJavaJarSampleLib/Sources/MySwiftLibrary/swift-java.config create mode 100644 Samples/SwiftAndJavaJarSampleLib/build.gradle create mode 120000 Samples/SwiftAndJavaJarSampleLib/gradlew create mode 120000 Samples/SwiftAndJavaJarSampleLib/gradlew.bat create mode 100644 Samples/SwiftAndJavaJarSampleLib/src/jmh/java/org/swift/swiftkit/JavaToSwiftBenchmark.java create mode 100644 Samples/SwiftAndJavaJarSampleLib/src/main/java/com/example/swift/HelloJava2Swift.java create mode 100644 Samples/SwiftAndJavaJarSampleLib/src/test/java/com/example/swift/MySwiftClassTest.java create mode 100644 Samples/SwiftAndJavaJarSampleLib/src/test/java/com/example/swift/MySwiftLibraryTest.java create mode 100644 Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/MySwiftClassTest.java create mode 100644 Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/SwiftArenaTest.java diff --git a/Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift b/Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift index f23a1dbf..94cd4aa6 100644 --- a/Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift +++ b/Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift @@ -23,6 +23,16 @@ struct JExtractSwiftBuildToolPlugin: BuildToolPlugin { // Note: Target doesn't have a directoryURL counterpart to directory, // so we cannot eliminate this deprecation warning. let sourceDir = target.directory.string + + let t = target.dependencies.first! + switch (t) { + case .target(let t): + t.sourceModule + case .product(let p): + p.sourceModules + @unknown default: + fatalError("Unknown target dependency type: \(t)") + } let toolURL = try context.tool(named: "JExtractSwiftTool").url let configuration = try readConfiguration(sourceDir: "\(sourceDir)") diff --git a/Samples/SwiftAndJavaJarSampleLib/Example.java b/Samples/SwiftAndJavaJarSampleLib/Example.java new file mode 100644 index 00000000..b5a2697b --- /dev/null +++ b/Samples/SwiftAndJavaJarSampleLib/Example.java @@ -0,0 +1,23 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import com.example.swift.MySwiftLibrary; + +public class Example { + + public static void main(String[] args) { + MySwiftLibrary.helloWorld(); + } + +} diff --git a/Samples/SwiftAndJavaJarSampleLib/Package.swift b/Samples/SwiftAndJavaJarSampleLib/Package.swift new file mode 100644 index 00000000..5f132239 --- /dev/null +++ b/Samples/SwiftAndJavaJarSampleLib/Package.swift @@ -0,0 +1,77 @@ +// swift-tools-version: 6.0 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import CompilerPluginSupport +import PackageDescription + +import class Foundation.FileManager +import class Foundation.ProcessInfo + +// Note: the JAVA_HOME environment variable must be set to point to where +// Java is installed, e.g., +// Library/Java/JavaVirtualMachines/openjdk-21.jdk/Contents/Home. +func findJavaHome() -> String { + if let home = ProcessInfo.processInfo.environment["JAVA_HOME"] { + return home + } + + // This is a workaround for envs (some IDEs) which have trouble with + // picking up env variables during the build process + let path = "\(FileManager.default.homeDirectoryForCurrentUser.path()).java_home" + if let home = try? String(contentsOfFile: path, encoding: .utf8) { + if let lastChar = home.last, lastChar.isNewline { + return String(home.dropLast()) + } + + return home + } + + fatalError("Please set the JAVA_HOME environment variable to point to where Java is installed.") +} +let javaHome = findJavaHome() + +let javaIncludePath = "\(javaHome)/include" +#if os(Linux) + let javaPlatformIncludePath = "\(javaIncludePath)/linux" +#elseif os(macOS) + let javaPlatformIncludePath = "\(javaIncludePath)/darwin" +#else + // TODO: Handle windows as well + #error("Currently only macOS and Linux platforms are supported, this may change in the future.") +#endif + +let package = Package( + name: "SwiftAndJavaJarSampleLib", + platforms: [ + .macOS(.v10_15) + ], + products: [ + .library( + name: "MySwiftLibrary", + type: .dynamic, + targets: ["MySwiftLibrary"] + ), + + ], + dependencies: [ + .package(name: "swift-java", path: "../../"), + ], + targets: [ + .target( + name: "MySwiftLibrary", + dependencies: [ + .product(name: "SwiftKitSwift", package: "swift-java"), + ], + exclude: [ + "swift-java.config", + ], + swiftSettings: [ + .swiftLanguageMode(.v5), + .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) + ], + plugins: [ + .plugin(name: "JExtractSwiftPlugin", package: "swift-java"), + ] + ), + ] +) diff --git a/Samples/SwiftAndJavaJarSampleLib/Sources/MySwiftLibrary/MySwiftLibrary.swift b/Samples/SwiftAndJavaJarSampleLib/Sources/MySwiftLibrary/MySwiftLibrary.swift new file mode 100644 index 00000000..84e4618f --- /dev/null +++ b/Samples/SwiftAndJavaJarSampleLib/Sources/MySwiftLibrary/MySwiftLibrary.swift @@ -0,0 +1,101 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +// This is a "plain Swift" file containing various types of declarations, +// that is exported to Java by using the `jextract-swift` tool. +// +// No annotations are necessary on the Swift side to perform the export. + +#if os(Linux) +import Glibc +#else +import Darwin.C +#endif + +public func helloWorld() { + p("\(#function)") +} + +public func globalTakeInt(i: Int) { + p("i:\(i)") +} + +public func globalTakeIntInt(i: Int, j: Int) { + p("i:\(i), j:\(j)") +} + +public func globalCallMeRunnable(run: () -> ()) { + run() +} + +public class MySwiftClass { + + public var len: Int + public var cap: Int + + public init(len: Int, cap: Int) { + self.len = len + self.cap = cap + + p("\(MySwiftClass.self).len = \(self.len)") + p("\(MySwiftClass.self).cap = \(self.cap)") + let addr = unsafeBitCast(self, to: UInt64.self) + p("initializer done, self = 0x\(String(addr, radix: 16, uppercase: true))") + } + + deinit { + let addr = unsafeBitCast(self, to: UInt64.self) + p("Deinit, self = 0x\(String(addr, radix: 16, uppercase: true))") + } + + public var counter: Int32 = 0 + + public func voidMethod() { + p("") + } + + public func takeIntMethod(i: Int) { + p("i:\(i)") + } + + public func echoIntMethod(i: Int) -> Int { + p("i:\(i)") + return i + } + + public func makeIntMethod() -> Int { + p("make int -> 12") + return 12 + } + + public func makeRandomIntMethod() -> Int { + return Int.random(in: 1..<256) + } +} + +// ==== Internal helpers + +private func p(_ msg: String, file: String = #fileID, line: UInt = #line, function: String = #function) { + print("[swift][\(file):\(line)](\(function)) \(msg)") + fflush(stdout) +} + +#if os(Linux) +// FIXME: why do we need this workaround? +@_silgen_name("_objc_autoreleaseReturnValue") +public func _objc_autoreleaseReturnValue(a: Any) {} + +@_silgen_name("objc_autoreleaseReturnValue") +public func objc_autoreleaseReturnValue(a: Any) {} +#endif diff --git a/Samples/SwiftAndJavaJarSampleLib/Sources/MySwiftLibrary/swift-java.config b/Samples/SwiftAndJavaJarSampleLib/Sources/MySwiftLibrary/swift-java.config new file mode 100644 index 00000000..6e5bc2af --- /dev/null +++ b/Samples/SwiftAndJavaJarSampleLib/Sources/MySwiftLibrary/swift-java.config @@ -0,0 +1,3 @@ +{ + "javaPackage": "com.example.swift" +} diff --git a/Samples/SwiftAndJavaJarSampleLib/build.gradle b/Samples/SwiftAndJavaJarSampleLib/build.gradle new file mode 100644 index 00000000..2125011d --- /dev/null +++ b/Samples/SwiftAndJavaJarSampleLib/build.gradle @@ -0,0 +1,184 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + + +import groovy.json.JsonSlurper +import org.swift.swiftkit.gradle.BuildUtils + +import java.nio.file.* + +plugins { + id("build-logic.java-library-conventions") + id "com.google.osdetector" version "1.7.3" + id("maven-publish") +} + +group = "org.swift.swiftkit" +version = "1.0-SNAPSHOT" + +def swiftBuildConfiguration() { + "release" +} + +repositories { + mavenLocal() + mavenCentral() +} + +java { + toolchain { + languageVersion.set(JavaLanguageVersion.of(22)) + } +} + +dependencies { + implementation(project(':SwiftKit')) + + testImplementation(platform("org.junit:junit-bom:5.10.0")) + testImplementation("org.junit.jupiter:junit-jupiter") +} + +// This is for development, when we edit the Swift swift-java project, the outputs of the generated sources may change. +// Thus, we also need to watch and re-build the top level project. +def compileSwiftJExtractPlugin = tasks.register("compileSwiftJExtractPlugin", Exec) { + description = "Rebuild the swift-java root project" + + inputs.file(new File(rootDir, "Package.swift")) + inputs.dir(new File(rootDir, "Sources")) + outputs.dir(new File(rootDir, ".build")) + + workingDir = rootDir + commandLine "swift" + args("build", + "-c", swiftBuildConfiguration(), + "--product", "SwiftKitSwift", + "--product", "JExtractSwiftPlugin", + "--product", "JExtractSwiftCommandPlugin") +} + +def jextract = tasks.register("jextract", Exec) { + description = "Builds swift sources, including swift-java source generation" + dependsOn compileSwiftJExtractPlugin + + // only because we depend on "live developing" the plugin while using this project to test it + inputs.file(new File(rootDir, "Package.swift")) + inputs.dir(new File(rootDir, "Sources")) + + inputs.file(new File(projectDir, "Package.swift")) + inputs.dir(new File(projectDir, "Sources")) + + // TODO: we can use package describe --type json to figure out which targets depend on JExtractSwiftPlugin and will produce outputs + // Avoid adding this directory, but create the expected one specifically for all targets + // which WILL produce sources because they have the plugin + outputs.dir(layout.buildDirectory.dir("../.build/plugins/outputs/${layout.projectDirectory.asFile.getName().toLowerCase()}")) + + File baseSwiftPluginOutputsDir = layout.buildDirectory.dir("../.build/plugins/outputs/").get().asFile + if (!baseSwiftPluginOutputsDir.exists()) { + baseSwiftPluginOutputsDir.mkdirs() + } + Files.walk(layout.buildDirectory.dir("../.build/plugins/outputs/").get().asFile.toPath()).each { + // Add any Java sources generated by the plugin to our sourceSet + if (it.endsWith("JExtractSwiftPlugin/src/generated/java")) { + outputs.dir(it) + } + } + + workingDir = layout.projectDirectory + commandLine "swift" + args("package", "jextract", "-v", "--log-level", "info") // TODO: pass log level from Gradle build +} + + +// Add the java-swift generated Java sources +sourceSets { + main { + java { + srcDir(jextract) + } + } + test { + java { + srcDir(jextract) + } + } +} + +tasks.build { + dependsOn("jextract") +} + +tasks.named('test', Test) { + useJUnitPlatform() +} + + +// ==== Jar publishing + +List swiftProductDylibPaths() { + + def process = ['swift', 'package', 'describe', '--type', 'json'].execute() + process.waitFor() + + if (process.exitValue() != 0) { + throw new RuntimeException("[swift describe] command failed with exit code: ${process.exitValue()}. Cannot find products! Output: ${process.err.text}") + } + + def json = new JsonSlurper().parseText(process.text) + + // TODO: require that we depend on swift-java + // TODO: all the products where the targets depend on swift-java plugin + def products = + json.targets.collect { target -> + target.product_memberships + }.flatten() + + + + def productDylibPaths = products.collect { + logger.info("[swift-java] Include Swift product: '${it}' in product resource paths.") + "${layout.projectDirectory}/.build/${swiftBuildConfiguration()}/lib${it}.dylib" + } + + return productDylibPaths +} + +processResources { + dependsOn "jextract" + + def dylibs = [ + "${layout.projectDirectory}/.build/${swiftBuildConfiguration()}/libSwiftKitSwift.dylib" + ] + dylibs.addAll(swiftProductDylibPaths()) + from(dylibs) +} + +jar { + archiveClassifier = osdetector.classifier +} + +base { + archivesName = "swift-and-java-jar-sample-lib" +} + +publishing { + publications { + maven(MavenPublication) { + artifactId = "swift-and-java-jar-sample-lib" + from components.java + } + } + repositories { + mavenLocal() + } +} diff --git a/Samples/SwiftAndJavaJarSampleLib/gradlew b/Samples/SwiftAndJavaJarSampleLib/gradlew new file mode 120000 index 00000000..343e0d2c --- /dev/null +++ b/Samples/SwiftAndJavaJarSampleLib/gradlew @@ -0,0 +1 @@ +../../gradlew \ No newline at end of file diff --git a/Samples/SwiftAndJavaJarSampleLib/gradlew.bat b/Samples/SwiftAndJavaJarSampleLib/gradlew.bat new file mode 120000 index 00000000..cb5a9464 --- /dev/null +++ b/Samples/SwiftAndJavaJarSampleLib/gradlew.bat @@ -0,0 +1 @@ +../../gradlew.bat \ No newline at end of file diff --git a/Samples/SwiftAndJavaJarSampleLib/src/jmh/java/org/swift/swiftkit/JavaToSwiftBenchmark.java b/Samples/SwiftAndJavaJarSampleLib/src/jmh/java/org/swift/swiftkit/JavaToSwiftBenchmark.java new file mode 100644 index 00000000..614697a3 --- /dev/null +++ b/Samples/SwiftAndJavaJarSampleLib/src/jmh/java/org/swift/swiftkit/JavaToSwiftBenchmark.java @@ -0,0 +1,54 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package org.swift.swiftkit; + +import java.util.concurrent.TimeUnit; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.infra.Blackhole; + +import com.example.swift.MySwiftClass; + +@SuppressWarnings("unused") +public class JavaToSwiftBenchmark { + + @State(Scope.Benchmark) + public static class BenchmarkState { + MySwiftClass obj; + + @Setup(Level.Trial) + public void beforeALl() { + System.loadLibrary("swiftCore"); + System.loadLibrary("ExampleSwiftLibrary"); + + // Tune down debug statements so they don't fill up stdout + System.setProperty("jextract.trace.downcalls", "false"); + + obj = new MySwiftClass(1, 2); + } + } + + @Benchmark @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.NANOSECONDS) + public void simpleSwiftApiCall(BenchmarkState state, Blackhole blackhole) { + blackhole.consume(state.obj.makeRandomIntMethod()); + } +} diff --git a/Samples/SwiftAndJavaJarSampleLib/src/main/java/com/example/swift/HelloJava2Swift.java b/Samples/SwiftAndJavaJarSampleLib/src/main/java/com/example/swift/HelloJava2Swift.java new file mode 100644 index 00000000..2a86e403 --- /dev/null +++ b/Samples/SwiftAndJavaJarSampleLib/src/main/java/com/example/swift/HelloJava2Swift.java @@ -0,0 +1,59 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package com.example.swift; + +// Import swift-extract generated sources + +import com.example.swift.MySwiftLibrary; +import com.example.swift.MySwiftClass; + +// Import javakit/swiftkit support libraries +import org.swift.swiftkit.SwiftArena; +import org.swift.swiftkit.SwiftKit; +import org.swift.swiftkit.SwiftValueWitnessTable; + +import java.util.Arrays; + +public class HelloJava2Swift { + + public static void main(String[] args) { + boolean traceDowncalls = Boolean.getBoolean("jextract.trace.downcalls"); + System.out.println("Property: jextract.trace.downcalls = " + traceDowncalls); + + System.out.print("Property: java.library.path = " +SwiftKit.getJavaLibraryPath()); + + examples(); + } + + static void examples() { + MySwiftLibrary.helloWorld(); + + MySwiftLibrary.globalTakeInt(1337); + + // Example of using an arena; MyClass.deinit is run at end of scope + try (var arena = SwiftArena.ofConfined()) { + MySwiftClass obj = new MySwiftClass(arena, 2222, 7777); + + // just checking retains/releases work + SwiftKit.retain(obj.$memorySegment()); + SwiftKit.release(obj.$memorySegment()); + + obj.voidMethod(); + obj.takeIntMethod(42); + } + + System.out.println("DONE."); + } +} diff --git a/Samples/SwiftAndJavaJarSampleLib/src/test/java/com/example/swift/MySwiftClassTest.java b/Samples/SwiftAndJavaJarSampleLib/src/test/java/com/example/swift/MySwiftClassTest.java new file mode 100644 index 00000000..fa17ef1a --- /dev/null +++ b/Samples/SwiftAndJavaJarSampleLib/src/test/java/com/example/swift/MySwiftClassTest.java @@ -0,0 +1,67 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package com.example.swift; + +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.swift.swiftkit.SwiftKit; + +import java.io.File; +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.*; + +public class MySwiftClassTest { + + void checkPaths(Throwable throwable) { + var paths = SwiftKit.getJavaLibraryPath().split(":"); + for (var path : paths) { + System.out.println("CHECKING PATH: " + path); + Stream.of(new File(path).listFiles()) + .filter(file -> !file.isDirectory()) + .forEach((file) -> { + System.out.println(" - " + file.getPath()); + }); + } + + throw new RuntimeException(throwable); + } + + @Test + void test_MySwiftClass_voidMethod() { + try { + MySwiftClass o = new MySwiftClass(12, 42); + o.voidMethod(); + } catch (Throwable throwable) { + checkPaths(throwable); + } + } + + @Test + void test_MySwiftClass_makeIntMethod() { + MySwiftClass o = new MySwiftClass(12, 42); + var got = o.makeIntMethod(); + assertEquals(12, got); + } + + @Test + @Disabled // TODO: Need var mangled names in interfaces + void test_MySwiftClass_property_len() { + MySwiftClass o = new MySwiftClass(12, 42); + var got = o.getLen(); + assertEquals(12, got); + } + +} diff --git a/Samples/SwiftAndJavaJarSampleLib/src/test/java/com/example/swift/MySwiftLibraryTest.java b/Samples/SwiftAndJavaJarSampleLib/src/test/java/com/example/swift/MySwiftLibraryTest.java new file mode 100644 index 00000000..ffa90359 --- /dev/null +++ b/Samples/SwiftAndJavaJarSampleLib/src/test/java/com/example/swift/MySwiftLibraryTest.java @@ -0,0 +1,65 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package com.example.swift; + +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.swift.swiftkit.SwiftKit; + +import java.util.Arrays; +import java.util.concurrent.CountDownLatch; +import java.util.stream.Collectors; + +import static org.junit.jupiter.api.Assertions.*; + +public class MySwiftLibraryTest { + + @Test + void call_helloWorld() { + MySwiftLibrary.helloWorld(); + + assertNotNull(MySwiftLibrary.helloWorld$address()); + } + + @Test + void call_globalTakeInt() { + MySwiftLibrary.globalTakeInt(12); + + assertNotNull(MySwiftLibrary.globalTakeInt$address()); + } + + @Test + @Disabled("Upcalls not yet implemented in new scheme") + @SuppressWarnings({"Convert2Lambda", "Convert2MethodRef"}) + void call_globalCallMeRunnable() { + CountDownLatch countDownLatch = new CountDownLatch(3); + + MySwiftLibrary.globalCallMeRunnable(new Runnable() { + @Override + public void run() { + countDownLatch.countDown(); + } + }); + assertEquals(2, countDownLatch.getCount()); + + MySwiftLibrary.globalCallMeRunnable(() -> countDownLatch.countDown()); + assertEquals(1, countDownLatch.getCount()); + + MySwiftLibrary.globalCallMeRunnable(countDownLatch::countDown); + assertEquals(0, countDownLatch.getCount()); + } + +} diff --git a/Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/MySwiftClassTest.java b/Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/MySwiftClassTest.java new file mode 100644 index 00000000..633d5f1c --- /dev/null +++ b/Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/MySwiftClassTest.java @@ -0,0 +1,39 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package org.swift.swiftkit; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.Test; + +import com.example.swift.MySwiftClass; + +public class MySwiftClassTest { + + @Test + void call_retain_retainCount_release() { + var arena = SwiftArena.ofConfined(); + var obj = new MySwiftClass(arena, 1, 2); + + assertEquals(1, SwiftKit.retainCount(obj.$memorySegment())); + // TODO: test directly on SwiftHeapObject inheriting obj + + SwiftKit.retain(obj.$memorySegment()); + assertEquals(2, SwiftKit.retainCount(obj.$memorySegment())); + + SwiftKit.release(obj.$memorySegment()); + assertEquals(1, SwiftKit.retainCount(obj.$memorySegment())); + } +} diff --git a/Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/SwiftArenaTest.java b/Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/SwiftArenaTest.java new file mode 100644 index 00000000..ad514e1b --- /dev/null +++ b/Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/SwiftArenaTest.java @@ -0,0 +1,75 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package org.swift.swiftkit; + +import com.example.swift.MySwiftClass; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.DisabledIf; +import org.swift.swiftkit.util.PlatformUtils; + +import java.util.Arrays; +import java.util.stream.Collectors; + +import static org.junit.jupiter.api.Assertions.*; +import static org.swift.swiftkit.SwiftKit.*; +import static org.swift.swiftkit.SwiftKit.retainCount; + +public class SwiftArenaTest { + + static boolean isAmd64() { + return PlatformUtils.isAmd64(); + } + + // FIXME: The destroy witness table call hangs on x86_64 platforms during the destroy witness table call + // See: https://github.com/swiftlang/swift-java/issues/97 + @Test + @DisabledIf("isAmd64") + public void arena_releaseClassOnClose_class_ok() { + try (var arena = SwiftArena.ofConfined()) { + var obj = new MySwiftClass(arena,1, 2); + + retain(obj.$memorySegment()); + assertEquals(2, retainCount(obj.$memorySegment())); + + release(obj.$memorySegment()); + assertEquals(1, retainCount(obj.$memorySegment())); + } + + // TODO: should we zero out the $memorySegment perhaps? + } + + @Test + public void arena_releaseClassOnClose_class_leaked() { + String memorySegmentDescription = ""; + + try { + try (var arena = SwiftArena.ofConfined()) { + var obj = new MySwiftClass(arena,1, 2); + memorySegmentDescription = obj.$memorySegment().toString(); + + // Pretend that we "leaked" the class, something still holds a reference to it while we try to destroy it + retain(obj.$memorySegment()); + assertEquals(2, retainCount(obj.$memorySegment())); + } + + fail("Expected exception to be thrown while the arena is closed!"); + } catch (Exception ex) { + // The message should point out which objects "leaked": + assertTrue(ex.getMessage().contains(memorySegmentDescription)); + } + + } +} diff --git a/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift b/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift index cb9fd7ed..5a367840 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift @@ -325,9 +325,9 @@ extension Swift2JavaTranslator { static final SymbolLookup SYMBOL_LOOKUP = getSymbolLookup(); private static SymbolLookup getSymbolLookup() { // Ensure Swift and our Lib are loaded during static initialization of the class. - System.loadLibrary("swiftCore"); - System.loadLibrary("SwiftKitSwift"); - System.loadLibrary(LIB_NAME); + SwiftKit.loadLibrary("swiftCore"); + SwiftKit.loadLibrary("SwiftKitSwift"); + SwiftKit.loadLibrary(LIB_NAME); if (PlatformUtils.isMacOS()) { return SymbolLookup.libraryLookup(System.mapLibraryName(LIB_NAME), LIBRARY_ARENA) diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftKit.java b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftKit.java index 1951c23e..858f5500 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftKit.java +++ b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftKit.java @@ -16,8 +16,14 @@ import org.swift.swiftkit.util.PlatformUtils; +import java.io.File; +import java.io.IOException; import java.lang.foreign.*; import java.lang.invoke.MethodHandle; +import java.nio.file.CopyOption; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; import java.util.Arrays; import java.util.Optional; import java.util.stream.Collectors; @@ -63,31 +69,31 @@ private static SymbolLookup getSymbolLookup() { public SwiftKit() { } - public static void traceDowncall(Object... args) { - var ex = new RuntimeException(); - - String traceArgs = Arrays.stream(args) - .map(Object::toString) - .collect(Collectors.joining(", ")); - System.out.printf("[java][%s:%d] Downcall: %s(%s)\n", - ex.getStackTrace()[1].getFileName(), - ex.getStackTrace()[1].getLineNumber(), - ex.getStackTrace()[1].getMethodName(), - traceArgs); - } - - public static void trace(Object... args) { - var ex = new RuntimeException(); - - String traceArgs = Arrays.stream(args) - .map(Object::toString) - .collect(Collectors.joining(", ")); - System.out.printf("[java][%s:%d] %s: %s\n", - ex.getStackTrace()[1].getFileName(), - ex.getStackTrace()[1].getLineNumber(), - ex.getStackTrace()[1].getMethodName(), - traceArgs); - } + public static void traceDowncall(Object... args) { + var ex = new RuntimeException(); + + String traceArgs = Arrays.stream(args) + .map(Object::toString) + .collect(Collectors.joining(", ")); + System.out.printf("[java][%s:%d] Downcall: %s(%s)\n", + ex.getStackTrace()[1].getFileName(), + ex.getStackTrace()[1].getLineNumber(), + ex.getStackTrace()[1].getMethodName(), + traceArgs); + } + + public static void trace(Object... args) { + var ex = new RuntimeException(); + + String traceArgs = Arrays.stream(args) + .map(Object::toString) + .collect(Collectors.joining(", ")); + System.out.printf("[java][%s:%d] %s: %s\n", + ex.getStackTrace()[1].getFileName(), + ex.getStackTrace()[1].getLineNumber(), + ex.getStackTrace()[1].getMethodName(), + traceArgs); + } static MemorySegment findOrThrow(String symbol) { return SYMBOL_LOOKUP.find(symbol) @@ -102,6 +108,42 @@ public static boolean getJextractTraceDowncalls() { return Boolean.getBoolean("jextract.trace.downcalls"); } + // ==== ------------------------------------------------------------------------------------------------------------ + // Loading libraries + + public static void loadLibrary(String libname) { + // TODO: avoid concurrent loadResource calls; one load is enough esp since we cause File IO when we do that + try { + // try to load a dylib from our classpath, e.g. when we included it in our jar + loadResourceLibrary(libname); + } catch (UnsatisfiedLinkError | RuntimeException e) { + // fallback to plain system path loading + System.loadLibrary(libname); + } + } + + public static void loadResourceLibrary(String libname) { + var resourceName = PlatformUtils.dynamicLibraryName(libname); + if (SwiftKit.TRACE_DOWNCALLS) { + System.out.println("[swift-java] Loading resource library: " + resourceName); + } + + try (var libInputStream = SwiftKit.class.getResourceAsStream("/" + resourceName)) { + if (libInputStream == null) { + throw new RuntimeException("Expected library '" + libname + "' ('" + resourceName + "') was not found as resource!"); + } + + // TODO: we could do an in memory file system here + var tempFile = File.createTempFile(libname, ""); + tempFile.deleteOnExit(); + Files.copy(libInputStream, tempFile.toPath(), StandardCopyOption.REPLACE_EXISTING); + + System.load(tempFile.getAbsolutePath()); + } catch (IOException e) { + throw new RuntimeException("Failed to load dynamic library '" + libname + "' ('" + resourceName + "') as resource!", e); + } + } + // ==== ------------------------------------------------------------------------------------------------------------ // free @@ -396,7 +438,6 @@ public static long getSwiftInt(MemorySegment memorySegment, long offset) { } - private static class swift_getTypeName { /** diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/util/PlatformUtils.java b/SwiftKit/src/main/java/org/swift/swiftkit/util/PlatformUtils.java index 2c51143f..6addb31d 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/util/PlatformUtils.java +++ b/SwiftKit/src/main/java/org/swift/swiftkit/util/PlatformUtils.java @@ -35,4 +35,19 @@ public static boolean isAmd64() { String arch = System.getProperty("os.arch"); return arch.equals("amd64") || arch.equals("x86_64"); } + + public static String dynamicLibraryName(String base) { + if (isLinux()) { + return "lib" + uppercaseFistLetter(base) + ".so"; + } else { + return "lib" + uppercaseFistLetter(base) + ".dylib"; + } + } + + static String uppercaseFistLetter(String base) { + if (base == null || base.isEmpty()) { + return base; + } + return base.substring(0, 1).toUpperCase() + base.substring(1); + } } From 77ace5f83028808eadc3faea00b23b3934a3df0e Mon Sep 17 00:00:00 2001 From: jrosen081 Date: Mon, 18 Nov 2024 21:09:46 -0500 Subject: [PATCH 185/426] Add support for failing build when multiple types are mapped to the same type --- Sources/Java2Swift/JavaToSwift.swift | 3 + .../JavaTranslator+Validation.swift | 72 +++++++++++++++++++ .../JavaTranslatorValidationTests.swift | 40 +++++++++++ 3 files changed, 115 insertions(+) create mode 100644 Sources/Java2SwiftLib/JavaTranslator+Validation.swift create mode 100644 Tests/Java2SwiftTests/JavaTranslatorValidationTests.swift diff --git a/Sources/Java2Swift/JavaToSwift.swift b/Sources/Java2Swift/JavaToSwift.swift index 1434629f..bc7af4af 100644 --- a/Sources/Java2Swift/JavaToSwift.swift +++ b/Sources/Java2Swift/JavaToSwift.swift @@ -267,6 +267,9 @@ struct JavaToSwift: ParsableCommand { allClassesToVisit.append(contentsOf: nestedClasses) } + // Validate configurations before writing any files + try translator.validateClassConfiguration() + // Translate all of the Java classes into Swift classes. for javaClass in javaClasses { translator.startNewFile() diff --git a/Sources/Java2SwiftLib/JavaTranslator+Validation.swift b/Sources/Java2SwiftLib/JavaTranslator+Validation.swift new file mode 100644 index 00000000..3cfe5d40 --- /dev/null +++ b/Sources/Java2SwiftLib/JavaTranslator+Validation.swift @@ -0,0 +1,72 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import Foundation + +package extension JavaTranslator { + struct SwiftTypeName: Hashable { + let swiftType: String + let swiftModule: String? + + package init(swiftType: String, swiftModule: String?) { + self.swiftType = swiftType + self.swiftModule = swiftModule + } + } + + struct SwiftToJavaMapping: Equatable { + let swiftType: SwiftTypeName + let javaTypes: [String] + + package init(swiftType: SwiftTypeName, javaTypes: [String]) { + self.swiftType = swiftType + self.javaTypes = javaTypes + } + } + + enum ValidationError: Error, CustomStringConvertible { + case multipleClassesMappedToSameName(swiftToJavaMapping: [SwiftToJavaMapping]) + + package var description: String { + switch self { + case .multipleClassesMappedToSameName(let swiftToJavaMapping): + """ + The following Java classes were mapped to the same Swift type: + \(swiftToJavaMapping.map { mapping in + "Swift Type: \(mapping.swiftType.swiftModule ?? "").\(mapping.swiftType.swiftType), Java Types: \(mapping.javaTypes.sorted().joined(separator: ", "))" + }.joined(separator: "\n")) + """ + } + } + + } + func validateClassConfiguration() throws { + // Group all classes by swift name + let groupedDictionary: [SwiftTypeName: [(String, (String, String?))]] = Dictionary(grouping: translatedClasses, by: { SwiftTypeName(swiftType: $0.value.swiftType, swiftModule: $0.value.swiftModule) }) + // Find all that are mapped to multiple names + let multipleClassesMappedToSameName: [SwiftTypeName: [(String, (String, String?))]] = groupedDictionary.filter { (key: SwiftTypeName, value: [(String, (String, String?))]) in + value.count > 1 + } + + if !multipleClassesMappedToSameName.isEmpty { + // Convert them to swift object and throw + var errorMappings = [SwiftToJavaMapping]() + for (swiftType, swiftJavaMappings) in multipleClassesMappedToSameName { + errorMappings.append(SwiftToJavaMapping(swiftType: swiftType, javaTypes: swiftJavaMappings.map(\.0))) + } + throw ValidationError.multipleClassesMappedToSameName(swiftToJavaMapping: errorMappings) + } + + } +} diff --git a/Tests/Java2SwiftTests/JavaTranslatorValidationTests.swift b/Tests/Java2SwiftTests/JavaTranslatorValidationTests.swift new file mode 100644 index 00000000..e5c3a951 --- /dev/null +++ b/Tests/Java2SwiftTests/JavaTranslatorValidationTests.swift @@ -0,0 +1,40 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import Java2SwiftLib +import XCTest + +final class JavaTranslatorValidationTests: XCTestCase { + func testValidationError() throws { + let translator = try JavaTranslator(swiftModuleName: "SwiftModule", environment: jvm.environment()) + translator.translatedClasses = [ + "TestClass": ("Class1", "Module1"), + "TestClass2": ("Class1", "Module2"), + "TestClass3": ("Class1", "Module1"), + "TestClass4": ("Class1", nil) + ] + + XCTAssertThrowsError(try translator.validateClassConfiguration()) { error in + XCTAssertTrue(error is JavaTranslator.ValidationError) + let validationError = error as! JavaTranslator.ValidationError + switch validationError { + case .multipleClassesMappedToSameName(let swiftToJavaMapping): + XCTAssertEqual(swiftToJavaMapping, [ + JavaTranslator.SwiftToJavaMapping(swiftType: .init(swiftType: "Class1", swiftModule: "Module1"), + javaTypes: ["TestClass", "TestClass3"]) + ]) + } + } + } +} From c6545d75503714271409b42e5c748e28e12f8d3a Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Tue, 19 Nov 2024 21:43:02 +0900 Subject: [PATCH 186/426] Deduplicate shared configuration between swiftpm plugins (#184) --- .github/workflows/pull_request.yml | 2 + .licenseignore | 2 + Package.swift | 18 +++--- .../JExtractSwiftCommandPlugin.swift | 57 ++++++++++--------- .../PluginsShared/Configuration.swift | 36 ------------ .../JExtractSwiftCommandPlugin/_PluginsShared | 1 + .../PluginsShared/Configuration.swift | 36 ------------ .../PluginsShared/PluginUtils.swift | 37 ------------ Plugins/Java2SwiftPlugin/Configuration.swift | 36 ------------ .../Java2SwiftPlugin/Java2SwiftPlugin.swift | 48 +++++++--------- Plugins/Java2SwiftPlugin/_PluginsShared | 1 + .../JavaCompilerPlugin.swift | 22 ------- Plugins/JavaCompilerPlugin/_PluginsShared | 1 + Plugins/PluginsShared/0_PLEASE_SYMLINK.txt | 3 + .../Configuration.swift | 42 ++++++++++++-- .../PluginsShared/PluginUtils.swift | 38 +++++++++++-- .../SwiftJavaPlugin+Errors.swift | 17 ++++++ .../SwiftJavaPluginProtocol.swift | 28 +++++++++ .../JExtractSwiftPlugin.swift | 47 ++++++++------- Plugins/SwiftJavaPlugin/_PluginsShared | 1 + Samples/JavaKitSampleApp/Package.swift | 1 + .../{Java2Swift.config => swift-java.config} | 0 Samples/JavaKitSampleApp/ci-validate.sh | 7 +++ .../{Java2Swift.config => swift-java.config} | 0 .../{Java2Swift.config => swift-java.config} | 0 .../{Java2Swift.config => swift-java.config} | 0 .../SwiftAndJavaJarSampleLib/Package.swift | 2 +- Samples/SwiftKitSampleApp/Package.swift | 2 +- Sources/Java2Swift/JavaToSwift.swift | 4 +- .../{Java2Swift.config => swift-java.config} | 0 .../{Java2Swift.config => swift-java.config} | 0 .../{Java2Swift.config => swift-java.config} | 0 .../{Java2Swift.config => swift-java.config} | 0 .../{Java2Swift.config => swift-java.config} | 0 .../{Java2Swift.config => swift-java.config} | 0 35 files changed, 222 insertions(+), 267 deletions(-) delete mode 100644 Plugins/JExtractSwiftCommandPlugin/PluginsShared/Configuration.swift create mode 120000 Plugins/JExtractSwiftCommandPlugin/_PluginsShared delete mode 100644 Plugins/JExtractSwiftPlugin/PluginsShared/Configuration.swift delete mode 100644 Plugins/JExtractSwiftPlugin/PluginsShared/PluginUtils.swift delete mode 100644 Plugins/Java2SwiftPlugin/Configuration.swift create mode 120000 Plugins/Java2SwiftPlugin/_PluginsShared create mode 120000 Plugins/JavaCompilerPlugin/_PluginsShared create mode 100644 Plugins/PluginsShared/0_PLEASE_SYMLINK.txt rename Plugins/{JavaCompilerPlugin => PluginsShared}/Configuration.swift (56%) rename Plugins/{JExtractSwiftCommandPlugin => }/PluginsShared/PluginUtils.swift (70%) create mode 100644 Plugins/PluginsShared/SwiftJavaPlugin+Errors.swift create mode 100644 Plugins/PluginsShared/SwiftJavaPluginProtocol.swift rename Plugins/{JExtractSwiftPlugin => SwiftJavaPlugin}/JExtractSwiftPlugin.swift (69%) create mode 120000 Plugins/SwiftJavaPlugin/_PluginsShared rename Samples/JavaKitSampleApp/Sources/JavaKitExample/{Java2Swift.config => swift-java.config} (100%) create mode 100755 Samples/JavaKitSampleApp/ci-validate.sh rename Samples/JavaProbablyPrime/Sources/JavaProbablyPrime/{Java2Swift.config => swift-java.config} (100%) rename Samples/JavaSieve/Sources/JavaMath/{Java2Swift.config => swift-java.config} (100%) rename Samples/JavaSieve/Sources/JavaSieve/{Java2Swift.config => swift-java.config} (100%) rename Sources/JavaKit/{Java2Swift.config => swift-java.config} (100%) rename Sources/JavaKitCollection/{Java2Swift.config => swift-java.config} (100%) rename Sources/JavaKitFunction/{Java2Swift.config => swift-java.config} (100%) rename Sources/JavaKitJar/{Java2Swift.config => swift-java.config} (100%) rename Sources/JavaKitNetwork/{Java2Swift.config => swift-java.config} (100%) rename Sources/JavaKitReflection/{Java2Swift.config => swift-java.config} (100%) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 8039b572..06db1ff2 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -28,6 +28,7 @@ jobs: image: ${{ (contains(matrix.swift_version, 'nightly') && 'swiftlang/swift') || 'swift' }}:${{ matrix.swift_version }}-${{ matrix.os_version }} env: JAVA_HOME: "/usr/lib/jvm/default-jdk" + SWIFT_JAVA_VERBOSE: true steps: - uses: actions/checkout@v4 - name: Prepare CI Environment @@ -53,6 +54,7 @@ jobs: image: ${{ (contains(matrix.swift_version, 'nightly') && 'swiftlang/swift') || 'swift' }}:${{ matrix.swift_version }}-${{ matrix.os_version }} env: JAVA_HOME: "/usr/lib/jvm/default-jdk" + SWIFT_JAVA_VERBOSE: true steps: - uses: actions/checkout@v4 - name: Prepare CI Environment diff --git a/.licenseignore b/.licenseignore index 04a64766..ce382547 100644 --- a/.licenseignore +++ b/.licenseignore @@ -41,3 +41,5 @@ gradlew.bat **/gradlew.bat **/ci-validate.sh **/DO_NOT_EDIT.txt +Plugins/**/_PluginsShared +Plugins/**/0_PLEASE_SYMLINK* \ No newline at end of file diff --git a/Package.swift b/Package.swift index 0d5a5dab..119aca6e 100644 --- a/Package.swift +++ b/Package.swift @@ -128,9 +128,9 @@ let package = Package( // ==== Plugin for wrapping Java classes in Swift .plugin( - name: "JExtractSwiftPlugin", + name: "SwiftJavaPlugin", targets: [ - "JExtractSwiftPlugin" + "SwiftJavaPlugin" ] ), .plugin( @@ -174,7 +174,7 @@ let package = Package( .target( name: "JavaKit", dependencies: ["JavaRuntime", "JavaKitMacros", "JavaTypes"], - exclude: ["Java2Swift.config"], + exclude: ["swift-java.config"], swiftSettings: [ .swiftLanguageMode(.v5), .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) @@ -201,7 +201,7 @@ let package = Package( .target( name: "JavaKitCollection", dependencies: ["JavaKit"], - exclude: ["Java2Swift.config"], + exclude: ["swift-java.config"], swiftSettings: [ .swiftLanguageMode(.v5), .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) @@ -210,7 +210,7 @@ let package = Package( .target( name: "JavaKitFunction", dependencies: ["JavaKit"], - exclude: ["Java2Swift.config"], + exclude: ["swift-java.config"], swiftSettings: [ .swiftLanguageMode(.v5), .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) @@ -219,7 +219,7 @@ let package = Package( .target( name: "JavaKitJar", dependencies: ["JavaKit", "JavaKitCollection"], - exclude: ["Java2Swift.config"], + exclude: ["swift-java.config"], swiftSettings: [ .swiftLanguageMode(.v5), .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) @@ -228,7 +228,7 @@ let package = Package( .target( name: "JavaKitNetwork", dependencies: ["JavaKit", "JavaKitCollection"], - exclude: ["Java2Swift.config"], + exclude: ["swift-java.config"], swiftSettings: [ .swiftLanguageMode(.v5), .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) @@ -237,7 +237,7 @@ let package = Package( .target( name: "JavaKitReflection", dependencies: ["JavaKit", "JavaKitCollection"], - exclude: ["Java2Swift.config"], + exclude: ["swift-java.config"], swiftSettings: [ .swiftLanguageMode(.v5), .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) @@ -347,7 +347,7 @@ let package = Package( ), .plugin( - name: "JExtractSwiftPlugin", + name: "SwiftJavaPlugin", capability: .buildTool(), dependencies: [ "JExtractSwiftTool" diff --git a/Plugins/JExtractSwiftCommandPlugin/JExtractSwiftCommandPlugin.swift b/Plugins/JExtractSwiftCommandPlugin/JExtractSwiftCommandPlugin.swift index 008bc7d7..65ce8971 100644 --- a/Plugins/JExtractSwiftCommandPlugin/JExtractSwiftCommandPlugin.swift +++ b/Plugins/JExtractSwiftCommandPlugin/JExtractSwiftCommandPlugin.swift @@ -16,9 +16,10 @@ import Foundation import PackagePlugin @main -final class JExtractSwiftCommandPlugin: BuildToolPlugin, CommandPlugin { +final class JExtractSwiftCommandPlugin: SwiftJavaPluginProtocol, BuildToolPlugin, CommandPlugin { - var verbose: Bool = false + var pluginName: String = "swift-java-command" + var verbose: Bool = getEnvironmentBool("SWIFT_JAVA_VERBOSE") /// Build the target before attempting to extract from it. /// This avoids trying to extract from broken sources. @@ -48,8 +49,8 @@ final class JExtractSwiftCommandPlugin: BuildToolPlugin, CommandPlugin { } for target in context.package.targets { - guard let configPath = getSwiftJavaConfig(target: target) else { - log("Skipping target '\(target.name)', has no 'swift-java.config' file") + guard getSwiftJavaConfigPath(target: target) != nil else { + log("[swift-java-command] Skipping jextract step: Missing swift-java.config for target '\(target.name)'") continue } @@ -73,21 +74,15 @@ final class JExtractSwiftCommandPlugin: BuildToolPlugin, CommandPlugin { let sourceDir = target.directory.string let configuration = try readConfiguration(sourceDir: "\(sourceDir)") - - // We use the the usual maven-style structure of "src/[generated|main|test]/java/..." - // that is common in JVM ecosystem - let outputDirectoryJava = context.pluginWorkDirectoryURL - .appending(path: "src") - .appending(path: "generated") - .appending(path: "java") - let outputDirectorySwift = context.pluginWorkDirectoryURL - .appending(path: "Sources") + guard let javaPackage = configuration.javaPackage else { + throw SwiftJavaPluginError.missingConfiguration(sourceDir: "\(sourceDir)", key: "javaPackage") + } var arguments: [String] = [ "--swift-module", sourceModule.name, - "--package-name", configuration.javaPackage, - "--output-directory-java", outputDirectoryJava.path(percentEncoded: false), - "--output-directory-swift", outputDirectorySwift.path(percentEncoded: false), + "--package-name", javaPackage, + "--output-directory-java", context.outputDirectoryJava.path(percentEncoded: false), + "--output-directory-swift", context.outputDirectorySwift.path(percentEncoded: false), // TODO: "--build-cache-directory", ... // Since plugins cannot depend on libraries we cannot detect what the output files will be, // as it depends on the contents of the input files. Therefore we have to implement this as a prebuild plugin. @@ -100,14 +95,17 @@ final class JExtractSwiftCommandPlugin: BuildToolPlugin, CommandPlugin { /// Perform the command on a specific target. func performCommand(context: PluginContext, target: Target, extraArguments _: [String]) throws { - // Make sure the target can builds properly - try self.packageManager.build(.target(target.name), parameters: .init()) - guard let sourceModule = target.sourceModule else { return } if self.buildInputs { + // Make sure the target can builds properly log("Pre-building target '\(target.name)' before extracting sources...") - try self.packageManager.build(.target(target.name), parameters: .init()) + let targetBuildResult = try self.packageManager.build(.target(target.name), parameters: .init()) + + guard targetBuildResult.succeeded else { + print("[swift-java-command] Build of '\(target.name)' failed: \(targetBuildResult.logText)") + return + } } let arguments = try prepareJExtractArguments(context: context, target: target) @@ -124,7 +122,13 @@ final class JExtractSwiftCommandPlugin: BuildToolPlugin, CommandPlugin { log("Post-extract building products with target '\(target.name)'...") for product in context.package.products where product.targets.contains(where: { $0.id == target.id }) { log("Post-extract building product '\(product.name)'...") - try self.packageManager.build(.product(product.name), parameters: .init()) + let buildResult = try self.packageManager.build(.product(product.name), parameters: .init()) + + if buildResult.succeeded { + log("Post-extract build: " + "done".green + ".") + } else { + log("Post-extract build: " + "done".red + "!") + } } } } @@ -146,16 +150,15 @@ final class JExtractSwiftCommandPlugin: BuildToolPlugin, CommandPlugin { } } - func log(_ message: @autoclosure () -> String, terminator: String = "\n") { - if self.verbose { - print("[swift-java-command] \(message())", terminator: terminator) - } - } } // Mini coloring helper, since we cannot have dependencies we keep it minimal here extension String { + var red: String { + "\u{001B}[0;31m" + "\(self)" + "\u{001B}[0;0m" + } var green: String { "\u{001B}[0;32m" + "\(self)" + "\u{001B}[0;0m" } -} \ No newline at end of file +} + diff --git a/Plugins/JExtractSwiftCommandPlugin/PluginsShared/Configuration.swift b/Plugins/JExtractSwiftCommandPlugin/PluginsShared/Configuration.swift deleted file mode 100644 index f917290c..00000000 --- a/Plugins/JExtractSwiftCommandPlugin/PluginsShared/Configuration.swift +++ /dev/null @@ -1,36 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of Swift.org project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -import Foundation - -/// Configuration for the JExtractSwift translation tool, provided on a per-target -/// basis. -struct Configuration: Codable { - var javaPackage: String -} - -func readConfiguration(sourceDir: String) throws -> Configuration { - let configFile = URL(filePath: sourceDir).appending(path: "swift-java.config") - do { - let configData = try Data(contentsOf: configFile) - return try JSONDecoder().decode(Configuration.self, from: configData) - } catch { - throw ConfigurationError(message: "Failed to parse JExtractSwift configuration at '\(configFile)!'", error: error) - } -} - -struct ConfigurationError: Error { - let message: String - let error: any Error -} diff --git a/Plugins/JExtractSwiftCommandPlugin/_PluginsShared b/Plugins/JExtractSwiftCommandPlugin/_PluginsShared new file mode 120000 index 00000000..de623a5e --- /dev/null +++ b/Plugins/JExtractSwiftCommandPlugin/_PluginsShared @@ -0,0 +1 @@ +../PluginsShared \ No newline at end of file diff --git a/Plugins/JExtractSwiftPlugin/PluginsShared/Configuration.swift b/Plugins/JExtractSwiftPlugin/PluginsShared/Configuration.swift deleted file mode 100644 index f917290c..00000000 --- a/Plugins/JExtractSwiftPlugin/PluginsShared/Configuration.swift +++ /dev/null @@ -1,36 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of Swift.org project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -import Foundation - -/// Configuration for the JExtractSwift translation tool, provided on a per-target -/// basis. -struct Configuration: Codable { - var javaPackage: String -} - -func readConfiguration(sourceDir: String) throws -> Configuration { - let configFile = URL(filePath: sourceDir).appending(path: "swift-java.config") - do { - let configData = try Data(contentsOf: configFile) - return try JSONDecoder().decode(Configuration.self, from: configData) - } catch { - throw ConfigurationError(message: "Failed to parse JExtractSwift configuration at '\(configFile)!'", error: error) - } -} - -struct ConfigurationError: Error { - let message: String - let error: any Error -} diff --git a/Plugins/JExtractSwiftPlugin/PluginsShared/PluginUtils.swift b/Plugins/JExtractSwiftPlugin/PluginsShared/PluginUtils.swift deleted file mode 100644 index 6ec58147..00000000 --- a/Plugins/JExtractSwiftPlugin/PluginsShared/PluginUtils.swift +++ /dev/null @@ -1,37 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of Swift.org project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -import Foundation - -// Note: the JAVA_HOME environment variable must be set to point to where -// Java is installed, e.g., -// Library/Java/JavaVirtualMachines/openjdk-21.jdk/Contents/Home. -func findJavaHome() -> String { - if let home = ProcessInfo.processInfo.environment["JAVA_HOME"] { - return home - } - - // This is a workaround for envs (some IDEs) which have trouble with - // picking up env variables during the build process - let path = "\(FileManager.default.homeDirectoryForCurrentUser.path()).java_home" - if let home = try? String(contentsOfFile: path, encoding: .utf8) { - if let lastChar = home.last, lastChar.isNewline { - return String(home.dropLast()) - } - - return home - } - - fatalError("Please set the JAVA_HOME environment variable to point to where Java is installed.") -} diff --git a/Plugins/Java2SwiftPlugin/Configuration.swift b/Plugins/Java2SwiftPlugin/Configuration.swift deleted file mode 100644 index c9b17d06..00000000 --- a/Plugins/Java2SwiftPlugin/Configuration.swift +++ /dev/null @@ -1,36 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of Swift.org project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -typealias JavaVersion = Int - -/// Configuration for the Java2Swift translation tool, provided on a per-target -/// basis. -/// -/// Note: there is a copy of this struct in the Java2Swift library. They -/// must be kept in sync. -struct Configuration: Codable { - /// The Java class path that should be passed along to the Java2Swift tool. - var classPath: String? = nil - - /// The Java classes that should be translated to Swift. The keys are - /// canonical Java class names (e.g., java.util.Vector) and the values are - /// the corresponding Swift names (e.g., JavaVector). - var classes: [String: String] = [:] - - // Compile for the specified Java SE release. - var sourceCompatibility: JavaVersion? - - // Generate class files suitable for the specified Java SE release. - var targetCompatibility: JavaVersion? -} diff --git a/Plugins/Java2SwiftPlugin/Java2SwiftPlugin.swift b/Plugins/Java2SwiftPlugin/Java2SwiftPlugin.swift index 452ec8b3..8c7045e0 100644 --- a/Plugins/Java2SwiftPlugin/Java2SwiftPlugin.swift +++ b/Plugins/Java2SwiftPlugin/Java2SwiftPlugin.swift @@ -15,10 +15,14 @@ import Foundation import PackagePlugin -fileprivate let Java2SwiftConfigFileName = "Java2Swift.config" +fileprivate let SwiftJavaConfigFileName = "swift-java.config" @main -struct Java2SwiftBuildToolPlugin: BuildToolPlugin { +struct Java2SwiftBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin { + + var pluginName: String = "swift-java-javac" + var verbose: Bool = getEnvironmentBool("SWIFT_JAVA_VERBOSE") + func createBuildCommands(context: PluginContext, target: Target) throws -> [Command] { guard let sourceModule = target.sourceModule else { return [] } @@ -29,7 +33,7 @@ struct Java2SwiftBuildToolPlugin: BuildToolPlugin { // The name of the configuration file JavaKit.config from the target for // which we are generating Swift wrappers for Java classes. let configFile = URL(filePath: sourceDir) - .appending(path: "Java2Swift.config") + .appending(path: SwiftJavaConfigFileName) let configData = try Data(contentsOf: configFile) let config = try JSONDecoder().decode(Configuration.self, from: configData) @@ -41,7 +45,7 @@ struct Java2SwiftBuildToolPlugin: BuildToolPlugin { // Look for a config file within this target. let dependencyConfigURL = dependencyURL - .appending(path: Java2SwiftConfigFileName) + .appending(path: SwiftJavaConfigFileName) let dependencyConfigString = dependencyConfigURL .path(percentEncoded: false) @@ -87,9 +91,14 @@ struct Java2SwiftBuildToolPlugin: BuildToolPlugin { } arguments.append(configFile.path(percentEncoded: false)) + guard let classes = config.classes else { + log("Config at \(configFile) did not have 'classes' configured, skipping java2swift step.") + return [] + } + /// Determine the set of Swift files that will be emitted by the Java2Swift /// tool. - let outputSwiftFiles = config.classes.map { (javaClassName, swiftName) in + let outputSwiftFiles = classes.map { (javaClassName, swiftName) in let swiftNestedName = swiftName.replacingOccurrences(of: ".", with: "+") return outputDirectory.appending(path: "\(swiftNestedName).swift") } @@ -125,10 +134,15 @@ struct Java2SwiftBuildToolPlugin: BuildToolPlugin { arguments += [ "--swift-native-implementation", className] } } + + guard let classes = config.classes else { + log("Skipping java2swift step: Missing 'classes' key in swift-java.config at '\(configFile.path)'") + return [] + } return [ .buildCommand( - displayName: "Wrapping \(config.classes.count) Java classes target \(sourceModule.name) in Swift", + displayName: "Wrapping \(classes.count) Java classes target \(sourceModule.name) in Swift", executable: try context.tool(named: "Java2Swift").url, arguments: arguments, inputFiles: [ configFile ] + compiledClassFiles, @@ -137,25 +151,3 @@ struct Java2SwiftBuildToolPlugin: BuildToolPlugin { ] } } - -// Note: the JAVA_HOME environment variable must be set to point to where -// Java is installed, e.g., -// Library/Java/JavaVirtualMachines/openjdk-21.jdk/Contents/Home. -func findJavaHome() -> String { - if let home = ProcessInfo.processInfo.environment["JAVA_HOME"] { - return home - } - - // This is a workaround for envs (some IDEs) which have trouble with - // picking up env variables during the build process - let path = "\(FileManager.default.homeDirectoryForCurrentUser.path()).java_home" - if let home = try? String(contentsOfFile: path, encoding: .utf8) { - if let lastChar = home.last, lastChar.isNewline { - return String(home.dropLast()) - } - - return home - } - - fatalError("Please set the JAVA_HOME environment variable to point to where Java is installed.") -} diff --git a/Plugins/Java2SwiftPlugin/_PluginsShared b/Plugins/Java2SwiftPlugin/_PluginsShared new file mode 120000 index 00000000..de623a5e --- /dev/null +++ b/Plugins/Java2SwiftPlugin/_PluginsShared @@ -0,0 +1 @@ +../PluginsShared \ No newline at end of file diff --git a/Plugins/JavaCompilerPlugin/JavaCompilerPlugin.swift b/Plugins/JavaCompilerPlugin/JavaCompilerPlugin.swift index 518073a2..b93fe403 100644 --- a/Plugins/JavaCompilerPlugin/JavaCompilerPlugin.swift +++ b/Plugins/JavaCompilerPlugin/JavaCompilerPlugin.swift @@ -78,25 +78,3 @@ struct JavaCompilerBuildToolPlugin: BuildToolPlugin { ] } } - -// Note: the JAVA_HOME environment variable must be set to point to where -// Java is installed, e.g., -// Library/Java/JavaVirtualMachines/openjdk-21.jdk/Contents/Home. -func findJavaHome() -> String { - if let home = ProcessInfo.processInfo.environment["JAVA_HOME"] { - return home - } - - // This is a workaround for envs (some IDEs) which have trouble with - // picking up env variables during the build process - let path = "\(FileManager.default.homeDirectoryForCurrentUser.path()).java_home" - if let home = try? String(contentsOfFile: path, encoding: .utf8) { - if let lastChar = home.last, lastChar.isNewline { - return String(home.dropLast()) - } - - return home - } - - fatalError("Please set the JAVA_HOME environment variable to point to where Java is installed.") -} diff --git a/Plugins/JavaCompilerPlugin/_PluginsShared b/Plugins/JavaCompilerPlugin/_PluginsShared new file mode 120000 index 00000000..de623a5e --- /dev/null +++ b/Plugins/JavaCompilerPlugin/_PluginsShared @@ -0,0 +1 @@ +../PluginsShared \ No newline at end of file diff --git a/Plugins/PluginsShared/0_PLEASE_SYMLINK.txt b/Plugins/PluginsShared/0_PLEASE_SYMLINK.txt new file mode 100644 index 00000000..40f0c528 --- /dev/null +++ b/Plugins/PluginsShared/0_PLEASE_SYMLINK.txt @@ -0,0 +1,3 @@ +This directory should be symlinked from all plugins so that we can avoid copy-pasting the contents. + +Package plugins cannot have dependencies, so this is a way to share sources common between all the plugins. \ No newline at end of file diff --git a/Plugins/JavaCompilerPlugin/Configuration.swift b/Plugins/PluginsShared/Configuration.swift similarity index 56% rename from Plugins/JavaCompilerPlugin/Configuration.swift rename to Plugins/PluginsShared/Configuration.swift index 96180760..769eef70 100644 --- a/Plugins/JavaCompilerPlugin/Configuration.swift +++ b/Plugins/PluginsShared/Configuration.swift @@ -12,21 +12,25 @@ // //===----------------------------------------------------------------------===// +import Foundation + typealias JavaVersion = Int -/// Configuration for the Java2Swift translation tool, provided on a per-target -/// basis. -/// -/// Note: there is a copy of this struct in the Java2Swift library. They -/// must be kept in sync. +/// Configuration for the SwiftJava plugins, provided on a per-target basis. struct Configuration: Codable { + // ==== swift 2 java --------------------------------------------------------- + + var javaPackage: String? + + // ==== java 2 swift --------------------------------------------------------- + /// The Java class path that should be passed along to the Java2Swift tool. var classPath: String? = nil /// The Java classes that should be translated to Swift. The keys are /// canonical Java class names (e.g., java.util.Vector) and the values are /// the corresponding Swift names (e.g., JavaVector). - var classes: [String: String] = [:] + var classes: [String: String]? = [:] // Compile for the specified Java SE release. var sourceCompatibility: JavaVersion? @@ -35,6 +39,17 @@ struct Configuration: Codable { var targetCompatibility: JavaVersion? } +func readConfiguration(sourceDir: String, file: String = #fileID, line: UInt = #line) throws -> Configuration { + let configFile = URL(filePath: sourceDir).appending(path: "swift-java.config") + do { + let configData = try Data(contentsOf: configFile) + return try JSONDecoder().decode(Configuration.self, from: configData) + } catch { + throw ConfigurationError(message: "Failed to parse SwiftJava configuration at '\(configFile)!'", error: error, + file: file, line: line) + } +} + extension Configuration { var compilerVersionArgs: [String] { var compilerVersionArgs = [String]() @@ -49,3 +64,18 @@ extension Configuration { return compilerVersionArgs } } + +struct ConfigurationError: Error { + let message: String + let error: any Error + + let file: String + let line: UInt + + init(message: String, error: any Error, file: String = #fileID, line: UInt = #line) { + self.message = message + self.error = error + self.file = file + self.line = line + } +} diff --git a/Plugins/JExtractSwiftCommandPlugin/PluginsShared/PluginUtils.swift b/Plugins/PluginsShared/PluginUtils.swift similarity index 70% rename from Plugins/JExtractSwiftCommandPlugin/PluginsShared/PluginUtils.swift rename to Plugins/PluginsShared/PluginUtils.swift index 320dfc19..bf4d0f0a 100644 --- a/Plugins/JExtractSwiftCommandPlugin/PluginsShared/PluginUtils.swift +++ b/Plugins/PluginsShared/PluginUtils.swift @@ -22,7 +22,7 @@ func findJavaHome() -> String { if let home = ProcessInfo.processInfo.environment["JAVA_HOME"] { return home } - + // This is a workaround for envs (some IDEs) which have trouble with // picking up env variables during the build process let path = "\(FileManager.default.homeDirectoryForCurrentUser.path()).java_home" @@ -30,19 +30,45 @@ func findJavaHome() -> String { if let lastChar = home.last, lastChar.isNewline { return String(home.dropLast()) } - + return home } - + fatalError("Please set the JAVA_HOME environment variable to point to where Java is installed.") } -func getSwiftJavaConfig(target: Target) -> String? { +func getSwiftJavaConfigPath(target: Target) -> String? { let configPath = URL(fileURLWithPath: target.directory.string).appending(component: "swift-java.config").path() - + if FileManager.default.fileExists(atPath: configPath) { - return configPath + return configPath } else { return nil } } + +func getEnvironmentBool(_ name: String) -> Bool { + if let value = ProcessInfo.processInfo.environment[name] { + switch value.lowercased() { + case "true", "yes", "1": true + case "false", "no", "0": false + default: false + } + } else { + false + } +} + +extension PluginContext { + var outputDirectoryJava: URL { + self.pluginWorkDirectoryURL + .appending(path: "src") + .appending(path: "generated") + .appending(path: "java") + } + + var outputDirectorySwift: URL { + self.pluginWorkDirectoryURL + .appending(path: "Sources") + } +} diff --git a/Plugins/PluginsShared/SwiftJavaPlugin+Errors.swift b/Plugins/PluginsShared/SwiftJavaPlugin+Errors.swift new file mode 100644 index 00000000..d9022830 --- /dev/null +++ b/Plugins/PluginsShared/SwiftJavaPlugin+Errors.swift @@ -0,0 +1,17 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +enum SwiftJavaPluginError: Error { + case missingConfiguration(sourceDir: String, key: String?, file: String = #file, line: UInt = #line) +} diff --git a/Plugins/PluginsShared/SwiftJavaPluginProtocol.swift b/Plugins/PluginsShared/SwiftJavaPluginProtocol.swift new file mode 100644 index 00000000..68f8964e --- /dev/null +++ b/Plugins/PluginsShared/SwiftJavaPluginProtocol.swift @@ -0,0 +1,28 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +protocol SwiftJavaPluginProtocol { + var verbose: Bool { get } + var pluginName: String { get } + + func log(_ message: @autoclosure () -> String, terminator: String) +} + +extension SwiftJavaPluginProtocol { + func log(_ message: @autoclosure () -> String, terminator: String = "\n") { +// if self.verbose { + print("[\(pluginName)] \(message())", terminator: terminator) +// } + } +} diff --git a/Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift b/Plugins/SwiftJavaPlugin/JExtractSwiftPlugin.swift similarity index 69% rename from Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift rename to Plugins/SwiftJavaPlugin/JExtractSwiftPlugin.swift index 94cd4aa6..f4255ff5 100644 --- a/Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift +++ b/Plugins/SwiftJavaPlugin/JExtractSwiftPlugin.swift @@ -16,39 +16,46 @@ import Foundation import PackagePlugin @main -struct JExtractSwiftBuildToolPlugin: BuildToolPlugin { +struct JExtractSwiftBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin { + + var pluginName: String = "swift-java" + var verbose: Bool = getEnvironmentBool("SWIFT_JAVA_VERBOSE") + func createBuildCommands(context: PluginContext, target: Target) throws -> [Command] { + let toolURL = try context.tool(named: "JExtractSwiftTool").url + guard let sourceModule = target.sourceModule else { return [] } // Note: Target doesn't have a directoryURL counterpart to directory, // so we cannot eliminate this deprecation warning. - let sourceDir = target.directory.string - - let t = target.dependencies.first! - switch (t) { - case .target(let t): - t.sourceModule - case .product(let p): - p.sourceModules - @unknown default: - fatalError("Unknown target dependency type: \(t)") + for dependency in target.dependencies { + switch (dependency) { + case .target(let t): + t.sourceModule + case .product(let p): + p.sourceModules + @unknown default: + fatalError("Unknown target dependency type: \(dependency)") + } } - let toolURL = try context.tool(named: "JExtractSwiftTool").url + let sourceDir = target.directory.string let configuration = try readConfiguration(sourceDir: "\(sourceDir)") - + + guard let javaPackage = configuration.javaPackage else { + // throw SwiftJavaPluginError.missingConfiguration(sourceDir: "\(sourceDir)", key: "javaPackage") + log("Skipping jextract step, no 'javaPackage' configuration in \(getSwiftJavaConfigPath(target: target) ?? "")") + return [] + } + // We use the the usual maven-style structure of "src/[generated|main|test]/java/..." // that is common in JVM ecosystem - let outputDirectoryJava = context.pluginWorkDirectoryURL - .appending(path: "src") - .appending(path: "generated") - .appending(path: "java") - let outputDirectorySwift = context.pluginWorkDirectoryURL - .appending(path: "Sources") + let outputDirectoryJava = context.outputDirectoryJava + let outputDirectorySwift = context.outputDirectorySwift var arguments: [String] = [ "--swift-module", sourceModule.name, - "--package-name", configuration.javaPackage, + "--package-name", javaPackage, "--output-directory-java", outputDirectoryJava.path(percentEncoded: false), "--output-directory-swift", outputDirectorySwift.path(percentEncoded: false), // TODO: "--build-cache-directory", ... diff --git a/Plugins/SwiftJavaPlugin/_PluginsShared b/Plugins/SwiftJavaPlugin/_PluginsShared new file mode 120000 index 00000000..de623a5e --- /dev/null +++ b/Plugins/SwiftJavaPlugin/_PluginsShared @@ -0,0 +1 @@ +../PluginsShared \ No newline at end of file diff --git a/Samples/JavaKitSampleApp/Package.swift b/Samples/JavaKitSampleApp/Package.swift index 8976bd41..46dfbd80 100644 --- a/Samples/JavaKitSampleApp/Package.swift +++ b/Samples/JavaKitSampleApp/Package.swift @@ -76,6 +76,7 @@ let package = Package( ], plugins: [ .plugin(name: "JavaCompilerPlugin", package: "swift-java"), + .plugin(name: "SwiftJavaPlugin", package: "swift-java"), .plugin(name: "Java2SwiftPlugin", package: "swift-java"), ] ), diff --git a/Samples/JavaKitSampleApp/Sources/JavaKitExample/Java2Swift.config b/Samples/JavaKitSampleApp/Sources/JavaKitExample/swift-java.config similarity index 100% rename from Samples/JavaKitSampleApp/Sources/JavaKitExample/Java2Swift.config rename to Samples/JavaKitSampleApp/Sources/JavaKitExample/swift-java.config diff --git a/Samples/JavaKitSampleApp/ci-validate.sh b/Samples/JavaKitSampleApp/ci-validate.sh new file mode 100755 index 00000000..eff61551 --- /dev/null +++ b/Samples/JavaKitSampleApp/ci-validate.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +swift build +"$JAVA_HOME/bin/java" \ + -cp .build/plugins/outputs/javakitsampleapp/JavaKitExample/destination/JavaCompilerPlugin/Java \ + -Djava.library.path=.build/debug \ + "com.example.swift.JavaKitSampleMain" diff --git a/Samples/JavaProbablyPrime/Sources/JavaProbablyPrime/Java2Swift.config b/Samples/JavaProbablyPrime/Sources/JavaProbablyPrime/swift-java.config similarity index 100% rename from Samples/JavaProbablyPrime/Sources/JavaProbablyPrime/Java2Swift.config rename to Samples/JavaProbablyPrime/Sources/JavaProbablyPrime/swift-java.config diff --git a/Samples/JavaSieve/Sources/JavaMath/Java2Swift.config b/Samples/JavaSieve/Sources/JavaMath/swift-java.config similarity index 100% rename from Samples/JavaSieve/Sources/JavaMath/Java2Swift.config rename to Samples/JavaSieve/Sources/JavaMath/swift-java.config diff --git a/Samples/JavaSieve/Sources/JavaSieve/Java2Swift.config b/Samples/JavaSieve/Sources/JavaSieve/swift-java.config similarity index 100% rename from Samples/JavaSieve/Sources/JavaSieve/Java2Swift.config rename to Samples/JavaSieve/Sources/JavaSieve/swift-java.config diff --git a/Samples/SwiftAndJavaJarSampleLib/Package.swift b/Samples/SwiftAndJavaJarSampleLib/Package.swift index 5f132239..a1212fd7 100644 --- a/Samples/SwiftAndJavaJarSampleLib/Package.swift +++ b/Samples/SwiftAndJavaJarSampleLib/Package.swift @@ -70,7 +70,7 @@ let package = Package( .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) ], plugins: [ - .plugin(name: "JExtractSwiftPlugin", package: "swift-java"), + .plugin(name: "SwiftJavaPlugin", package: "swift-java"), ] ), ] diff --git a/Samples/SwiftKitSampleApp/Package.swift b/Samples/SwiftKitSampleApp/Package.swift index f12ecfd6..bfd3ecbe 100644 --- a/Samples/SwiftKitSampleApp/Package.swift +++ b/Samples/SwiftKitSampleApp/Package.swift @@ -70,7 +70,7 @@ let package = Package( .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) ], plugins: [ - .plugin(name: "JExtractSwiftPlugin", package: "swift-java"), + .plugin(name: "SwiftJavaPlugin", package: "swift-java"), ] ), ] diff --git a/Sources/Java2Swift/JavaToSwift.swift b/Sources/Java2Swift/JavaToSwift.swift index 1434629f..125191bd 100644 --- a/Sources/Java2Swift/JavaToSwift.swift +++ b/Sources/Java2Swift/JavaToSwift.swift @@ -369,8 +369,8 @@ struct JavaToSwift: ParsableCommand { // Write the file. try writeContents( contents, - to: "Java2Swift.config", - description: "Java2Swift configuration file" + to: "swift-java.config", + description: "swift-java configuration file" ) } } diff --git a/Sources/JavaKit/Java2Swift.config b/Sources/JavaKit/swift-java.config similarity index 100% rename from Sources/JavaKit/Java2Swift.config rename to Sources/JavaKit/swift-java.config diff --git a/Sources/JavaKitCollection/Java2Swift.config b/Sources/JavaKitCollection/swift-java.config similarity index 100% rename from Sources/JavaKitCollection/Java2Swift.config rename to Sources/JavaKitCollection/swift-java.config diff --git a/Sources/JavaKitFunction/Java2Swift.config b/Sources/JavaKitFunction/swift-java.config similarity index 100% rename from Sources/JavaKitFunction/Java2Swift.config rename to Sources/JavaKitFunction/swift-java.config diff --git a/Sources/JavaKitJar/Java2Swift.config b/Sources/JavaKitJar/swift-java.config similarity index 100% rename from Sources/JavaKitJar/Java2Swift.config rename to Sources/JavaKitJar/swift-java.config diff --git a/Sources/JavaKitNetwork/Java2Swift.config b/Sources/JavaKitNetwork/swift-java.config similarity index 100% rename from Sources/JavaKitNetwork/Java2Swift.config rename to Sources/JavaKitNetwork/swift-java.config diff --git a/Sources/JavaKitReflection/Java2Swift.config b/Sources/JavaKitReflection/swift-java.config similarity index 100% rename from Sources/JavaKitReflection/Java2Swift.config rename to Sources/JavaKitReflection/swift-java.config From 28fb69f142757d42fac1f58a9fc880d600f86850 Mon Sep 17 00:00:00 2001 From: Luke Howard Date: Tue, 19 Nov 2024 23:43:57 +1100 Subject: [PATCH 187/426] Detach from any threads we have attached to. (#173) --- .../JavaKitVM/JavaVirtualMachine.swift | 9 +- .../JavaKitVM/ThreadLocalStorage.swift | 90 +++++++++++++++++++ 2 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 Sources/JavaKit/JavaKitVM/ThreadLocalStorage.swift diff --git a/Sources/JavaKit/JavaKitVM/JavaVirtualMachine.swift b/Sources/JavaKit/JavaKitVM/JavaVirtualMachine.swift index 7769fa17..6348dc3c 100644 --- a/Sources/JavaKit/JavaKitVM/JavaVirtualMachine.swift +++ b/Sources/JavaKit/JavaKitVM/JavaVirtualMachine.swift @@ -24,6 +24,11 @@ public final class JavaVirtualMachine: @unchecked Sendable { /// The JNI version that we depend on. static let jniVersion = JNI_VERSION_1_6 + /// Thread-local storage to detach from thread on exit + private static let destroyTLS = ThreadLocalStorage { _ in + try? JavaVirtualMachine.shared().detachCurrentThread() + } + /// The Java virtual machine instance. private let jvm: JavaVMPointer @@ -146,12 +151,14 @@ extension JavaVirtualMachine { throw attachError } + JavaVirtualMachine.destroyTLS.set(environment!) + return environment!.assumingMemoryBound(to: JNIEnv?.self) } /// Detach the current thread from the Java Virtual Machine. All Java /// threads waiting for this thread to die are notified. - public func detachCurrentThread() throws { + func detachCurrentThread() throws { if let resultError = VMError(fromJNIError: jvm.pointee!.pointee.DetachCurrentThread(jvm)) { throw resultError } diff --git a/Sources/JavaKit/JavaKitVM/ThreadLocalStorage.swift b/Sources/JavaKit/JavaKitVM/ThreadLocalStorage.swift new file mode 100644 index 00000000..7ea0b50a --- /dev/null +++ b/Sources/JavaKit/JavaKitVM/ThreadLocalStorage.swift @@ -0,0 +1,90 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +#if canImport(Darwin) +import Darwin +#elseif canImport(Bionic) +import Bionic +#elseif canImport(Glibc) +import Glibc +#elseif canImport(Musl) +import Musl +#elseif canImport(WinSDK) +import WinSDK +#endif + +#if !(canImport(Darwin) || canImport(Bionic) || canImport(Glibc) || canImport(Musl) || canImport(WinSDK)) +private var _globalTlsValue: UnsafeMutableRawPointer? +#endif + +package struct ThreadLocalStorage: ~Copyable { +#if canImport(Darwin) || canImport(Bionic) || canImport(Glibc) || canImport(Musl) + private typealias PlatformKey = pthread_key_t +#elseif canImport(WinSDK) + private typealias PlatformKey = DWORD +#else + private typealias PlatformKey = Void +#endif + +#if canImport(Darwin) + package typealias Value = UnsafeMutableRawPointer +#else + package typealias Value = UnsafeMutableRawPointer? +#endif + + package typealias OnThreadExit = @convention(c) (_: Value) -> () + +#if canImport(Darwin) || canImport(Bionic) || canImport(Glibc) || canImport(Musl) + private var _key: PlatformKey +#elseif canImport(WinSDK) + private let _key: PlatformKey +#endif + + package init(onThreadExit: OnThreadExit) { +#if canImport(Darwin) || canImport(Bionic) || canImport(Glibc) || canImport(Musl) + _key = 0 + pthread_key_create(&_key, onThreadExit) +#elseif canImport(WinSDK) + key = FlsAlloc(onThreadExit) +#endif + } + + package func get() -> UnsafeMutableRawPointer? { +#if canImport(Darwin) || canImport(Bionic) || canImport(Glibc) || canImport(Musl) + pthread_getspecific(_key) +#elseif canImport(WinSDK) + FlsGetValue(_key) +#else + _globalTlsValue +#endif + } + + package func set(_ value: Value) { +#if canImport(Darwin) || canImport(Bionic) || canImport(Glibc) || canImport(Musl) + pthread_setspecific(_key, value) +#elseif canImport(WinSDK) + FlsSetValue(_key, value) +#else + _globalTlsValue = value +#endif + } + + deinit { +#if canImport(Darwin) || canImport(Bionic) || canImport(Glibc) || canImport(Musl) + pthread_key_delete(_key) +#elseif canImport(WinSDK) + FlsFree(_key) +#endif + } +} From 250bb24083c0447f62e7b63b09f628cefcac2b34 Mon Sep 17 00:00:00 2001 From: jrosen081 Date: Wed, 20 Nov 2024 22:31:44 -0500 Subject: [PATCH 188/426] PR Feedback --- .../Java2SwiftLib/JavaTranslator+Validation.swift | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/Sources/Java2SwiftLib/JavaTranslator+Validation.swift b/Sources/Java2SwiftLib/JavaTranslator+Validation.swift index 3cfe5d40..c85cedb0 100644 --- a/Sources/Java2SwiftLib/JavaTranslator+Validation.swift +++ b/Sources/Java2SwiftLib/JavaTranslator+Validation.swift @@ -12,8 +12,6 @@ // //===----------------------------------------------------------------------===// -import Foundation - package extension JavaTranslator { struct SwiftTypeName: Hashable { let swiftType: String @@ -42,14 +40,17 @@ package extension JavaTranslator { switch self { case .multipleClassesMappedToSameName(let swiftToJavaMapping): """ - The following Java classes were mapped to the same Swift type: - \(swiftToJavaMapping.map { mapping in - "Swift Type: \(mapping.swiftType.swiftModule ?? "").\(mapping.swiftType.swiftType), Java Types: \(mapping.javaTypes.sorted().joined(separator: ", "))" - }.joined(separator: "\n")) + The following Java classes were mapped to the same Swift type name: + \(swiftToJavaMapping.map(mappingDescription(mapping:)).joined(separator: "\n")) """ } } + private func mappingDescription(mapping: SwiftToJavaMapping) -> String { + let javaTypes = mapping.javaTypes.map { "'\($0)'" }.joined(separator: ", ") + return "Swift Type: '\(mapping.swiftType.swiftModule ?? "")'.'\(mapping.swiftType.swiftType)', Java Types: \(javaTypes)" + + } } func validateClassConfiguration() throws { // Group all classes by swift name @@ -63,7 +64,7 @@ package extension JavaTranslator { // Convert them to swift object and throw var errorMappings = [SwiftToJavaMapping]() for (swiftType, swiftJavaMappings) in multipleClassesMappedToSameName { - errorMappings.append(SwiftToJavaMapping(swiftType: swiftType, javaTypes: swiftJavaMappings.map(\.0))) + errorMappings.append(SwiftToJavaMapping(swiftType: swiftType, javaTypes: swiftJavaMappings.map(\.0).sorted())) } throw ValidationError.multipleClassesMappedToSameName(swiftToJavaMapping: errorMappings) } From c769b1a4cc57468b70efa14796c817efcfb11dd1 Mon Sep 17 00:00:00 2001 From: Jack Rosen Date: Mon, 25 Nov 2024 21:30:58 -0500 Subject: [PATCH 189/426] Add Support for Threadsafe and NotThreadSafe annotations (#188) --- .../JavaKitExample/JavaKitExample.swift | 3 ++ .../com/example/swift/ThreadSafe.java | 22 ++++++++++++++ .../example/swift/ThreadSafeHelperClass.java | 20 +++++++++++++ .../Sources/JavaKitExample/swift-java.config | 3 +- .../Java2SwiftLib/JavaClassTranslator.swift | 30 +++++++++++++++++++ .../JavaClass+Reflection.swift | 3 ++ 6 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 Samples/JavaKitSampleApp/Sources/JavaKitExample/com/example/swift/ThreadSafe.java create mode 100644 Samples/JavaKitSampleApp/Sources/JavaKitExample/com/example/swift/ThreadSafeHelperClass.java diff --git a/Samples/JavaKitSampleApp/Sources/JavaKitExample/JavaKitExample.swift b/Samples/JavaKitSampleApp/Sources/JavaKitExample/JavaKitExample.swift index 42a5b789..366e8894 100644 --- a/Samples/JavaKitSampleApp/Sources/JavaKitExample/JavaKitExample.swift +++ b/Samples/JavaKitSampleApp/Sources/JavaKitExample/JavaKitExample.swift @@ -76,6 +76,9 @@ extension HelloSwift: HelloSwiftNativeMethods { print("Caught Java error: \(error)") } + // Make sure that the thread safe class is sendable + let threadSafe: Sendable = ThreadSafeHelperClass(environment: javaEnvironment) + return i * j } diff --git a/Samples/JavaKitSampleApp/Sources/JavaKitExample/com/example/swift/ThreadSafe.java b/Samples/JavaKitSampleApp/Sources/JavaKitExample/com/example/swift/ThreadSafe.java new file mode 100644 index 00000000..2b1b358d --- /dev/null +++ b/Samples/JavaKitSampleApp/Sources/JavaKitExample/com/example/swift/ThreadSafe.java @@ -0,0 +1,22 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package com.example.swift; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +public @interface ThreadSafe { +} diff --git a/Samples/JavaKitSampleApp/Sources/JavaKitExample/com/example/swift/ThreadSafeHelperClass.java b/Samples/JavaKitSampleApp/Sources/JavaKitExample/com/example/swift/ThreadSafeHelperClass.java new file mode 100644 index 00000000..179b8cd6 --- /dev/null +++ b/Samples/JavaKitSampleApp/Sources/JavaKitExample/com/example/swift/ThreadSafeHelperClass.java @@ -0,0 +1,20 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package com.example.swift; + +@ThreadSafe +public class ThreadSafeHelperClass { + public ThreadSafeHelperClass() { } +} diff --git a/Samples/JavaKitSampleApp/Sources/JavaKitExample/swift-java.config b/Samples/JavaKitSampleApp/Sources/JavaKitExample/swift-java.config index b4e7368d..a86b5a4f 100644 --- a/Samples/JavaKitSampleApp/Sources/JavaKitExample/swift-java.config +++ b/Samples/JavaKitSampleApp/Sources/JavaKitExample/swift-java.config @@ -2,6 +2,7 @@ "classes" : { "com.example.swift.HelloSwift" : "HelloSwift", "com.example.swift.HelloSubclass" : "HelloSubclass", - "com.example.swift.JavaKitSampleMain" : "JavaKitSampleMain" + "com.example.swift.JavaKitSampleMain" : "JavaKitSampleMain", + "com.example.swift.ThreadSafeHelperClass" : "ThreadSafeHelperClass" } } diff --git a/Sources/Java2SwiftLib/JavaClassTranslator.swift b/Sources/Java2SwiftLib/JavaClassTranslator.swift index b0b0628f..e2753790 100644 --- a/Sources/Java2SwiftLib/JavaClassTranslator.swift +++ b/Sources/Java2SwiftLib/JavaClassTranslator.swift @@ -52,6 +52,9 @@ struct JavaClassTranslator { /// The Swift names of the interfaces that this class implements. let swiftInterfaces: [String] + /// The annotations of the Java class + let annotations: [Annotation] + /// The (instance) fields of the Java class. var fields: [Field] = [] @@ -164,6 +167,8 @@ struct JavaClassTranslator { } } + self.annotations = javaClass.getAnnotations().compactMap(\.self) + // Collect all of the class members that we will need to translate. // TODO: Switch over to "declared" versions of these whenever we don't need // to see inherited members. @@ -274,6 +279,7 @@ extension JavaClassTranslator { if let nativeMethodsProtocol = renderNativeMethodsProtocol() { allDecls.append(nativeMethodsProtocol) } + allDecls.append(contentsOf: renderAnnotationExtensions()) return allDecls } @@ -483,6 +489,30 @@ extension JavaClassTranslator { return protocolDecl.formatted(using: translator.format).cast(DeclSyntax.self) } + func renderAnnotationExtensions() -> [DeclSyntax] { + var extensions: [DeclSyntax] = [] + + for annotation in annotations { + let annotationName = annotation.annotationType().getName().splitSwiftTypeName().name + if annotationName == "ThreadSafe" || annotationName == "Immutable" { // If we are threadsafe, mark as unchecked Sendable + extensions.append( + """ + extension \(raw: swiftTypeName): @unchecked Swift.Sendable { } + """ + ) + } else if annotationName == "NotThreadSafe" { // If we are _not_ threadsafe, mark sendable unavailable + extensions.append( + """ + @available(unavailable, *) + extension \(raw: swiftTypeName): Swift.Sendable { } + """ + ) + } + } + + return extensions + } + /// Render the given Java constructor as a Swift initializer. package func renderConstructor( _ javaConstructor: Constructor diff --git a/Sources/JavaKitReflection/JavaClass+Reflection.swift b/Sources/JavaKitReflection/JavaClass+Reflection.swift index e5505144..1f2120e0 100644 --- a/Sources/JavaKitReflection/JavaClass+Reflection.swift +++ b/Sources/JavaKitReflection/JavaClass+Reflection.swift @@ -43,4 +43,7 @@ extension JavaClass { @JavaMethod public func getGenericInterfaces() -> [Type?] + + @JavaMethod + public func getAnnotations() -> [Annotation?] } From 2cf42ce3f016876e03a513cd68047628fd76896d Mon Sep 17 00:00:00 2001 From: Jack Rosen Date: Thu, 28 Nov 2024 08:10:50 -0500 Subject: [PATCH 190/426] Adds support for optional mapping (#189) --- Makefile | 12 +-- .../JavaKitExample/JavaKitExample.swift | 18 ++++- .../example/swift/ThreadSafeHelperClass.java | 21 +++++ .../Java2SwiftLib/JavaClassTranslator.swift | 63 ++++++++++++++- Sources/Java2SwiftLib/StringExtras.swift | 15 ++++ Sources/JavaKit/AnyJavaObject.swift | 6 -- Sources/JavaKit/Optional+JavaOptional.swift | 81 +++++++++++++++++++ Sources/JavaKit/generated/JavaClass.swift | 6 ++ .../JavaKit/generated/JavaClassLoader.swift | 4 +- Sources/JavaKit/generated/JavaDouble.swift | 7 ++ Sources/JavaKit/generated/JavaFloat.swift | 7 ++ Sources/JavaKit/generated/JavaInteger.swift | 7 ++ Sources/JavaKit/generated/JavaLong.swift | 7 ++ Sources/JavaKit/generated/JavaOptional.swift | 51 ++++++++++++ .../generated/JavaOptionalDouble.swift | 44 ++++++++++ .../JavaKit/generated/JavaOptionalInt.swift | 44 ++++++++++ .../JavaKit/generated/JavaOptionalLong.swift | 44 ++++++++++ Sources/JavaKit/generated/JavaString.swift | 7 ++ Sources/JavaKit/swift-java.config | 6 +- .../JavaKitCollection/generated/HashMap.swift | 50 ++++++++++++ .../JavaKitCollection/generated/TreeMap.swift | 50 ------------ .../generated/URLClassLoader.swift | 3 + 22 files changed, 483 insertions(+), 70 deletions(-) create mode 100644 Sources/JavaKit/Optional+JavaOptional.swift create mode 100644 Sources/JavaKit/generated/JavaOptional.swift create mode 100644 Sources/JavaKit/generated/JavaOptionalDouble.swift create mode 100644 Sources/JavaKit/generated/JavaOptionalInt.swift create mode 100644 Sources/JavaKit/generated/JavaOptionalLong.swift diff --git a/Makefile b/Makefile index d8f8717a..4b24b5a3 100644 --- a/Makefile +++ b/Makefile @@ -68,27 +68,27 @@ Java2Swift: $(BUILD_DIR)/debug/Java2Swift generate-JavaKit: Java2Swift mkdir -p Sources/JavaKit/generated - $(BUILD_DIR)/debug/Java2Swift --module-name JavaKit -o Sources/JavaKit/generated Sources/JavaKit/Java2Swift.config + $(BUILD_DIR)/debug/Java2Swift --module-name JavaKit -o Sources/JavaKit/generated Sources/JavaKit/swift-java.config generate-JavaKitCollection: Java2Swift mkdir -p Sources/JavaKitCollection/generated - $(BUILD_DIR)/debug/Java2Swift --module-name JavaKitCollection --depends-on JavaKit=Sources/JavaKit/Java2Swift.config -o Sources/JavaKitCollection/generated Sources/JavaKitCollection/Java2Swift.config + $(BUILD_DIR)/debug/Java2Swift --module-name JavaKitCollection --depends-on JavaKit=Sources/JavaKit/swift-java.config -o Sources/JavaKitCollection/generated Sources/JavaKitCollection/swift-java.config generate-JavaKitFunction: Java2Swift mkdir -p Sources/JavaKitFunction/generated - $(BUILD_DIR)/debug/Java2Swift --module-name JavaKitFunction --depends-on JavaKit=Sources/JavaKit/Java2Swift.config -o Sources/JavaKitFunction/generated Sources/JavaKitFunction/Java2Swift.config + $(BUILD_DIR)/debug/Java2Swift --module-name JavaKitFunction --depends-on JavaKit=Sources/JavaKit/swift-java.config -o Sources/JavaKitFunction/generated Sources/JavaKitFunction/swift-java.config generate-JavaKitReflection: Java2Swift generate-JavaKit generate-JavaKitCollection mkdir -p Sources/JavaKitReflection/generated - $(BUILD_DIR)/debug/Java2Swift --module-name JavaKitReflection --depends-on JavaKit=Sources/JavaKit/Java2Swift.config --depends-on JavaKitCollection=Sources/JavaKitCollection/Java2Swift.config -o Sources/JavaKitReflection/generated Sources/JavaKitReflection/Java2Swift.config + $(BUILD_DIR)/debug/Java2Swift --module-name JavaKitReflection --depends-on JavaKit=Sources/JavaKit/swift-java.config --depends-on JavaKitCollection=Sources/JavaKitCollection/swift-java.config -o Sources/JavaKitReflection/generated Sources/JavaKitReflection/swift-java.config generate-JavaKitJar: Java2Swift generate-JavaKit generate-JavaKitCollection mkdir -p Sources/JavaKitJar/generated - $(BUILD_DIR)/debug/Java2Swift --module-name JavaKitJar --depends-on JavaKit=Sources/JavaKit/Java2Swift.config --depends-on JavaKitCollection=Sources/JavaKitCollection/Java2Swift.config -o Sources/JavaKitJar/generated Sources/JavaKitJar/Java2Swift.config + $(BUILD_DIR)/debug/Java2Swift --module-name JavaKitJar --depends-on JavaKit=Sources/JavaKit/swift-java.config --depends-on JavaKitCollection=Sources/JavaKitCollection/swift-java.config -o Sources/JavaKitJar/generated Sources/JavaKitJar/swift-java.config generate-JavaKitNetwork: Java2Swift generate-JavaKit generate-JavaKitCollection mkdir -p Sources/JavaKitNetwork/generated - $(BUILD_DIR)/debug/Java2Swift --module-name JavaKitNetwork --depends-on JavaKit=Sources/JavaKit/Java2Swift.config --depends-on JavaKitCollection=Sources/JavaKitCollection/Java2Swift.config -o Sources/JavaKitNetwork/generated Sources/JavaKitNetwork/Java2Swift.config + $(BUILD_DIR)/debug/Java2Swift --module-name JavaKitNetwork --depends-on JavaKit=Sources/JavaKit/swift-java.config --depends-on JavaKitCollection=Sources/JavaKitCollection/swift-java.config -o Sources/JavaKitNetwork/generated Sources/JavaKitNetwork/swift-java.config javakit-generate: generate-JavaKit generate-JavaKitReflection generate-JavaKitJar generate-JavaKitNetwork diff --git a/Samples/JavaKitSampleApp/Sources/JavaKitExample/JavaKitExample.swift b/Samples/JavaKitSampleApp/Sources/JavaKitExample/JavaKitExample.swift index 366e8894..f074fee6 100644 --- a/Samples/JavaKitSampleApp/Sources/JavaKitExample/JavaKitExample.swift +++ b/Samples/JavaKitSampleApp/Sources/JavaKitExample/JavaKitExample.swift @@ -77,11 +77,27 @@ extension HelloSwift: HelloSwiftNativeMethods { } // Make sure that the thread safe class is sendable - let threadSafe: Sendable = ThreadSafeHelperClass(environment: javaEnvironment) + let helper = ThreadSafeHelperClass(environment: javaEnvironment) + let threadSafe: Sendable = helper + + checkOptionals(helper: helper) return i * j } + func checkOptionals(helper: ThreadSafeHelperClass) { + let text: JavaString? = helper.textOptional + let value: String? = helper.getValueOptional(Optional.none) + let textFunc: JavaString? = helper.getTextOptional() + let doubleOpt: Double? = helper.valOptional + let longOpt: Int64? = helper.fromOptional(21 as Int32?) + print("Optional text = \(text)") + print("Optional string value = \(value)") + print("Optional text function returned \(textFunc)") + print("Optional double function returned \(doubleOpt)") + print("Optional long function returned \(longOpt)") + } + @JavaMethod func throwMessageFromSwift(_ message: String) throws -> String { throw SwiftWrappedError.message(message) diff --git a/Samples/JavaKitSampleApp/Sources/JavaKitExample/com/example/swift/ThreadSafeHelperClass.java b/Samples/JavaKitSampleApp/Sources/JavaKitExample/com/example/swift/ThreadSafeHelperClass.java index 179b8cd6..3b7793f0 100644 --- a/Samples/JavaKitSampleApp/Sources/JavaKitExample/com/example/swift/ThreadSafeHelperClass.java +++ b/Samples/JavaKitSampleApp/Sources/JavaKitExample/com/example/swift/ThreadSafeHelperClass.java @@ -14,7 +14,28 @@ package com.example.swift; +import java.util.Optional; +import java.util.OptionalLong; +import java.util.OptionalInt; +import java.util.OptionalDouble; + @ThreadSafe public class ThreadSafeHelperClass { public ThreadSafeHelperClass() { } + + public Optional text = Optional.of(""); + + public final OptionalDouble val = OptionalDouble.of(2); + + public String getValue(Optional name) { + return name.orElse(""); + } + + public Optional getText() { + return text; + } + + public OptionalLong from(OptionalInt value) { + return OptionalLong.of(value.getAsInt()); + } } diff --git a/Sources/Java2SwiftLib/JavaClassTranslator.swift b/Sources/Java2SwiftLib/JavaClassTranslator.swift index e2753790..bfd1657f 100644 --- a/Sources/Java2SwiftLib/JavaClassTranslator.swift +++ b/Sources/Java2SwiftLib/JavaClassTranslator.swift @@ -567,9 +567,39 @@ extension JavaClassTranslator { let overrideOpt = (translateAsClass && !javaMethod.isStatic && isOverride(javaMethod)) ? "override " : "" - return """ - \(methodAttribute)\(raw: accessModifier)\(raw: overrideOpt)func \(raw: swiftMethodName)\(raw: genericParameterClause)(\(raw: parametersStr))\(raw: throwsStr)\(raw: resultTypeStr)\(raw: whereClause) - """ + + if resultType.optionalWrappedType() != nil || parameters.contains(where: { $0.type.trimmedDescription.optionalWrappedType() != nil }) { + let parameters = parameters.map { param -> (clause: FunctionParameterSyntax, passedArg: String) in + let name = param.secondName!.trimmedDescription + + return if let optionalType = param.type.trimmedDescription.optionalWrappedType() { + (clause: "_ \(raw: name): \(raw: optionalType)", passedArg: "\(name).toJavaOptional()") + } else { + (clause: param, passedArg: "\(name)") + } + } + + let resultOptional: String = resultType.optionalWrappedType() ?? resultType + let baseBody: ExprSyntax = "\(raw: javaMethod.throwsCheckedException ? "try " : "")\(raw: swiftMethodName)(\(raw: parameters.map(\.passedArg).joined(separator: ", ")))" + let body: ExprSyntax = if let optionalType = resultType.optionalWrappedType() { + "Optional(javaOptional: \(baseBody))" + } else { + baseBody + } + + + return """ + \(methodAttribute)\(raw: accessModifier)\(raw: overrideOpt)func \(raw: swiftMethodName)\(raw: genericParameterClause)(\(raw: parametersStr))\(raw: throwsStr)\(raw: resultTypeStr)\(raw: whereClause) + + \(raw: accessModifier)\(raw: overrideOpt)func \(raw: swiftMethodName)Optional\(raw: genericParameterClause)(\(raw: parameters.map(\.clause.description).joined(separator: ", ")))\(raw: throwsStr) -> \(raw: resultOptional)\(raw: whereClause) { + \(body) + } + """ + } else { + return """ + \(methodAttribute)\(raw: accessModifier)\(raw: overrideOpt)func \(raw: swiftMethodName)\(raw: genericParameterClause)(\(raw: parametersStr))\(raw: throwsStr)\(raw: resultTypeStr)\(raw: whereClause) + """ + } } /// Render a single Java field into the corresponding Swift property, or @@ -582,10 +612,35 @@ extension JavaClassTranslator { ) let fieldAttribute: AttributeSyntax = javaField.isStatic ? "@JavaStaticField" : "@JavaField"; let swiftFieldName = javaField.getName().escapedSwiftName - return """ + + if let optionalType = typeName.optionalWrappedType() { + let setter = if !javaField.isFinal { + """ + + set { + \(swiftFieldName) = newValue.toJavaOptional() + } + """ + } else { + "" + } + return """ + \(fieldAttribute)(isFinal: \(raw: javaField.isFinal)) + public var \(raw: swiftFieldName): \(raw: typeName) + + + public var \(raw: swiftFieldName)Optional: \(raw: optionalType) { + get { + Optional(javaOptional: \(raw: swiftFieldName)) + }\(raw: setter) + } + """ + } else { + return """ \(fieldAttribute)(isFinal: \(raw: javaField.isFinal)) public var \(raw: swiftFieldName): \(raw: typeName) """ + } } package func renderEnum(name: String) -> [DeclSyntax] { diff --git a/Sources/Java2SwiftLib/StringExtras.swift b/Sources/Java2SwiftLib/StringExtras.swift index f26d7c1b..e69f379c 100644 --- a/Sources/Java2SwiftLib/StringExtras.swift +++ b/Sources/Java2SwiftLib/StringExtras.swift @@ -39,4 +39,19 @@ extension String { public func replacing(_ character: Character, with replacement: Character) -> String { return replacingOccurrences(of: String(character), with: String(replacement)) } + + public func optionalWrappedType() -> String? { + if self == "JavaOptionalInt!" || self == "JavaOptionalInt?" { + return "Int32?" + } else if self == "JavaOptionalLong!" || self == "JavaOptionalLong?" { + return "Int64?" + } else if self == "JavaOptionalDouble!" || self == "JavaOptionalDouble?" { + return "Double?" + } else if hasPrefix("JavaOptional<") { + let offsetCount = "JavaOptional<".count + return "\(String(self[index(startIndex, offsetBy: offsetCount)..")!]))?" + } else { + return nil + } + } } diff --git a/Sources/JavaKit/AnyJavaObject.swift b/Sources/JavaKit/AnyJavaObject.swift index 27c3e06d..5e0a88d0 100644 --- a/Sources/JavaKit/AnyJavaObject.swift +++ b/Sources/JavaKit/AnyJavaObject.swift @@ -56,12 +56,6 @@ public protocol CustomJavaClassLoader: AnyJavaObject { static func getJavaClassLoader(in environment: JNIEnvironment) throws -> JavaClassLoader! } -/// Add getClassLoader() to JavaObject as it is otherwise recursively defined -extension JavaObject { - @JavaMethod - public func getClassLoader() throws -> JavaClassLoader! -} - extension AnyJavaObject { /// Retrieve the underlying Java object. public var javaThis: jobject { diff --git a/Sources/JavaKit/Optional+JavaOptional.swift b/Sources/JavaKit/Optional+JavaOptional.swift new file mode 100644 index 00000000..c9becd58 --- /dev/null +++ b/Sources/JavaKit/Optional+JavaOptional.swift @@ -0,0 +1,81 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +public extension Optional where Wrapped: AnyJavaObject { + func toJavaOptional() -> JavaOptional { + return try! JavaClass>().ofNullable(self?.as(JavaObject.self)).as(JavaOptional.self)! + } + + init(javaOptional: JavaOptional?) { + if let javaOptional { + self = javaOptional.isPresent() ? javaOptional.get().as(Wrapped.self) : Optional.none + } else { + self = nil + } + } +} + +public extension Optional where Wrapped == Double { + func toJavaOptional() -> JavaOptionalDouble { + if let self { + return try! JavaClass().of(self)! + } else { + return try! JavaClass().empty()! + } + } + + init(javaOptional: JavaOptionalDouble?) { + if let javaOptional { + self = javaOptional.isPresent() ? javaOptional.getAsDouble() : nil + } else { + self = nil + } + } +} + +public extension Optional where Wrapped == Int32 { + func toJavaOptional() -> JavaOptionalInt { + if let self { + return try! JavaClass().of(self)! + } else { + return try! JavaClass().empty()! + } + } + + init(javaOptional: JavaOptionalInt?) { + if let javaOptional { + self = javaOptional.isPresent() ? javaOptional.getAsInt() : nil + } else { + self = nil + } + } +} + +public extension Optional where Wrapped == Int64 { + func toJavaOptional() -> JavaOptionalLong { + if let self { + return try! JavaClass().of(self)! + } else { + return try! JavaClass().empty()! + } + } + + init(javaOptional: JavaOptionalLong?) { + if let javaOptional { + self = javaOptional.isPresent() ? javaOptional.getAsLong() : nil + } else { + self = nil + } + } +} diff --git a/Sources/JavaKit/generated/JavaClass.swift b/Sources/JavaKit/generated/JavaClass.swift index b66835aa..03d7f5e6 100644 --- a/Sources/JavaKit/generated/JavaClass.swift +++ b/Sources/JavaKit/generated/JavaClass.swift @@ -51,6 +51,9 @@ open class JavaClass: JavaObject { @JavaMethod open func isRecord() -> Bool + @JavaMethod + open func getClassLoader() -> JavaClassLoader! + @JavaMethod open func newInstance() throws -> JavaObject! @@ -130,6 +133,9 @@ open class JavaClass: JavaObject { open func isSealed() -> Bool } extension JavaClass { + @JavaStaticMethod + public func forName(_ arg0: String, _ arg1: Bool, _ arg2: JavaClassLoader?) throws -> JavaClass! where ObjectType == JavaClass + @JavaStaticMethod public func forName(_ arg0: String) throws -> JavaClass! where ObjectType == JavaClass diff --git a/Sources/JavaKit/generated/JavaClassLoader.swift b/Sources/JavaKit/generated/JavaClassLoader.swift index 43eaeb4e..6c877cc3 100644 --- a/Sources/JavaKit/generated/JavaClassLoader.swift +++ b/Sources/JavaKit/generated/JavaClassLoader.swift @@ -31,10 +31,10 @@ open class JavaClassLoader: JavaObject { open func resolveClass(_ arg0: JavaClass?) @JavaMethod - open func defineClass(_ arg0: [Int8], _ arg1: Int32, _ arg2: Int32) throws -> JavaClass! + open func defineClass(_ arg0: String, _ arg1: [Int8], _ arg2: Int32, _ arg3: Int32) throws -> JavaClass! @JavaMethod - open func defineClass(_ arg0: String, _ arg1: [Int8], _ arg2: Int32, _ arg3: Int32) throws -> JavaClass! + open func defineClass(_ arg0: [Int8], _ arg1: Int32, _ arg2: Int32) throws -> JavaClass! @JavaMethod open func findLibrary(_ arg0: String) -> String diff --git a/Sources/JavaKit/generated/JavaDouble.swift b/Sources/JavaKit/generated/JavaDouble.swift index 4eaa425e..efa77a95 100644 --- a/Sources/JavaKit/generated/JavaDouble.swift +++ b/Sources/JavaKit/generated/JavaDouble.swift @@ -45,6 +45,13 @@ open class JavaDouble: JavaNumber { @JavaMethod open override func doubleValue() -> Double + @JavaMethod + open func describeConstable() -> JavaOptional! + + open func describeConstableOptional() -> JavaDouble? { + Optional(javaOptional: describeConstable()) + } + @JavaMethod open func isNaN() -> Bool } diff --git a/Sources/JavaKit/generated/JavaFloat.swift b/Sources/JavaKit/generated/JavaFloat.swift index 6ad0536e..0c38d1ae 100644 --- a/Sources/JavaKit/generated/JavaFloat.swift +++ b/Sources/JavaKit/generated/JavaFloat.swift @@ -48,6 +48,13 @@ open class JavaFloat: JavaNumber { @JavaMethod open override func doubleValue() -> Double + @JavaMethod + open func describeConstable() -> JavaOptional! + + open func describeConstableOptional() -> JavaFloat? { + Optional(javaOptional: describeConstable()) + } + @JavaMethod open func isNaN() -> Bool } diff --git a/Sources/JavaKit/generated/JavaInteger.swift b/Sources/JavaKit/generated/JavaInteger.swift index 7aadd187..e5cd5fc1 100644 --- a/Sources/JavaKit/generated/JavaInteger.swift +++ b/Sources/JavaKit/generated/JavaInteger.swift @@ -41,6 +41,13 @@ open class JavaInteger: JavaNumber { @JavaMethod open override func doubleValue() -> Double + + @JavaMethod + open func describeConstable() -> JavaOptional! + + open func describeConstableOptional() -> JavaInteger? { + Optional(javaOptional: describeConstable()) + } } extension JavaClass { @JavaStaticField(isFinal: true) diff --git a/Sources/JavaKit/generated/JavaLong.swift b/Sources/JavaKit/generated/JavaLong.swift index 4cbe97ba..491ef1dd 100644 --- a/Sources/JavaKit/generated/JavaLong.swift +++ b/Sources/JavaKit/generated/JavaLong.swift @@ -41,6 +41,13 @@ open class JavaLong: JavaNumber { @JavaMethod open override func doubleValue() -> Double + + @JavaMethod + open func describeConstable() -> JavaOptional! + + open func describeConstableOptional() -> JavaLong? { + Optional(javaOptional: describeConstable()) + } } extension JavaClass { @JavaStaticField(isFinal: true) diff --git a/Sources/JavaKit/generated/JavaOptional.swift b/Sources/JavaKit/generated/JavaOptional.swift new file mode 100644 index 00000000..bd77cfed --- /dev/null +++ b/Sources/JavaKit/generated/JavaOptional.swift @@ -0,0 +1,51 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaRuntime + +@JavaClass("java.util.Optional") +open class JavaOptional: JavaObject { + @JavaMethod + open func get() -> JavaObject! + + @JavaMethod + open override func equals(_ arg0: JavaObject?) -> Bool + + @JavaMethod + open override func toString() -> String + + @JavaMethod + open override func hashCode() -> Int32 + + @JavaMethod + open func isEmpty() -> Bool + + @JavaMethod + open func isPresent() -> Bool + + @JavaMethod + open func orElse(_ arg0: JavaObject?) -> JavaObject! + + @JavaMethod + open func orElseThrow() -> JavaObject! +} +extension JavaClass { + @JavaStaticMethod + public func of(_ arg0: JavaObject?) -> JavaOptional! where ObjectType == JavaOptional + + public func ofOptional(_ arg0: JavaObject?) -> JavaObject? where ObjectType == JavaOptional { + Optional(javaOptional: of(arg0)) + } + + @JavaStaticMethod + public func empty() -> JavaOptional! where ObjectType == JavaOptional + + public func emptyOptional() -> JavaObject? where ObjectType == JavaOptional { + Optional(javaOptional: empty()) + } + + @JavaStaticMethod + public func ofNullable(_ arg0: JavaObject?) -> JavaOptional! where ObjectType == JavaOptional + + public func ofNullableOptional(_ arg0: JavaObject?) -> JavaObject? where ObjectType == JavaOptional { + Optional(javaOptional: ofNullable(arg0)) + } +} diff --git a/Sources/JavaKit/generated/JavaOptionalDouble.swift b/Sources/JavaKit/generated/JavaOptionalDouble.swift new file mode 100644 index 00000000..5926282a --- /dev/null +++ b/Sources/JavaKit/generated/JavaOptionalDouble.swift @@ -0,0 +1,44 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaRuntime + +@JavaClass("java.util.OptionalDouble") +open class JavaOptionalDouble: JavaObject { + @JavaMethod + open override func equals(_ arg0: JavaObject?) -> Bool + + @JavaMethod + open override func toString() -> String + + @JavaMethod + open override func hashCode() -> Int32 + + @JavaMethod + open func isEmpty() -> Bool + + @JavaMethod + open func isPresent() -> Bool + + @JavaMethod + open func orElse(_ arg0: Double) -> Double + + @JavaMethod + open func orElseThrow() -> Double + + @JavaMethod + open func getAsDouble() -> Double +} +extension JavaClass { + @JavaStaticMethod + public func of(_ arg0: Double) -> JavaOptionalDouble! + + public func ofOptional(_ arg0: Double) -> Double? { + Optional(javaOptional: of(arg0)) + } + + @JavaStaticMethod + public func empty() -> JavaOptionalDouble! + + public func emptyOptional() -> Double? { + Optional(javaOptional: empty()) + } +} diff --git a/Sources/JavaKit/generated/JavaOptionalInt.swift b/Sources/JavaKit/generated/JavaOptionalInt.swift new file mode 100644 index 00000000..1237a085 --- /dev/null +++ b/Sources/JavaKit/generated/JavaOptionalInt.swift @@ -0,0 +1,44 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaRuntime + +@JavaClass("java.util.OptionalInt") +open class JavaOptionalInt: JavaObject { + @JavaMethod + open override func equals(_ arg0: JavaObject?) -> Bool + + @JavaMethod + open override func toString() -> String + + @JavaMethod + open override func hashCode() -> Int32 + + @JavaMethod + open func isEmpty() -> Bool + + @JavaMethod + open func isPresent() -> Bool + + @JavaMethod + open func orElse(_ arg0: Int32) -> Int32 + + @JavaMethod + open func orElseThrow() -> Int32 + + @JavaMethod + open func getAsInt() -> Int32 +} +extension JavaClass { + @JavaStaticMethod + public func of(_ arg0: Int32) -> JavaOptionalInt! + + public func ofOptional(_ arg0: Int32) -> Int32? { + Optional(javaOptional: of(arg0)) + } + + @JavaStaticMethod + public func empty() -> JavaOptionalInt! + + public func emptyOptional() -> Int32? { + Optional(javaOptional: empty()) + } +} diff --git a/Sources/JavaKit/generated/JavaOptionalLong.swift b/Sources/JavaKit/generated/JavaOptionalLong.swift new file mode 100644 index 00000000..79a9e06f --- /dev/null +++ b/Sources/JavaKit/generated/JavaOptionalLong.swift @@ -0,0 +1,44 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaRuntime + +@JavaClass("java.util.OptionalLong") +open class JavaOptionalLong: JavaObject { + @JavaMethod + open override func equals(_ arg0: JavaObject?) -> Bool + + @JavaMethod + open override func toString() -> String + + @JavaMethod + open override func hashCode() -> Int32 + + @JavaMethod + open func isEmpty() -> Bool + + @JavaMethod + open func isPresent() -> Bool + + @JavaMethod + open func orElse(_ arg0: Int64) -> Int64 + + @JavaMethod + open func orElseThrow() -> Int64 + + @JavaMethod + open func getAsLong() -> Int64 +} +extension JavaClass { + @JavaStaticMethod + public func of(_ arg0: Int64) -> JavaOptionalLong! + + public func ofOptional(_ arg0: Int64) -> Int64? { + Optional(javaOptional: of(arg0)) + } + + @JavaStaticMethod + public func empty() -> JavaOptionalLong! + + public func emptyOptional() -> Int64? { + Optional(javaOptional: empty()) + } +} diff --git a/Sources/JavaKit/generated/JavaString.swift b/Sources/JavaKit/generated/JavaString.swift index adf1993d..34d0080c 100644 --- a/Sources/JavaKit/generated/JavaString.swift +++ b/Sources/JavaKit/generated/JavaString.swift @@ -206,6 +206,13 @@ open class JavaString: JavaObject { @JavaMethod open func intern() -> String + + @JavaMethod + open func describeConstable() -> JavaOptional! + + open func describeConstableOptional() -> JavaString? { + Optional(javaOptional: describeConstable()) + } } extension JavaClass { @JavaStaticMethod diff --git a/Sources/JavaKit/swift-java.config b/Sources/JavaKit/swift-java.config index d02a10ed..34751edd 100644 --- a/Sources/JavaKit/swift-java.config +++ b/Sources/JavaKit/swift-java.config @@ -18,6 +18,10 @@ "java.lang.Short" : "JavaShort", "java.lang.String" : "JavaString", "java.lang.Throwable" : "Throwable", - "java.lang.Void" : "JavaVoid" + "java.lang.Void" : "JavaVoid", + "java.util.Optional": "JavaOptional", + "java.util.OptionalDouble": "JavaOptionalDouble", + "java.util.OptionalInt": "JavaOptionalInt", + "java.util.OptionalLong": "JavaOptionalLong" } } diff --git a/Sources/JavaKitCollection/generated/HashMap.swift b/Sources/JavaKitCollection/generated/HashMap.swift index 424dfbb9..e8cfa118 100644 --- a/Sources/JavaKitCollection/generated/HashMap.swift +++ b/Sources/JavaKitCollection/generated/HashMap.swift @@ -61,6 +61,56 @@ open class HashMap: JavaObject { @JavaMethod open func getOrDefault(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject! } +extension HashMap { + @JavaClass("java.util.AbstractMap$SimpleEntry") + open class SimpleEntry: JavaObject { + @JavaMethod + @_nonoverride public convenience init(_ arg0: JavaObject?, _ arg1: JavaObject?, environment: JNIEnvironment? = nil) + + @JavaMethod + open override func equals(_ arg0: JavaObject?) -> Bool + + @JavaMethod + open override func toString() -> String + + @JavaMethod + open override func hashCode() -> Int32 + + @JavaMethod + open func getValue() -> JavaObject! + + @JavaMethod + open func getKey() -> JavaObject! + + @JavaMethod + open func setValue(_ arg0: JavaObject?) -> JavaObject! + } +} +extension HashMap { + @JavaClass("java.util.AbstractMap$SimpleImmutableEntry") + open class SimpleImmutableEntry: JavaObject { + @JavaMethod + @_nonoverride public convenience init(_ arg0: JavaObject?, _ arg1: JavaObject?, environment: JNIEnvironment? = nil) + + @JavaMethod + open override func equals(_ arg0: JavaObject?) -> Bool + + @JavaMethod + open override func toString() -> String + + @JavaMethod + open override func hashCode() -> Int32 + + @JavaMethod + open func getValue() -> JavaObject! + + @JavaMethod + open func getKey() -> JavaObject! + + @JavaMethod + open func setValue(_ arg0: JavaObject?) -> JavaObject! + } +} extension JavaClass { @JavaStaticMethod public func newHashMap(_ arg0: Int32) -> HashMap! where ObjectType == HashMap diff --git a/Sources/JavaKitCollection/generated/TreeMap.swift b/Sources/JavaKitCollection/generated/TreeMap.swift index 7796d555..79560905 100644 --- a/Sources/JavaKitCollection/generated/TreeMap.swift +++ b/Sources/JavaKitCollection/generated/TreeMap.swift @@ -70,53 +70,3 @@ open class TreeMap: JavaObject { @JavaMethod open func lastKey() -> JavaObject! } -extension TreeMap { - @JavaClass("java.util.AbstractMap$SimpleEntry") - open class SimpleEntry: JavaObject { - @JavaMethod - @_nonoverride public convenience init(_ arg0: JavaObject?, _ arg1: JavaObject?, environment: JNIEnvironment? = nil) - - @JavaMethod - open override func equals(_ arg0: JavaObject?) -> Bool - - @JavaMethod - open override func toString() -> String - - @JavaMethod - open override func hashCode() -> Int32 - - @JavaMethod - open func getValue() -> JavaObject! - - @JavaMethod - open func getKey() -> JavaObject! - - @JavaMethod - open func setValue(_ arg0: JavaObject?) -> JavaObject! - } -} -extension TreeMap { - @JavaClass("java.util.AbstractMap$SimpleImmutableEntry") - open class SimpleImmutableEntry: JavaObject { - @JavaMethod - @_nonoverride public convenience init(_ arg0: JavaObject?, _ arg1: JavaObject?, environment: JNIEnvironment? = nil) - - @JavaMethod - open override func equals(_ arg0: JavaObject?) -> Bool - - @JavaMethod - open override func toString() -> String - - @JavaMethod - open override func hashCode() -> Int32 - - @JavaMethod - open func getValue() -> JavaObject! - - @JavaMethod - open func getKey() -> JavaObject! - - @JavaMethod - open func setValue(_ arg0: JavaObject?) -> JavaObject! - } -} diff --git a/Sources/JavaKitNetwork/generated/URLClassLoader.swift b/Sources/JavaKitNetwork/generated/URLClassLoader.swift index ba977e07..eac9c14c 100644 --- a/Sources/JavaKitNetwork/generated/URLClassLoader.swift +++ b/Sources/JavaKitNetwork/generated/URLClassLoader.swift @@ -27,6 +27,9 @@ open class URLClassLoader: JavaObject { open func getURLs() -> [URL?] } extension JavaClass { + @JavaStaticMethod + public func newInstance(_ arg0: [URL?], _ arg1: JavaClassLoader?) -> URLClassLoader! + @JavaStaticMethod public func newInstance(_ arg0: [URL?]) -> URLClassLoader! } From bb3317683372cf9006e1ffb3101bf7b7f906498e Mon Sep 17 00:00:00 2001 From: Jack Rosen Date: Fri, 29 Nov 2024 00:21:10 -0500 Subject: [PATCH 191/426] Update Class Layout to use Runtime Metadata (#190) Co-authored-by: Konrad `ktoso` Malawski --- .../Swift2JavaTranslator+Printing.swift | 13 ++-- .../ClassPrintingTests.swift | 65 +++++++++++++++++++ 2 files changed, 71 insertions(+), 7 deletions(-) create mode 100644 Tests/JExtractSwiftTests/ClassPrintingTests.swift diff --git a/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift b/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift index 5a367840..76721e46 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift @@ -205,6 +205,11 @@ extension Swift2JavaTranslator { ) printer.print("") + // Layout of the class + printClassMemoryLayout(&printer, decl) + + printer.print("") + // Initializers for initDecl in decl.initializers { printClassConstructors(&printer, initDecl) @@ -264,9 +269,6 @@ extension Swift2JavaTranslator { printClassConstants(printer: &printer) printTypeMappingDecls(&printer) - // Layout of the class - printClassMemoryLayout(&printer, decl) - body(&printer) } } @@ -384,12 +386,9 @@ extension Swift2JavaTranslator { } private func printClassMemoryLayout(_ printer: inout CodePrinter, _ decl: ImportedNominalType) { - // TODO: make use of the swift runtime to get the layout printer.print( """ - private static final GroupLayout $LAYOUT = MemoryLayout.structLayout( - SWIFT_POINTER - ).withName("\(decl.swiftTypeName)"); + private static final GroupLayout $LAYOUT = (GroupLayout) SwiftValueWitnessTable.layoutOfSwiftType(TYPE_METADATA.$memorySegment()); public final GroupLayout $layout() { return $LAYOUT; diff --git a/Tests/JExtractSwiftTests/ClassPrintingTests.swift b/Tests/JExtractSwiftTests/ClassPrintingTests.swift new file mode 100644 index 00000000..57c06f7e --- /dev/null +++ b/Tests/JExtractSwiftTests/ClassPrintingTests.swift @@ -0,0 +1,65 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import JExtractSwift +import Testing + +struct ClassPrintingTests { + let class_interfaceFile = + """ + // swift-interface-format-version: 1.0 + // swift-compiler-version: Apple Swift version 6.0 effective-5.10 (swiftlang-6.0.0.7.6 clang-1600.0.24.1) + // swift-module-flags: -target arm64-apple-macosx15.0 -enable-objc-interop -enable-library-evolution -module-name MySwiftLibrary + import Darwin.C + import Darwin + import Swift + import _Concurrency + import _StringProcessing + import _SwiftConcurrencyShims + + public class MySwiftClass { + public init(len: Swift.Int, cap: Swift.Int) + + public func helloMemberFunction() + + public func makeInt() -> Int + + @objc deinit + } + """ + + @Test("Import: class layout") + func class_layout() throws { + let st = Swift2JavaTranslator( + javaPackage: "com.example.swift", + swiftModuleName: "__FakeModule" + ) + + try assertOutput(st, input: class_interfaceFile, .java, expectedChunks: [ + """ + public static final SwiftAnyType TYPE_METADATA = + new SwiftAnyType(SwiftKit.swiftjava.getType("__FakeModule", "MySwiftClass")); + public final SwiftAnyType $swiftType() { + return TYPE_METADATA; + } + + + private static final GroupLayout $LAYOUT = (GroupLayout) SwiftValueWitnessTable.layoutOfSwiftType(TYPE_METADATA.$memorySegment()); + public final GroupLayout $layout() { + return $LAYOUT; + } + """ + ]) + } +} From f63150a040b4c0c6271cbfd5892f2a1e5884924e Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Mon, 2 Dec 2024 12:31:17 +0900 Subject: [PATCH 192/426] Fix how we spell "classpath" consistently (#192) --- .../JavaSieve/Sources/JavaSieve/main.swift | 2 +- .../Sources/JavaSieve/swift-java.config | 2 +- Sources/Java2Swift/JavaToSwift.swift | 22 +++++++++---------- Sources/Java2SwiftLib/Configuration.swift | 6 ++--- .../JavaKitVM/JavaVirtualMachine.swift | 20 ++++++++--------- USER_GUIDE.md | 6 ++--- 6 files changed, 29 insertions(+), 29 deletions(-) diff --git a/Samples/JavaSieve/Sources/JavaSieve/main.swift b/Samples/JavaSieve/Sources/JavaSieve/main.swift index b06cc6bb..6d262b9f 100644 --- a/Samples/JavaSieve/Sources/JavaSieve/main.swift +++ b/Samples/JavaSieve/Sources/JavaSieve/main.swift @@ -15,7 +15,7 @@ import JavaKit import JavaMath -let jvm = try JavaVirtualMachine.shared(classPath: ["QuadraticSieve-1.0.jar"]) +let jvm = try JavaVirtualMachine.shared(classpath: ["QuadraticSieve-1.0.jar"]) do { let sieveClass = try JavaClass(environment: jvm.environment()) for prime in sieveClass.findPrimes(100)! { diff --git a/Samples/JavaSieve/Sources/JavaSieve/swift-java.config b/Samples/JavaSieve/Sources/JavaSieve/swift-java.config index 61d5cb31..7ef33db9 100644 --- a/Samples/JavaSieve/Sources/JavaSieve/swift-java.config +++ b/Samples/JavaSieve/Sources/JavaSieve/swift-java.config @@ -1,5 +1,5 @@ { - "classPath" : "QuadraticSieve-1.0.jar", + "classpath" : "QuadraticSieve-1.0.jar", "classes" : { "com.gazman.quadratic_sieve.QuadraticSieve" : "QuadraticSieve", "com.gazman.quadratic_sieve.core.BaseFact" : "BaseFact", diff --git a/Sources/Java2Swift/JavaToSwift.swift b/Sources/Java2Swift/JavaToSwift.swift index 072aced2..35bffc74 100644 --- a/Sources/Java2Swift/JavaToSwift.swift +++ b/Sources/Java2Swift/JavaToSwift.swift @@ -136,38 +136,38 @@ struct JavaToSwift: ParsableCommand { // Form a class path from all of our input sources: // * Command-line option --classpath - var classPathPieces: [String] = classpath + var classpathPieces: [String] = classpath switch generationMode { case .configuration(jarFile: let jarFile): // * Jar file (in `-jar` mode) - classPathPieces.append(jarFile) + classpathPieces.append(jarFile) case .classWrappers(let config): // * Class path specified in the configuration file (if any) - config.classPath.map { classPathPieces.append($0) } + config.classpath.map { classpathPieces.append($0) } } // * Classes paths from all dependent configuration files for (_, config) in dependentConfigs { - config.classPath.map { classPathPieces.append($0) } + config.classpath.map { classpathPieces.append($0) } } // Bring up the Java VM. - let jvm = try JavaVirtualMachine.shared(classPath: classPathPieces) + let jvm = try JavaVirtualMachine.shared(classpath: classpathPieces) // Run the generation step. - let classPath = classPathPieces.joined(separator: ":") + let classpath = classpathPieces.joined(separator: ":") switch generationMode { case .configuration(jarFile: let jarFile): try emitConfiguration( forJarFile: jarFile, - classPath: classPath, + classpath: classpath, environment: jvm.environment() ) case .classWrappers(let config): try generateWrappers( config: config, - classPath: classPath, + classpath: classpath, dependentConfigs: dependentConfigs, environment: jvm.environment() ) @@ -177,7 +177,7 @@ struct JavaToSwift: ParsableCommand { /// Generate wrapper mutating func generateWrappers( config: Configuration, - classPath: String, + classpath: String, dependentConfigs: [(String, Configuration)], environment: JNIEnvironment ) throws { @@ -340,10 +340,10 @@ struct JavaToSwift: ParsableCommand { mutating func emitConfiguration( forJarFile jarFileName: String, - classPath: String, + classpath: String, environment: JNIEnvironment ) throws { - var configuration = Configuration(classPath: classPath) + var configuration = Configuration(classpath: classpath) let jarFile = try JarFile(jarFileName, false, environment: environment) for entry in jarFile.entries()! { diff --git a/Sources/Java2SwiftLib/Configuration.swift b/Sources/Java2SwiftLib/Configuration.swift index be92dd84..2cda8476 100644 --- a/Sources/Java2SwiftLib/Configuration.swift +++ b/Sources/Java2SwiftLib/Configuration.swift @@ -21,7 +21,7 @@ package typealias JavaVersion = Int /// must be kept in sync. package struct Configuration: Codable { /// The Java class path that should be passed along to the Java2Swift tool. - package var classPath: String? = nil + package var classpath: String? = nil /// The Java classes that should be translated to Swift. The keys are /// canonical Java class names (e.g., java.util.Vector) and the values are @@ -32,12 +32,12 @@ package struct Configuration: Codable { package var targetCompatibility: JavaVersion? package init( - classPath: String? = nil, + classpath: String? = nil, classes: [String : String] = [:], sourceCompatibility: JavaVersion? = nil, targetCompatibility: JavaVersion? = nil ) { - self.classPath = classPath + self.classpath = classpath self.classes = classes self.sourceCompatibility = sourceCompatibility self.targetCompatibility = targetCompatibility diff --git a/Sources/JavaKit/JavaKitVM/JavaVirtualMachine.swift b/Sources/JavaKit/JavaKitVM/JavaVirtualMachine.swift index 6348dc3c..61f01f51 100644 --- a/Sources/JavaKit/JavaKitVM/JavaVirtualMachine.swift +++ b/Sources/JavaKit/JavaKitVM/JavaVirtualMachine.swift @@ -44,7 +44,7 @@ public final class JavaVirtualMachine: @unchecked Sendable { /// Initialize a new Java virtual machine instance. /// /// - Parameters: - /// - classPath: The directories, JAR files, and ZIP files in which the JVM + /// - classpath: The directories, JAR files, and ZIP files in which the JVM /// should look to find classes. This maps to the VM option /// `-Djava.class.path=`. /// - vmOptions: Options that should be passed along to the JVM, which will @@ -52,7 +52,7 @@ public final class JavaVirtualMachine: @unchecked Sendable { /// - ignoreUnrecognized: Whether the JVM should ignore any VM options it /// does not recognize. private init( - classPath: [String] = [], + classpath: [String] = [], vmOptions: [String] = [], ignoreUnrecognized: Bool = false ) throws { @@ -64,14 +64,14 @@ public final class JavaVirtualMachine: @unchecked Sendable { // Construct the complete list of VM options. var allVMOptions: [String] = [] - if !classPath.isEmpty { + if !classpath.isEmpty { let fileManager = FileManager.default - for path in classPath { + for path in classpath { if !fileManager.fileExists(atPath: path) { - throw JavaKitError.classPathEntryNotFound(entry: path, classPath: classPath) + throw JavaKitError.classpathEntryNotFound(entry: path, classpath: classpath) } } - let colonSeparatedClassPath = classPath.joined(separator: ":") + let colonSeparatedClassPath = classpath.joined(separator: ":") allVMOptions.append("-Djava.class.path=\(colonSeparatedClassPath)") } allVMOptions.append(contentsOf: vmOptions) @@ -183,7 +183,7 @@ extension JavaVirtualMachine { /// calls. /// /// - Parameters: - /// - classPath: The directories, JAR files, and ZIP files in which the JVM + /// - classpath: The directories, JAR files, and ZIP files in which the JVM /// should look to find classes. This maps to the VM option /// `-Djava.class.path=`. /// - vmOptions: Options that should be passed along to the JVM, which will @@ -191,7 +191,7 @@ extension JavaVirtualMachine { /// - ignoreUnrecognized: Whether the JVM should ignore any VM options it /// does not recognize. public static func shared( - classPath: [String] = [], + classpath: [String] = [], vmOptions: [String] = [], ignoreUnrecognized: Bool = false ) throws -> JavaVirtualMachine { @@ -225,7 +225,7 @@ extension JavaVirtualMachine { let javaVirtualMachine: JavaVirtualMachine do { javaVirtualMachine = try JavaVirtualMachine( - classPath: classPath, + classpath: classpath, vmOptions: vmOptions, ignoreUnrecognized: ignoreUnrecognized ) @@ -289,6 +289,6 @@ extension JavaVirtualMachine { } enum JavaKitError: Error { - case classPathEntryNotFound(entry: String, classPath: [String]) + case classpathEntryNotFound(entry: String, classpath: [String]) } } diff --git a/USER_GUIDE.md b/USER_GUIDE.md index e352670e..2abe8ea0 100644 --- a/USER_GUIDE.md +++ b/USER_GUIDE.md @@ -111,7 +111,7 @@ The resulting configuration file will look something like this: ```json { - "classPath" : "QuadraticSieve-1.0.jar", + "classpath" : "QuadraticSieve-1.0.jar", "classes" : { "com.gazman.quadratic_sieve.QuadraticSieve" : "QuadraticSieve", "com.gazman.quadratic_sieve.core.BaseFact" : "BaseFact", @@ -206,7 +206,7 @@ Putting it all together, we can define a main program in `Sources/JavaSieve/main ```swift import JavaKit -let jvm = try JavaVirtualMachine.shared(classPath: ["QuadraticSieve-1.0.jar"]) +let jvm = try JavaVirtualMachine.shared(classpath: ["QuadraticSieve-1.0.jar"]) do { let sieveClass = try JavaClass(environment: jvm.environment()) for prime in sieveClass.findPrimes(100)! { @@ -217,7 +217,7 @@ do { } ``` -Note that we are passing the Jar file in the `classPath` argument when initializing the `JavaVirtualMachine` instance. Otherwise, the program will fail with an error because it cannot find the Java class `com.gazman.quadratic_sieve.primes.SieveOfEratosthenes`. +Note that we are passing the Jar file in the `classpath` argument when initializing the `JavaVirtualMachine` instance. Otherwise, the program will fail with an error because it cannot find the Java class `com.gazman.quadratic_sieve.primes.SieveOfEratosthenes`. ### Downcasting From 79882d8800a0b8dc9e39c3c069685d509777d332 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Tue, 10 Dec 2024 10:59:59 +0900 Subject: [PATCH 193/426] Fetching dependencies declared in swift-java.config (#191) --- .github/scripts/validate_sample.sh | 32 ++ .github/scripts/validate_samples.sh | 37 -- .github/workflows/pull_request.yml | 14 +- .licenseignore | 3 +- JavaKit/build.gradle | 77 +++ JavaKit/gradlew | 1 + JavaKit/gradlew.bat | 1 + .../javakit/annotations/UsedFromSwift.java | 28 + .../dependencies/DependencyResolver.java | 303 +++++++++++ .../SwiftJavaBootstrapException.java | 25 + .../dependencies/SystemClassLoaderUnsafe.java | 46 ++ Package.swift | 44 +- .../Java2SwiftPlugin/Java2SwiftPlugin.swift | 135 +++-- Plugins/PluginsShared/Configuration.swift | 81 --- .../PluginsShared/JavaKitConfigurationShared | 1 + Plugins/PluginsShared/PluginUtils.swift | 5 + Samples/JavaDependencySampleApp/Package.swift | 101 ++++ .../Sources/JavaCommonsCSV/dummy.swift | 13 + .../Sources/JavaCommonsCSV/swift-java.config | 9 + .../Sources/JavaDependencySample/main.swift | 47 ++ .../JavaDependencySample/swift-java.config | 2 + .../JavaDependencySampleApp/ci-validate.sh | 10 + Samples/JavaKitSampleApp/ci-validate.sh | 3 + Samples/JavaProbablyPrime/ci-validate.sh | 3 + Samples/JavaSieve/.gitignore | 1 + Samples/JavaSieve/README.md | 3 +- .../JavaSieve/Sources/JavaSieve/main.swift | 6 +- .../Sources/JavaSieve/swift-java.config | 2 +- Samples/JavaSieve/ci-validate.sh | 2 +- Sources/JExtractSwift/Swift2Java.swift | 1 + .../JavaToSwift+EmitConfiguration.swift | 122 +++++ .../JavaToSwift+FetchDependencies.swift | 122 +++++ .../JavaToSwift+GenerateWrappers.swift | 145 +++++ Sources/Java2Swift/JavaToSwift.swift | 500 +++++++++--------- Sources/Java2Swift/String+Extensions.swift | 62 +++ Sources/Java2SwiftLib/Configuration.swift | 45 -- .../JavaTranslator+Configuration.swift | 7 +- .../JavaTranslator+Validation.swift | 2 +- Sources/Java2SwiftLib/JavaTranslator.swift | 1 + .../JavaKitVM/JavaVirtualMachine.swift | 68 ++- .../Configuration.swift | 191 +++++++ .../DependencyResolver.swift | 32 ++ .../swift-java.config | 9 + .../TerminalColors.swift | 0 settings.gradle | 1 + 45 files changed, 1872 insertions(+), 471 deletions(-) create mode 100755 .github/scripts/validate_sample.sh delete mode 100755 .github/scripts/validate_samples.sh create mode 100644 JavaKit/build.gradle create mode 120000 JavaKit/gradlew create mode 120000 JavaKit/gradlew.bat create mode 100644 JavaKit/src/main/java/org/swift/javakit/annotations/UsedFromSwift.java create mode 100644 JavaKit/src/main/java/org/swift/javakit/dependencies/DependencyResolver.java create mode 100644 JavaKit/src/main/java/org/swift/javakit/dependencies/SwiftJavaBootstrapException.java create mode 100644 JavaKit/src/main/java/org/swift/javakit/dependencies/SystemClassLoaderUnsafe.java delete mode 100644 Plugins/PluginsShared/Configuration.swift create mode 120000 Plugins/PluginsShared/JavaKitConfigurationShared create mode 100644 Samples/JavaDependencySampleApp/Package.swift create mode 100644 Samples/JavaDependencySampleApp/Sources/JavaCommonsCSV/dummy.swift create mode 100644 Samples/JavaDependencySampleApp/Sources/JavaCommonsCSV/swift-java.config create mode 100644 Samples/JavaDependencySampleApp/Sources/JavaDependencySample/main.swift create mode 100644 Samples/JavaDependencySampleApp/Sources/JavaDependencySample/swift-java.config create mode 100755 Samples/JavaDependencySampleApp/ci-validate.sh create mode 100644 Sources/Java2Swift/JavaToSwift+EmitConfiguration.swift create mode 100644 Sources/Java2Swift/JavaToSwift+FetchDependencies.swift create mode 100644 Sources/Java2Swift/JavaToSwift+GenerateWrappers.swift create mode 100644 Sources/Java2Swift/String+Extensions.swift delete mode 100644 Sources/Java2SwiftLib/Configuration.swift create mode 100644 Sources/JavaKitConfigurationShared/Configuration.swift create mode 100644 Sources/JavaKitDependencyResolver/DependencyResolver.swift create mode 100644 Sources/JavaKitDependencyResolver/swift-java.config rename Sources/{JExtractSwift => JavaKitShared}/TerminalColors.swift (100%) diff --git a/.github/scripts/validate_sample.sh b/.github/scripts/validate_sample.sh new file mode 100755 index 00000000..7e0ab3d2 --- /dev/null +++ b/.github/scripts/validate_sample.sh @@ -0,0 +1,32 @@ +#!/bin/bash + +# shellcheck disable=SC2034 +declare -r GREEN='\033[0;32m' +declare -r BOLD='\033[1m' +declare -r RESET='\033[0m' + +declare -r sampleDir="$1" +declare -r CI_VALIDATE_SCRIPT='ci-validate.sh' + +echo "" +echo "" +echo "========================================================================" +printf "Validate sample '${BOLD}%s${RESET}' using: " "$sampleDir" +cd "$sampleDir" || exit +if [[ $(find . -name ${CI_VALIDATE_SCRIPT} -maxdepth 1) ]]; then + echo -e "Custom ${BOLD}${CI_VALIDATE_SCRIPT}${RESET} script..." + ./${CI_VALIDATE_SCRIPT} || exit +elif [[ $(find . -name 'build.gradle*' -maxdepth 1) ]]; then + echo -e "${BOLD}Gradle${RESET} build..." + ./gradlew build || ./gradlew build --info # re-run to get better failure output +else + echo -e "${BOLD}SwiftPM${RESET} build..." + swift build || exit +fi + +echo -e "Validated sample '${BOLD}${sampleDir}${RESET}': ${BOLD}passed${RESET}." +cd - || exit + +echo +printf "Done validating sample: %s" "${sampleDir}" +echo -e "${GREEN}done${RESET}." diff --git a/.github/scripts/validate_samples.sh b/.github/scripts/validate_samples.sh deleted file mode 100755 index 26273575..00000000 --- a/.github/scripts/validate_samples.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/bash - -# shellcheck disable=SC2034 -declare -r GREEN='\033[0;32m' -declare -r BOLD='\033[1m' -declare -r RESET='\033[0m' - -# shellcheck disable=SC2155 -declare -r SAMPLE_PACKAGES=$(find Samples -name Package.swift -maxdepth 2) -declare -r CI_VALIDATE_SCRIPT='ci-validate.sh' - -for samplePackage in ${SAMPLE_PACKAGES} ; do - sampleDir=$(dirname "$samplePackage") - - echo "" - echo "" - echo "========================================================================" - printf "Validate sample '${BOLD}%s${RESET}' using: " "$sampleDir" - cd "$sampleDir" || exit - if [[ $(find . -name ${CI_VALIDATE_SCRIPT} -maxdepth 1) ]]; then - echo -e "Custom ${BOLD}${CI_VALIDATE_SCRIPT}${RESET} script..." - ./${CI_VALIDATE_SCRIPT} || exit - elif [[ $(find . -name 'build.gradle*' -maxdepth 1) ]]; then - echo -e "${BOLD}Gradle${RESET} build..." - ./gradlew build || ./gradlew build --info # re-run to get better failure output - else - echo -e "${BOLD}SwiftPM${RESET} build..." - swift build || exit - fi - - echo -e "Validated sample '${BOLD}${sampleDir}${RESET}': ${BOLD}passed${RESET}." - cd - || exit -done - -echo -printf "Done validating samples: " -echo -e "${GREEN}done${RESET}." diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 06db1ff2..d289296d 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -82,8 +82,18 @@ jobs: - uses: actions/checkout@v4 - name: Prepare CI Environment uses: ./.github/actions/prepare_env - - name: Verify Samples (All) - run: .github/scripts/validate_samples.sh + - name: "Verify Sample: JavaDependencySampleApp" + run: .github/scripts/validate_sample.sh Samples/JavaDependencySampleApp + - name: "Verify Sample: JavaKitSampleApp" + run: .github/scripts/validate_sample.sh Samples/JavaKitSampleApp + - name: "Verify Sample: JavaProbablyPrime" + run: .github/scripts/validate_sample.sh Samples/JavaProbablyPrime + - name: "Verify Sample: JavaSieve" + run: .github/scripts/validate_sample.sh Samples/JavaSieve + - name: "Verify Sample: SwiftAndJavaJarSampleLib" + run: .github/scripts/validate_sample.sh Samples/SwiftAndJavaJarSampleLib + - name: "Verify Sample: SwiftKitSampleApp" + run: .github/scripts/validate_sample.sh Samples/SwiftKitSampleApp # TODO: Benchmark compile crashes in CI, enable when nightly toolchains in better shape. # - name: Build (Swift) Benchmarks # run: "swift package --package-path Benchmarks/ benchmark list" diff --git a/.licenseignore b/.licenseignore index ce382547..5f93c9a6 100644 --- a/.licenseignore +++ b/.licenseignore @@ -42,4 +42,5 @@ gradlew.bat **/ci-validate.sh **/DO_NOT_EDIT.txt Plugins/**/_PluginsShared -Plugins/**/0_PLEASE_SYMLINK* \ No newline at end of file +Plugins/**/0_PLEASE_SYMLINK* +Plugins/PluginsShared/JavaKitConfigurationShared \ No newline at end of file diff --git a/JavaKit/build.gradle b/JavaKit/build.gradle new file mode 100644 index 00000000..8eed1c6e --- /dev/null +++ b/JavaKit/build.gradle @@ -0,0 +1,77 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +plugins { + id("build-logic.java-library-conventions") +} + +group = "org.swift.javakit" +version = "1.0-SNAPSHOT" + +repositories { + mavenCentral() +} + +java { + toolchain { + languageVersion.set(JavaLanguageVersion.of(22)) + } +} + +dependencies { + implementation("dev.gradleplugins:gradle-api:8.10.1") + + testImplementation(platform("org.junit:junit-bom:5.10.0")) + testImplementation("org.junit.jupiter:junit-jupiter") +} + +tasks.test { + useJUnitPlatform() + testLogging { + events("passed", "skipped", "failed") + } +} + +// Copy the gradle wrapper we're using into the resulting jar's resources. +// We'll use it to bootstrap dependencies (and gradle!) if there is none yet. +tasks.processResources { + from('gradlew') { + into 'gradle/' + } + from('gradlew.bat') { + into 'gradle/' + } + from('../gradle/wrapper/gradle-wrapper.jar') { + into 'gradle/wrapper/' + } + from('../gradle/wrapper/gradle-wrapper.properties') { + into 'gradle/wrapper/' + } +} + +//task fatJar(type: Jar) { +// archiveBaseName = 'java-kit-fat-jar' +// duplicatesStrategy = DuplicatesStrategy.EXCLUDE +// from { configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } } +// with jar +//} + +// Task necessary to bootstrap +task printRuntimeClasspath { + def runtimeClasspath = sourceSets.main.runtimeClasspath + inputs.files(runtimeClasspath) + doLast { + println("CLASSPATH:${runtimeClasspath.asPath}") + } +} diff --git a/JavaKit/gradlew b/JavaKit/gradlew new file mode 120000 index 00000000..502f5a2d --- /dev/null +++ b/JavaKit/gradlew @@ -0,0 +1 @@ +../gradlew \ No newline at end of file diff --git a/JavaKit/gradlew.bat b/JavaKit/gradlew.bat new file mode 120000 index 00000000..28401328 --- /dev/null +++ b/JavaKit/gradlew.bat @@ -0,0 +1 @@ +../gradlew.bat \ No newline at end of file diff --git a/JavaKit/src/main/java/org/swift/javakit/annotations/UsedFromSwift.java b/JavaKit/src/main/java/org/swift/javakit/annotations/UsedFromSwift.java new file mode 100644 index 00000000..ad9e7918 --- /dev/null +++ b/JavaKit/src/main/java/org/swift/javakit/annotations/UsedFromSwift.java @@ -0,0 +1,28 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package org.swift.javakit.annotations; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * Since some public methods may not appear as used in Java source code, but are used by Swift, + * we can use this source annotation to mark such entry points to not accidentally remove them with + * "safe delete" refactorings in Java IDEs which would be unaware of the usages from Swift. + */ +@SuppressWarnings("unused") // used from Swift +@Retention(RetentionPolicy.SOURCE) +public @interface UsedFromSwift { +} diff --git a/JavaKit/src/main/java/org/swift/javakit/dependencies/DependencyResolver.java b/JavaKit/src/main/java/org/swift/javakit/dependencies/DependencyResolver.java new file mode 100644 index 00000000..ff4085c9 --- /dev/null +++ b/JavaKit/src/main/java/org/swift/javakit/dependencies/DependencyResolver.java @@ -0,0 +1,303 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package org.swift.javakit.dependencies; + +import org.gradle.tooling.GradleConnector; +import org.swift.javakit.annotations.UsedFromSwift; + +import java.io.*; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardOpenOption; +import java.util.Arrays; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * Fetches dependencies using the Gradle resolver and returns the resulting classpath which includes + * the fetched dependency and all of its dependencies. + */ +@UsedFromSwift +@SuppressWarnings("unused") +public class DependencyResolver { + + private static final String COMMAND_OUTPUT_LINE_PREFIX_CLASSPATH = "CLASSPATH:"; + private static final String CLASSPATH_CACHE_FILENAME = "JavaKitDependencyResolver.swift-java.classpath"; + + public static String GRADLE_API_DEPENDENCY = "dev.gradleplugins:gradle-api:8.10.1"; + public static String[] BASE_DEPENDENCIES = { + GRADLE_API_DEPENDENCY + }; + + /** + * May throw runtime exceptions including {@link org.gradle.api.internal.artifacts.ivyservice.TypedResolveException} + * if unable to resolve a dependency. + */ + @UsedFromSwift + @SuppressWarnings("unused") + public static String resolveDependenciesToClasspath(String projectBaseDirectoryString, String[] dependencies) throws IOException { + try { + simpleLog("Fetch dependencies: " + Arrays.toString(dependencies)); + simpleLog("Classpath: " + System.getProperty("java.class.path")); + var projectBasePath = new File(projectBaseDirectoryString).toPath(); + + File projectDir = Files.createTempDirectory("java-swift-dependencies").toFile(); + projectDir.mkdirs(); + + if (hasDependencyResolverDependenciesLoaded()) { + // === Resolve dependencies using Gradle API in-process + simpleLog("Gradle API runtime dependency is available, resolve dependencies..."); + return resolveDependenciesUsingAPI(projectDir, dependencies); + } + + // === Bootstrap the resolver dependencies and cache them + simpleLog("Gradle API not available on classpath, bootstrap %s dependencies: %s" + .formatted(DependencyResolver.class.getSimpleName(), Arrays.toString(BASE_DEPENDENCIES))); + String dependencyResolverDependenciesClasspath = bootstrapDependencyResolverClasspath(); + writeDependencyResolverClasspath(projectBasePath, dependencyResolverDependenciesClasspath); + + // --- Resolve dependencies using sub-process process + // TODO: it would be nice to just add the above classpath to the system classloader and here call the API + // immediately, but that's challenging and not a stable API we can rely on (hacks exist to add paths + // to system classloader but are not reliable). + printBuildFiles(projectDir, dependencies); + return resolveDependenciesWithSubprocess(projectDir); + } catch (Exception e) { + e.printStackTrace(); + throw e; + } + } + + + /** + * Use an external {@code gradle} invocation in order to download dependencies such that we can use `gradle-api` + * next time we want to resolve dependencies. This uses an external process and is slightly worse than using the API + * directly. + * + * @return classpath obtained for the dependencies + * @throws IOException if file IO failed during mock project creation + * @throws SwiftJavaBootstrapException if the resolve failed for some other reason + */ + private static String bootstrapDependencyResolverClasspath() throws IOException, SwiftJavaBootstrapException { + var dependencies = BASE_DEPENDENCIES; + simpleLog("Bootstrap gradle-api for DependencyResolver: " + Arrays.toString(dependencies)); + + File bootstrapDir = Files.createTempDirectory("swift-java-dependency-resolver").toFile(); + bootstrapDir.mkdirs(); + simpleLog("Bootstrap dependencies using project at: %s".formatted(bootstrapDir)); + + printBuildFiles(bootstrapDir, dependencies); + + var bootstrapClasspath = resolveDependenciesWithSubprocess(bootstrapDir); + simpleLog("Prepared dependency resolver bootstrap classpath: " + bootstrapClasspath.split(":").length + " entries"); + + return bootstrapClasspath; + + } + + private static String resolveDependenciesWithSubprocess(File gradleProjectDir) throws IOException { + if (!gradleProjectDir.isDirectory()) { + throw new IllegalArgumentException("Gradle project directory is not a directory: " + gradleProjectDir); + } + + File stdoutFile = File.createTempFile("swift-java-bootstrap", ".stdout", gradleProjectDir); + stdoutFile.deleteOnExit(); + File stderrFile = File.createTempFile("swift-java-bootstrap", ".stderr", gradleProjectDir); + stderrFile.deleteOnExit(); + + try { + ProcessBuilder gradleBuilder = new ProcessBuilder("./gradlew", ":printRuntimeClasspath"); + gradleBuilder.directory(gradleProjectDir); + gradleBuilder.redirectOutput(stdoutFile); + gradleBuilder.redirectError(stderrFile); + Process gradleProcess = gradleBuilder.start(); + gradleProcess.waitFor(10, TimeUnit.MINUTES); // TODO: must be configurable + + if (gradleProcess.exitValue() != 0) { + throw new SwiftJavaBootstrapException("Failed to resolve bootstrap dependencies, exit code: " + gradleProcess.exitValue()); + } + + Stream lines = Files.readAllLines(stdoutFile.toPath()).stream(); + var bootstrapClasspath = getClasspathFromGradleCommandOutput(lines); + return bootstrapClasspath; + } catch (Exception ex) { + simpleLog("stdoutFile = " + stdoutFile); + simpleLog("stderrFile = " + stderrFile); + + ex.printStackTrace(); + throw new SwiftJavaBootstrapException("Failed to bootstrap dependencies necessary for " + + DependencyResolver.class.getCanonicalName() + "! " + + "Make sure to invoke SwiftPM with --disable-sandbox because " + + "swift-java needs network access to fetch java dependencies.", ex); + } + } + + private static void writeDependencyResolverClasspath(Path projectBasePath, String dependencyResolverDependenciesClasspath) throws IOException { + File swiftBuildDirectory = new File(String.valueOf(projectBasePath), ".build"); + swiftBuildDirectory.mkdirs(); + + File dependencyResolverClasspathCacheFile = new File(swiftBuildDirectory, CLASSPATH_CACHE_FILENAME); + dependencyResolverClasspathCacheFile.createNewFile(); + simpleLog("Cache %s dependencies classpath at: '%s'. Subsequent dependency resolutions will use gradle-api." + .formatted(DependencyResolver.class.getSimpleName(), dependencyResolverClasspathCacheFile.toPath())); + + Files.writeString( + dependencyResolverClasspathCacheFile.toPath(), + dependencyResolverDependenciesClasspath, + StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING); + } + + /** + * Detect if we have the necessary dependencies loaded. + */ + @UsedFromSwift + public static boolean hasDependencyResolverDependenciesLoaded() { + return hasDependencyResolverDependenciesLoaded(DependencyResolver.class.getClassLoader()); + } + + /** + * Resolve dependencies in the passed project directory and return the resulting classpath. + * + * @return classpath which was resolved for the dependencies + */ + private static String resolveDependenciesUsingAPI(File projectDir, String[] dependencies) throws IOException { + printBuildFiles(projectDir, dependencies); + + var connection = GradleConnector.newConnector() + .forProjectDirectory(projectDir) + .connect(); + + try (connection) { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + PrintStream printStream = new PrintStream(outputStream); + + connection.newBuild().forTasks(":printRuntimeClasspath") + .setStandardError(new NoopOutputStream()) + .setStandardOutput(printStream) + .run(); + + var all = outputStream.toString(); + var classpathString = Arrays.stream(all.split("\n")) + .filter(s -> s.startsWith(COMMAND_OUTPUT_LINE_PREFIX_CLASSPATH)) + .map(s -> s.substring(COMMAND_OUTPUT_LINE_PREFIX_CLASSPATH.length())) + .findFirst().orElseThrow(() -> new RuntimeException("Could not find classpath output from ':printRuntimeClasspath' task.")); + + // remove output directories of the project we used for the dependency resolution + var classpath = Arrays.stream(classpathString + .split(":")) + .filter(s -> !s.startsWith(projectDir.getAbsolutePath())) + .collect(Collectors.joining(":")); + + + return classpath; + } + } + + private static String getClasspathFromGradleCommandOutput(Stream lines) { + return lines.filter(s -> s.startsWith(COMMAND_OUTPUT_LINE_PREFIX_CLASSPATH)) + .map(s -> s.substring(COMMAND_OUTPUT_LINE_PREFIX_CLASSPATH.length())) + .findFirst().orElseThrow(() -> new RuntimeException("Could not find classpath output from gradle command output task.")); + } + + + private static boolean hasDependencyResolverDependenciesLoaded(ClassLoader classLoader) { + try { + classLoader.loadClass("org.gradle.tooling.GradleConnector"); + return true; + } catch (ClassNotFoundException e) { + return false; + } + } + + private static void printBuildFiles(File projectDir, String[] dependencies) throws IOException { + // === build.gradle + File buildFile = new File(projectDir, "build.gradle"); + try (PrintWriter writer = new PrintWriter(buildFile)) { + writer.println("plugins { id 'java-library' }"); + writer.println("repositories { mavenCentral() }"); + + writer.println("dependencies {"); + for (String dependency : dependencies) { + writer.println("implementation(\"" + dependency + "\")"); + } + writer.println("}"); + + writer.println(""" + task printRuntimeClasspath { + def runtimeClasspath = sourceSets.main.runtimeClasspath + inputs.files(runtimeClasspath) + doLast { + println("CLASSPATH:${runtimeClasspath.asPath}") + } + } + """); + } + + // === settings.gradle + File settingsFile = new File(projectDir, "settings.gradle.kts"); + try (PrintWriter writer = new PrintWriter(settingsFile)) { + writer.println(""" + rootProject.name = "swift-java-resolve-temp-project" + """); + } + + // === gradle wrapper files, so we can even download gradle when necessary to bootstrap + File gradlew = new File(projectDir, "gradlew"); + writeResourceToFile("/gradle/gradlew", gradlew); + gradlew.setExecutable(true); + + File gradlewBat = new File(projectDir, "gradlew.bat"); + writeResourceToFile("/gradle/gradlew.bat", gradlewBat); + gradlew.setExecutable(true); + + File gradleDir = new File(projectDir, "gradle"); + File gradleWrapperDir = new File(gradleDir, "wrapper"); + gradleWrapperDir.mkdirs(); + + File gradleWrapperJar = new File(gradleWrapperDir, "gradle-wrapper.jar"); + writeResourceToFile("/gradle/wrapper/gradle-wrapper.jar", gradleWrapperJar); + File gradleWrapperProps = new File(gradleWrapperDir, "gradle-wrapper.properties"); + writeResourceToFile("/gradle/wrapper/gradle-wrapper.properties", gradleWrapperProps); + } + + private static void writeResourceToFile(String resource, File target) throws IOException { + try (PrintWriter writer = new PrintWriter(target)) { + try (InputStream inputStream = DependencyResolver.class.getResourceAsStream(resource)) { + if (inputStream == null) { + throw new FileNotFoundException("Not found: gradlew wrapper in resources!"); + } + try (var os = new BufferedOutputStream(new FileOutputStream(target))) { + byte[] buffer = new byte[8192]; // Buffer size of 8 KB + int bytesRead; + while ((bytesRead = inputStream.read(buffer)) != -1) { + os.write(buffer, 0, bytesRead); + } + } + } + } + } + + private static void simpleLog(String message) { + System.err.println("[info][swift-java/" + DependencyResolver.class.getSimpleName() + "] " + message); + } + + private static class NoopOutputStream extends OutputStream { + @Override + public void write(int b) throws IOException { + // ignore + } + } +} diff --git a/JavaKit/src/main/java/org/swift/javakit/dependencies/SwiftJavaBootstrapException.java b/JavaKit/src/main/java/org/swift/javakit/dependencies/SwiftJavaBootstrapException.java new file mode 100644 index 00000000..3c8d475a --- /dev/null +++ b/JavaKit/src/main/java/org/swift/javakit/dependencies/SwiftJavaBootstrapException.java @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package org.swift.javakit.dependencies; + +public class SwiftJavaBootstrapException extends RuntimeException { + public SwiftJavaBootstrapException(String message) { + super(message); + } + + public SwiftJavaBootstrapException(String message, Exception ex) { + super(message, ex); + } +} diff --git a/JavaKit/src/main/java/org/swift/javakit/dependencies/SystemClassLoaderUnsafe.java b/JavaKit/src/main/java/org/swift/javakit/dependencies/SystemClassLoaderUnsafe.java new file mode 100644 index 00000000..d8d4f64a --- /dev/null +++ b/JavaKit/src/main/java/org/swift/javakit/dependencies/SystemClassLoaderUnsafe.java @@ -0,0 +1,46 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package org.swift.javakit.dependencies; + +import java.io.File; +import java.net.URL; +import java.net.URLClassLoader; + +public final class SystemClassLoaderUnsafe { + + private SystemClassLoaderUnsafe() {} + + /** + * Use internal methods to add a path to the system classloader. + * If this ever starts throwing in new JDK versions, we may need to abandon this technique. + * + * @param path path to add to the current system classloader. + */ + public static void addPath(String path) { + try { + var url = new File(path).toURI().toURL(); + var urlClassLoader = (URLClassLoader) ClassLoader.getSystemClassLoader(); + var method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class); + method.setAccessible(true); + method.invoke(urlClassLoader, url); + } catch (Throwable ex) { + throw new RuntimeException("Unable to add path to system class loader! " + + "This is not supported API and may indeed start failing in the future. " + + "If/when this happens, we have to change the bootstrap logic to instead " + + "create a new JVM with the new bootstrap classpath, " + + "rather than add paths to the existing one.", ex); + } + } +} diff --git a/Package.swift b/Package.swift index 119aca6e..f6645115 100644 --- a/Package.swift +++ b/Package.swift @@ -40,7 +40,7 @@ let javaIncludePath = "\(javaHome)/include" #endif let package = Package( - name: "JavaKit", + name: "SwiftJava", platforms: [ .macOS(.v10_15) ], @@ -171,9 +171,29 @@ let package = Package( .swiftLanguageMode(.v5) ] ), + + .target( + name: "JavaKitDependencyResolver", + dependencies: [ + "JavaKit", + ], + exclude: [ + "swift-java.config", + ], + swiftSettings: [ + .swiftLanguageMode(.v5), + .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]), + ] + ), + .target( name: "JavaKit", - dependencies: ["JavaRuntime", "JavaKitMacros", "JavaTypes"], + dependencies: [ + "JavaRuntime", + "JavaKitMacros", + "JavaTypes", + "JavaKitConfigurationShared", // for Configuration reading at runtime + ], exclude: ["swift-java.config"], swiftSettings: [ .swiftLanguageMode(.v5), @@ -183,10 +203,8 @@ let package = Package( .unsafeFlags( [ "-L\(javaHome)/lib/server", - "-Xlinker", - "-rpath", - "-Xlinker", - "\(javaHome)/lib/server", + "-Xlinker", "-rpath", + "-Xlinker", "\(javaHome)/lib/server", ], .when(platforms: [.linux, .macOS]) ), @@ -282,6 +300,14 @@ let package = Package( ] ), + .target( + name: "JavaKitConfigurationShared" + ), + + .target( + name: "JavaKitShared" + ), + .target( name: "Java2SwiftLib", dependencies: [ @@ -293,6 +319,9 @@ let package = Package( "JavaKitReflection", "JavaKitNetwork", "JavaTypes", + "JavaKitShared", + "JavaKitConfigurationShared", + "JavaKitDependencyResolver", ], swiftSettings: [ .swiftLanguageMode(.v5), @@ -312,6 +341,8 @@ let package = Package( "JavaKitJar", "JavaKitNetwork", "Java2SwiftLib", + "JavaKitDependencyResolver", + "JavaKitShared", ], swiftSettings: [ @@ -329,6 +360,7 @@ let package = Package( .product(name: "SwiftSyntaxBuilder", package: "swift-syntax"), .product(name: "ArgumentParser", package: "swift-argument-parser"), "JavaTypes", + "JavaKitShared", ], swiftSettings: [ .swiftLanguageMode(.v5), diff --git a/Plugins/Java2SwiftPlugin/Java2SwiftPlugin.swift b/Plugins/Java2SwiftPlugin/Java2SwiftPlugin.swift index 8c7045e0..d932ee97 100644 --- a/Plugins/Java2SwiftPlugin/Java2SwiftPlugin.swift +++ b/Plugins/Java2SwiftPlugin/Java2SwiftPlugin.swift @@ -20,12 +20,16 @@ fileprivate let SwiftJavaConfigFileName = "swift-java.config" @main struct Java2SwiftBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin { - var pluginName: String = "swift-java-javac" + var pluginName: String = "swift-java" var verbose: Bool = getEnvironmentBool("SWIFT_JAVA_VERBOSE") func createBuildCommands(context: PluginContext, target: Target) throws -> [Command] { + log("Create build commands for target '\(target.name)'") guard let sourceModule = target.sourceModule else { return [] } + let executable = try context.tool(named: "Java2Swift").url + var commands: [Command] = [] + // Note: Target doesn't have a directoryURL counterpart to directory, // so we cannot eliminate this deprecation warning. let sourceDir = target.directory.string @@ -34,13 +38,17 @@ struct Java2SwiftBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin { // which we are generating Swift wrappers for Java classes. let configFile = URL(filePath: sourceDir) .appending(path: SwiftJavaConfigFileName) - let configData = try Data(contentsOf: configFile) - let config = try JSONDecoder().decode(Configuration.self, from: configData) + let config = try readConfiguration(sourceDir: sourceDir) + + log("Config on path: \(configFile.path(percentEncoded: false))") + log("Config was: \(config)") + var javaDependencies = config.dependencies ?? [] /// Find the manifest files from other Java2Swift executions in any targets /// this target depends on. var dependentConfigFiles: [(String, URL)] = [] func searchForConfigFiles(in target: any Target) { + // log("Search for config files in target: \(target.name)") let dependencyURL = URL(filePath: target.directory.string) // Look for a config file within this target. @@ -58,10 +66,13 @@ struct Java2SwiftBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin { for dependency in target.dependencies { switch dependency { case .target(let target): + // log("Dependency target: \(target.name)") searchForConfigFiles(in: target) case .product(let product): + // log("Dependency product: \(product.name)") for target in product.targets { + // log("Dependency product: \(product.name), target: \(target.name)") searchForConfigFiles(in: target) } @@ -72,16 +83,14 @@ struct Java2SwiftBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin { // Process indirect target dependencies. for dependency in target.recursiveTargetDependencies { + // log("Recursive dependency target: \(dependency.name)") searchForConfigFiles(in: dependency) } - let outputDirectory = context.pluginWorkDirectoryURL - .appending(path: "generated") - - var arguments: [String] = [ - "--module-name", sourceModule.name, - "--output-directory", outputDirectory.path(percentEncoded: false), - ] + var arguments: [String] = [] + arguments += argumentsModuleName(sourceModule: sourceModule) + arguments += argumentsOutputDirectory(context: context) + arguments += dependentConfigFiles.flatMap { moduleAndConfigFile in let (moduleName, configFile) = moduleAndConfigFile return [ @@ -91,17 +100,25 @@ struct Java2SwiftBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin { } arguments.append(configFile.path(percentEncoded: false)) - guard let classes = config.classes else { - log("Config at \(configFile) did not have 'classes' configured, skipping java2swift step.") - return [] - } - - /// Determine the set of Swift files that will be emitted by the Java2Swift - /// tool. +// guard let classes = config.classes else { +// log("Config at \(configFile) did not have 'classes' configured, skipping java2swift step.") +// return [] +// } + let classes = config.classes ?? [:] + print("Classes to wrap: \(classes.map(\.key))") + + /// Determine the set of Swift files that will be emitted by the Java2Swift tool. + // TODO: this is not precise and won't work with more advanced Java files, e.g. lambdas etc. + let outputDirectoryGenerated = self.outputDirectory(context: context, generated: true) let outputSwiftFiles = classes.map { (javaClassName, swiftName) in let swiftNestedName = swiftName.replacingOccurrences(of: ".", with: "+") - return outputDirectory.appending(path: "\(swiftNestedName).swift") + return outputDirectoryGenerated.appending(path: "\(swiftNestedName).swift") } + + arguments += [ + "--cache-directory", + context.pluginWorkDirectoryURL.path(percentEncoded: false) + ] // Find the Java .class files generated from prior plugins. let compiledClassFiles = sourceModule.pluginGeneratedResources.filter { url in @@ -115,7 +132,7 @@ struct Java2SwiftBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin { while classpath.lastPathComponent != "Java" { classpath.deleteLastPathComponent() } - arguments += [ "--classpath", classpath.path() ] + arguments += ["--classpath", classpath.path()] // For each of the class files, note that it can have Swift-native // implementations. We figure this out based on the path. @@ -131,23 +148,81 @@ struct Java2SwiftBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin { let className = classNameComponents .reversed() .joined(separator: ".") - arguments += [ "--swift-native-implementation", className] + arguments += ["--swift-native-implementation", className] } } - guard let classes = config.classes else { - log("Skipping java2swift step: Missing 'classes' key in swift-java.config at '\(configFile.path)'") - return [] + var fetchDependenciesOutputFiles: [URL] = [] + if let dependencies = config.dependencies, !dependencies.isEmpty { + let displayName = "Fetch (Java) dependencies for Swift target \(sourceModule.name)" + log("Prepared: \(displayName)") + + fetchDependenciesOutputFiles += [ + outputFilePath(context: context, generated: false, filename: "\(sourceModule.name).swift-java.classpath") + ] + + commands += [ + .buildCommand( + displayName: displayName, + executable: executable, + arguments: [ + "--fetch", configFile.path(percentEncoded: false), + "--module-name", sourceModule.name, + "--output-directory", outputDirectory(context: context, generated: false).path(percentEncoded: false) + ], + environment: [:], + inputFiles: [configFile], + outputFiles: fetchDependenciesOutputFiles + ) + ] + } else { + log("No dependencies to fetch for target \(sourceModule.name)") } + + if !outputSwiftFiles.isEmpty { + commands += [ + .buildCommand( + displayName: "Wrapping \(classes.count) Java classes in Swift target '\(sourceModule.name)'", + executable: executable, + arguments: arguments, + inputFiles: compiledClassFiles + fetchDependenciesOutputFiles + [ + configFile + ], + outputFiles: outputSwiftFiles + ) + ] + } else { + log("No Swift output files, skip wrapping") + } + + return commands + } +} +extension Java2SwiftBuildToolPlugin { + func argumentsModuleName(sourceModule: Target) -> [String] { return [ - .buildCommand( - displayName: "Wrapping \(classes.count) Java classes target \(sourceModule.name) in Swift", - executable: try context.tool(named: "Java2Swift").url, - arguments: arguments, - inputFiles: [ configFile ] + compiledClassFiles, - outputFiles: outputSwiftFiles - ) + "--module-name", sourceModule.name ] } + + func argumentsOutputDirectory(context: PluginContext, generated: Bool = true) -> [String] { + return [ + "--output-directory", + outputDirectory(context: context, generated: generated).path(percentEncoded: false) + ] + } + + func outputDirectory(context: PluginContext, generated: Bool = true) -> URL { + let dir = context.pluginWorkDirectoryURL + if generated { + return dir.appending(path: "generated") + } else { + return dir + } + } + + func outputFilePath(context: PluginContext, generated: Bool, filename: String) -> URL { + outputDirectory(context: context, generated: generated).appending(path: filename) + } } diff --git a/Plugins/PluginsShared/Configuration.swift b/Plugins/PluginsShared/Configuration.swift deleted file mode 100644 index 769eef70..00000000 --- a/Plugins/PluginsShared/Configuration.swift +++ /dev/null @@ -1,81 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of Swift.org project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -import Foundation - -typealias JavaVersion = Int - -/// Configuration for the SwiftJava plugins, provided on a per-target basis. -struct Configuration: Codable { - // ==== swift 2 java --------------------------------------------------------- - - var javaPackage: String? - - // ==== java 2 swift --------------------------------------------------------- - - /// The Java class path that should be passed along to the Java2Swift tool. - var classPath: String? = nil - - /// The Java classes that should be translated to Swift. The keys are - /// canonical Java class names (e.g., java.util.Vector) and the values are - /// the corresponding Swift names (e.g., JavaVector). - var classes: [String: String]? = [:] - - // Compile for the specified Java SE release. - var sourceCompatibility: JavaVersion? - - // Generate class files suitable for the specified Java SE release. - var targetCompatibility: JavaVersion? -} - -func readConfiguration(sourceDir: String, file: String = #fileID, line: UInt = #line) throws -> Configuration { - let configFile = URL(filePath: sourceDir).appending(path: "swift-java.config") - do { - let configData = try Data(contentsOf: configFile) - return try JSONDecoder().decode(Configuration.self, from: configData) - } catch { - throw ConfigurationError(message: "Failed to parse SwiftJava configuration at '\(configFile)!'", error: error, - file: file, line: line) - } -} - -extension Configuration { - var compilerVersionArgs: [String] { - var compilerVersionArgs = [String]() - - if let sourceCompatibility { - compilerVersionArgs += ["--source", String(sourceCompatibility)] - } - if let targetCompatibility { - compilerVersionArgs += ["--target", String(targetCompatibility)] - } - - return compilerVersionArgs - } -} - -struct ConfigurationError: Error { - let message: String - let error: any Error - - let file: String - let line: UInt - - init(message: String, error: any Error, file: String = #fileID, line: UInt = #line) { - self.message = message - self.error = error - self.file = file - self.line = line - } -} diff --git a/Plugins/PluginsShared/JavaKitConfigurationShared b/Plugins/PluginsShared/JavaKitConfigurationShared new file mode 120000 index 00000000..d5c765df --- /dev/null +++ b/Plugins/PluginsShared/JavaKitConfigurationShared @@ -0,0 +1 @@ +../../Sources/JavaKitConfigurationShared \ No newline at end of file diff --git a/Plugins/PluginsShared/PluginUtils.swift b/Plugins/PluginsShared/PluginUtils.swift index bf4d0f0a..6932253a 100644 --- a/Plugins/PluginsShared/PluginUtils.swift +++ b/Plugins/PluginsShared/PluginUtils.swift @@ -71,4 +71,9 @@ extension PluginContext { self.pluginWorkDirectoryURL .appending(path: "Sources") } + + func cachedClasspathFile(moduleName: String) -> URL { + self.pluginWorkDirectoryURL + .appending(path: "\(moduleName)", directoryHint: .notDirectory) + } } diff --git a/Samples/JavaDependencySampleApp/Package.swift b/Samples/JavaDependencySampleApp/Package.swift new file mode 100644 index 00000000..3d210e36 --- /dev/null +++ b/Samples/JavaDependencySampleApp/Package.swift @@ -0,0 +1,101 @@ +// swift-tools-version: 6.0 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import CompilerPluginSupport +import PackageDescription + +import class Foundation.FileManager +import class Foundation.ProcessInfo + +// Note: the JAVA_HOME environment variable must be set to point to where +// Java is installed, e.g., +// Library/Java/JavaVirtualMachines/openjdk-21.jdk/Contents/Home. +func findJavaHome() -> String { + if let home = ProcessInfo.processInfo.environment["JAVA_HOME"] { + return home + } + + // This is a workaround for envs (some IDEs) which have trouble with + // picking up env variables during the build process + let path = "\(FileManager.default.homeDirectoryForCurrentUser.path()).java_home" + if let home = try? String(contentsOfFile: path, encoding: .utf8) { + if let lastChar = home.last, lastChar.isNewline { + return String(home.dropLast()) + } + + return home + } + + fatalError("Please set the JAVA_HOME environment variable to point to where Java is installed.") +} +let javaHome = findJavaHome() + +let javaIncludePath = "\(javaHome)/include" +#if os(Linux) + let javaPlatformIncludePath = "\(javaIncludePath)/linux" +#elseif os(macOS) + let javaPlatformIncludePath = "\(javaIncludePath)/darwin" +#else + // TODO: Handle windows as well + #error("Currently only macOS and Linux platforms are supported, this may change in the future.") +#endif + +let package = Package( + name: "JavaDependencySampleApp", + platforms: [ + .macOS(.v13), + .iOS(.v13), + .tvOS(.v13), + .watchOS(.v6), + .macCatalyst(.v13), + ], + + products: [ + .executable( + name: "JavaDependencySample", + targets: ["JavaDependencySample"] + ), + ], + + dependencies: [ + .package(name: "swift-java", path: "../../") + ], + + targets: [ + .executableTarget( + name: "JavaDependencySample", + dependencies: [ + .product(name: "JavaKit", package: "swift-java"), + .product(name: "JavaRuntime", package: "swift-java"), + .product(name: "JavaKitFunction", package: "swift-java"), + "JavaCommonsCSV" + ], + exclude: ["swift-java.config"], + swiftSettings: [ + .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]), + .swiftLanguageMode(.v5), + ], + plugins: [ + .plugin(name: "Java2SwiftPlugin", package: "swift-java"), + ] + ), + + .target( + name: "JavaCommonsCSV", + dependencies: [ + .product(name: "JavaKit", package: "swift-java"), + .product(name: "JavaKitFunction", package: "swift-java"), + .product(name: "JavaKitCollection", package: "swift-java"), + ], + exclude: ["swift-java.config"], + swiftSettings: [ + .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]), + .swiftLanguageMode(.v5), + ], + plugins: [ + .plugin(name: "Java2SwiftPlugin", package: "swift-java"), + ] + ), + + ] +) diff --git a/Samples/JavaDependencySampleApp/Sources/JavaCommonsCSV/dummy.swift b/Samples/JavaDependencySampleApp/Sources/JavaCommonsCSV/dummy.swift new file mode 100644 index 00000000..76f848f9 --- /dev/null +++ b/Samples/JavaDependencySampleApp/Sources/JavaCommonsCSV/dummy.swift @@ -0,0 +1,13 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// diff --git a/Samples/JavaDependencySampleApp/Sources/JavaCommonsCSV/swift-java.config b/Samples/JavaDependencySampleApp/Sources/JavaCommonsCSV/swift-java.config new file mode 100644 index 00000000..3ab83f79 --- /dev/null +++ b/Samples/JavaDependencySampleApp/Sources/JavaCommonsCSV/swift-java.config @@ -0,0 +1,9 @@ +{ + "classes" : { + "org.apache.commons.io.FilenameUtils" : "FilenameUtils", + "org.apache.commons.io.IOCase" : "IOCase" + }, + "dependencies" : [ + "org.apache.commons:commons-csv:1.12.0" + ] +} diff --git a/Samples/JavaDependencySampleApp/Sources/JavaDependencySample/main.swift b/Samples/JavaDependencySampleApp/Sources/JavaDependencySample/main.swift new file mode 100644 index 00000000..86770ee8 --- /dev/null +++ b/Samples/JavaDependencySampleApp/Sources/JavaDependencySample/main.swift @@ -0,0 +1,47 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import JavaKit +import JavaKitFunction +import JavaKitConfigurationShared +import Foundation + +// Import the commons-csv library wrapper: +import JavaCommonsCSV + +print("") +print("") +print("-----------------------------------------------------------------------") +print("Start Sample app...") + +// Make sure we have the classpath loaded +// TODO: this is more complex than that, need to account for dependencies of our module +let currentDir = FileManager.default.currentDirectoryPath +let swiftJavaClasspath = findSwiftJavaClasspaths() + +// 1) Start a JVM with appropriate classpath +let jvm = try JavaVirtualMachine.shared(classpath: swiftJavaClasspath) + +// 2) Get the FilenameUtils Java class so we can call the static methods on it +let FilenameUtilsClass = try JavaClass() + +// Some silly sample path we want to work with: +let path = "/example/path/executable.exe" +print("Path = \(path)") + +let ext = try! FilenameUtilsClass.getExtension(path) +print("org.apache.commons.io.FilenameUtils.getExtension = \(ext)") +precondition(ext == "exe") + +print("Done.") diff --git a/Samples/JavaDependencySampleApp/Sources/JavaDependencySample/swift-java.config b/Samples/JavaDependencySampleApp/Sources/JavaDependencySample/swift-java.config new file mode 100644 index 00000000..7a73a41b --- /dev/null +++ b/Samples/JavaDependencySampleApp/Sources/JavaDependencySample/swift-java.config @@ -0,0 +1,2 @@ +{ +} \ No newline at end of file diff --git a/Samples/JavaDependencySampleApp/ci-validate.sh b/Samples/JavaDependencySampleApp/ci-validate.sh new file mode 100755 index 00000000..86f83978 --- /dev/null +++ b/Samples/JavaDependencySampleApp/ci-validate.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +set -e +set -x + +cd ../../JavaKit +./gradlew build + +cd - +swift run --disable-sandbox diff --git a/Samples/JavaKitSampleApp/ci-validate.sh b/Samples/JavaKitSampleApp/ci-validate.sh index eff61551..f453a00b 100755 --- a/Samples/JavaKitSampleApp/ci-validate.sh +++ b/Samples/JavaKitSampleApp/ci-validate.sh @@ -1,5 +1,8 @@ #!/bin/sh +set -e +set -x + swift build "$JAVA_HOME/bin/java" \ -cp .build/plugins/outputs/javakitsampleapp/JavaKitExample/destination/JavaCompilerPlugin/Java \ diff --git a/Samples/JavaProbablyPrime/ci-validate.sh b/Samples/JavaProbablyPrime/ci-validate.sh index 948a390c..0bdd86d1 100755 --- a/Samples/JavaProbablyPrime/ci-validate.sh +++ b/Samples/JavaProbablyPrime/ci-validate.sh @@ -1,3 +1,6 @@ #!/bin/sh +set -e +set -x + swift run JavaProbablyPrime 1337 \ No newline at end of file diff --git a/Samples/JavaSieve/.gitignore b/Samples/JavaSieve/.gitignore index 0023a534..6e1b4ce3 100644 --- a/Samples/JavaSieve/.gitignore +++ b/Samples/JavaSieve/.gitignore @@ -6,3 +6,4 @@ DerivedData/ .swiftpm/configuration/registries.json .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata .netrc +quadratic-sieve-Java \ No newline at end of file diff --git a/Samples/JavaSieve/README.md b/Samples/JavaSieve/README.md index b8dc3c9a..09fbde83 100644 --- a/Samples/JavaSieve/README.md +++ b/Samples/JavaSieve/README.md @@ -12,10 +12,9 @@ This example wraps an [open-source Java library](https://github.com/gazman-sdk/q git clone https://github.com/gazman-sdk/quadratic-sieve-Java cd quadratic-sieve-Java sh ./gradlew jar +cd .. ``` -Then, copy the resulting Jar file (`./build/libs/QuadraticSieve-1.0.jar`) into the `Samples/JavaSieve` directory. - Now we're ready to build and run the Swift program from `Samples/JavaSieve`: ``` diff --git a/Samples/JavaSieve/Sources/JavaSieve/main.swift b/Samples/JavaSieve/Sources/JavaSieve/main.swift index 6d262b9f..e2047713 100644 --- a/Samples/JavaSieve/Sources/JavaSieve/main.swift +++ b/Samples/JavaSieve/Sources/JavaSieve/main.swift @@ -15,7 +15,11 @@ import JavaKit import JavaMath -let jvm = try JavaVirtualMachine.shared(classpath: ["QuadraticSieve-1.0.jar"]) +let jvm = try JavaVirtualMachine.shared(classpath: [ + "quadratic-sieve-Java/build/libs/QuadraticSieve-1.0.jar", + ".", +]) + do { let sieveClass = try JavaClass(environment: jvm.environment()) for prime in sieveClass.findPrimes(100)! { diff --git a/Samples/JavaSieve/Sources/JavaSieve/swift-java.config b/Samples/JavaSieve/Sources/JavaSieve/swift-java.config index 7ef33db9..7e055d1c 100644 --- a/Samples/JavaSieve/Sources/JavaSieve/swift-java.config +++ b/Samples/JavaSieve/Sources/JavaSieve/swift-java.config @@ -1,5 +1,5 @@ { - "classpath" : "QuadraticSieve-1.0.jar", + "classpath" : ".:quadratic-sieve-Java/build/libs/QuadraticSieve-1.0.jar", "classes" : { "com.gazman.quadratic_sieve.QuadraticSieve" : "QuadraticSieve", "com.gazman.quadratic_sieve.core.BaseFact" : "BaseFact", diff --git a/Samples/JavaSieve/ci-validate.sh b/Samples/JavaSieve/ci-validate.sh index 3eebd3ca..730a8ba8 100755 --- a/Samples/JavaSieve/ci-validate.sh +++ b/Samples/JavaSieve/ci-validate.sh @@ -1,3 +1,3 @@ #!/bin/bash -echo "Not validated in CI..." +echo "This sample is not verified in CI because old Gradle in the project making it hard to use its ./gradlew" \ No newline at end of file diff --git a/Sources/JExtractSwift/Swift2Java.swift b/Sources/JExtractSwift/Swift2Java.swift index 2167c391..a46d1ab4 100644 --- a/Sources/JExtractSwift/Swift2Java.swift +++ b/Sources/JExtractSwift/Swift2Java.swift @@ -16,6 +16,7 @@ import ArgumentParser import Foundation import SwiftSyntax import SwiftSyntaxBuilder +import JavaKitShared /// Command-line utility, similar to `jextract` to export Swift types to Java. public struct SwiftToJava: ParsableCommand { diff --git a/Sources/Java2Swift/JavaToSwift+EmitConfiguration.swift b/Sources/Java2Swift/JavaToSwift+EmitConfiguration.swift new file mode 100644 index 00000000..fd567234 --- /dev/null +++ b/Sources/Java2Swift/JavaToSwift+EmitConfiguration.swift @@ -0,0 +1,122 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import Foundation +import ArgumentParser +import Java2SwiftLib +import JavaKit +import JavaKitJar +import Java2SwiftLib +import JavaKitDependencyResolver +import JavaKitConfigurationShared + +extension JavaToSwift { + + // TODO: make this perhaps "emit type mappings" + mutating func emitConfiguration( + classpath: String, + environment: JNIEnvironment + ) throws { + print("[java-swift] Generate Java->Swift type mappings. Active filter: \(javaPackageFilter)") + print("[java-swift] Classpath: \(classpath)") + + if classpath.isEmpty { + print("[warning][java-swift] Classpath is empty!") + } + + // Get a fresh or existing configuration we'll amend + var (amendExistingConfig, configuration) = try getBaseConfigurationForWrite() + if amendExistingConfig { + print("[swift-java] Amend existing swift-java.config file...") + } + configuration.classpath = classpath // TODO: is this correct? + + // Import types from all the classpath entries; + // Note that we use the package level filtering, so users have some control over what gets imported. + for entry in classpath.split(separator: ":").map(String.init) { + print("[debug][swift-java] Importing classpath entry: \(entry)") + if entry.hasSuffix(".jar") { + let jarFile = try JarFile(entry, false, environment: environment) + try addJavaToSwiftMappings( + to: &configuration, + forJar: jarFile, + environment: environment + ) + } else if FileManager.default.fileExists(atPath: entry) { + print("[warning][swift-java] Currently unable handle directory classpath entries for config generation! Skipping: \(entry)") + } else { + print("[warning][swift-java] Classpath entry does not exist, skipping: \(entry)") + } + } + + // Encode the configuration. + let contents = try configuration.renderJSON() + + // Write the file. + try writeContents( + contents, + to: "swift-java.config", + description: "swift-java configuration file" + ) + } + + mutating func addJavaToSwiftMappings( + to configuration: inout Configuration, + forJar jarFile: JarFile, + environment: JNIEnvironment + ) throws { + for entry in jarFile.entries()! { + // We only look at class files in the Jar file. + guard entry.getName().hasSuffix(".class") else { + continue + } + + // Skip some "common" files we know that would be duplicated in every jar + guard !entry.getName().hasPrefix("META-INF") else { + continue + } + guard !entry.getName().hasSuffix("package-info") else { + continue + } + guard !entry.getName().hasSuffix("package-info.class") else { + continue + } + + // If this is a local class, it cannot be mapped into Swift. + if entry.getName().isLocalJavaClass { + continue + } + + let javaCanonicalName = String(entry.getName().replacing("/", with: ".") + .dropLast(".class".count)) + + if let javaPackageFilter { + if !javaCanonicalName.hasPrefix(javaPackageFilter) { + // Skip classes which don't match our expected prefix + continue + } + } + + if configuration.classes?[javaCanonicalName] != nil { + // We never overwrite an existing class mapping configuration. + // E.g. the user may have configured a custom name for a type. + continue + } + + configuration.classes?[javaCanonicalName] = + javaCanonicalName.defaultSwiftNameForJavaClass + } + } + +} \ No newline at end of file diff --git a/Sources/Java2Swift/JavaToSwift+FetchDependencies.swift b/Sources/Java2Swift/JavaToSwift+FetchDependencies.swift new file mode 100644 index 00000000..391abb27 --- /dev/null +++ b/Sources/Java2Swift/JavaToSwift+FetchDependencies.swift @@ -0,0 +1,122 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import Foundation +import Java2SwiftLib +import JavaKit +import Foundation +import JavaKitJar +import Java2SwiftLib +import JavaKitDependencyResolver +import JavaKitConfigurationShared +import JavaKitShared + +extension JavaToSwift { + + /// Must be the same as `DependencyResolver#CLASSPATH_CACHE_FILENAME` on the java side. + var JavaKitDependencyResolverClasspathCacheFilename: String { + "JavaKitDependencyResolver.swift-java.classpath" + } + var JavaKitDependencyResolverClasspathCacheFilePath: String { + ".build/\(JavaKitDependencyResolverClasspathCacheFilename)" + } + + func fetchDependenciesCachedClasspath() -> [String]? { + let cachedClasspathURL = URL( + fileURLWithPath: FileManager.default.currentDirectoryPath + "/" + JavaKitDependencyResolverClasspathCacheFilePath) + + guard FileManager.default.fileExists(atPath: cachedClasspathURL.path) else { + return [] + } + + guard let javaKitDependencyResolverCachedClasspath = try? String(contentsOf: cachedClasspathURL) else { + return [] + } + + print("[debug][swift-java] Cached dependency resolver classpath: \(javaKitDependencyResolverCachedClasspath)") + return javaKitDependencyResolverCachedClasspath.split(separator: ":").map(String.init) + } + + func fetchDependencies(moduleName: String, + dependencies: [JavaDependencyDescriptor], + baseClasspath: [String], + environment: JNIEnvironment) throws -> ResolvedDependencyClasspath { + let deps = dependencies.map { $0.descriptionGradleStyle } + print("[debug][swift-java] Resolve and fetch dependencies for: \(deps)") + let resolverClass = try JavaClass(environment: environment) + + let fullClasspath = try resolverClass.resolveDependenciesToClasspath( + projectBaseDirectory: URL(fileURLWithPath: ".").path, + dependencies: deps) + .split(separator: ":") + + let classpathEntries = fullClasspath.filter { + $0.hasSuffix(".jar") + } + let classpath = classpathEntries.joined(separator: ":") + + print("[info][swift-java] Resolved classpath for \(deps.count) dependencies of '\(moduleName)', classpath entries: \(classpathEntries.count), ", terminator: "") + print("done.".green) + + return ResolvedDependencyClasspath(for: dependencies, classpath: classpath) + } +} + +extension JavaToSwift { + mutating func writeFetchedDependenciesClasspath( + moduleName: String, + cacheDir: String, + resolvedClasspath: ResolvedDependencyClasspath) throws { + // Convert the artifact name to a module name + // e.g. reactive-streams -> ReactiveStreams + + // The file contents are just plain + let contents = resolvedClasspath.classpath + + // Write the file + try writeContents( + contents, + outputDirectoryOverride: URL(fileURLWithPath: cacheDir), + to: "\(moduleName).swift-java.classpath", + description: "swift-java.classpath file for module \(moduleName)" + ) + } + + public func artifactIDAsModuleID(_ artifactID: String) -> String { + let components = artifactID.split(whereSeparator: { $0 == "-" }) + let camelCased = components.map { $0.capitalized }.joined() + return camelCased + } +} + +struct ResolvedDependencyClasspath: CustomStringConvertible { + /// The dependency identifiers this is the classpath for. + let rootDependencies: [JavaDependencyDescriptor] + + /// Plain string representation of a Java classpath + let classpath: String + + var classpathEntries: [String] { + classpath.split(separator: ":").map(String.init) + } + + init(for rootDependencies: [JavaDependencyDescriptor], classpath: String) { + self.rootDependencies = rootDependencies + self.classpath = classpath + } + + var description: String { + "JavaClasspath(for: \(rootDependencies), classpath: \(classpath))" + } +} diff --git a/Sources/Java2Swift/JavaToSwift+GenerateWrappers.swift b/Sources/Java2Swift/JavaToSwift+GenerateWrappers.swift new file mode 100644 index 00000000..99f83b4e --- /dev/null +++ b/Sources/Java2Swift/JavaToSwift+GenerateWrappers.swift @@ -0,0 +1,145 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import Foundation +import ArgumentParser +import Java2SwiftLib +import JavaKit +import JavaKitJar +import Java2SwiftLib +import JavaKitDependencyResolver +import JavaKitConfigurationShared + +extension JavaToSwift { + mutating func generateWrappers( + config: Configuration, + classpath: String, + dependentConfigs: [(String, Configuration)], + environment: JNIEnvironment + ) throws { + guard let moduleName else { + fatalError("--module-name must be set in 'generate wrappers' mode!") + } + let translator = JavaTranslator( + swiftModuleName: moduleName, + environment: environment, + translateAsClass: true + ) + + // Keep track of all of the Java classes that will have + // Swift-native implementations. + translator.swiftNativeImplementations = Set(swiftNativeImplementation) + + // Note all of the dependent configurations. + for (swiftModuleName, dependentConfig) in dependentConfigs { + translator.addConfiguration( + dependentConfig, + forSwiftModule: swiftModuleName + ) + } + + // Add the configuration for this module. + translator.addConfiguration(config, forSwiftModule: moduleName) + + // Load all of the explicitly-requested classes. + let classLoader = try JavaClass(environment: environment) + .getSystemClassLoader()! + var javaClasses: [JavaClass] = [] + for (javaClassName, _) in config.classes ?? [:] { + guard let javaClass = try classLoader.loadClass(javaClassName) else { + print("warning: could not find Java class '\(javaClassName)'") + continue + } + + // Add this class to the list of classes we'll translate. + javaClasses.append(javaClass) + } + + // Find all of the nested classes for each class, adding them to the list + // of classes to be translated if they were already specified. + var allClassesToVisit = javaClasses + var currentClassIndex: Int = 0 + while currentClassIndex < allClassesToVisit.count { + defer { + currentClassIndex += 1 + } + + // The current class we're in. + let currentClass = allClassesToVisit[currentClassIndex] + guard let currentSwiftName = translator.translatedClasses[currentClass.getName()]?.swiftType else { + continue + } + + // Find all of the nested classes that weren't explicitly translated + // already. + let nestedClasses: [JavaClass] = currentClass.getClasses().compactMap { nestedClass in + guard let nestedClass else { return nil } + + // If this is a local class, we're done. + let javaClassName = nestedClass.getName() + if javaClassName.isLocalJavaClass { + return nil + } + + // If this class has been explicitly mentioned, we're done. + if translator.translatedClasses[javaClassName] != nil { + return nil + } + + // Record this as a translated class. + let swiftUnqualifiedName = javaClassName.javaClassNameToCanonicalName + .defaultSwiftNameForJavaClass + + + let swiftName = "\(currentSwiftName).\(swiftUnqualifiedName)" + translator.translatedClasses[javaClassName] = (swiftName, nil) + return nestedClass + } + + // If there were no new nested classes, there's nothing to do. + if nestedClasses.isEmpty { + continue + } + + // Record all of the nested classes that we will visit. + translator.nestedClasses[currentClass.getName()] = nestedClasses + allClassesToVisit.append(contentsOf: nestedClasses) + } + + // Validate configurations before writing any files + try translator.validateClassConfiguration() + + // Translate all of the Java classes into Swift classes. + for javaClass in javaClasses { + translator.startNewFile() + let swiftClassDecls = try translator.translateClass(javaClass) + let importDecls = translator.getImportDecls() + + let swiftFileText = """ + // Auto-generated by Java-to-Swift wrapper generator. + \(importDecls.map { $0.description }.joined()) + \(swiftClassDecls.map { $0.description }.joined(separator: "\n")) + + """ + + let swiftFileName = try! translator.getSwiftTypeName(javaClass, preferValueTypes: false) + .swiftName.replacing(".", with: "+") + ".swift" + try writeContents( + swiftFileText, + to: swiftFileName, + description: "Java class '\(javaClass.getName())' translation" + ) + } + } +} \ No newline at end of file diff --git a/Sources/Java2Swift/JavaToSwift.swift b/Sources/Java2Swift/JavaToSwift.swift index 35bffc74..0d196933 100644 --- a/Sources/Java2Swift/JavaToSwift.swift +++ b/Sources/Java2Swift/JavaToSwift.swift @@ -21,6 +21,8 @@ import JavaKitNetwork import JavaKitReflection import SwiftSyntax import SwiftSyntaxBuilder +import JavaKitConfigurationShared +import JavaKitShared /// Command-line utility to drive the export of Java classes into Swift types. @main @@ -28,7 +30,7 @@ struct JavaToSwift: ParsableCommand { static var _commandName: String { "Java2Swift" } @Option(help: "The name of the Swift module into which the resulting Swift types will be generated.") - var moduleName: String + var moduleName: String? @Option( help: @@ -36,12 +38,16 @@ struct JavaToSwift: ParsableCommand { ) var dependsOn: [String] = [] + // TODO: This should be a "make wrappers" option that just detects when we give it a jar @Flag( help: "Specifies that the input is a Jar file whose public classes will be loaded. The output of Java2Swift will be a configuration file (Java2Swift.config) that can be used as input to a subsequent Java2Swift invocation to generate wrappers for those public classes." ) var jar: Bool = false + @Flag(help: "Fetch dependencies from given target (containing swift-java configuration) or dependency string") + var fetch: Bool = false + @Option( name: [.customLong("cp"), .customLong("classpath")], help: "Class search path of directories and zip/jar files from which Java classes can be loaded." @@ -56,6 +62,30 @@ struct JavaToSwift: ParsableCommand { @Option(name: .shortAndLong, help: "The directory in which to output the generated Swift files or the Java2Swift configuration file.") var outputDirectory: String? = nil + + @Option(name: .shortAndLong, help: "Directory where to write cached values (e.g. swift-java.classpath files)") + var cacheDirectory: String? = nil + + var effectiveCacheDirectory: String? { + if let cacheDirectory { + return cacheDirectory + } else if let outputDirectory { + return outputDirectory + } else { + return nil + } + } + + @Option(name: .shortAndLong, help: "How to handle an existing swift-java.config; by default 'overwrite' by can be changed to amending a configuration") + var existingConfig: ExistingConfigFileMode = .overwrite + public enum ExistingConfigFileMode: String, ExpressibleByArgument, Codable { + case overwrite + case amend + } + + @Option(name: .shortAndLong, help: "While scanning a classpath, inspect only types included in this package") + var javaPackageFilter: String? = nil + @Argument( help: "The input file, which is either a Java2Swift configuration file or (if '-jar' was specified) a Jar file." @@ -65,6 +95,27 @@ struct JavaToSwift: ParsableCommand { /// Whether we have ensured that the output directory exists. var createdOutputDirectory: Bool = false + var moduleBaseDir: Foundation.URL? { + if let outputDirectory { + if outputDirectory == "-" { + return nil + } + + return URL(fileURLWithPath: outputDirectory) + } + + guard let moduleName else { + return nil + } + + // Put the result into Sources/\(moduleName). + let baseDir = URL(fileURLWithPath: ".") + .appendingPathComponent("Sources", isDirectory: true) + .appendingPathComponent(moduleName, isDirectory: true) + + return baseDir + } + /// The output directory in which to place the generated files, which will /// be the specified directory (--output-directory or -o option) if given, /// or a default directory derived from the other command-line arguments. @@ -79,6 +130,10 @@ struct JavaToSwift: ParsableCommand { return URL(fileURLWithPath: outputDirectory) } + guard let moduleName else { + fatalError("--module-name must be set!") + } + // Put the result into Sources/\(moduleName). let baseDir = URL(fileURLWithPath: ".") .appendingPathComponent("Sources", isDirectory: true) @@ -97,200 +152,198 @@ struct JavaToSwift: ParsableCommand { return outputDir } - /// Describes what kind of generation action is being performed by - /// Java2Swift. - enum GenerationMode { + /// Describes what kind of generation action is being performed by swift-java. + enum ToolMode { /// Generate a configuration file given a Jar file. - case configuration(jarFile: String) + case configuration(extraClasspath: String) // FIXME: this is more like "extract" configuration from classpath /// Generate Swift wrappers for Java classes based on the given /// configuration. - case classWrappers(Configuration) - } + case classWrappers // (Configuration) - mutating func run() throws { - // Determine the mode in which we'll execute. - let generationMode: GenerationMode - if jar { - generationMode = .configuration(jarFile: input) - } else { - let config = try JavaTranslator.readConfiguration(from: URL(fileURLWithPath: input)) - generationMode = .classWrappers(config) - } + /// Fetch dependencies for a module + case fetchDependencies // (Configuration) + // FIXME each mode should have its own config? + } - // Load all of the dependent configurations and associate them with Swift - // modules. - let dependentConfigs = try dependsOn.map { dependentConfig in - guard let equalLoc = dependentConfig.firstIndex(of: "=") else { - throw JavaToSwiftError.badConfigOption(dependentConfig) + mutating func run() { + print("[info][swift-java] Run: \(CommandLine.arguments.joined(separator: " "))") + do { + let config: Configuration + + // Determine the mode in which we'll execute. + let toolMode: ToolMode + if jar { + if let moduleBaseDir { + config = try readConfiguration(sourceDir: moduleBaseDir.path) + } else { + config = Configuration() + } + toolMode = .configuration(extraClasspath: input) + } else if fetch { + config = try JavaTranslator.readConfiguration(from: URL(fileURLWithPath: input)) + guard let dependencies = config.dependencies else { + print("[swift-java] Running in 'fetch dependencies' mode but dependencies list was empty!") + print("[swift-java] Nothing to do: done.") + return + } + toolMode = .fetchDependencies + } else { + config = try JavaTranslator.readConfiguration(from: URL(fileURLWithPath: input)) + toolMode = .classWrappers } - let afterEqual = dependentConfig.index(after: equalLoc) - let swiftModuleName = String(dependentConfig[..] = currentClass.getClasses().compactMap { nestedClass in - guard let nestedClass else { return nil } - - // If this is a local class, we're done. - let javaClassName = nestedClass.getName() - if javaClassName.isLocalJavaClass { - return nil + // Add extra classpath entries which are specific to building the JavaKit project and samples + let classpathBuildJavaKitEntries = [ // FIXME: THIS IS A TRICK UNTIL WE FIGURE OUT HOW TO BOOTSTRAP THIS PART + FileManager.default.currentDirectoryPath, + FileManager.default.currentDirectoryPath + "/.build", + FileManager.default.currentDirectoryPath + "/JavaKit/build/libs", + URL(fileURLWithPath: FileManager.default.currentDirectoryPath) + .deletingLastPathComponent() + .deletingLastPathComponent().absoluteURL.path + "/JavaKit/build/libs/JavaKit-1.0-SNAPSHOT.jar" + ] + classpathEntries += classpathBuildJavaKitEntries + + // Bring up the Java VM. + // TODO: print only in verbose mode + let classpath = classpathEntries.joined(separator: ":") + print("[debug][swift-java] Initialize JVM with classpath: \(classpath)") + + let jvm = try JavaVirtualMachine.shared(classpath: classpathEntries) + + // FIXME: we should resolve dependencies here perhaps + // if let dependencies = config.dependencies { + // print("[info][swift-java] Resolve dependencies...") + // let dependencyClasspath = try fetchDependencies( + // moduleName: moduleName, + // dependencies: dependencies, + // baseClasspath: classpathOptionEntries, + // environment: jvm.environment() + // ) + // classpathEntries += dependencyClasspath.classpathEntries + // } + + // * Classespaths from all dependent configuration files + for (_, config) in dependentConfigs { + // TODO: may need to resolve the dependent configs rather than just get their configs + // TODO: We should cache the resolved classpaths as well so we don't do it many times + config.classpath.map { entry in + print("[swift-java] Add dependent config classpath element: \(entry)") + classpathEntries.append(entry) } + } - // If this class has been explicitly mentioned, we're done. - if translator.translatedClasses[javaClassName] != nil { - return nil + // Run the task. + switch toolMode { + case .configuration: + try emitConfiguration( + classpath: classpath, + environment: jvm.environment() + ) + + case .classWrappers/*(let config)*/: + try generateWrappers( + config: config, + classpath: classpath, + dependentConfigs: dependentConfigs, + environment: jvm.environment() + ) + + case .fetchDependencies: + guard let dependencies = config.dependencies else { + fatalError("Configuration for fetching dependencies must have 'dependencies' defined!") + } + guard let moduleName = self.moduleName else { + fatalError("Fetching dependencies must specify module name (--module-name)!") + } + guard let effectiveCacheDirectory else { + fatalError("Fetching dependencies must effective cache directory! Specify --output-directory or --cache-directory") } - // Record this as a translated class. - let swiftUnqualifiedName = javaClassName.javaClassNameToCanonicalName - .defaultSwiftNameForJavaClass - + print("[debug][swift-java] Base classpath to fetch dependencies: \(classpathOptionEntries)") - let swiftName = "\(currentSwiftName).\(swiftUnqualifiedName)" - translator.translatedClasses[javaClassName] = (swiftName, nil) - return nestedClass - } + let dependencyClasspath = try fetchDependencies( + moduleName: moduleName, + dependencies: dependencies, + baseClasspath: classpathOptionEntries, + environment: jvm.environment() + ) - // If there were no new nested classes, there's nothing to do. - if nestedClasses.isEmpty { - continue + try writeFetchedDependenciesClasspath( + moduleName: moduleName, + cacheDir: effectiveCacheDirectory, + resolvedClasspath: dependencyClasspath) } - - // Record all of the nested classes that we will visit. - translator.nestedClasses[currentClass.getName()] = nestedClasses - allClassesToVisit.append(contentsOf: nestedClasses) + } catch { + // We fail like this since throwing out of the run often ends up hiding the failure reason when it is executed as SwiftPM plugin (!) + let message = "Failed with error: \(error)" + print("[error][java-swift] \(message)") + fatalError(message) } - // Validate configurations before writing any files - try translator.validateClassConfiguration() - - // Translate all of the Java classes into Swift classes. - for javaClass in javaClasses { - translator.startNewFile() - let swiftClassDecls = try translator.translateClass(javaClass) - let importDecls = translator.getImportDecls() - - let swiftFileText = """ - // Auto-generated by Java-to-Swift wrapper generator. - \(importDecls.map { $0.description }.joined()) - \(swiftClassDecls.map { $0.description }.joined(separator: "\n")) - - """ - - let swiftFileName = try! translator.getSwiftTypeName(javaClass, preferValueTypes: false) - .swiftName.replacing(".", with: "+") + ".swift" - try writeContents( - swiftFileText, - to: swiftFileName, - description: "Java class '\(javaClass.getName())' translation" - ) - } + // Just for debugging so it is clear which command has finished + print("[debug][swift-java] " + "Done: ".green + CommandLine.arguments.joined(separator: " ").green) } private func names(from javaClassNameOpt: String) -> (javaClassName: String, swiftName: String) { @@ -314,8 +367,22 @@ struct JavaToSwift: ParsableCommand { return (javaClassName, swiftName.javaClassNameToCanonicalName) } - mutating func writeContents(_ contents: String, to filename: String, description: String) throws { - guard let outputDir = actualOutputDirectory else { + mutating func writeContents( + _ contents: String, + to filename: String, description: String) throws { + try writeContents( + contents, + outputDirectoryOverride: self.actualOutputDirectory, + to: filename, + description: description) + } + + mutating func writeContents( + _ contents: String, + outputDirectoryOverride: Foundation.URL?, + to filename: String, + description: String) throws { + guard let outputDir = (outputDirectoryOverride ?? actualOutputDirectory) else { print("// \(filename) - \(description)") print(contents) return @@ -333,48 +400,28 @@ struct JavaToSwift: ParsableCommand { // Write the file: let file = outputDir.appendingPathComponent(filename) - print("Writing \(description) to '\(file.path)'...", terminator: "") + print("[debug][swift-java] Writing \(description) to '\(file.path)'... ", terminator: "") try contents.write(to: file, atomically: true, encoding: .utf8) - print(" done.") + print("done.".green) } +} - mutating func emitConfiguration( - forJarFile jarFileName: String, - classpath: String, - environment: JNIEnvironment - ) throws { - var configuration = Configuration(classpath: classpath) - - let jarFile = try JarFile(jarFileName, false, environment: environment) - for entry in jarFile.entries()! { - // We only look at class files in the Jar file. - guard entry.getName().hasSuffix(".class") else { - continue - } - - // If this is a local class, it cannot be mapped into Swift. - if entry.getName().isLocalJavaClass { - continue - } - - let javaCanonicalName = String(entry.getName().replacing("/", with: ".") - .dropLast(".class".count)) - configuration.classes[javaCanonicalName] = - javaCanonicalName.defaultSwiftNameForJavaClass +extension JavaToSwift { + /// Get base configuration, depending on if we are to 'amend' or 'overwrite' the existing configuration. + package func getBaseConfigurationForWrite() throws -> (Bool, Configuration) { + guard let actualOutputDirectory = self.actualOutputDirectory else { + // If output has no path there's nothing to amend + return (false, .init()) } - // Encode the configuration. - let encoder = JSONEncoder() - encoder.outputFormatting = [.prettyPrinted, .sortedKeys] - var contents = String(data: try encoder.encode(configuration), encoding: .utf8)! - contents.append("\n") - - // Write the file. - try writeContents( - contents, - to: "swift-java.config", - description: "swift-java configuration file" - ) + switch self.existingConfig { + case .overwrite: + // always make up a fresh instance if we're overwriting + return (false, .init()) + case .amend: + let configPath = actualOutputDirectory + return (true, try readConfiguration(sourceDir: configPath.path)) + } } } @@ -391,19 +438,6 @@ extension JavaToSwiftError: CustomStringConvertible { } } -extension String { - /// For a String that's of the form java.util.Vector, return the "Vector" - /// part. - fileprivate var defaultSwiftNameForJavaClass: String { - if let dotLoc = lastIndex(of: ".") { - let afterDot = index(after: dotLoc) - return String(self[afterDot...]).javaClassNameToCanonicalName.adjustedSwiftTypeName - } - - return javaClassNameToCanonicalName.adjustedSwiftTypeName - } -} - @JavaClass("java.lang.ClassLoader") public struct ClassLoader { @JavaMethod @@ -415,29 +449,3 @@ extension JavaClass { public func getSystemClassLoader() -> ClassLoader? } -extension String { - /// Replace all of the $'s for nested names with "." to turn a Java class - /// name into a Java canonical class name, - fileprivate var javaClassNameToCanonicalName: String { - return replacing("$", with: ".") - } - - /// Whether this is the name of an anonymous class. - fileprivate var isLocalJavaClass: Bool { - for segment in split(separator: "$") { - if let firstChar = segment.first, firstChar.isNumber { - return true - } - } - - return false - } - - /// Adjust type name for "bad" type names that don't work well in Swift. - fileprivate var adjustedSwiftTypeName: String { - switch self { - case "Type": return "JavaType" - default: return self - } - } -} diff --git a/Sources/Java2Swift/String+Extensions.swift b/Sources/Java2Swift/String+Extensions.swift new file mode 100644 index 00000000..ba26f892 --- /dev/null +++ b/Sources/Java2Swift/String+Extensions.swift @@ -0,0 +1,62 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import Foundation +import ArgumentParser +import Java2SwiftLib +import JavaKit +import JavaKitJar +import Java2SwiftLib +import JavaKitDependencyResolver +import JavaKitConfigurationShared + +extension String { + /// For a String that's of the form java.util.Vector, return the "Vector" + /// part. + var defaultSwiftNameForJavaClass: String { + if let dotLoc = lastIndex(of: ".") { + let afterDot = index(after: dotLoc) + return String(self[afterDot...]).javaClassNameToCanonicalName.adjustedSwiftTypeName + } + + return javaClassNameToCanonicalName.adjustedSwiftTypeName + } +} + +extension String { + /// Replace all of the $'s for nested names with "." to turn a Java class + /// name into a Java canonical class name, + var javaClassNameToCanonicalName: String { + return replacing("$", with: ".") + } + + /// Whether this is the name of an anonymous class. + var isLocalJavaClass: Bool { + for segment in split(separator: "$") { + if let firstChar = segment.first, firstChar.isNumber { + return true + } + } + + return false + } + + /// Adjust type name for "bad" type names that don't work well in Swift. + var adjustedSwiftTypeName: String { + switch self { + case "Type": return "JavaType" + default: return self + } + } +} diff --git a/Sources/Java2SwiftLib/Configuration.swift b/Sources/Java2SwiftLib/Configuration.swift deleted file mode 100644 index 2cda8476..00000000 --- a/Sources/Java2SwiftLib/Configuration.swift +++ /dev/null @@ -1,45 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of Swift.org project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -package typealias JavaVersion = Int - -/// Configuration for the Java2Swift translation tool, provided on a per-target -/// basis. -/// -/// Note: there is a copy of this struct in the Java2Swift plugin. They -/// must be kept in sync. -package struct Configuration: Codable { - /// The Java class path that should be passed along to the Java2Swift tool. - package var classpath: String? = nil - - /// The Java classes that should be translated to Swift. The keys are - /// canonical Java class names (e.g., java.util.Vector) and the values are - /// the corresponding Swift names (e.g., JavaVector). - package var classes: [String: String] = [:] - - package var sourceCompatibility: JavaVersion? - package var targetCompatibility: JavaVersion? - - package init( - classpath: String? = nil, - classes: [String : String] = [:], - sourceCompatibility: JavaVersion? = nil, - targetCompatibility: JavaVersion? = nil - ) { - self.classpath = classpath - self.classes = classes - self.sourceCompatibility = sourceCompatibility - self.targetCompatibility = targetCompatibility - } -} diff --git a/Sources/Java2SwiftLib/JavaTranslator+Configuration.swift b/Sources/Java2SwiftLib/JavaTranslator+Configuration.swift index b84d7a1e..e0f6d0cb 100644 --- a/Sources/Java2SwiftLib/JavaTranslator+Configuration.swift +++ b/Sources/Java2SwiftLib/JavaTranslator+Configuration.swift @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// import Foundation +import JavaKitConfigurationShared extension JavaTranslator { /// Read a configuration file from the given URL. @@ -24,7 +25,11 @@ extension JavaTranslator { /// Load the configuration file with the given name to populate the known set of /// translated Java classes. package func addConfiguration(_ config: Configuration, forSwiftModule swiftModule: String) { - for (javaClassName, swiftName) in config.classes { + guard let classes = config.classes else { + return + } + + for (javaClassName, swiftName) in classes { translatedClasses[javaClassName] = ( swiftType: swiftName, swiftModule: swiftModule diff --git a/Sources/Java2SwiftLib/JavaTranslator+Validation.swift b/Sources/Java2SwiftLib/JavaTranslator+Validation.swift index c85cedb0..9d4d00ca 100644 --- a/Sources/Java2SwiftLib/JavaTranslator+Validation.swift +++ b/Sources/Java2SwiftLib/JavaTranslator+Validation.swift @@ -52,7 +52,7 @@ package extension JavaTranslator { } } - func validateClassConfiguration() throws { + func validateClassConfiguration() throws(ValidationError) { // Group all classes by swift name let groupedDictionary: [SwiftTypeName: [(String, (String, String?))]] = Dictionary(grouping: translatedClasses, by: { SwiftTypeName(swiftType: $0.value.swiftType, swiftModule: $0.value.swiftModule) }) // Find all that are mapped to multiple names diff --git a/Sources/Java2SwiftLib/JavaTranslator.swift b/Sources/Java2SwiftLib/JavaTranslator.swift index 69edac6c..225d3868 100644 --- a/Sources/Java2SwiftLib/JavaTranslator.swift +++ b/Sources/Java2SwiftLib/JavaTranslator.swift @@ -17,6 +17,7 @@ import JavaKitReflection import JavaTypes import SwiftBasicFormat import SwiftSyntax +import JavaKitConfigurationShared import SwiftSyntaxBuilder /// Utility that translates Java classes into Swift source code to access diff --git a/Sources/JavaKit/JavaKitVM/JavaVirtualMachine.swift b/Sources/JavaKit/JavaKitVM/JavaVirtualMachine.swift index 61f01f51..0800a89e 100644 --- a/Sources/JavaKit/JavaKitVM/JavaVirtualMachine.swift +++ b/Sources/JavaKit/JavaKitVM/JavaVirtualMachine.swift @@ -32,13 +32,16 @@ public final class JavaVirtualMachine: @unchecked Sendable { /// The Java virtual machine instance. private let jvm: JavaVMPointer + let classpath: [String] + /// Whether to destroy the JVM on deinit. - private let destroyOnDeinit: Bool + private let destroyOnDeinit: LockedState // FIXME: we should require macOS 15 and then use Synchronization /// Adopt an existing JVM pointer. public init(adoptingJVM jvm: JavaVMPointer) { self.jvm = jvm - self.destroyOnDeinit = false + self.classpath = [] // FIXME: bad... + self.destroyOnDeinit = .init(initialState: false) } /// Initialize a new Java virtual machine instance. @@ -56,6 +59,7 @@ public final class JavaVirtualMachine: @unchecked Sendable { vmOptions: [String] = [], ignoreUnrecognized: Bool = false ) throws { + self.classpath = classpath var jvm: JavaVMPointer? = nil var environment: UnsafeMutableRawPointer? = nil var vmArgs = JavaVMInitArgs() @@ -68,7 +72,8 @@ public final class JavaVirtualMachine: @unchecked Sendable { let fileManager = FileManager.default for path in classpath { if !fileManager.fileExists(atPath: path) { - throw JavaKitError.classpathEntryNotFound(entry: path, classpath: classpath) + // FIXME: this should be configurable, a classpath missing a directory isn't reason to blow up + print("[warning][swift-java][JavaVirtualMachine] Missing classpath element: \(URL(fileURLWithPath: path).absoluteString)") // TODO: stderr } } let colonSeparatedClassPath = classpath.joined(separator: ":") @@ -104,20 +109,38 @@ public final class JavaVirtualMachine: @unchecked Sendable { } self.jvm = jvm! - self.destroyOnDeinit = true + self.destroyOnDeinit = .init(initialState: true) + } + + public func destroyJVM() throws { + try self.detachCurrentThread() + if let error = VMError(fromJNIError: jvm.pointee!.pointee.DestroyJavaVM(jvm)) { + throw error + } + + destroyOnDeinit.withLock { $0 = false } // we destroyed explicitly, disable destroy in deinit } deinit { - if destroyOnDeinit { - // Destroy the JVM. - if let resultError = VMError(fromJNIError: jvm.pointee!.pointee.DestroyJavaVM(jvm)) { - fatalError("Failed to destroy the JVM: \(resultError)") + if destroyOnDeinit.withLock({ $0 }) { + do { + try destroyJVM() + } catch { + fatalError("Failed to destroy the JVM: \(error)") } } } } +extension JavaVirtualMachine: CustomStringConvertible { + public var description: String { + "\(Self.self)(\(jvm))" + } +} + +// ==== ------------------------------------------------------------------------ // MARK: Java thread management. + extension JavaVirtualMachine { /// Produce the JNI environment for the active thread, attaching this /// thread to the JVM if it isn't already. @@ -148,6 +171,7 @@ extension JavaVirtualMachine { // If we failed to attach, report that. if let attachError = VMError(fromJNIError: attachResult) { + fatalError("JVM Error: \(attachError)") throw attachError } @@ -164,8 +188,9 @@ extension JavaVirtualMachine { } } } - +// ==== ------------------------------------------------------------------------ // MARK: Shared Java Virtual Machine management. + extension JavaVirtualMachine { /// The globally shared JavaVirtualMachine instance, behind a lock. /// @@ -190,15 +215,26 @@ extension JavaVirtualMachine { /// be prefixed by the class-path argument described above. /// - ignoreUnrecognized: Whether the JVM should ignore any VM options it /// does not recognize. + /// - replace: replace the existing shared JVM instance public static func shared( classpath: [String] = [], vmOptions: [String] = [], - ignoreUnrecognized: Bool = false + ignoreUnrecognized: Bool = false, + replace: Bool = false ) throws -> JavaVirtualMachine { - try sharedJVM.withLock { (sharedJVMPointer: inout JavaVirtualMachine?) in + precondition(!classpath.contains(where: { $0.contains(":") }), "Classpath element must not contain `:`! Split the path into elements! Was: \(classpath)") + + return try sharedJVM.withLock { (sharedJVMPointer: inout JavaVirtualMachine?) in // If we already have a JavaVirtualMachine instance, return it. - if let existingInstance = sharedJVMPointer { - return existingInstance + if replace { + print("[swift-java] Replace JVM instance!") + try sharedJVMPointer?.destroyJVM() + sharedJVMPointer = nil + } else { + if let existingInstance = sharedJVMPointer { + // FIXME: this isn't ideal; we silently ignored that we may have requested a different classpath or options + return existingInstance + } } while true { @@ -273,9 +309,9 @@ extension JavaVirtualMachine { case invalidArguments /// Unknown JNI error. - case unknown(jint) + case unknown(jint, file: String, line: UInt) - init?(fromJNIError error: jint) { + init?(fromJNIError error: jint, file: String = #fileID, line: UInt = #line) { switch error { case JNI_OK: return nil case JNI_EDETACHED: self = .threadDetached @@ -283,7 +319,7 @@ extension JavaVirtualMachine { case JNI_ENOMEM: self = .outOfMemory case JNI_EEXIST: self = .existingVM case JNI_EINVAL: self = .invalidArguments - default: self = .unknown(error) + default: self = .unknown(error, file: file, line: line) } } } diff --git a/Sources/JavaKitConfigurationShared/Configuration.swift b/Sources/JavaKitConfigurationShared/Configuration.swift new file mode 100644 index 00000000..2078c544 --- /dev/null +++ b/Sources/JavaKitConfigurationShared/Configuration.swift @@ -0,0 +1,191 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import Foundation + +//////////////////////////////////////////////////////////////////////////////// +// This file is only supposed to be edited in `Shared/` and must be symlinked // +// from everywhere else! We cannot share dependencies with or between plugins // +//////////////////////////////////////////////////////////////////////////////// + +public typealias JavaVersion = Int + +/// Configuration for the SwiftJava plugins, provided on a per-target basis. +public struct Configuration: Codable { + // ==== swift 2 java --------------------------------------------------------- + + public var javaPackage: String? + + // ==== java 2 swift --------------------------------------------------------- + + /// The Java class path that should be passed along to the Java2Swift tool. + public var classpath: String? = nil + + public var classpathEntries: [String] { + guard let classpath else { + return [] + } + + return classpath.split(separator: ":").map(String.init) + } + + /// The Java classes that should be translated to Swift. The keys are + /// canonical Java class names (e.g., java.util.Vector) and the values are + /// the corresponding Swift names (e.g., JavaVector). + public var classes: [String: String]? = [:] + + // Compile for the specified Java SE release. + public var sourceCompatibility: JavaVersion? + + // Generate class files suitable for the specified Java SE release. + public var targetCompatibility: JavaVersion? + + // ==== dependencies --------------------------------------------------------- + + // Java dependencies we need to fetch for this target. + public var dependencies: [JavaDependencyDescriptor]? + + public init() { + } + +} + +/// Represents a maven-style Java dependency. +public struct JavaDependencyDescriptor: Hashable, Codable { + public var groupID: String + public var artifactID: String + public var version: String + + public init(from decoder: any Decoder) throws { + let container = try decoder.singleValueContainer() + let string = try container.decode(String.self) + let parts = string.split(separator: ":") + + if parts.count == 1 && string.hasPrefix(":") { + self.groupID = "" + self.artifactID = ":" + String(parts.first!) + self.version = "" + return + } + + guard parts.count == 3 else { + throw JavaDependencyDescriptorError(message: "Illegal dependency, did not match: `groupID:artifactID:version`, parts: '\(parts)'") + } + + self.groupID = String(parts[0]) + self.artifactID = String(parts[1]) + self.version = String(parts[2]) + } + + public var descriptionGradleStyle: String { + [groupID, artifactID, version].joined(separator: ":") + } + + public func encode(to encoder: any Encoder) throws { + var container = encoder.singleValueContainer() + try container.encode("\(self.groupID):\(self.artifactID):\(self.version)") + } + + struct JavaDependencyDescriptorError: Error { + let message: String + } +} + +public func readConfiguration(sourceDir: String, file: String = #fileID, line: UInt = #line) throws -> Configuration { + // Workaround since filePath is macOS 13 + let sourcePath = + if sourceDir.hasPrefix("file://") { sourceDir } else { "file://" + sourceDir } + let configPath = URL(string: sourcePath)!.appendingPathComponent("swift-java.config", isDirectory: false) + + return try readConfiguration(configPath: configPath, file: file, line: line) +} + +public func readConfiguration(configPath: URL, file: String = #fileID, line: UInt = #line) throws -> Configuration { + do { + let configData = try Data(contentsOf: configPath) + return try JSONDecoder().decode(Configuration.self, from: configData) + } catch { + throw ConfigurationError(message: "Failed to parse SwiftJava configuration at '\(configPath)'!", error: error, + file: file, line: line) + } +} + +public func findSwiftJavaClasspaths(in basePath: String = FileManager.default.currentDirectoryPath) -> [String] { + let fileManager = FileManager.default + + let baseURL = URL(fileURLWithPath: basePath) + var classpathEntries: [String] = [] + + print("[debug][swift-java] Searching for *.swift-java.classpath files in: \(baseURL)") + guard let enumerator = fileManager.enumerator(at: baseURL, includingPropertiesForKeys: []) else { + print("[warning][swift-java] Failed to get enumerator for \(baseURL)") + return [] + } + + for case let fileURL as URL in enumerator { + if fileURL.lastPathComponent.hasSuffix(".swift-java.classpath") { + print("[debug][swift-java] Constructing classpath with entries from: \(fileURL.relativePath)") + if let contents = try? String(contentsOf: fileURL) { + let entries = contents.split(separator: ":").map(String.init) + for entry in entries { + print("[debug][swift-java] Classpath += \(entry)") + } + classpathEntries += entries + } + } + } + + return classpathEntries +} + +extension Configuration { + public var compilerVersionArgs: [String] { + var compilerVersionArgs = [String]() + + if let sourceCompatibility { + compilerVersionArgs += ["--source", String(sourceCompatibility)] + } + if let targetCompatibility { + compilerVersionArgs += ["--target", String(targetCompatibility)] + } + + return compilerVersionArgs + } +} + +extension Configuration { + /// Render the configuration as JSON text. + public func renderJSON() throws -> String { + let encoder = JSONEncoder() + encoder.outputFormatting = [.prettyPrinted, .sortedKeys] + var contents = String(data: try encoder.encode(self), encoding: .utf8)! + contents.append("\n") + return contents + } +} + +public struct ConfigurationError: Error { + let message: String + let error: any Error + + let file: String + let line: UInt + + init(message: String, error: any Error, file: String = #fileID, line: UInt = #line) { + self.message = message + self.error = error + self.file = file + self.line = line + } +} diff --git a/Sources/JavaKitDependencyResolver/DependencyResolver.swift b/Sources/JavaKitDependencyResolver/DependencyResolver.swift new file mode 100644 index 00000000..697e3d2a --- /dev/null +++ b/Sources/JavaKitDependencyResolver/DependencyResolver.swift @@ -0,0 +1,32 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import JavaKit +import JavaRuntime + +@JavaInterface("org.swift.javakit.dependencies.DependencyResolver") +public struct DependencyResolver { +} + +extension JavaClass { + + @JavaStaticMethod + public func resolveDependenciesToClasspath( + projectBaseDirectory: String, + dependencies: [String]) throws -> String + + @JavaStaticMethod + public func hasDependencyResolverDependenciesLoaded() -> Bool + +} \ No newline at end of file diff --git a/Sources/JavaKitDependencyResolver/swift-java.config b/Sources/JavaKitDependencyResolver/swift-java.config new file mode 100644 index 00000000..d2d9f448 --- /dev/null +++ b/Sources/JavaKitDependencyResolver/swift-java.config @@ -0,0 +1,9 @@ +{ + "dependencies": [ + ":JavaKit", + ] + , + "__classes": { + "org.swift.javakit.dependencies.DependencyResolver": "DependencyResolver" + } + } diff --git a/Sources/JExtractSwift/TerminalColors.swift b/Sources/JavaKitShared/TerminalColors.swift similarity index 100% rename from Sources/JExtractSwift/TerminalColors.swift rename to Sources/JavaKitShared/TerminalColors.swift diff --git a/settings.gradle b/settings.gradle index fa0fa5bd..c1168a68 100644 --- a/settings.gradle +++ b/settings.gradle @@ -18,6 +18,7 @@ pluginManagement { rootProject.name = "swift-java" +include "JavaKit" include "SwiftKit" // Include sample apps -- you can run them via `gradle Name:run` From 207d071700a2d8fd912f2132ac34fb4adcb5bc5a Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Tue, 10 Dec 2024 14:10:36 +0900 Subject: [PATCH 194/426] Cleanup: Remove not used SystemClassLoaderUnsafe (#197) --- .../dependencies/SystemClassLoaderUnsafe.java | 46 ------------------- .../swift-java.config | 4 -- 2 files changed, 50 deletions(-) delete mode 100644 JavaKit/src/main/java/org/swift/javakit/dependencies/SystemClassLoaderUnsafe.java diff --git a/JavaKit/src/main/java/org/swift/javakit/dependencies/SystemClassLoaderUnsafe.java b/JavaKit/src/main/java/org/swift/javakit/dependencies/SystemClassLoaderUnsafe.java deleted file mode 100644 index d8d4f64a..00000000 --- a/JavaKit/src/main/java/org/swift/javakit/dependencies/SystemClassLoaderUnsafe.java +++ /dev/null @@ -1,46 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of Swift.org project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -package org.swift.javakit.dependencies; - -import java.io.File; -import java.net.URL; -import java.net.URLClassLoader; - -public final class SystemClassLoaderUnsafe { - - private SystemClassLoaderUnsafe() {} - - /** - * Use internal methods to add a path to the system classloader. - * If this ever starts throwing in new JDK versions, we may need to abandon this technique. - * - * @param path path to add to the current system classloader. - */ - public static void addPath(String path) { - try { - var url = new File(path).toURI().toURL(); - var urlClassLoader = (URLClassLoader) ClassLoader.getSystemClassLoader(); - var method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class); - method.setAccessible(true); - method.invoke(urlClassLoader, url); - } catch (Throwable ex) { - throw new RuntimeException("Unable to add path to system class loader! " + - "This is not supported API and may indeed start failing in the future. " + - "If/when this happens, we have to change the bootstrap logic to instead " + - "create a new JVM with the new bootstrap classpath, " + - "rather than add paths to the existing one.", ex); - } - } -} diff --git a/Sources/JavaKitDependencyResolver/swift-java.config b/Sources/JavaKitDependencyResolver/swift-java.config index d2d9f448..6ea5aa87 100644 --- a/Sources/JavaKitDependencyResolver/swift-java.config +++ b/Sources/JavaKitDependencyResolver/swift-java.config @@ -2,8 +2,4 @@ "dependencies": [ ":JavaKit", ] - , - "__classes": { - "org.swift.javakit.dependencies.DependencyResolver": "DependencyResolver" - } } From 1f23265d7853b9b623c0f31119d945fdbb1f5369 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Wed, 11 Dec 2024 14:51:50 +0900 Subject: [PATCH 195/426] Vendor experimental Subprocess --- JavaKit/build.gradle | 21 +- .../dependencies/DependencyResolver.java | 6 +- Package.swift | 47 +- .../JavaDependencySampleApp/ci-validate.sh | 4 +- .../include/_CShimsTargetConditionals.h | 50 + Sources/_CShims/include/process_shims.h | 72 + Sources/_CShims/process_shims.c | 337 +++++ Sources/_Subprocess/LockedState.swift | 158 +++ .../Platforms/Subprocess+Darwin.swift | 350 +++++ .../Platforms/Subprocess+Linux.swift | 284 ++++ .../Platforms/Subprocess+Unix.swift | 455 +++++++ .../Platforms/Subprocess+Windows.swift | 1209 +++++++++++++++++ Sources/_Subprocess/Subprocess+API.swift | 462 +++++++ .../Subprocess+AsyncDataSequence.swift | 83 ++ .../Subprocess+Configuration.swift | 767 +++++++++++ Sources/_Subprocess/Subprocess+IO.swift | 435 ++++++ Sources/_Subprocess/Subprocess+Teardown.swift | 118 ++ Sources/_Subprocess/Subprocess.swift | 312 +++++ 18 files changed, 5150 insertions(+), 20 deletions(-) create mode 100644 Sources/_CShims/include/_CShimsTargetConditionals.h create mode 100644 Sources/_CShims/include/process_shims.h create mode 100644 Sources/_CShims/process_shims.c create mode 100644 Sources/_Subprocess/LockedState.swift create mode 100644 Sources/_Subprocess/Platforms/Subprocess+Darwin.swift create mode 100644 Sources/_Subprocess/Platforms/Subprocess+Linux.swift create mode 100644 Sources/_Subprocess/Platforms/Subprocess+Unix.swift create mode 100644 Sources/_Subprocess/Platforms/Subprocess+Windows.swift create mode 100644 Sources/_Subprocess/Subprocess+API.swift create mode 100644 Sources/_Subprocess/Subprocess+AsyncDataSequence.swift create mode 100644 Sources/_Subprocess/Subprocess+Configuration.swift create mode 100644 Sources/_Subprocess/Subprocess+IO.swift create mode 100644 Sources/_Subprocess/Subprocess+Teardown.swift create mode 100644 Sources/_Subprocess/Subprocess.swift diff --git a/JavaKit/build.gradle b/JavaKit/build.gradle index 8eed1c6e..70982e90 100644 --- a/JavaKit/build.gradle +++ b/JavaKit/build.gradle @@ -60,18 +60,13 @@ tasks.processResources { } } -//task fatJar(type: Jar) { -// archiveBaseName = 'java-kit-fat-jar' -// duplicatesStrategy = DuplicatesStrategy.EXCLUDE -// from { configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } } -// with jar -//} +// Task necessary to bootstrap and EXIT, this is to prevent hangs when used via SwiftPM plugin. +tasks.register('printRuntimeClasspath') { + dependsOn 'jar' -// Task necessary to bootstrap -task printRuntimeClasspath { - def runtimeClasspath = sourceSets.main.runtimeClasspath - inputs.files(runtimeClasspath) - doLast { - println("CLASSPATH:${runtimeClasspath.asPath}") - } + def runtimeClasspath = sourceSets.main.runtimeClasspath + inputs.files(runtimeClasspath) + doLast { + println("SWIFT_JAVA_CLASSPATH:${runtimeClasspath.asPath}") + } } diff --git a/JavaKit/src/main/java/org/swift/javakit/dependencies/DependencyResolver.java b/JavaKit/src/main/java/org/swift/javakit/dependencies/DependencyResolver.java index ff4085c9..0e801525 100644 --- a/JavaKit/src/main/java/org/swift/javakit/dependencies/DependencyResolver.java +++ b/JavaKit/src/main/java/org/swift/javakit/dependencies/DependencyResolver.java @@ -34,7 +34,7 @@ @SuppressWarnings("unused") public class DependencyResolver { - private static final String COMMAND_OUTPUT_LINE_PREFIX_CLASSPATH = "CLASSPATH:"; + private static final String COMMAND_OUTPUT_LINE_PREFIX_CLASSPATH = "SWIFT_JAVA_CLASSPATH:"; private static final String CLASSPATH_CACHE_FILENAME = "JavaKitDependencyResolver.swift-java.classpath"; public static String GRADLE_API_DEPENDENCY = "dev.gradleplugins:gradle-api:8.10.1"; @@ -236,11 +236,11 @@ private static void printBuildFiles(File projectDir, String[] dependencies) thro writer.println("}"); writer.println(""" - task printRuntimeClasspath { + tasks.register("printRuntimeClasspath") { def runtimeClasspath = sourceSets.main.runtimeClasspath inputs.files(runtimeClasspath) doLast { - println("CLASSPATH:${runtimeClasspath.asPath}") + println("SWIFT_JAVA_CLASSPATH:${runtimeClasspath.asPath}") } } """); diff --git a/Package.swift b/Package.swift index f6645115..50b5da2a 100644 --- a/Package.swift +++ b/Package.swift @@ -139,7 +139,7 @@ let package = Package( "JExtractSwiftCommandPlugin" ] ), - + // ==== Examples .library( @@ -152,6 +152,9 @@ let package = Package( dependencies: [ .package(url: "https://github.com/swiftlang/swift-syntax", from: "600.0.1"), .package(url: "https://github.com/apple/swift-argument-parser", from: "1.5.0"), + .package(url: "https://github.com/apple/swift-system", from: "1.4.0"), + + // Benchmarking .package(url: "https://github.com/ordo-one/package-benchmark", .upToNextMajor(from: "1.4.0")), ], targets: [ @@ -183,6 +186,9 @@ let package = Package( swiftSettings: [ .swiftLanguageMode(.v5), .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]), + ], + plugins: [ + "SwiftJavaBootstrapJavaPlugin", ] ), @@ -211,7 +217,7 @@ let package = Package( .unsafeFlags( [ "-L\(javaHome)/lib" - ], + ], .when(platforms: [.windows])), .linkedLibrary("jvm"), ] @@ -378,6 +384,25 @@ let package = Package( ] ), + .executableTarget( + name: "SwiftJavaBootstrapJavaTool", + dependencies: [ + "JavaKitConfigurationShared", // for Configuration reading at runtime + "_Subprocess", + ], + swiftSettings: [ + .swiftLanguageMode(.v5) + ] + ), + + .plugin( + name: "SwiftJavaBootstrapJavaPlugin", + capability: .buildTool(), + dependencies: [ + "SwiftJavaBootstrapJavaTool" + ] + ), + .plugin( name: "SwiftJavaPlugin", capability: .buildTool(), @@ -442,6 +467,24 @@ let package = Package( .swiftLanguageMode(.v5), .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) ] + ), + + // Experimental Foundation Subprocess Copy + .target( + name: "_CShims", + swiftSettings: [ + .swiftLanguageMode(.v5) + ] + ), + .target( + name: "_Subprocess", + dependencies: [ + "_CShims", + .product(name: "SystemPackage", package: "swift-system"), + ], + swiftSettings: [ + .swiftLanguageMode(.v5) + ] ) ] ) diff --git a/Samples/JavaDependencySampleApp/ci-validate.sh b/Samples/JavaDependencySampleApp/ci-validate.sh index 86f83978..207aa343 100755 --- a/Samples/JavaDependencySampleApp/ci-validate.sh +++ b/Samples/JavaDependencySampleApp/ci-validate.sh @@ -3,8 +3,8 @@ set -e set -x -cd ../../JavaKit -./gradlew build +swift build --product SwiftJavaBootstrapJavaTool +.build/arm64-apple-macosx/debug/SwiftJavaBootstrapJavaTool --fetch /Users/ktoso/code/swift-java/Sources/JavaKitDependencyResolver/swift-java.config --module-name JavaKitDependencyResolver --output-directory && .build/plugins/outputs/swift-java/JavaKitDependencyResolver/destination/SwiftJavaBootstrapJavaPlugin cd - swift run --disable-sandbox diff --git a/Sources/_CShims/include/_CShimsTargetConditionals.h b/Sources/_CShims/include/_CShimsTargetConditionals.h new file mode 100644 index 00000000..fef2eaf2 --- /dev/null +++ b/Sources/_CShims/include/_CShimsTargetConditionals.h @@ -0,0 +1,50 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2021 - 2022 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// + +#ifndef _SHIMS_TARGET_CONDITIONALS_H +#define _SHIMS_TARGET_CONDITIONALS_H + +#if __has_include() +#include +#endif + +#if (defined(__APPLE__) && defined(__MACH__)) +#define TARGET_OS_MAC 1 +#else +#define TARGET_OS_MAC 0 +#endif + +#if defined(__linux__) +#define TARGET_OS_LINUX 1 +#else +#define TARGET_OS_LINUX 0 +#endif + +#if defined(__unix__) +#define TARGET_OS_BSD 1 +#else +#define TARGET_OS_BSD 0 +#endif + +#if defined(_WIN32) +#define TARGET_OS_WINDOWS 1 +#else +#define TARGET_OS_WINDOWS 0 +#endif + +#if defined(__wasi__) +#define TARGET_OS_WASI 1 +#else +#define TARGET_OS_WASI 0 +#endif + +#endif // _SHIMS_TARGET_CONDITIONALS_H diff --git a/Sources/_CShims/include/process_shims.h b/Sources/_CShims/include/process_shims.h new file mode 100644 index 00000000..3b03d103 --- /dev/null +++ b/Sources/_CShims/include/process_shims.h @@ -0,0 +1,72 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// +//===----------------------------------------------------------------------===// + +#ifndef process_shims_h +#define process_shims_h + +#include "_CShimsTargetConditionals.h" + +#if !TARGET_OS_WINDOWS +#include + +#if _POSIX_SPAWN +#include +#endif + +#if TARGET_OS_MAC +int _subprocess_spawn( + pid_t * _Nonnull pid, + const char * _Nonnull exec_path, + const posix_spawn_file_actions_t _Nullable * _Nonnull file_actions, + const posix_spawnattr_t _Nullable * _Nonnull spawn_attrs, + char * _Nullable const args[_Nonnull], + char * _Nullable const env[_Nullable], + uid_t * _Nullable uid, + gid_t * _Nullable gid, + int number_of_sgroups, const gid_t * _Nullable sgroups, + int create_session +); +#endif // TARGET_OS_MAC + +int _subprocess_fork_exec( + pid_t * _Nonnull pid, + const char * _Nonnull exec_path, + const char * _Nullable working_directory, + const int file_descriptors[_Nonnull], + char * _Nullable const args[_Nonnull], + char * _Nullable const env[_Nullable], + uid_t * _Nullable uid, + gid_t * _Nullable gid, + gid_t * _Nullable process_group_id, + int number_of_sgroups, const gid_t * _Nullable sgroups, + int create_session, + void (* _Nullable configurator)(void) +); + +int _was_process_exited(int status); +int _get_exit_code(int status); +int _was_process_signaled(int status); +int _get_signal_code(int status); +int _was_process_suspended(int status); + +#if TARGET_OS_LINUX +int _shims_snprintf( + char * _Nonnull str, + int len, + const char * _Nonnull format, + char * _Nonnull str1, + char * _Nonnull str2 +); +#endif + +#endif // !TARGET_OS_WINDOWS + +#endif /* process_shims_h */ diff --git a/Sources/_CShims/process_shims.c b/Sources/_CShims/process_shims.c new file mode 100644 index 00000000..2d7d4a4a --- /dev/null +++ b/Sources/_CShims/process_shims.c @@ -0,0 +1,337 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// +//===----------------------------------------------------------------------===// + +#include "include/_CShimsTargetConditionals.h" +#include "include/process_shims.h" + +#if !TARGET_OS_WINDOWS +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +int _was_process_exited(int status) { + return WIFEXITED(status); +} + +int _get_exit_code(int status) { + return WEXITSTATUS(status); +} + +int _was_process_signaled(int status) { + return WIFSIGNALED(status); +} + +int _get_signal_code(int status) { + return WTERMSIG(status); +} + +int _was_process_suspended(int status) { + return WIFSTOPPED(status); +} + +#if TARGET_OS_LINUX +#include + +int _shims_snprintf( + char * _Nonnull str, + int len, + const char * _Nonnull format, + char * _Nonnull str1, + char * _Nonnull str2 +) { + return snprintf(str, len, format, str1, str2); +} +#endif + +// MARK: - Darwin (posix_spawn) +#if TARGET_OS_MAC + +int _subprocess_spawn( + pid_t * _Nonnull pid, + const char * _Nonnull exec_path, + const posix_spawn_file_actions_t _Nullable * _Nonnull file_actions, + const posix_spawnattr_t _Nullable * _Nonnull spawn_attrs, + char * _Nullable const args[_Nonnull], + char * _Nullable const env[_Nullable], + uid_t * _Nullable uid, + gid_t * _Nullable gid, + int number_of_sgroups, const gid_t * _Nullable sgroups, + int create_session +) { + int require_pre_fork = uid != NULL || + gid != NULL || + number_of_sgroups > 0 || + create_session > 0; + + if (require_pre_fork != 0) { +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated" + pid_t childPid = vfork(); +#pragma GCC diagnostic pop + if (childPid != 0) { + *pid = childPid; + return childPid < 0 ? errno : 0; + } + + if (number_of_sgroups > 0 && sgroups != NULL) { + if (setgroups(number_of_sgroups, sgroups) != 0) { + return errno; + } + } + + if (uid != NULL) { + if (setuid(*uid) != 0) { + return errno; + } + } + + if (gid != NULL) { + if (setgid(*gid) != 0) { + return errno; + } + } + + if (create_session != 0) { + (void)setsid(); + } + } + + // Set POSIX_SPAWN_SETEXEC if we already forked + if (require_pre_fork) { + short flags = 0; + int rc = posix_spawnattr_getflags(spawn_attrs, &flags); + if (rc != 0) { + return rc; + } + + rc = posix_spawnattr_setflags( + (posix_spawnattr_t *)spawn_attrs, flags | POSIX_SPAWN_SETEXEC + ); + if (rc != 0) { + return rc; + } + } + + // Spawn + return posix_spawn(pid, exec_path, file_actions, spawn_attrs, args, env); +} + +#endif // TARGET_OS_MAC + +// MARK: - Linux (fork/exec + posix_spawn fallback) + +#if _POSIX_SPAWN +static int _subprocess_posix_spawn_fallback( + pid_t * _Nonnull pid, + const char * _Nonnull exec_path, + const char * _Nullable working_directory, + const int file_descriptors[_Nonnull], + char * _Nullable const args[_Nonnull], + char * _Nullable const env[_Nullable], + gid_t * _Nullable process_group_id +) { + // Setup stdin, stdout, and stderr + posix_spawn_file_actions_t file_actions; + + int rc = posix_spawn_file_actions_init(&file_actions); + if (rc != 0) { return rc; } + if (file_descriptors[0] >= 0) { + rc = posix_spawn_file_actions_adddup2( + &file_actions, file_descriptors[0], STDIN_FILENO + ); + if (rc != 0) { return rc; } + } + if (file_descriptors[2] >= 0) { + rc = posix_spawn_file_actions_adddup2( + &file_actions, file_descriptors[2], STDOUT_FILENO + ); + if (rc != 0) { return rc; } + } + if (file_descriptors[4] >= 0) { + rc = posix_spawn_file_actions_adddup2( + &file_actions, file_descriptors[4], STDERR_FILENO + ); + if (rc != 0) { return rc; } + } + + // Close parent side + if (file_descriptors[1] >= 0) { + rc = posix_spawn_file_actions_addclose(&file_actions, file_descriptors[1]); + if (rc != 0) { return rc; } + } + if (file_descriptors[3] >= 0) { + rc = posix_spawn_file_actions_addclose(&file_actions, file_descriptors[3]); + if (rc != 0) { return rc; } + } + if (file_descriptors[5] >= 0) { + rc = posix_spawn_file_actions_addclose(&file_actions, file_descriptors[5]); + if (rc != 0) { return rc; } + } + + // Setup spawnattr + posix_spawnattr_t spawn_attr; + rc = posix_spawnattr_init(&spawn_attr); + if (rc != 0) { return rc; } + // Masks + sigset_t no_signals; + sigset_t all_signals; + sigemptyset(&no_signals); + sigfillset(&all_signals); + rc = posix_spawnattr_setsigmask(&spawn_attr, &no_signals); + if (rc != 0) { return rc; } + rc = posix_spawnattr_setsigdefault(&spawn_attr, &all_signals); + if (rc != 0) { return rc; } + // Flags + short flags = POSIX_SPAWN_SETSIGMASK | POSIX_SPAWN_SETSIGDEF; + if (process_group_id != NULL) { + flags |= POSIX_SPAWN_SETPGROUP; + rc = posix_spawnattr_setpgroup(&spawn_attr, *process_group_id); + if (rc != 0) { return rc; } + } + rc = posix_spawnattr_setflags(&spawn_attr, flags); + + // Spawn! + rc = posix_spawn( + pid, exec_path, + &file_actions, &spawn_attr, + args, env + ); + posix_spawn_file_actions_destroy(&file_actions); + posix_spawnattr_destroy(&spawn_attr); + return rc; +} +#endif // _POSIX_SPAWN + +int _subprocess_fork_exec( + pid_t * _Nonnull pid, + const char * _Nonnull exec_path, + const char * _Nullable working_directory, + const int file_descriptors[_Nonnull], + char * _Nullable const args[_Nonnull], + char * _Nullable const env[_Nullable], + uid_t * _Nullable uid, + gid_t * _Nullable gid, + gid_t * _Nullable process_group_id, + int number_of_sgroups, const gid_t * _Nullable sgroups, + int create_session, + void (* _Nullable configurator)(void) +) { + int require_pre_fork = working_directory != NULL || + uid != NULL || + gid != NULL || + process_group_id != NULL || + (number_of_sgroups > 0 && sgroups != NULL) || + create_session || + configurator != NULL; + +#if _POSIX_SPAWN + // If posix_spawn is available on this platform and + // we do not require prefork, use posix_spawn if possible. + // + // (Glibc's posix_spawn does not support + // `POSIX_SPAWN_SETEXEC` therefore we have to keep + // using fork/exec if `require_pre_fork` is true. + if (require_pre_fork == 0) { + return _subprocess_posix_spawn_fallback( + pid, exec_path, + working_directory, + file_descriptors, + args, env, + process_group_id + ); + } +#endif + + pid_t child_pid = fork(); + if (child_pid != 0) { + *pid = child_pid; + return child_pid < 0 ? errno : 0; + } + + if (working_directory != NULL) { + if (chdir(working_directory) != 0) { + return errno; + } + } + + + if (uid != NULL) { + if (setuid(*uid) != 0) { + return errno; + } + } + + if (gid != NULL) { + if (setgid(*gid) != 0) { + return errno; + } + } + + if (number_of_sgroups > 0 && sgroups != NULL) { + if (setgroups(number_of_sgroups, sgroups) != 0) { + return errno; + } + } + + if (create_session != 0) { + (void)setsid(); + } + + if (process_group_id != NULL) { + (void)setpgid(0, *process_group_id); + } + + // Bind stdin, stdout, and stderr + int rc = 0; + if (file_descriptors[0] >= 0) { + rc = dup2(file_descriptors[0], STDIN_FILENO); + if (rc < 0) { return errno; } + } + if (file_descriptors[2] >= 0) { + rc = dup2(file_descriptors[2], STDOUT_FILENO); + if (rc < 0) { return errno; } + } + if (file_descriptors[4] >= 0) { + rc = dup2(file_descriptors[4], STDERR_FILENO); + if (rc < 0) { return errno; } + } + // Close parent side + if (file_descriptors[1] >= 0) { + rc = close(file_descriptors[1]); + } + if (file_descriptors[3] >= 0) { + rc = close(file_descriptors[3]); + } + if (file_descriptors[4] >= 0) { + rc = close(file_descriptors[5]); + } + if (rc != 0) { + return errno; + } + // Run custom configuratior + if (configurator != NULL) { + configurator(); + } + // Finally, exec + execve(exec_path, args, env); + // If we got here, something went wrong + return errno; +} + +#endif // !TARGET_OS_WINDOWS + diff --git a/Sources/_Subprocess/LockedState.swift b/Sources/_Subprocess/LockedState.swift new file mode 100644 index 00000000..0cde3b94 --- /dev/null +++ b/Sources/_Subprocess/LockedState.swift @@ -0,0 +1,158 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2022 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// + +#if canImport(os) +internal import os +#if FOUNDATION_FRAMEWORK && canImport(C.os.lock) +internal import C.os.lock +#endif +#elseif canImport(Bionic) +import Bionic +#elseif canImport(Glibc) +import Glibc +#elseif canImport(Musl) +import Musl +#elseif canImport(WinSDK) +import WinSDK +#endif + +package struct LockedState { + + // Internal implementation for a cheap lock to aid sharing code across platforms + private struct _Lock { +#if canImport(os) + typealias Primitive = os_unfair_lock +#elseif canImport(Bionic) || canImport(Glibc) || canImport(Musl) + typealias Primitive = pthread_mutex_t +#elseif canImport(WinSDK) + typealias Primitive = SRWLOCK +#elseif os(WASI) + // WASI is single-threaded, so we don't need a lock. + typealias Primitive = Void +#endif + + typealias PlatformLock = UnsafeMutablePointer + var _platformLock: PlatformLock + + fileprivate static func initialize(_ platformLock: PlatformLock) { +#if canImport(os) + platformLock.initialize(to: os_unfair_lock()) +#elseif canImport(Bionic) || canImport(Glibc) + pthread_mutex_init(platformLock, nil) +#elseif canImport(WinSDK) + InitializeSRWLock(platformLock) +#elseif os(WASI) + // no-op +#endif + } + + fileprivate static func deinitialize(_ platformLock: PlatformLock) { +#if canImport(Bionic) || canImport(Glibc) + pthread_mutex_destroy(platformLock) +#endif + platformLock.deinitialize(count: 1) + } + + static fileprivate func lock(_ platformLock: PlatformLock) { +#if canImport(os) + os_unfair_lock_lock(platformLock) +#elseif canImport(Bionic) || canImport(Glibc) + pthread_mutex_lock(platformLock) +#elseif canImport(WinSDK) + AcquireSRWLockExclusive(platformLock) +#elseif os(WASI) + // no-op +#endif + } + + static fileprivate func unlock(_ platformLock: PlatformLock) { +#if canImport(os) + os_unfair_lock_unlock(platformLock) +#elseif canImport(Bionic) || canImport(Glibc) + pthread_mutex_unlock(platformLock) +#elseif canImport(WinSDK) + ReleaseSRWLockExclusive(platformLock) +#elseif os(WASI) + // no-op +#endif + } + } + + private class _Buffer: ManagedBuffer { + deinit { + withUnsafeMutablePointerToElements { + _Lock.deinitialize($0) + } + } + } + + private let _buffer: ManagedBuffer + + package init(initialState: State) { + _buffer = _Buffer.create(minimumCapacity: 1, makingHeaderWith: { buf in + buf.withUnsafeMutablePointerToElements { + _Lock.initialize($0) + } + return initialState + }) + } + + package func withLock(_ body: @Sendable (inout State) throws -> T) rethrows -> T { + try withLockUnchecked(body) + } + + package func withLockUnchecked(_ body: (inout State) throws -> T) rethrows -> T { + try _buffer.withUnsafeMutablePointers { state, lock in + _Lock.lock(lock) + defer { _Lock.unlock(lock) } + return try body(&state.pointee) + } + } + + // Ensures the managed state outlives the locked scope. + package func withLockExtendingLifetimeOfState(_ body: @Sendable (inout State) throws -> T) rethrows -> T { + try _buffer.withUnsafeMutablePointers { state, lock in + _Lock.lock(lock) + return try withExtendedLifetime(state.pointee) { + defer { _Lock.unlock(lock) } + return try body(&state.pointee) + } + } + } +} + +extension LockedState where State == Void { + package init() { + self.init(initialState: ()) + } + + package func withLock(_ body: @Sendable () throws -> R) rethrows -> R { + return try withLock { _ in + try body() + } + } + + package func lock() { + _buffer.withUnsafeMutablePointerToElements { lock in + _Lock.lock(lock) + } + } + + package func unlock() { + _buffer.withUnsafeMutablePointerToElements { lock in + _Lock.unlock(lock) + } + } +} + +extension LockedState: @unchecked Sendable where State: Sendable {} + diff --git a/Sources/_Subprocess/Platforms/Subprocess+Darwin.swift b/Sources/_Subprocess/Platforms/Subprocess+Darwin.swift new file mode 100644 index 00000000..2d02cd1d --- /dev/null +++ b/Sources/_Subprocess/Platforms/Subprocess+Darwin.swift @@ -0,0 +1,350 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// +//===----------------------------------------------------------------------===// + +#if canImport(Darwin) + +#if canImport(FoundationEssentials) +import FoundationEssentials +#elseif canImport(Foundation) +import Foundation +#endif + +import Darwin +import Dispatch +import SystemPackage + +#if FOUNDATION_FRAMEWORK +@_implementationOnly import _FoundationCShims +#else +import _CShims +#endif + +// Darwin specific implementation +extension Subprocess.Configuration { + internal typealias StringOrRawBytes = Subprocess.StringOrRawBytes + + internal func spawn( + withInput input: Subprocess.ExecutionInput, + output: Subprocess.ExecutionOutput, + error: Subprocess.ExecutionOutput + ) throws -> Subprocess { + let (executablePath, + env, argv, + intendedWorkingDir, + uidPtr, gidPtr, supplementaryGroups + ) = try self.preSpawn() + defer { + for ptr in env { ptr?.deallocate() } + for ptr in argv { ptr?.deallocate() } + uidPtr?.deallocate() + gidPtr?.deallocate() + } + + // Setup file actions and spawn attributes + var fileActions: posix_spawn_file_actions_t? = nil + var spawnAttributes: posix_spawnattr_t? = nil + // Setup stdin, stdout, and stderr + posix_spawn_file_actions_init(&fileActions) + defer { + posix_spawn_file_actions_destroy(&fileActions) + } + // Input + var result: Int32 = -1 + if let inputRead = input.getReadFileDescriptor() { + result = posix_spawn_file_actions_adddup2(&fileActions, inputRead.rawValue, 0) + guard result == 0 else { + try self.cleanupAll(input: input, output: output, error: error) + throw POSIXError(.init(rawValue: result) ?? .ENODEV) + } + } + if let inputWrite = input.getWriteFileDescriptor() { + // Close parent side + result = posix_spawn_file_actions_addclose(&fileActions, inputWrite.rawValue) + guard result == 0 else { + try self.cleanupAll(input: input, output: output, error: error) + throw POSIXError(.init(rawValue: result) ?? .ENODEV) + } + } + // Output + if let outputWrite = output.getWriteFileDescriptor() { + result = posix_spawn_file_actions_adddup2(&fileActions, outputWrite.rawValue, 1) + guard result == 0 else { + try self.cleanupAll(input: input, output: output, error: error) + throw POSIXError(.init(rawValue: result) ?? .ENODEV) + } + } + if let outputRead = output.getReadFileDescriptor() { + // Close parent side + result = posix_spawn_file_actions_addclose(&fileActions, outputRead.rawValue) + guard result == 0 else { + try self.cleanupAll(input: input, output: output, error: error) + throw POSIXError(.init(rawValue: result) ?? .ENODEV) + } + } + // Error + if let errorWrite = error.getWriteFileDescriptor() { + result = posix_spawn_file_actions_adddup2(&fileActions, errorWrite.rawValue, 2) + guard result == 0 else { + try self.cleanupAll(input: input, output: output, error: error) + throw POSIXError(.init(rawValue: result) ?? .ENODEV) + } + } + if let errorRead = error.getReadFileDescriptor() { + // Close parent side + result = posix_spawn_file_actions_addclose(&fileActions, errorRead.rawValue) + guard result == 0 else { + try self.cleanupAll(input: input, output: output, error: error) + throw POSIXError(.init(rawValue: result) ?? .ENODEV) + } + } + // Setup spawnAttributes + posix_spawnattr_init(&spawnAttributes) + defer { + posix_spawnattr_destroy(&spawnAttributes) + } + var noSignals = sigset_t() + var allSignals = sigset_t() + sigemptyset(&noSignals) + sigfillset(&allSignals) + posix_spawnattr_setsigmask(&spawnAttributes, &noSignals) + posix_spawnattr_setsigdefault(&spawnAttributes, &allSignals) + // Configure spawnattr + var spawnAttributeError: Int32 = 0 + var flags: Int32 = POSIX_SPAWN_CLOEXEC_DEFAULT | + POSIX_SPAWN_SETSIGMASK | POSIX_SPAWN_SETSIGDEF + if let pgid = self.platformOptions.processGroupID { + flags |= POSIX_SPAWN_SETPGROUP + spawnAttributeError = posix_spawnattr_setpgroup(&spawnAttributes, pid_t(pgid)) + } + spawnAttributeError = posix_spawnattr_setflags(&spawnAttributes, Int16(flags)) + // Set QualityOfService + // spanattr_qos seems to only accept `QOS_CLASS_UTILITY` or `QOS_CLASS_BACKGROUND` + // and returns an error of `EINVAL` if anything else is provided + if spawnAttributeError == 0 && self.platformOptions.qualityOfService == .utility{ + spawnAttributeError = posix_spawnattr_set_qos_class_np(&spawnAttributes, QOS_CLASS_UTILITY) + } else if spawnAttributeError == 0 && self.platformOptions.qualityOfService == .background { + spawnAttributeError = posix_spawnattr_set_qos_class_np(&spawnAttributes, QOS_CLASS_BACKGROUND) + } + + // Setup cwd + var chdirError: Int32 = 0 + if intendedWorkingDir != .currentWorkingDirectory { + chdirError = intendedWorkingDir.withPlatformString { workDir in + return posix_spawn_file_actions_addchdir_np(&fileActions, workDir) + } + } + + // Error handling + if chdirError != 0 || spawnAttributeError != 0 { + try self.cleanupAll(input: input, output: output, error: error) + if spawnAttributeError != 0 { + throw POSIXError(.init(rawValue: result) ?? .ENODEV) + } + + if chdirError != 0 { + throw CocoaError(.fileNoSuchFile, userInfo: [ + .debugDescriptionErrorKey: "Cannot failed to change the working directory to \(intendedWorkingDir) with errno \(chdirError)" + ]) + } + } + // Run additional config + if let spawnConfig = self.platformOptions.preSpawnProcessConfigurator { + try spawnConfig(&spawnAttributes, &fileActions) + } + // Spawn + var pid: pid_t = 0 + let spawnError: CInt = executablePath.withCString { exePath in + return supplementaryGroups.withOptionalUnsafeBufferPointer { sgroups in + return _subprocess_spawn( + &pid, exePath, + &fileActions, &spawnAttributes, + argv, env, + uidPtr, gidPtr, + Int32(supplementaryGroups?.count ?? 0), sgroups?.baseAddress, + self.platformOptions.createSession ? 1 : 0 + ) + } + } + // Spawn error + if spawnError != 0 { + try self.cleanupAll(input: input, output: output, error: error) + throw POSIXError(.init(rawValue: spawnError) ?? .ENODEV) + } + return Subprocess( + processIdentifier: .init(value: pid), + executionInput: input, + executionOutput: output, + executionError: error + ) + } +} + +// Special keys used in Error's user dictionary +extension String { + static let debugDescriptionErrorKey = "NSDebugDescription" +} + +// MARK: - Platform Specific Options +extension Subprocess { + /// The collection of platform-specific settings + /// to configure the subprocess when running + public struct PlatformOptions: Sendable { + public var qualityOfService: QualityOfService = .default + /// Set user ID for the subprocess + public var userID: uid_t? = nil + /// Set the real and effective group ID and the saved + /// set-group-ID of the subprocess, equivalent to calling + /// `setgid()` on the child process. + /// Group ID is used to control permissions, particularly + /// for file access. + public var groupID: gid_t? = nil + /// Set list of supplementary group IDs for the subprocess + public var supplementaryGroups: [gid_t]? = nil + /// Set the process group for the subprocess, equivalent to + /// calling `setpgid()` on the child process. + /// Process group ID is used to group related processes for + /// controlling signals. + public var processGroupID: pid_t? = nil + /// Creates a session and sets the process group ID + /// i.e. Detach from the terminal. + public var createSession: Bool = false + /// A lightweight code requirement that you use to + /// evaluate the executable for a launching process. + public var launchRequirementData: Data? = nil + /// An ordered list of steps in order to tear down the child + /// process in case the parent task is cancelled before + /// the child proces terminates. + /// Always ends in sending a `.kill` signal at the end. + public var teardownSequence: [TeardownStep] = [] + /// A closure to configure platform-specific + /// spawning constructs. This closure enables direct + /// configuration or override of underlying platform-specific + /// spawn settings that `Subprocess` utilizes internally, + /// in cases where Subprocess does not provide higher-level + /// APIs for such modifications. + /// + /// On Darwin, Subprocess uses `posix_spawn()` as the + /// underlying spawning mechanism. This closure allows + /// modification of the `posix_spawnattr_t` spawn attribute + /// and file actions `posix_spawn_file_actions_t` before + /// they are sent to `posix_spawn()`. + public var preSpawnProcessConfigurator: ( + @Sendable ( + inout posix_spawnattr_t?, + inout posix_spawn_file_actions_t? + ) throws -> Void + )? = nil + + public init() {} + } +} + +extension Subprocess.PlatformOptions: Hashable { + public static func == (lhs: Subprocess.PlatformOptions, rhs: Subprocess.PlatformOptions) -> Bool { + // Since we can't compare closure equality, + // as long as preSpawnProcessConfigurator is set + // always returns false so that `PlatformOptions` + // with it set will never equal to each other + if lhs.preSpawnProcessConfigurator != nil || + rhs.preSpawnProcessConfigurator != nil { + return false + } + return lhs.qualityOfService == rhs.qualityOfService && + lhs.userID == rhs.userID && + lhs.groupID == rhs.groupID && + lhs.supplementaryGroups == rhs.supplementaryGroups && + lhs.processGroupID == rhs.processGroupID && + lhs.createSession == rhs.createSession && + lhs.launchRequirementData == rhs.launchRequirementData + } + + public func hash(into hasher: inout Hasher) { + hasher.combine(self.qualityOfService) + hasher.combine(self.userID) + hasher.combine(self.groupID) + hasher.combine(self.supplementaryGroups) + hasher.combine(self.processGroupID) + hasher.combine(self.createSession) + hasher.combine(self.launchRequirementData) + // Since we can't really hash closures, + // use an UUID such that as long as + // `preSpawnProcessConfigurator` is set, it will + // never equal to other PlatformOptions + if self.preSpawnProcessConfigurator != nil { + hasher.combine(UUID()) + } + } +} + +extension Subprocess.PlatformOptions : CustomStringConvertible, CustomDebugStringConvertible { + internal func description(withIndent indent: Int) -> String { + let indent = String(repeating: " ", count: indent * 4) + return """ +PlatformOptions( +\(indent) qualityOfService: \(self.qualityOfService), +\(indent) userID: \(String(describing: userID)), +\(indent) groupID: \(String(describing: groupID)), +\(indent) supplementaryGroups: \(String(describing: supplementaryGroups)), +\(indent) processGroupID: \(String(describing: processGroupID)), +\(indent) createSession: \(createSession), +\(indent) launchRequirementData: \(String(describing: launchRequirementData)), +\(indent) preSpawnProcessConfigurator: \(self.preSpawnProcessConfigurator == nil ? "not set" : "set") +\(indent)) +""" + } + + public var description: String { + return self.description(withIndent: 0) + } + + public var debugDescription: String { + return self.description(withIndent: 0) + } +} + +// MARK: - Process Monitoring +@Sendable +internal func monitorProcessTermination( + forProcessWithIdentifier pid: Subprocess.ProcessIdentifier +) async throws -> Subprocess.TerminationStatus { + return try await withCheckedThrowingContinuation { continuation in + let source = DispatchSource.makeProcessSource( + identifier: pid.value, + eventMask: [.exit], + queue: .global() + ) + source.setEventHandler { + source.cancel() + var siginfo = siginfo_t() + let rc = waitid(P_PID, id_t(pid.value), &siginfo, WEXITED) + guard rc == 0 else { + continuation.resume(throwing: POSIXError(.init(rawValue: errno) ?? .ENODEV)) + return + } + switch siginfo.si_code { + case .init(CLD_EXITED): + continuation.resume(returning: .exited(siginfo.si_status)) + return + case .init(CLD_KILLED), .init(CLD_DUMPED): + continuation.resume(returning: .unhandledException(siginfo.si_status)) + case .init(CLD_TRAPPED), .init(CLD_STOPPED), .init(CLD_CONTINUED), .init(CLD_NOOP): + // Ignore these signals because they are not related to + // process exiting + break + default: + fatalError("Unexpected exit status: \(siginfo.si_code)") + } + } + source.resume() + } +} + +#endif // canImport(Darwin) diff --git a/Sources/_Subprocess/Platforms/Subprocess+Linux.swift b/Sources/_Subprocess/Platforms/Subprocess+Linux.swift new file mode 100644 index 00000000..10d39e94 --- /dev/null +++ b/Sources/_Subprocess/Platforms/Subprocess+Linux.swift @@ -0,0 +1,284 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// +//===----------------------------------------------------------------------===// + +#if canImport(Glibc) + +import Glibc +import Dispatch +import SystemPackage +import FoundationEssentials +import _CShims + +// Linux specific implementations +extension Subprocess.Configuration { + internal typealias StringOrRawBytes = Subprocess.StringOrRawBytes + + internal func spawn( + withInput input: Subprocess.ExecutionInput, + output: Subprocess.ExecutionOutput, + error: Subprocess.ExecutionOutput + ) throws -> Subprocess { + _setupMonitorSignalHandler() + + let (executablePath, + env, argv, + intendedWorkingDir, + uidPtr, gidPtr, + supplementaryGroups + ) = try self.preSpawn() + var processGroupIDPtr: UnsafeMutablePointer? = nil + if let processGroupID = self.platformOptions.processGroupID { + processGroupIDPtr = .allocate(capacity: 1) + processGroupIDPtr?.pointee = gid_t(processGroupID) + } + defer { + for ptr in env { ptr?.deallocate() } + for ptr in argv { ptr?.deallocate() } + uidPtr?.deallocate() + gidPtr?.deallocate() + processGroupIDPtr?.deallocate() + } + + let fileDescriptors: [CInt] = [ + input.getReadFileDescriptor()?.rawValue ?? -1, + input.getWriteFileDescriptor()?.rawValue ?? -1, + output.getWriteFileDescriptor()?.rawValue ?? -1, + output.getReadFileDescriptor()?.rawValue ?? -1, + error.getWriteFileDescriptor()?.rawValue ?? -1, + error.getReadFileDescriptor()?.rawValue ?? -1 + ] + + var workingDirectory: String? + if intendedWorkingDir != FilePath.currentWorkingDirectory { + // Only pass in working directory if it's different + workingDirectory = intendedWorkingDir.string + } + // Spawn + var pid: pid_t = 0 + let spawnError: CInt = executablePath.withCString { exePath in + return workingDirectory.withOptionalCString { workingDir in + return supplementaryGroups.withOptionalUnsafeBufferPointer { sgroups in + return fileDescriptors.withUnsafeBufferPointer { fds in + return _subprocess_fork_exec( + &pid, exePath, workingDir, + fds.baseAddress!, + argv, env, + uidPtr, gidPtr, + processGroupIDPtr, + CInt(supplementaryGroups?.count ?? 0), sgroups?.baseAddress, + self.platformOptions.createSession ? 1 : 0, + self.platformOptions.preSpawnProcessConfigurator + ) + } + } + } + } + // Spawn error + if spawnError != 0 { + try self.cleanupAll(input: input, output: output, error: error) + throw POSIXError(.init(rawValue: spawnError) ?? .ENODEV) + } + return Subprocess( + processIdentifier: .init(value: pid), + executionInput: input, + executionOutput: output, + executionError: error + ) + } +} + +// MARK: - Platform Specific Options +extension Subprocess { + /// The collection of platform-specific settings + /// to configure the subprocess when running + public struct PlatformOptions: Sendable { + // Set user ID for the subprocess + public var userID: uid_t? = nil + /// Set the real and effective group ID and the saved + /// set-group-ID of the subprocess, equivalent to calling + /// `setgid()` on the child process. + /// Group ID is used to control permissions, particularly + /// for file access. + public var groupID: gid_t? = nil + // Set list of supplementary group IDs for the subprocess + public var supplementaryGroups: [gid_t]? = nil + /// Set the process group for the subprocess, equivalent to + /// calling `setpgid()` on the child process. + /// Process group ID is used to group related processes for + /// controlling signals. + public var processGroupID: pid_t? = nil + // Creates a session and sets the process group ID + // i.e. Detach from the terminal. + public var createSession: Bool = false + /// An ordered list of steps in order to tear down the child + /// process in case the parent task is cancelled before + /// the child proces terminates. + /// Always ends in sending a `.kill` signal at the end. + public var teardownSequence: [TeardownStep] = [] + /// A closure to configure platform-specific + /// spawning constructs. This closure enables direct + /// configuration or override of underlying platform-specific + /// spawn settings that `Subprocess` utilizes internally, + /// in cases where Subprocess does not provide higher-level + /// APIs for such modifications. + /// + /// On Linux, Subprocess uses `fork/exec` as the + /// underlying spawning mechanism. This closure is called + /// after `fork()` but before `exec()`. You may use it to + /// call any necessary process setup functions. + public var preSpawnProcessConfigurator: (@convention(c) @Sendable () -> Void)? = nil + + public init() {} + } +} + +extension Subprocess.PlatformOptions: Hashable { + public static func ==( + lhs: Subprocess.PlatformOptions, + rhs: Subprocess.PlatformOptions + ) -> Bool { + // Since we can't compare closure equality, + // as long as preSpawnProcessConfigurator is set + // always returns false so that `PlatformOptions` + // with it set will never equal to each other + if lhs.preSpawnProcessConfigurator != nil || + rhs.preSpawnProcessConfigurator != nil { + return false + } + return lhs.userID == rhs.userID && + lhs.groupID == rhs.groupID && + lhs.supplementaryGroups == rhs.supplementaryGroups && + lhs.processGroupID == rhs.processGroupID && + lhs.createSession == rhs.createSession + } + + public func hash(into hasher: inout Hasher) { + hasher.combine(userID) + hasher.combine(groupID) + hasher.combine(supplementaryGroups) + hasher.combine(processGroupID) + hasher.combine(createSession) + // Since we can't really hash closures, + // use an UUID such that as long as + // `preSpawnProcessConfigurator` is set, it will + // never equal to other PlatformOptions + if self.preSpawnProcessConfigurator != nil { + hasher.combine(UUID()) + } + } +} + +extension Subprocess.PlatformOptions : CustomStringConvertible, CustomDebugStringConvertible { + internal func description(withIndent indent: Int) -> String { + let indent = String(repeating: " ", count: indent * 4) + return """ +PlatformOptions( +\(indent) userID: \(String(describing: userID)), +\(indent) groupID: \(String(describing: groupID)), +\(indent) supplementaryGroups: \(String(describing: supplementaryGroups)), +\(indent) processGroupID: \(String(describing: processGroupID)), +\(indent) createSession: \(createSession), +\(indent) preSpawnProcessConfigurator: \(self.preSpawnProcessConfigurator == nil ? "not set" : "set") +\(indent)) +""" + } + + public var description: String { + return self.description(withIndent: 0) + } + + public var debugDescription: String { + return self.description(withIndent: 0) + } +} + +// Special keys used in Error's user dictionary +extension String { + static let debugDescriptionErrorKey = "DebugDescription" +} + +// MARK: - Process Monitoring +@Sendable +internal func monitorProcessTermination( + forProcessWithIdentifier pid: Subprocess.ProcessIdentifier +) async throws -> Subprocess.TerminationStatus { + return try await withCheckedThrowingContinuation { continuation in + _childProcessContinuations.withLock { continuations in + if let existing = continuations.removeValue(forKey: pid.value), + case .status(let existingStatus) = existing { + // We already have existing status to report + continuation.resume(returning: existingStatus) + } else { + // Save the continuation for handler + continuations[pid.value] = .continuation(continuation) + } + } + } +} + +private enum ContinuationOrStatus { + case continuation(CheckedContinuation) + case status(Subprocess.TerminationStatus) +} + +private let _childProcessContinuations: LockedState< + [pid_t: ContinuationOrStatus] +> = LockedState(initialState: [:]) + +private var signalSource: (any DispatchSourceSignal)? = nil +private let setup: () = { + signalSource = DispatchSource.makeSignalSource( + signal: SIGCHLD, + queue: .global() + ) + signalSource?.setEventHandler { + _childProcessContinuations.withLock { continuations in + while true { + var siginfo = siginfo_t() + guard waitid(P_ALL, id_t(0), &siginfo, WEXITED) == 0 else { + return + } + var status: Subprocess.TerminationStatus? = nil + switch siginfo.si_code { + case .init(CLD_EXITED): + status = .exited(siginfo._sifields._sigchld.si_status) + case .init(CLD_KILLED), .init(CLD_DUMPED): + status = .unhandledException(siginfo._sifields._sigchld.si_status) + case .init(CLD_TRAPPED), .init(CLD_STOPPED), .init(CLD_CONTINUED): + // Ignore these signals because they are not related to + // process exiting + break + default: + fatalError("Unexpected exit status: \(siginfo.si_code)") + } + if let status = status { + let pid = siginfo._sifields._sigchld.si_pid + if let existing = continuations.removeValue(forKey: pid), + case .continuation(let c) = existing { + c.resume(returning: status) + } else { + // We don't have continuation yet, just state status + continuations[pid] = .status(status) + } + } + } + } + } + signalSource?.resume() +}() + +private func _setupMonitorSignalHandler() { + // Only executed once + setup +} + +#endif // canImport(Glibc) + diff --git a/Sources/_Subprocess/Platforms/Subprocess+Unix.swift b/Sources/_Subprocess/Platforms/Subprocess+Unix.swift new file mode 100644 index 00000000..3155743c --- /dev/null +++ b/Sources/_Subprocess/Platforms/Subprocess+Unix.swift @@ -0,0 +1,455 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// +//===----------------------------------------------------------------------===// + +#if canImport(Darwin) || canImport(Glibc) + +#if canImport(FoundationEssentials) +import FoundationEssentials +#elseif canImport(Foundation) +import Foundation +#endif + +#if canImport(Darwin) +import Darwin +#elseif canImport(Glibc) +import Glibc +#endif + +#if FOUNDATION_FRAMEWORK +@_implementationOnly import _FoundationCShims +#else +import _CShims +#endif + +import Dispatch +import SystemPackage + +// MARK: - Signals +extension Subprocess { + /// Signals are standardized messages sent to a running program + /// to trigger specific behavior, such as quitting or error handling. + public struct Signal : Hashable, Sendable { + /// The underlying platform specific value for the signal + public let rawValue: Int32 + + private init(rawValue: Int32) { + self.rawValue = rawValue + } + + /// The `.interrupt` signal is sent to a process by its + /// controlling terminal when a user wishes to interrupt + /// the process. + public static var interrupt: Self { .init(rawValue: SIGINT) } + /// The `.terminate` signal is sent to a process to request its + /// termination. Unlike the `.kill` signal, it can be caught + /// and interpreted or ignored by the process. This allows + /// the process to perform nice termination releasing resources + /// and saving state if appropriate. `.interrupt` is nearly + /// identical to `.terminate`. + public static var terminate: Self { .init(rawValue: SIGTERM) } + /// The `.suspend` signal instructs the operating system + /// to stop a process for later resumption. + public static var suspend: Self { .init(rawValue: SIGSTOP) } + /// The `resume` signal instructs the operating system to + /// continue (restart) a process previously paused by the + /// `.suspend` signal. + public static var resume: Self { .init(rawValue: SIGCONT) } + /// The `.kill` signal is sent to a process to cause it to + /// terminate immediately (kill). In contrast to `.terminate` + /// and `.interrupt`, this signal cannot be caught or ignored, + /// and the receiving process cannot perform any + /// clean-up upon receiving this signal. + public static var kill: Self { .init(rawValue: SIGKILL) } + /// The `.terminalClosed` signal is sent to a process when + /// its controlling terminal is closed. In modern systems, + /// this signal usually means that the controlling pseudo + /// or virtual terminal has been closed. + public static var terminalClosed: Self { .init(rawValue: SIGHUP) } + /// The `.quit` signal is sent to a process by its controlling + /// terminal when the user requests that the process quit + /// and perform a core dump. + public static var quit: Self { .init(rawValue: SIGQUIT) } + /// The `.userDefinedOne` signal is sent to a process to indicate + /// user-defined conditions. + public static var userDefinedOne: Self { .init(rawValue: SIGUSR1) } + /// The `.userDefinedTwo` signal is sent to a process to indicate + /// user-defined conditions. + public static var userDefinedTwo: Self { .init(rawValue: SIGUSR2) } + /// The `.alarm` signal is sent to a process when the corresponding + /// time limit is reached. + public static var alarm: Self { .init(rawValue: SIGALRM) } + /// The `.windowSizeChange` signal is sent to a process when + /// its controlling terminal changes its size (a window change). + public static var windowSizeChange: Self { .init(rawValue: SIGWINCH) } + } + + /// Send the given signal to the child process. + /// - Parameters: + /// - signal: The signal to send. + /// - shouldSendToProcessGroup: Whether this signal should be sent to + /// the entire process group. + public func send(_ signal: Signal, toProcessGroup shouldSendToProcessGroup: Bool) throws { + let pid = shouldSendToProcessGroup ? -(self.processIdentifier.value) : self.processIdentifier.value + guard kill(pid, signal.rawValue) == 0 else { + throw POSIXError(.init(rawValue: errno)!) + } + } + + internal func tryTerminate() -> Error? { + do { + try self.send(.kill, toProcessGroup: true) + } catch { + guard let posixError: POSIXError = error as? POSIXError else { + return error + } + // Ignore ESRCH (no such process) + if posixError.code != .ESRCH { + return error + } + } + return nil + } +} + +// MARK: - Environment Resolution +extension Subprocess.Environment { + internal static let pathEnvironmentVariableName = "PATH" + + internal func pathValue() -> String? { + switch self.config { + case .inherit(let overrides): + // If PATH value exists in overrides, use it + if let value = overrides[.string(Self.pathEnvironmentVariableName)] { + return value.stringValue + } + // Fall back to current process + return ProcessInfo.processInfo.environment[Self.pathEnvironmentVariableName] + case .custom(let fullEnvironment): + if let value = fullEnvironment[.string(Self.pathEnvironmentVariableName)] { + return value.stringValue + } + return nil + } + } + + // This method follows the standard "create" rule: `env` needs to be + // manually deallocated + internal func createEnv() -> [UnsafeMutablePointer?] { + func createFullCString( + fromKey keyContainer: Subprocess.StringOrRawBytes, + value valueContainer: Subprocess.StringOrRawBytes + ) -> UnsafeMutablePointer { + let rawByteKey: UnsafeMutablePointer = keyContainer.createRawBytes() + let rawByteValue: UnsafeMutablePointer = valueContainer.createRawBytes() + defer { + rawByteKey.deallocate() + rawByteValue.deallocate() + } + /// length = `key` + `=` + `value` + `\null` + let totalLength = keyContainer.count + 1 + valueContainer.count + 1 + let fullString: UnsafeMutablePointer = .allocate(capacity: totalLength) + #if canImport(Darwin) + _ = snprintf(ptr: fullString, totalLength, "%s=%s", rawByteKey, rawByteValue) + #else + _ = _shims_snprintf(fullString, CInt(totalLength), "%s=%s", rawByteKey, rawByteValue) + #endif + return fullString + } + + var env: [UnsafeMutablePointer?] = [] + switch self.config { + case .inherit(let updates): + var current = ProcessInfo.processInfo.environment + for (keyContainer, valueContainer) in updates { + if let stringKey = keyContainer.stringValue { + // Remove the value from current to override it + current.removeValue(forKey: stringKey) + } + // Fast path + if case .string(let stringKey) = keyContainer, + case .string(let stringValue) = valueContainer { + let fullString = "\(stringKey)=\(stringValue)" + env.append(strdup(fullString)) + continue + } + + env.append(createFullCString(fromKey: keyContainer, value: valueContainer)) + } + // Add the rest of `current` to env + for (key, value) in current { + let fullString = "\(key)=\(value)" + env.append(strdup(fullString)) + } + case .custom(let customValues): + for (keyContainer, valueContainer) in customValues { + // Fast path + if case .string(let stringKey) = keyContainer, + case .string(let stringValue) = valueContainer { + let fullString = "\(stringKey)=\(stringValue)" + env.append(strdup(fullString)) + continue + } + env.append(createFullCString(fromKey: keyContainer, value: valueContainer)) + } + } + env.append(nil) + return env + } +} + +// MARK: Args Creation +extension Subprocess.Arguments { + // This method follows the standard "create" rule: `args` needs to be + // manually deallocated + internal func createArgs(withExecutablePath executablePath: String) -> [UnsafeMutablePointer?] { + var argv: [UnsafeMutablePointer?] = self.storage.map { $0.createRawBytes() } + // argv[0] = executable path + if let override = self.executablePathOverride { + argv.insert(override.createRawBytes(), at: 0) + } else { + argv.insert(strdup(executablePath), at: 0) + } + argv.append(nil) + return argv + } +} + +// MARK: - ProcessIdentifier +extension Subprocess { + /// A platform independent identifier for a subprocess. + public struct ProcessIdentifier: Sendable, Hashable, Codable { + /// The platform specific process identifier value + public let value: pid_t + + public init(value: pid_t) { + self.value = value + } + } +} + +extension Subprocess.ProcessIdentifier : CustomStringConvertible, CustomDebugStringConvertible { + public var description: String { "\(self.value)" } + + public var debugDescription: String { "\(self.value)" } +} + +// MARK: - Executable Searching +extension Subprocess.Executable { + internal static var defaultSearchPaths: Set { + return Set([ + "/usr/bin", + "/bin", + "/usr/sbin", + "/sbin", + "/usr/local/bin" + ]) + } + + internal func resolveExecutablePath(withPathValue pathValue: String?) -> String? { + switch self.storage { + case .executable(let executableName): + // If the executableName in is already a full path, return it directly + if Subprocess.Configuration.pathAccessible(executableName, mode: X_OK) { + return executableName + } + // Get $PATH from environment + let searchPaths: Set + if let pathValue = pathValue { + let localSearchPaths = pathValue.split(separator: ":").map { String($0) } + searchPaths = Set(localSearchPaths).union(Self.defaultSearchPaths) + } else { + searchPaths = Self.defaultSearchPaths + } + + for path in searchPaths { + let fullPath = "\(path)/\(executableName)" + let fileExists = Subprocess.Configuration.pathAccessible(fullPath, mode: X_OK) + if fileExists { + return fullPath + } + } + case .path(let executablePath): + // Use path directly + return executablePath.string + } + return nil + } +} + +// MARK: - Configuration +extension Subprocess.Configuration { + internal func preSpawn() throws -> ( + executablePath: String, + env: [UnsafeMutablePointer?], + argv: [UnsafeMutablePointer?], + intendedWorkingDir: FilePath, + uidPtr: UnsafeMutablePointer?, + gidPtr: UnsafeMutablePointer?, + supplementaryGroups: [gid_t]? + ) { + // Prepare environment + let env = self.environment.createEnv() + // Prepare executable path + guard let executablePath = self.executable.resolveExecutablePath( + withPathValue: self.environment.pathValue()) else { + for ptr in env { ptr?.deallocate() } + throw CocoaError(.executableNotLoadable, userInfo: [ + .debugDescriptionErrorKey : "\(self.executable.description) is not an executable" + ]) + } + // Prepare arguments + let argv: [UnsafeMutablePointer?] = self.arguments.createArgs(withExecutablePath: executablePath) + // Prepare workingDir + let intendedWorkingDir = self.workingDirectory + guard Self.pathAccessible(intendedWorkingDir.string, mode: F_OK) else { + for ptr in env { ptr?.deallocate() } + for ptr in argv { ptr?.deallocate() } + throw CocoaError(.fileNoSuchFile, userInfo: [ + .debugDescriptionErrorKey : "Failed to set working directory to \(intendedWorkingDir)" + ]) + } + + var uidPtr: UnsafeMutablePointer? = nil + if let userID = self.platformOptions.userID { + uidPtr = .allocate(capacity: 1) + uidPtr?.pointee = userID + } + var gidPtr: UnsafeMutablePointer? = nil + if let groupID = self.platformOptions.groupID { + gidPtr = .allocate(capacity: 1) + gidPtr?.pointee = groupID + } + var supplementaryGroups: [gid_t]? + if let groupsValue = self.platformOptions.supplementaryGroups { + supplementaryGroups = groupsValue + } + return ( + executablePath: executablePath, + env: env, argv: argv, + intendedWorkingDir: intendedWorkingDir, + uidPtr: uidPtr, gidPtr: gidPtr, + supplementaryGroups: supplementaryGroups + ) + } + + internal static func pathAccessible(_ path: String, mode: Int32) -> Bool { + return path.withCString { + return access($0, mode) == 0 + } + } +} + +// MARK: - FileDescriptor extensions +extension FileDescriptor { + internal static func openDevNull( + withAcessMode mode: FileDescriptor.AccessMode + ) throws -> FileDescriptor { + let devnull: FileDescriptor = try .open("/dev/null", mode) + return devnull + } + + internal var platformDescriptor: Subprocess.PlatformFileDescriptor { + return self + } + + internal func readChunk(upToLength maxLength: Int) async throws -> Data? { + return try await withCheckedThrowingContinuation { continuation in + DispatchIO.read( + fromFileDescriptor: self.rawValue, + maxLength: maxLength, + runningHandlerOn: .global() + ) { data, error in + if error != 0 { + continuation.resume(throwing: POSIXError(.init(rawValue: error) ?? .ENODEV)) + return + } + if data.isEmpty { + continuation.resume(returning: nil) + } else { + continuation.resume(returning: Data(data)) + } + } + } + } + + internal func readUntilEOF(upToLength maxLength: Int) async throws -> Data { + return try await withCheckedThrowingContinuation { continuation in + let dispatchIO = DispatchIO( + type: .stream, + fileDescriptor: self.rawValue, + queue: .global() + ) { error in + if error != 0 { + continuation.resume(throwing: POSIXError(.init(rawValue: error) ?? .ENODEV)) + } + } + var buffer: Data = Data() + dispatchIO.read( + offset: 0, + length: maxLength, + queue: .global() + ) { done, data, error in + guard error == 0 else { + continuation.resume(throwing: POSIXError(.init(rawValue: error) ?? .ENODEV)) + return + } + if let data = data { + buffer += Data(data) + } + if done { + dispatchIO.close() + continuation.resume(returning: buffer) + } + } + } + } + + internal func write(_ data: S) async throws where S.Element == UInt8 { + try await withCheckedThrowingContinuation { (continuation: CheckedContinuation) -> Void in + let dispatchData: DispatchData = Array(data).withUnsafeBytes { + return DispatchData(bytes: $0) + } + DispatchIO.write( + toFileDescriptor: self.rawValue, + data: dispatchData, + runningHandlerOn: .global() + ) { _, error in + guard error == 0 else { + continuation.resume( + throwing: POSIXError( + .init(rawValue: error) ?? .ENODEV) + ) + return + } + continuation.resume() + } + } + } +} + +extension Subprocess { + internal typealias PlatformFileDescriptor = FileDescriptor +} + +// MARK: - Read Buffer Size +extension Subprocess { + @inline(__always) + internal static var readBufferSize: Int { +#if canImport(Darwin) + return 16384 +#else + // FIXME: Use Platform.pageSize here + return 4096 +#endif // canImport(Darwin) + } +} + +#endif // canImport(Darwin) || canImport(Glibc) diff --git a/Sources/_Subprocess/Platforms/Subprocess+Windows.swift b/Sources/_Subprocess/Platforms/Subprocess+Windows.swift new file mode 100644 index 00000000..98ec40bf --- /dev/null +++ b/Sources/_Subprocess/Platforms/Subprocess+Windows.swift @@ -0,0 +1,1209 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// +//===----------------------------------------------------------------------===// + +#if canImport(WinSDK) + +import WinSDK +import Dispatch +import SystemPackage +import FoundationEssentials + +// Windows specific implementation +extension Subprocess.Configuration { + internal func spawn( + withInput input: Subprocess.ExecutionInput, + output: Subprocess.ExecutionOutput, + error: Subprocess.ExecutionOutput + ) throws -> Subprocess { + // Spawn differently depending on whether + // we need to spawn as a user + if let userCredentials = self.platformOptions.userCredentials { + return try self.spawnAsUser( + withInput: input, + output: output, + error: error, + userCredentials: userCredentials + ) + } else { + return try self.spawnDirect( + withInput: input, + output: output, + error: error + ) + } + } + + internal func spawnDirect( + withInput input: Subprocess.ExecutionInput, + output: Subprocess.ExecutionOutput, + error: Subprocess.ExecutionOutput + ) throws -> Subprocess { + let ( + applicationName, + commandAndArgs, + environment, + intendedWorkingDir + ) = try self.preSpawn() + var startupInfo = try self.generateStartupInfo( + withInput: input, + output: output, + error: error + ) + var processInfo: PROCESS_INFORMATION = PROCESS_INFORMATION() + var createProcessFlags = self.generateCreateProcessFlag() + // Give calling process a chance to modify flag and startup info + if let configurator = self.platformOptions.preSpawnProcessConfigurator { + try configurator(&createProcessFlags, &startupInfo) + } + // Spawn! + try applicationName.withOptionalNTPathRepresentation { applicationNameW in + try commandAndArgs.withCString( + encodedAs: UTF16.self + ) { commandAndArgsW in + try environment.withCString( + encodedAs: UTF16.self + ) { environmentW in + try intendedWorkingDir.withNTPathRepresentation { intendedWorkingDirW in + let created = CreateProcessW( + applicationNameW, + UnsafeMutablePointer(mutating: commandAndArgsW), + nil, // lpProcessAttributes + nil, // lpThreadAttributes + true, // bInheritHandles + createProcessFlags, + UnsafeMutableRawPointer(mutating: environmentW), + intendedWorkingDirW, + &startupInfo, + &processInfo + ) + guard created else { + let windowsError = GetLastError() + try self.cleanupAll( + input: input, + output: output, + error: error + ) + throw CocoaError.windowsError( + underlying: windowsError, + errorCode: .fileWriteUnknown + ) + } + } + } + } + } + // We don't need the handle objects, so close it right away + guard CloseHandle(processInfo.hThread) else { + let windowsError = GetLastError() + try self.cleanupAll( + input: input, + output: output, + error: error + ) + throw CocoaError.windowsError( + underlying: windowsError, + errorCode: .fileReadUnknown + ) + } + guard CloseHandle(processInfo.hProcess) else { + let windowsError = GetLastError() + try self.cleanupAll( + input: input, + output: output, + error: error + ) + throw CocoaError.windowsError( + underlying: windowsError, + errorCode: .fileReadUnknown + ) + } + let pid = Subprocess.ProcessIdentifier( + processID: processInfo.dwProcessId, + threadID: processInfo.dwThreadId + ) + return Subprocess( + processIdentifier: pid, + executionInput: input, + executionOutput: output, + executionError: error, + consoleBehavior: self.platformOptions.consoleBehavior + ) + } + + internal func spawnAsUser( + withInput input: Subprocess.ExecutionInput, + output: Subprocess.ExecutionOutput, + error: Subprocess.ExecutionOutput, + userCredentials: Subprocess.PlatformOptions.UserCredentials + ) throws -> Subprocess { + let ( + applicationName, + commandAndArgs, + environment, + intendedWorkingDir + ) = try self.preSpawn() + var startupInfo = try self.generateStartupInfo( + withInput: input, + output: output, + error: error + ) + var processInfo: PROCESS_INFORMATION = PROCESS_INFORMATION() + var createProcessFlags = self.generateCreateProcessFlag() + // Give calling process a chance to modify flag and startup info + if let configurator = self.platformOptions.preSpawnProcessConfigurator { + try configurator(&createProcessFlags, &startupInfo) + } + // Spawn (featuring pyamid!) + try userCredentials.username.withCString( + encodedAs: UTF16.self + ) { usernameW in + try userCredentials.password.withCString( + encodedAs: UTF16.self + ) { passwordW in + try userCredentials.domain.withOptionalCString( + encodedAs: UTF16.self + ) { domainW in + try applicationName.withOptionalNTPathRepresentation { applicationNameW in + try commandAndArgs.withCString( + encodedAs: UTF16.self + ) { commandAndArgsW in + try environment.withCString( + encodedAs: UTF16.self + ) { environmentW in + try intendedWorkingDir.withNTPathRepresentation { intendedWorkingDirW in + let created = CreateProcessWithLogonW( + usernameW, + domainW, + passwordW, + DWORD(LOGON_WITH_PROFILE), + applicationNameW, + UnsafeMutablePointer(mutating: commandAndArgsW), + createProcessFlags, + UnsafeMutableRawPointer(mutating: environmentW), + intendedWorkingDirW, + &startupInfo, + &processInfo + ) + guard created else { + let windowsError = GetLastError() + try self.cleanupAll( + input: input, + output: output, + error: error + ) + throw CocoaError.windowsError( + underlying: windowsError, + errorCode: .fileWriteUnknown + ) + } + } + } + } + } + } + } + } + // We don't need the handle objects, so close it right away + guard CloseHandle(processInfo.hThread) else { + let windowsError = GetLastError() + try self.cleanupAll( + input: input, + output: output, + error: error + ) + throw CocoaError.windowsError( + underlying: windowsError, + errorCode: .fileReadUnknown + ) + } + guard CloseHandle(processInfo.hProcess) else { + let windowsError = GetLastError() + try self.cleanupAll( + input: input, + output: output, + error: error + ) + throw CocoaError.windowsError( + underlying: windowsError, + errorCode: .fileReadUnknown + ) + } + let pid = Subprocess.ProcessIdentifier( + processID: processInfo.dwProcessId, + threadID: processInfo.dwThreadId + ) + return Subprocess( + processIdentifier: pid, + executionInput: input, + executionOutput: output, + executionError: error, + consoleBehavior: self.platformOptions.consoleBehavior + ) + } +} + +// MARK: - Platform Specific Options +extension Subprocess { + /// The collection of platform-specific settings + /// to configure the subprocess when running + public struct PlatformOptions: Sendable { + /// A `UserCredentials` to use spawning the subprocess + /// as a different user + public struct UserCredentials: Sendable, Hashable { + // The name of the user. This is the name + // of the user account to run as. + public var username: String + // The clear-text password for the account. + public var password: String + // The name of the domain or server whose account database + // contains the account. + public var domain: String? + } + + /// `ConsoleBehavior` defines how should the console appear + /// when spawning a new process + public struct ConsoleBehavior: Sendable, Hashable { + internal enum Storage: Sendable, Hashable { + case createNew + case detatch + case inherit + } + + internal let storage: Storage + + private init(_ storage: Storage) { + self.storage = storage + } + + /// The subprocess has a new console, instead of + /// inheriting its parent's console (the default). + public static let createNew: Self = .init(.createNew) + /// For console processes, the new process does not + /// inherit its parent's console (the default). + /// The new process can call the `AllocConsole` + /// function at a later time to create a console. + public static let detatch: Self = .init(.detatch) + /// The subprocess inherits its parent's console. + public static let inherit: Self = .init(.inherit) + } + + /// `ConsoleBehavior` defines how should the window appear + /// when spawning a new process + public struct WindowStyle: Sendable, Hashable { + internal enum Storage: Sendable, Hashable { + case normal + case hidden + case maximized + case minimized + } + + internal let storage: Storage + + internal var platformStyle: WORD { + switch self.storage { + case .hidden: return WORD(SW_HIDE) + case .maximized: return WORD(SW_SHOWMAXIMIZED) + case .minimized: return WORD(SW_SHOWMINIMIZED) + default: return WORD(SW_SHOWNORMAL) + } + } + + private init(_ storage: Storage) { + self.storage = storage + } + + /// Activates and displays a window of normal size + public static let normal: Self = .init(.normal) + /// Does not activate a new window + public static let hidden: Self = .init(.hidden) + /// Activates the window and displays it as a maximized window. + public static let maximized: Self = .init(.maximized) + /// Activates the window and displays it as a minimized window. + public static let minimized: Self = .init(.minimized) + } + + /// Sets user credentials when starting the process as another user + public var userCredentials: UserCredentials? = nil + /// The console behavior of the new process, + /// default to inheriting the console from parent process + public var consoleBehavior: ConsoleBehavior = .inherit + /// Window style to use when the process is started + public var windowStyle: WindowStyle = .normal + /// Whether to create a new process group for the new + /// process. The process group includes all processes + /// that are descendants of this root process. + /// The process identifier of the new process group + /// is the same as the process identifier. + public var createProcessGroup: Bool = false + /// A closure to configure platform-specific + /// spawning constructs. This closure enables direct + /// configuration or override of underlying platform-specific + /// spawn settings that `Subprocess` utilizes internally, + /// in cases where Subprocess does not provide higher-level + /// APIs for such modifications. + /// + /// On Windows, Subprocess uses `CreateProcessW()` as the + /// underlying spawning mechanism. This closure allows + /// modification of the `dwCreationFlags` creation flag + /// and startup info `STARTUPINFOW` before + /// they are sent to `CreateProcessW()`. + public var preSpawnProcessConfigurator: ( + @Sendable ( + inout DWORD, + inout STARTUPINFOW + ) throws -> Void + )? = nil + + public init() {} + } +} + +extension Subprocess.PlatformOptions: Hashable { + public static func == ( + lhs: Subprocess.PlatformOptions, + rhs: Subprocess.PlatformOptions + ) -> Bool { + // Since we can't compare closure equality, + // as long as preSpawnProcessConfigurator is set + // always returns false so that `PlatformOptions` + // with it set will never equal to each other + if lhs.preSpawnProcessConfigurator != nil || rhs.preSpawnProcessConfigurator != nil { + return false + } + return lhs.userCredentials == rhs.userCredentials && lhs.consoleBehavior == rhs.consoleBehavior && lhs.windowStyle == rhs.windowStyle && + lhs.createProcessGroup == rhs.createProcessGroup + } + + public func hash(into hasher: inout Hasher) { + hasher.combine(userCredentials) + hasher.combine(consoleBehavior) + hasher.combine(windowStyle) + hasher.combine(createProcessGroup) + // Since we can't really hash closures, + // use an UUID such that as long as + // `preSpawnProcessConfigurator` is set, it will + // never equal to other PlatformOptions + if self.preSpawnProcessConfigurator != nil { + hasher.combine(UUID()) + } + } +} + +extension Subprocess.PlatformOptions : CustomStringConvertible, CustomDebugStringConvertible { + internal func description(withIndent indent: Int) -> String { + let indent = String(repeating: " ", count: indent * 4) + return """ +PlatformOptions( +\(indent) userCredentials: \(String(describing: self.userCredentials)), +\(indent) consoleBehavior: \(String(describing: self.consoleBehavior)), +\(indent) windowStyle: \(String(describing: self.windowStyle)), +\(indent) createProcessGroup: \(self.createProcessGroup), +\(indent) preSpawnProcessConfigurator: \(self.preSpawnProcessConfigurator == nil ? "not set" : "set") +\(indent)) +""" + } + + public var description: String { + return self.description(withIndent: 0) + } + + public var debugDescription: String { + return self.description(withIndent: 0) + } +} + +// MARK: - Process Monitoring +@Sendable +internal func monitorProcessTermination( + forProcessWithIdentifier pid: Subprocess.ProcessIdentifier +) async throws -> Subprocess.TerminationStatus { + // Once the continuation resumes, it will need to unregister the wait, so + // yield the wait handle back to the calling scope. + var waitHandle: HANDLE? + defer { + if let waitHandle { + _ = UnregisterWait(waitHandle) + } + } + guard let processHandle = OpenProcess( + DWORD(PROCESS_QUERY_INFORMATION | SYNCHRONIZE), + false, + pid.processID + ) else { + return .exited(1) + } + + try? await withCheckedThrowingContinuation { (continuation: CheckedContinuation) in + // Set up a callback that immediately resumes the continuation and does no + // other work. + let context = Unmanaged.passRetained(continuation as AnyObject).toOpaque() + let callback: WAITORTIMERCALLBACK = { context, _ in + let continuation = Unmanaged.fromOpaque(context!).takeRetainedValue() as! CheckedContinuation + continuation.resume() + } + + // We only want the callback to fire once (and not be rescheduled.) Waiting + // may take an arbitrarily long time, so let the thread pool know that too. + let flags = ULONG(WT_EXECUTEONLYONCE | WT_EXECUTELONGFUNCTION) + guard RegisterWaitForSingleObject( + &waitHandle, processHandle, callback, context, INFINITE, flags + ) else { + continuation.resume(throwing: CocoaError.windowsError( + underlying: GetLastError(), + errorCode: .fileWriteUnknown) + ) + return + } + } + + var status: DWORD = 0 + guard GetExitCodeProcess(processHandle, &status) else { + // The child process terminated but we couldn't get its status back. + // Assume generic failure. + return .exited(1) + } + let exitCodeValue = CInt(bitPattern: .init(status)) + if exitCodeValue >= 0 { + return .exited(status) + } else { + return .unhandledException(status) + } +} + +// MARK: - Subprocess Control +extension Subprocess { + /// Terminate the current subprocess with the given exit code + /// - Parameter exitCode: The exit code to use for the subprocess. + public func terminate(withExitCode exitCode: DWORD) throws { + guard let processHandle = OpenProcess( + // PROCESS_ALL_ACCESS + DWORD(STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xFFFF), + false, + self.processIdentifier.processID + ) else { + throw CocoaError.windowsError( + underlying: GetLastError(), + errorCode: .fileWriteUnknown + ) + } + defer { + CloseHandle(processHandle) + } + guard TerminateProcess(processHandle, exitCode) else { + throw CocoaError.windowsError( + underlying: GetLastError(), + errorCode: .fileWriteUnknown + ) + } + } + + /// Suspend the current subprocess + public func suspend() throws { + guard let processHandle = OpenProcess( + // PROCESS_ALL_ACCESS + DWORD(STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xFFFF), + false, + self.processIdentifier.processID + ) else { + throw CocoaError.windowsError( + underlying: GetLastError(), + errorCode: .fileWriteUnknown + ) + } + defer { + CloseHandle(processHandle) + } + + let NTSuspendProcess: Optional<(@convention(c) (HANDLE) -> LONG)> = + unsafeBitCast( + GetProcAddress( + GetModuleHandleA("ntdll.dll"), + "NtSuspendProcess" + ), + to: Optional<(@convention(c) (HANDLE) -> LONG)>.self + ) + guard let NTSuspendProcess = NTSuspendProcess else { + throw CocoaError(.executableNotLoadable) + } + guard NTSuspendProcess(processHandle) >= 0 else { + throw CocoaError.windowsError( + underlying: GetLastError(), + errorCode: .fileWriteUnknown + ) + } + } + + /// Resume the current subprocess after suspension + public func resume() throws { + guard let processHandle = OpenProcess( + // PROCESS_ALL_ACCESS + DWORD(STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xFFFF), + false, + self.processIdentifier.processID + ) else { + throw CocoaError.windowsError( + underlying: GetLastError(), + errorCode: .fileWriteUnknown + ) + } + defer { + CloseHandle(processHandle) + } + + let NTResumeProcess: Optional<(@convention(c) (HANDLE) -> LONG)> = + unsafeBitCast( + GetProcAddress( + GetModuleHandleA("ntdll.dll"), + "NtResumeProcess" + ), + to: Optional<(@convention(c) (HANDLE) -> LONG)>.self + ) + guard let NTResumeProcess = NTResumeProcess else { + throw CocoaError(.executableNotLoadable) + } + guard NTResumeProcess(processHandle) >= 0 else { + throw CocoaError.windowsError( + underlying: GetLastError(), + errorCode: .fileWriteUnknown + ) + } + } + + internal func tryTerminate() -> Error? { + do { + try self.terminate(withExitCode: 0) + } catch { + return error + } + return nil + } +} + +// MARK: - Executable Searching +extension Subprocess.Executable { + // Technically not needed for CreateProcess since + // it takes process name. It's here to support + // Executable.resolveExecutablePath + internal func resolveExecutablePath(withPathValue pathValue: String?) -> String? { + switch self.storage { + case .executable(let executableName): + return executableName.withCString( + encodedAs: UTF16.self + ) { exeName -> String? in + return pathValue.withOptionalCString( + encodedAs: UTF16.self + ) { path -> String? in + let pathLenth = SearchPathW( + path, + exeName, + nil, 0, nil, nil + ) + guard pathLenth > 0 else { + return nil + } + return withUnsafeTemporaryAllocation( + of: WCHAR.self, capacity: Int(pathLenth) + 1 + ) { + _ = SearchPathW( + path, + exeName, nil, + pathLenth + 1, + $0.baseAddress, nil + ) + return String(decodingCString: $0.baseAddress!, as: UTF16.self) + } + } + } + case .path(let executablePath): + // Use path directly + return executablePath.string + } + } +} + +// MARK: - Environment Resolution +extension Subprocess.Environment { + internal static let pathEnvironmentVariableName = "Path" + + internal func pathValue() -> String? { + switch self.config { + case .inherit(let overrides): + // If PATH value exists in overrides, use it + if let value = overrides[.string(Self.pathEnvironmentVariableName)] { + return value.stringValue + } + // Fall back to current process + return ProcessInfo.processInfo.environment[Self.pathEnvironmentVariableName] + case .custom(let fullEnvironment): + if let value = fullEnvironment[.string(Self.pathEnvironmentVariableName)] { + return value.stringValue + } + return nil + } + } +} + +// MARK: - ProcessIdentifier +extension Subprocess { + /// A platform independent identifier for a subprocess. + public struct ProcessIdentifier: Sendable, Hashable, Codable { + /// Windows specifc process identifier value + public let processID: DWORD + /// Windows specific thread identifier associated with process + public let threadID: DWORD + + internal init( + processID: DWORD, + threadID: DWORD + ) { + self.processID = processID + self.threadID = threadID + } + } +} + +extension Subprocess.ProcessIdentifier: CustomStringConvertible, CustomDebugStringConvertible { + public var description: String { + return "(processID: \(self.processID), threadID: \(self.threadID))" + } + + public var debugDescription: String { + return description + } +} + +// MARK: - Private Utils +extension Subprocess.Configuration { + private func preSpawn() throws -> ( + applicationName: String?, + commandAndArgs: String, + environment: String, + intendedWorkingDir: String + ) { + // Prepare environment + var env: [String : String] = [:] + switch self.environment.config { + case .custom(let customValues): + // Use the custom values directly + for customKey in customValues.keys { + guard case .string(let stringKey) = customKey, + let valueContainer = customValues[customKey], + case .string(let stringValue) = valueContainer else { + fatalError("Windows does not support non unicode String as environments") + } + env.updateValue(stringValue, forKey: stringKey) + } + case .inherit(let updateValues): + // Combine current environment + env = ProcessInfo.processInfo.environment + for updatingKey in updateValues.keys { + // Override the current environment values + guard case .string(let stringKey) = updatingKey, + let valueContainer = updateValues[updatingKey], + case .string(let stringValue) = valueContainer else { + fatalError("Windows does not support non unicode String as environments") + } + env.updateValue(stringValue, forKey: stringKey) + } + } + // On Windows, the PATH is required in order to locate dlls needed by + // the process so we should also pass that to the child + let pathVariableName = Subprocess.Environment.pathEnvironmentVariableName + if env[pathVariableName] == nil, + let parentPath = ProcessInfo.processInfo.environment[pathVariableName] { + env[pathVariableName] = parentPath + } + // The environment string must be terminated by a double + // null-terminator. Otherwise, CreateProcess will fail with + // INVALID_PARMETER. + let environmentString = env.map { + $0.key + "=" + $0.value + }.joined(separator: "\0") + "\0\0" + + // Prepare arguments + let ( + applicationName, + commandAndArgs + ) = try self.generateWindowsCommandAndAgruments() + // Validate workingDir + guard Self.pathAccessible(self.workingDirectory.string) else { + throw CocoaError(.fileNoSuchFile, userInfo: [ + .debugDescriptionErrorKey : "Failed to set working directory to \(self.workingDirectory)" + ]) + } + return ( + applicationName: applicationName, + commandAndArgs: commandAndArgs, + environment: environmentString, + intendedWorkingDir: self.workingDirectory.string + ) + } + + private func generateCreateProcessFlag() -> DWORD { + var flags = CREATE_UNICODE_ENVIRONMENT + switch self.platformOptions.consoleBehavior.storage { + case .createNew: + flags |= CREATE_NEW_CONSOLE + case .detatch: + flags |= DETACHED_PROCESS + case .inherit: + break + } + if self.platformOptions.createProcessGroup { + flags |= CREATE_NEW_PROCESS_GROUP + } + return DWORD(flags) + } + + private func generateStartupInfo( + withInput input: Subprocess.ExecutionInput, + output: Subprocess.ExecutionOutput, + error: Subprocess.ExecutionOutput + ) throws -> STARTUPINFOW { + var info: STARTUPINFOW = STARTUPINFOW() + info.cb = DWORD(MemoryLayout.size) + info.dwFlags |= DWORD(STARTF_USESTDHANDLES) + + if self.platformOptions.windowStyle.storage != .normal { + info.wShowWindow = self.platformOptions.windowStyle.platformStyle + info.dwFlags |= DWORD(STARTF_USESHOWWINDOW) + } + // Bind IOs + // Input + if let inputRead = input.getReadFileDescriptor() { + info.hStdInput = inputRead.platformDescriptor + } + if let inputWrite = input.getWriteFileDescriptor() { + // Set parent side to be uninhertable + SetHandleInformation( + inputWrite.platformDescriptor, + DWORD(HANDLE_FLAG_INHERIT), + 0 + ) + } + // Output + if let outputWrite = output.getWriteFileDescriptor() { + info.hStdOutput = outputWrite.platformDescriptor + } + if let outputRead = output.getReadFileDescriptor() { + // Set parent side to be uninhertable + SetHandleInformation( + outputRead.platformDescriptor, + DWORD(HANDLE_FLAG_INHERIT), + 0 + ) + } + // Error + if let errorWrite = error.getWriteFileDescriptor() { + info.hStdError = errorWrite.platformDescriptor + } + if let errorRead = error.getReadFileDescriptor() { + // Set parent side to be uninhertable + SetHandleInformation( + errorRead.platformDescriptor, + DWORD(HANDLE_FLAG_INHERIT), + 0 + ) + } + return info + } + + private func generateWindowsCommandAndAgruments() throws -> ( + applicationName: String?, + commandAndArgs: String + ) { + // CreateProcess accepts partial names + let executableNameOrPath: String + switch self.executable.storage { + case .path(let path): + executableNameOrPath = path.string + case .executable(let name): + // Technically CreateProcessW accepts just the name + // of the executable, therefore we don't need to + // actually resolve the path. However, to maintain + // the same behavior as other platforms, still check + // here to make sure the executable actually exists + guard self.executable.resolveExecutablePath( + withPathValue: self.environment.pathValue() + ) != nil else { + throw CocoaError(.executableNotLoadable, userInfo: [ + .debugDescriptionErrorKey : "\(self.executable.description) is not an executable" + ]) + } + executableNameOrPath = name + } + var args = self.arguments.storage.map { + guard case .string(let stringValue) = $0 else { + // We should never get here since the API + // is guarded off + fatalError("Windows does not support non unicode String as arguments") + } + return stringValue + } + // The first parameter of CreateProcessW, `lpApplicationName` + // is optional. If it's nil, CreateProcessW uses argument[0] + // as the execuatble name. + // We should only set lpApplicationName if it's different from + // argument[0] (i.e. executablePathOverride) + var applicationName: String? = nil + if case .string(let overrideName) = self.arguments.executablePathOverride { + // Use the override as argument0 and set applicationName + args.insert(overrideName, at: 0) + applicationName = executableNameOrPath + } else { + // Set argument[0] to be executableNameOrPath + args.insert(executableNameOrPath, at: 0) + } + return ( + applicationName: applicationName, + commandAndArgs: self.quoteWindowsCommandLine(args) + ) + } + + // Taken from SCF + private func quoteWindowsCommandLine(_ commandLine: [String]) -> String { + func quoteWindowsCommandArg(arg: String) -> String { + // Windows escaping, adapted from Daniel Colascione's "Everyone quotes + // command line arguments the wrong way" - Microsoft Developer Blog + if !arg.contains(where: {" \t\n\"".contains($0)}) { + return arg + } + + // To escape the command line, we surround the argument with quotes. However + // the complication comes due to how the Windows command line parser treats + // backslashes (\) and quotes (") + // + // - \ is normally treated as a literal backslash + // - e.g. foo\bar\baz => foo\bar\baz + // - However, the sequence \" is treated as a literal " + // - e.g. foo\"bar => foo"bar + // + // But then what if we are given a path that ends with a \? Surrounding + // foo\bar\ with " would be "foo\bar\" which would be an unterminated string + + // since it ends on a literal quote. To allow this case the parser treats: + // + // - \\" as \ followed by the " metachar + // - \\\" as \ followed by a literal " + // - In general: + // - 2n \ followed by " => n \ followed by the " metachar + // - 2n+1 \ followed by " => n \ followed by a literal " + var quoted = "\"" + var unquoted = arg.unicodeScalars + + while !unquoted.isEmpty { + guard let firstNonBackslash = unquoted.firstIndex(where: { $0 != "\\" }) else { + // String ends with a backslash e.g. foo\bar\, escape all the backslashes + // then add the metachar " below + let backslashCount = unquoted.count + quoted.append(String(repeating: "\\", count: backslashCount * 2)) + break + } + let backslashCount = unquoted.distance(from: unquoted.startIndex, to: firstNonBackslash) + if (unquoted[firstNonBackslash] == "\"") { + // This is a string of \ followed by a " e.g. foo\"bar. Escape the + // backslashes and the quote + quoted.append(String(repeating: "\\", count: backslashCount * 2 + 1)) + quoted.append(String(unquoted[firstNonBackslash])) + } else { + // These are just literal backslashes + quoted.append(String(repeating: "\\", count: backslashCount)) + quoted.append(String(unquoted[firstNonBackslash])) + } + // Drop the backslashes and the following character + unquoted.removeFirst(backslashCount + 1) + } + quoted.append("\"") + return quoted + } + return commandLine.map(quoteWindowsCommandArg).joined(separator: " ") + } + + private static func pathAccessible(_ path: String) -> Bool { + return path.withCString(encodedAs: UTF16.self) { + let attrs = GetFileAttributesW($0) + return attrs != INVALID_FILE_ATTRIBUTES + } + } +} + +// MARK: - PlatformFileDescriptor Type +extension Subprocess { + internal typealias PlatformFileDescriptor = HANDLE +} + +// MARK: - Read Buffer Size +extension Subprocess { + @inline(__always) + internal static var readBufferSize: Int { + // FIXME: Use Platform.pageSize here + var sysInfo: SYSTEM_INFO = SYSTEM_INFO() + GetSystemInfo(&sysInfo) + return Int(sysInfo.dwPageSize) + } +} + +// MARK: - Pipe Support +extension FileDescriptor { + internal static func pipe() throws -> ( + readEnd: FileDescriptor, + writeEnd: FileDescriptor + ) { + var saAttributes: SECURITY_ATTRIBUTES = SECURITY_ATTRIBUTES() + saAttributes.nLength = DWORD(MemoryLayout.size) + saAttributes.bInheritHandle = true + saAttributes.lpSecurityDescriptor = nil + + var readHandle: HANDLE? = nil + var writeHandle: HANDLE? = nil + guard CreatePipe(&readHandle, &writeHandle, &saAttributes, 0), + readHandle != INVALID_HANDLE_VALUE, + writeHandle != INVALID_HANDLE_VALUE, + let readHandle: HANDLE = readHandle, + let writeHandle: HANDLE = writeHandle else { + throw CocoaError.windowsError( + underlying: GetLastError(), + errorCode: .fileReadUnknown + ) + } + let readFd = _open_osfhandle( + intptr_t(bitPattern: readHandle), + FileDescriptor.AccessMode.readOnly.rawValue + ) + let writeFd = _open_osfhandle( + intptr_t(bitPattern: writeHandle), + FileDescriptor.AccessMode.writeOnly.rawValue + ) + + return ( + readEnd: FileDescriptor(rawValue: readFd), + writeEnd: FileDescriptor(rawValue: writeFd) + ) + } + + internal static func openDevNull( + withAcessMode mode: FileDescriptor.AccessMode + ) throws -> FileDescriptor { + return try "NUL".withPlatformString { + let handle = CreateFileW( + $0, + DWORD(GENERIC_WRITE), + DWORD(FILE_SHARE_WRITE), + nil, + DWORD(OPEN_EXISTING), + DWORD(FILE_ATTRIBUTE_NORMAL), + nil + ) + guard let handle = handle, + handle != INVALID_HANDLE_VALUE else { + throw CocoaError.windowsError( + underlying: GetLastError(), + errorCode: .fileReadUnknown + ) + } + let devnull = _open_osfhandle( + intptr_t(bitPattern: handle), + mode.rawValue + ) + return FileDescriptor(rawValue: devnull) + } + } + + var platformDescriptor: Subprocess.PlatformFileDescriptor { + return HANDLE(bitPattern: _get_osfhandle(self.rawValue))! + } + + internal func read(upToLength maxLength: Int) async throws -> Data { + // TODO: Figure out a better way to asynchornously read + return try await withCheckedThrowingContinuation { continuation in + DispatchQueue.global(qos: .userInitiated).async { + var totalBytesRead: Int = 0 + var lastError: DWORD? = nil + let values = Array( + unsafeUninitializedCapacity: maxLength + ) { buffer, initializedCount in + while true { + guard let baseAddress = buffer.baseAddress else { + initializedCount = 0 + break + } + let bufferPtr = baseAddress.advanced(by: totalBytesRead) + var bytesRead: DWORD = 0 + let readSucceed = ReadFile( + self.platformDescriptor, + UnsafeMutableRawPointer(mutating: bufferPtr), + DWORD(maxLength - totalBytesRead), + &bytesRead, + nil + ) + if !readSucceed { + // Windows throws ERROR_BROKEN_PIPE when the pipe is closed + let error = GetLastError() + if error == ERROR_BROKEN_PIPE { + // We are done reading + initializedCount = totalBytesRead + } else { + // We got some error + lastError = error + initializedCount = 0 + } + break + } else { + // We succesfully read the current round + totalBytesRead += Int(bytesRead) + } + + if totalBytesRead >= maxLength { + initializedCount = min(maxLength, totalBytesRead) + break + } + } + } + if let lastError = lastError { + continuation.resume(throwing: CocoaError.windowsError( + underlying: lastError, + errorCode: .fileReadUnknown) + ) + } else { + continuation.resume(returning: Data(values)) + } + } + } + } + + internal func write(_ data: S) async throws where S.Element == UInt8 { + // TODO: Figure out a better way to asynchornously write + try await withCheckedThrowingContinuation { ( + continuation: CheckedContinuation + ) -> Void in + DispatchQueue.global(qos: .userInitiated).async { + let buffer = Array(data) + buffer.withUnsafeBytes { ptr in + var writtenBytes: DWORD = 0 + let writeSucceed = WriteFile( + self.platformDescriptor, + ptr.baseAddress, + DWORD(buffer.count), + &writtenBytes, + nil + ) + if !writeSucceed { + continuation.resume(throwing: CocoaError.windowsError( + underlying: GetLastError(), + errorCode: .fileWriteUnknown) + ) + } else { + continuation.resume() + } + } + } + } + } +} + +extension String { + static let debugDescriptionErrorKey = "DebugDescription" +} + +// MARK: - CocoaError + Win32 +internal let NSUnderlyingErrorKey = "NSUnderlyingError" + +extension CocoaError { + static func windowsError(underlying: DWORD, errorCode: Code) -> CocoaError { + let userInfo = [ + NSUnderlyingErrorKey : Win32Error(underlying) + ] + return CocoaError(errorCode, userInfo: userInfo) + } +} + +private extension Optional where Wrapped == String { + func withOptionalCString( + encodedAs targetEncoding: Encoding.Type, + _ body: (UnsafePointer?) throws -> Result + ) rethrows -> Result where Encoding : _UnicodeEncoding { + switch self { + case .none: + return try body(nil) + case .some(let value): + return try value.withCString(encodedAs: targetEncoding, body) + } + } + + func withOptionalNTPathRepresentation( + _ body: (UnsafePointer?) throws -> Result + ) throws -> Result { + switch self { + case .none: + return try body(nil) + case .some(let value): + return try value.withNTPathRepresentation(body) + } + } +} + +// MARK: - Remove these when merging back to SwiftFoundation +extension String { + internal func withNTPathRepresentation( + _ body: (UnsafePointer) throws -> Result + ) throws -> Result { + guard !isEmpty else { + throw CocoaError(.fileReadInvalidFileName) + } + + var iter = self.utf8.makeIterator() + let bLeadingSlash = if [._slash, ._backslash].contains(iter.next()), iter.next()?.isLetter ?? false, iter.next() == ._colon { true } else { false } + + // Strip the leading `/` on a RFC8089 path (`/[drive-letter]:/...` ). A + // leading slash indicates a rooted path on the drive for the current + // working directory. + return try Substring(self.utf8.dropFirst(bLeadingSlash ? 1 : 0)).withCString(encodedAs: UTF16.self) { pwszPath in + // 1. Normalize the path first. + let dwLength: DWORD = GetFullPathNameW(pwszPath, 0, nil, nil) + return try withUnsafeTemporaryAllocation(of: WCHAR.self, capacity: Int(dwLength)) { + guard GetFullPathNameW(pwszPath, DWORD($0.count), $0.baseAddress, nil) > 0 else { + throw CocoaError.windowsError( + underlying: GetLastError(), + errorCode: .fileReadUnknown + ) + } + + // 2. Perform the operation on the normalized path. + return try body($0.baseAddress!) + } + } + } +} + +struct Win32Error: Error { + public typealias Code = DWORD + public let code: Code + + public static var errorDomain: String { + return "NSWin32ErrorDomain" + } + + public init(_ code: Code) { + self.code = code + } +} + +internal extension UInt8 { + static var _slash: UInt8 { UInt8(ascii: "/") } + static var _backslash: UInt8 { UInt8(ascii: "\\") } + static var _colon: UInt8 { UInt8(ascii: ":") } + + var isLetter: Bool? { + return (0x41 ... 0x5a) ~= self || (0x61 ... 0x7a) ~= self + } +} + +#endif // canImport(WinSDK) diff --git a/Sources/_Subprocess/Subprocess+API.swift b/Sources/_Subprocess/Subprocess+API.swift new file mode 100644 index 00000000..b202fedf --- /dev/null +++ b/Sources/_Subprocess/Subprocess+API.swift @@ -0,0 +1,462 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// +//===----------------------------------------------------------------------===// + +import SystemPackage +#if canImport(FoundationEssentials) +import FoundationEssentials +#elseif canImport(Foundation) +import Foundation +#endif + +extension Subprocess { + /// Run a executable with given parameters and capture its + /// standard output and standard error. + /// - Parameters: + /// - executable: The executable to run. + /// - arguments: The arguments to pass to the executable. + /// - environment: The environment to use for the process. + /// - workingDirectory: The working directory to use for the subprocess. + /// - platformOptions: The platform specific options to use + /// when running the executable. + /// - input: The input to send to the executable. + /// - output: The method to use for collecting the standard output. + /// - error: The method to use for collecting the standard error. + /// - Returns: `CollectedResult` which contains process identifier, + /// termination status, captured standard output and standard error. + public static func run( + _ executable: Executable, + arguments: Arguments = [], + environment: Environment = .inherit, + workingDirectory: FilePath? = nil, + platformOptions: PlatformOptions = PlatformOptions(), + input: InputMethod = .noInput, + output: CollectedOutputMethod = .collect(), + error: CollectedOutputMethod = .collect() + ) async throws -> CollectedResult { + let result = try await self.run( + executable, + arguments: arguments, + environment: environment, + workingDirectory: workingDirectory, + platformOptions: platformOptions, + input: input, + output: .init(method: output.method), + error: .init(method: error.method) + ) { subprocess in + let (standardOutput, standardError) = try await subprocess.captureIOs() + return ( + processIdentifier: subprocess.processIdentifier, + standardOutput: standardOutput, + standardError: standardError + ) + } + return CollectedResult( + processIdentifier: result.value.processIdentifier, + terminationStatus: result.terminationStatus, + standardOutput: result.value.standardOutput, + standardError: result.value.standardError + ) + } + + /// Run a executable with given parameters and capture its + /// standard output and standard error. + /// - Parameters: + /// - executable: The executable to run. + /// - arguments: The arguments to pass to the executable. + /// - environment: The environment to use for the process. + /// - workingDirectory: The working directory to use for the subprocess. + /// - platformOptions: The platform specific options to use + /// when running the executable. + /// - input: The input to send to the executable. + /// - output: The method to use for collecting the standard output. + /// - error: The method to use for collecting the standard error. + /// - Returns: `CollectedResult` which contains process identifier, + /// termination status, captured standard output and standard error. + public static func run( + _ executable: Executable, + arguments: Arguments = [], + environment: Environment = .inherit, + workingDirectory: FilePath? = nil, + platformOptions: PlatformOptions = PlatformOptions(), + input: some Sequence, + output: CollectedOutputMethod = .collect(), + error: CollectedOutputMethod = .collect() + ) async throws -> CollectedResult { + let result = try await self.run( + executable, + arguments: arguments, + environment: environment, + workingDirectory: workingDirectory, + platformOptions: platformOptions, + output: .init(method: output.method), + error: .init(method: output.method) + ) { subprocess, writer in + return try await withThrowingTaskGroup(of: CapturedIOs?.self) { group in + group.addTask { + try await writer.write(input) + try await writer.finish() + return nil + } + group.addTask { + return try await subprocess.captureIOs() + } + var capturedIOs: CapturedIOs! + while let result = try await group.next() { + if result != nil { + capturedIOs = result + } + } + return ( + processIdentifier: subprocess.processIdentifier, + standardOutput: capturedIOs.standardOutput, + standardError: capturedIOs.standardError + ) + } + } + return CollectedResult( + processIdentifier: result.value.processIdentifier, + terminationStatus: result.terminationStatus, + standardOutput: result.value.standardOutput, + standardError: result.value.standardError + ) + } + + /// Run a executable with given parameters and capture its + /// standard output and standard error. + /// - Parameters: + /// - executable: The executable to run. + /// - arguments: The arguments to pass to the executable. + /// - environment: The environment to use for the process. + /// - workingDirectory: The working directory to use for the subprocess. + /// - platformOptions: The platform specific options to use + /// when running the executable. + /// - input: The input to send to the executable. + /// - output: The method to use for collecting the standard output. + /// - error: The method to use for collecting the standard error. + /// - Returns: `CollectedResult` which contains process identifier, + /// termination status, captured standard output and standard error. + public static func run( + _ executable: Executable, + arguments: Arguments = [], + environment: Environment = .inherit, + workingDirectory: FilePath? = nil, + platformOptions: PlatformOptions = PlatformOptions(), + input: S, + output: CollectedOutputMethod = .collect(), + error: CollectedOutputMethod = .collect() + ) async throws -> CollectedResult where S.Element == UInt8 { + let result = try await self.run( + executable, + arguments: arguments, + environment: environment, + workingDirectory: workingDirectory, + platformOptions: platformOptions, + output: .init(method: output.method), + error: .init(method: output.method) + ) { subprocess, writer in + return try await withThrowingTaskGroup(of: CapturedIOs?.self) { group in + group.addTask { + try await writer.write(input) + try await writer.finish() + return nil + } + group.addTask { + return try await subprocess.captureIOs() + } + var capturedIOs: CapturedIOs! + while let result = try await group.next() { + capturedIOs = result + } + return ( + processIdentifier: subprocess.processIdentifier, + standardOutput: capturedIOs.standardOutput, + standardError: capturedIOs.standardError + ) + } + } + return CollectedResult( + processIdentifier: result.value.processIdentifier, + terminationStatus: result.terminationStatus, + standardOutput: result.value.standardOutput, + standardError: result.value.standardError + ) + } +} + +// MARK: Custom Execution Body +extension Subprocess { + /// Run a executable with given parameters and a custom closure + /// to manage the running subprocess' lifetime and its IOs. + /// - Parameters: + /// - executable: The executable to run. + /// - arguments: The arguments to pass to the executable. + /// - environment: The environment in which to run the executable. + /// - workingDirectory: The working directory in which to run the executable. + /// - platformOptions: The platform specific options to use + /// when running the executable. + /// - input: The input to send to the executable. + /// - output: The method to use for redirecting the standard output. + /// - error: The method to use for redirecting the standard error. + /// - body: The custom execution body to manually control the running process + /// - Returns a ExecutableResult type containing the return value + /// of the closure. + public static func run( + _ executable: Executable, + arguments: Arguments = [], + environment: Environment = .inherit, + workingDirectory: FilePath? = nil, + platformOptions: PlatformOptions = PlatformOptions(), + input: InputMethod = .noInput, + output: RedirectedOutputMethod = .redirectToSequence, + error: RedirectedOutputMethod = .redirectToSequence, + _ body: (sending @escaping (Subprocess) async throws -> R) + ) async throws -> ExecutionResult { + return try await Configuration( + executable: executable, + arguments: arguments, + environment: environment, + workingDirectory: workingDirectory, + platformOptions: platformOptions + ) + .run(input: input, output: output, error: error, body) + } + + /// Run a executable with given parameters and a custom closure + /// to manage the running subprocess' lifetime and its IOs. + /// - Parameters: + /// - executable: The executable to run. + /// - arguments: The arguments to pass to the executable. + /// - environment: The environment in which to run the executable. + /// - workingDirectory: The working directory in which to run the executable. + /// - platformOptions: The platform specific options to use + /// when running the executable. + /// - input: The input to send to the executable. + /// - output: The method to use for redirecting the standard output. + /// - error: The method to use for redirecting the standard error. + /// - body: The custom execution body to manually control the running process + /// - Returns a `ExecutableResult` type containing the return value + /// of the closure. + public static func run( + _ executable: Executable, + arguments: Arguments = [], + environment: Environment = .inherit, + workingDirectory: FilePath? = nil, + platformOptions: PlatformOptions = PlatformOptions(), + input: some Sequence, + output: RedirectedOutputMethod = .redirectToSequence, + error: RedirectedOutputMethod = .redirectToSequence, + _ body: (sending @escaping (Subprocess) async throws -> R) + ) async throws -> ExecutionResult { + return try await Configuration( + executable: executable, + arguments: arguments, + environment: environment, + workingDirectory: workingDirectory, + platformOptions: platformOptions + ) + .run(output: output, error: error) { execution, writer in + return try await withThrowingTaskGroup(of: R?.self) { group in + group.addTask { + try await writer.write(input) + try await writer.finish() + return nil + } + group.addTask { + return try await body(execution) + } + var result: R! + while let next = try await group.next() { + result = next + } + return result + } + } + } + + /// Run a executable with given parameters and a custom closure + /// to manage the running subprocess' lifetime and its IOs. + /// - Parameters: + /// - executable: The executable to run. + /// - arguments: The arguments to pass to the executable. + /// - environment: The environment in which to run the executable. + /// - workingDirectory: The working directory in which to run the executable. + /// - platformOptions: The platform specific options to use + /// when running the executable. + /// - input: The input to send to the executable. + /// - output: The method to use for redirecting the standard output. + /// - error: The method to use for redirecting the standard error. + /// - body: The custom execution body to manually control the running process + /// - Returns a `ExecutableResult` type containing the return value + /// of the closure. + public static func run( + _ executable: Executable, + arguments: Arguments = [], + environment: Environment = .inherit, + workingDirectory: FilePath? = nil, + platformOptions: PlatformOptions = PlatformOptions(), + input: S, + output: RedirectedOutputMethod = .redirectToSequence, + error: RedirectedOutputMethod = .redirectToSequence, + _ body: (sending @escaping (Subprocess) async throws -> R) + ) async throws -> ExecutionResult where S.Element == UInt8 { + return try await Configuration( + executable: executable, + arguments: arguments, + environment: environment, + workingDirectory: workingDirectory, + platformOptions: platformOptions + ) + .run(output: output, error: error) { execution, writer in + return try await withThrowingTaskGroup(of: R?.self) { group in + group.addTask { + try await writer.write(input) + try await writer.finish() + return nil + } + group.addTask { + return try await body(execution) + } + var result: R! + while let next = try await group.next() { + result = next + } + return result + } + } + } + + /// Run a executable with given parameters and a custom closure + /// to manage the running subprocess' lifetime and write to its + /// standard input via `StandardInputWriter` + /// - Parameters: + /// - executable: The executable to run. + /// - arguments: The arguments to pass to the executable. + /// - environment: The environment in which to run the executable. + /// - workingDirectory: The working directory in which to run the executable. + /// - platformOptions: The platform specific options to use + /// when running the executable. + /// - output: The method to use for redirecting the standard output. + /// - error: The method to use for redirecting the standard error. + /// - body: The custom execution body to manually control the running process + /// - Returns a ExecutableResult type containing the return value + /// of the closure. + public static func run( + _ executable: Executable, + arguments: Arguments = [], + environment: Environment = .inherit, + workingDirectory: FilePath? = nil, + platformOptions: PlatformOptions = PlatformOptions(), + output: RedirectedOutputMethod = .redirectToSequence, + error: RedirectedOutputMethod = .redirectToSequence, + _ body: (sending @escaping (Subprocess, StandardInputWriter) async throws -> R) + ) async throws -> ExecutionResult { + return try await Configuration( + executable: executable, + arguments: arguments, + environment: environment, + workingDirectory: workingDirectory, + platformOptions: platformOptions + ) + .run(output: output, error: error, body) + } +} + +// MARK: - Configuration Based +extension Subprocess { + /// Run a executable with given parameters specified by a + /// `Subprocess.Configuration` + /// - Parameters: + /// - configuration: The `Subprocess` configuration to run. + /// - output: The method to use for redirecting the standard output. + /// - error: The method to use for redirecting the standard error. + /// - body: The custom configuration body to manually control + /// the running process and write to its standard input. + /// - Returns a ExecutableResult type containing the return value + /// of the closure. + public static func run( + _ configuration: Configuration, + output: RedirectedOutputMethod = .redirectToSequence, + error: RedirectedOutputMethod = .redirectToSequence, + _ body: (sending @escaping (Subprocess, StandardInputWriter) async throws -> R) + ) async throws -> ExecutionResult { + return try await configuration.run(output: output, error: error, body) + } +} + +// MARK: - Detached +extension Subprocess { + /// Run a executable with given parameters and return its process + /// identifier immediately without monitoring the state of the + /// subprocess nor waiting until it exits. + /// + /// This method is useful for launching subprocesses that outlive their + /// parents (for example, daemons and trampolines). + /// + /// - Parameters: + /// - executable: The executable to run. + /// - arguments: The arguments to pass to the executable. + /// - environment: The environment to use for the process. + /// - workingDirectory: The working directory for the process. + /// - platformOptions: The platform specific options to use for the process. + /// - input: A file descriptor to bind to the subprocess' standard input. + /// - output: A file descriptor to bind to the subprocess' standard output. + /// - error: A file descriptor to bind to the subprocess' standard error. + /// - Returns: the process identifier for the subprocess. + public static func runDetached( + _ executable: Executable, + arguments: Arguments = [], + environment: Environment = .inherit, + workingDirectory: FilePath? = nil, + platformOptions: PlatformOptions = PlatformOptions(), + input: FileDescriptor? = nil, + output: FileDescriptor? = nil, + error: FileDescriptor? = nil + ) throws -> ProcessIdentifier { + // Create input + let executionInput: ExecutionInput + let executionOutput: ExecutionOutput + let executionError: ExecutionOutput + if let inputFd = input { + executionInput = .init(storage: .fileDescriptor(inputFd, false)) + } else { + let devnull: FileDescriptor = try .openDevNull(withAcessMode: .readOnly) + executionInput = .init(storage: .noInput(devnull)) + } + if let outputFd = output { + executionOutput = .init(storage: .fileDescriptor(outputFd, false)) + } else { + let devnull: FileDescriptor = try .openDevNull(withAcessMode: .writeOnly) + executionOutput = .init(storage: .discarded(devnull)) + } + if let errorFd = error { + executionError = .init( + storage: .fileDescriptor(errorFd, false) + ) + } else { + let devnull: FileDescriptor = try .openDevNull(withAcessMode: .writeOnly) + executionError = .init(storage: .discarded(devnull)) + } + // Spawn! + let config: Configuration = Configuration( + executable: executable, + arguments: arguments, + environment: environment, + workingDirectory: workingDirectory, + platformOptions: platformOptions + ) + return try config.spawn( + withInput: executionInput, + output: executionOutput, + error: executionError + ).processIdentifier + } +} + diff --git a/Sources/_Subprocess/Subprocess+AsyncDataSequence.swift b/Sources/_Subprocess/Subprocess+AsyncDataSequence.swift new file mode 100644 index 00000000..d2026fef --- /dev/null +++ b/Sources/_Subprocess/Subprocess+AsyncDataSequence.swift @@ -0,0 +1,83 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// +//===----------------------------------------------------------------------===// + +import SystemPackage +import Dispatch + +#if canImport(FoundationEssentials) +import FoundationEssentials +#elseif canImport(Foundation) +import Foundation +#endif + +extension Subprocess { + public struct AsyncDataSequence: AsyncSequence, Sendable, _AsyncSequence { + public typealias Error = any Swift.Error + + public typealias Element = Data + + @_nonSendable + public struct Iterator: AsyncIteratorProtocol { + public typealias Element = Data + + private let fileDescriptor: FileDescriptor + private var buffer: [UInt8] + private var currentPosition: Int + private var finished: Bool + + internal init(fileDescriptor: FileDescriptor) { + self.fileDescriptor = fileDescriptor + self.buffer = [] + self.currentPosition = 0 + self.finished = false + } + + public mutating func next() async throws -> Data? { + let data = try await self.fileDescriptor.readChunk( + upToLength: Subprocess.readBufferSize + ) + if data == nil { + // We finished reading. Close the file descriptor now + try self.fileDescriptor.close() + return nil + } + return data + } + } + + private let fileDescriptor: FileDescriptor + + init(fileDescriptor: FileDescriptor) { + self.fileDescriptor = fileDescriptor + } + + public func makeAsyncIterator() -> Iterator { + return Iterator(fileDescriptor: self.fileDescriptor) + } + } +} + +extension RangeReplaceableCollection { + /// Creates a new instance of a collection containing the elements of an asynchronous sequence. + /// + /// - Parameter source: The asynchronous sequence of elements for the new collection. + @inlinable + public init(_ source: Source) async rethrows where Source.Element == Element { + self.init() + for try await item in source { + append(item) + } + } +} + +public protocol _AsyncSequence: AsyncSequence { + associatedtype Error +} diff --git a/Sources/_Subprocess/Subprocess+Configuration.swift b/Sources/_Subprocess/Subprocess+Configuration.swift new file mode 100644 index 00000000..68915eea --- /dev/null +++ b/Sources/_Subprocess/Subprocess+Configuration.swift @@ -0,0 +1,767 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// +//===----------------------------------------------------------------------===// + +@preconcurrency import SystemPackage + + +#if canImport(Darwin) +import Darwin +#elseif canImport(Glibc) +import Glibc +#elseif canImport(WinSDK) +import WinSDK +#endif + +#if canImport(FoundationEssentials) +import FoundationEssentials +#elseif canImport(Foundation) +import Foundation +#endif + +extension Subprocess { + /// A collection of configurations parameters to use when + /// spawning a subprocess. + public struct Configuration: Sendable, Hashable { + + internal enum RunState: Sendable { + case workBody(Result) + case monitorChildProcess(TerminationStatus) + } + + /// The executable to run. + public var executable: Executable + /// The arguments to pass to the executable. + public var arguments: Arguments + /// The environment to use when running the executable. + public var environment: Environment + /// The working directory to use when running the executable. + public var workingDirectory: FilePath + /// The platform specifc options to use when + /// running the subprocess. + public var platformOptions: PlatformOptions + + public init( + executable: Executable, + arguments: Arguments = [], + environment: Environment = .inherit, + workingDirectory: FilePath? = nil, + platformOptions: PlatformOptions = PlatformOptions() + ) { + self.executable = executable + self.arguments = arguments + self.environment = environment + self.workingDirectory = workingDirectory ?? .currentWorkingDirectory + self.platformOptions = platformOptions + } + + /// Close each input individually, and throw the first error if there's multiple errors thrown + @Sendable + private func cleanup( + process: Subprocess, + childSide: Bool, parentSide: Bool, + attemptToTerminateSubProcess: Bool + ) async throws { + guard childSide || parentSide || attemptToTerminateSubProcess else { + return + } + + // Attempt to teardown the subprocess + if attemptToTerminateSubProcess { + await process.teardown( + using: self.platformOptions.teardownSequence + ) + } + + let inputCloseFunc: () throws -> Void + let outputCloseFunc: () throws -> Void + let errorCloseFunc: () throws -> Void + if childSide && parentSide { + // Close all + inputCloseFunc = process.executionInput.closeAll + outputCloseFunc = process.executionOutput.closeAll + errorCloseFunc = process.executionError.closeAll + } else if childSide { + // Close child only + inputCloseFunc = process.executionInput.closeChildSide + outputCloseFunc = process.executionOutput.closeChildSide + errorCloseFunc = process.executionError.closeChildSide + } else { + // Close parent only + inputCloseFunc = process.executionInput.closeParentSide + outputCloseFunc = process.executionOutput.closeParentSide + errorCloseFunc = process.executionError.closeParentSide + } + + var inputError: Error? + var outputError: Error? + var errorError: Error? // lol + do { + try inputCloseFunc() + } catch { + inputError = error + } + + do { + try outputCloseFunc() + } catch { + outputError = error + } + + do { + try errorCloseFunc() + } catch { + errorError = error // lolol + } + + if let inputError = inputError { + throw inputError + } + + if let outputError = outputError { + throw outputError + } + + if let errorError = errorError { + throw errorError + } + } + + /// Close each input individually, and throw the first error if there's multiple errors thrown + @Sendable + internal func cleanupAll( + input: ExecutionInput, + output: ExecutionOutput, + error: ExecutionOutput + ) throws { + var inputError: Error? + var outputError: Error? + var errorError: Error? + + do { + try input.closeAll() + } catch { + inputError = error + } + + do { + try output.closeAll() + } catch { + outputError = error + } + + do { + try error.closeAll() + } catch { + errorError = error + } + + if let inputError = inputError { + throw inputError + } + if let outputError = outputError { + throw outputError + } + if let errorError = errorError { + throw errorError + } + } + + internal func run( + output: RedirectedOutputMethod, + error: RedirectedOutputMethod, + _ body: sending @escaping (Subprocess, StandardInputWriter) async throws -> R + ) async throws -> ExecutionResult { + let (readFd, writeFd) = try FileDescriptor.pipe() + let executionInput: ExecutionInput = .init(storage: .customWrite(readFd, writeFd)) + let executionOutput: ExecutionOutput = try output.createExecutionOutput() + let executionError: ExecutionOutput = try error.createExecutionOutput() + let process: Subprocess = try self.spawn( + withInput: executionInput, + output: executionOutput, + error: executionError) + // After spawn, cleanup child side fds + try await self.cleanup( + process: process, + childSide: true, + parentSide: false, + attemptToTerminateSubProcess: false + ) + return try await withAsyncTaskCancellationHandler { + return try await withThrowingTaskGroup(of: RunState.self) { group in + group.addTask { + let status = try await monitorProcessTermination( + forProcessWithIdentifier: process.processIdentifier) + return .monitorChildProcess(status) + } + group.addTask { + do { + let result = try await body(process, .init(input: executionInput)) + try await self.cleanup( + process: process, + childSide: false, + parentSide: true, + attemptToTerminateSubProcess: false + ) + return .workBody(result) + } catch { + // Cleanup everything + try await self.cleanup( + process: process, + childSide: false, + parentSide: true, + attemptToTerminateSubProcess: false + ) + throw error + } + } + + var result: R! + var terminationStatus: TerminationStatus! + while let state = try await group.next() { + switch state { + case .monitorChildProcess(let status): + // We don't really care about termination status here + terminationStatus = status + case .workBody(let workResult): + result = workResult + } + } + return ExecutionResult(terminationStatus: terminationStatus, value: result) + } + } onCancel: { + // Attempt to terminate the child process + // Since the task has already been cancelled, + // this is the best we can do + try? await self.cleanup( + process: process, + childSide: true, + parentSide: true, + attemptToTerminateSubProcess: true + ) + } + } + + internal func run( + input: InputMethod, + output: RedirectedOutputMethod, + error: RedirectedOutputMethod, + _ body: (sending @escaping (Subprocess) async throws -> R) + ) async throws -> ExecutionResult { + let executionInput = try input.createExecutionInput() + let executionOutput = try output.createExecutionOutput() + let executionError = try error.createExecutionOutput() + let process = try self.spawn( + withInput: executionInput, + output: executionOutput, + error: executionError) + // After spawn, clean up child side + try await self.cleanup( + process: process, + childSide: true, + parentSide: false, + attemptToTerminateSubProcess: false + ) + return try await withAsyncTaskCancellationHandler { + return try await withThrowingTaskGroup(of: RunState.self) { group in + group.addTask { + let status = try await monitorProcessTermination( + forProcessWithIdentifier: process.processIdentifier) + return .monitorChildProcess(status) + } + group.addTask { + do { + let result = try await body(process) + try await self.cleanup( + process: process, + childSide: false, + parentSide: true, + attemptToTerminateSubProcess: false + ) + return .workBody(result) + } catch { + try await self.cleanup( + process: process, + childSide: false, + parentSide: true, + attemptToTerminateSubProcess: false + ) + throw error + } + } + + var result: R! + var terminationStatus: TerminationStatus! + while let state = try await group.next() { + switch state { + case .monitorChildProcess(let status): + terminationStatus = status + case .workBody(let workResult): + result = workResult + } + } + return ExecutionResult(terminationStatus: terminationStatus, value: result) + } + } onCancel: { + // Attempt to terminate the child process + // Since the task has already been cancelled, + // this is the best we can do + try? await self.cleanup( + process: process, + childSide: true, + parentSide: true, + attemptToTerminateSubProcess: true + ) + } + } + } +} + +extension Subprocess.Configuration : CustomStringConvertible, CustomDebugStringConvertible { + public var description: String { + return """ +Subprocess.Configuration( + executable: \(self.executable.description), + arguments: \(self.arguments.description), + environment: \(self.environment.description), + workingDirectory: \(self.workingDirectory), + platformOptions: \(self.platformOptions.description(withIndent: 1)) +) +""" + } + + public var debugDescription: String { + return """ +Subprocess.Configuration( + executable: \(self.executable.debugDescription), + arguments: \(self.arguments.debugDescription), + environment: \(self.environment.debugDescription), + workingDirectory: \(self.workingDirectory), + platformOptions: \(self.platformOptions.description(withIndent: 1)) +) +""" + } +} + +// MARK: - Executable +extension Subprocess { + /// `Subprocess.Executable` defines how should the executable + /// be looked up for execution. + public struct Executable: Sendable, Hashable { + internal enum Configuration: Sendable, Hashable { + case executable(String) + case path(FilePath) + } + + internal let storage: Configuration + + private init(_config: Configuration) { + self.storage = _config + } + + /// Locate the executable by its name. + /// `Subprocess` will use `PATH` value to + /// determine the full path to the executable. + public static func named(_ executableName: String) -> Self { + return .init(_config: .executable(executableName)) + } + /// Locate the executable by its full path. + /// `Subprocess` will use this path directly. + public static func at(_ filePath: FilePath) -> Self { + return .init(_config: .path(filePath)) + } + /// Returns the full executable path given the environment value. + public func resolveExecutablePath(in environment: Environment) -> FilePath? { + if let path = self.resolveExecutablePath(withPathValue: environment.pathValue()) { + return FilePath(path) + } + return nil + } + } +} + +extension Subprocess.Executable : CustomStringConvertible, CustomDebugStringConvertible { + public var description: String { + switch storage { + case .executable(let executableName): + return executableName + case .path(let filePath): + return filePath.string + } + } + + public var debugDescription: String { + switch storage { + case .executable(let string): + return "executable(\(string))" + case .path(let filePath): + return "path(\(filePath.string))" + } + } +} + +// MARK: - Arguments +extension Subprocess { + /// A collection of arguments to pass to the subprocess. + public struct Arguments: Sendable, ExpressibleByArrayLiteral, Hashable { + public typealias ArrayLiteralElement = String + + internal let storage: [StringOrRawBytes] + internal let executablePathOverride: StringOrRawBytes? + + /// Create an Arguments object using the given literal values + public init(arrayLiteral elements: String...) { + self.storage = elements.map { .string($0) } + self.executablePathOverride = nil + } + /// Create an Arguments object using the given array + public init(_ array: [String]) { + self.storage = array.map { .string($0) } + self.executablePathOverride = nil + } + +#if !os(Windows) // Windows does NOT support arg0 override + /// Create an `Argument` object using the given values, but + /// override the first Argument value to `executablePathOverride`. + /// If `executablePathOverride` is nil, + /// `Arguments` will automatically use the executable path + /// as the first argument. + /// - Parameters: + /// - executablePathOverride: the value to override the first argument. + /// - remainingValues: the rest of the argument value + public init(executablePathOverride: String?, remainingValues: [String]) { + self.storage = remainingValues.map { .string($0) } + if let executablePathOverride = executablePathOverride { + self.executablePathOverride = .string(executablePathOverride) + } else { + self.executablePathOverride = nil + } + } + + /// Create an `Argument` object using the given values, but + /// override the first Argument value to `executablePathOverride`. + /// If `executablePathOverride` is nil, + /// `Arguments` will automatically use the executable path + /// as the first argument. + /// - Parameters: + /// - executablePathOverride: the value to override the first argument. + /// - remainingValues: the rest of the argument value + public init(executablePathOverride: Data?, remainingValues: [Data]) { + self.storage = remainingValues.map { .rawBytes($0.toArray()) } + if let override = executablePathOverride { + self.executablePathOverride = .rawBytes(override.toArray()) + } else { + self.executablePathOverride = nil + } + } + + public init(_ array: [Data]) { + self.storage = array.map { .rawBytes($0.toArray()) } + self.executablePathOverride = nil + } +#endif + } +} + +extension Subprocess.Arguments : CustomStringConvertible, CustomDebugStringConvertible { + public var description: String { + var result: [String] = self.storage.map(\.description) + + if let override = self.executablePathOverride { + result.insert("override\(override.description)", at: 0) + } + return result.description + } + + public var debugDescription: String { return self.description } +} + +// MARK: - Environment +extension Subprocess { + /// A set of environment variables to use when executing the subprocess. + public struct Environment: Sendable, Hashable { + internal enum Configuration: Sendable, Hashable { + case inherit([StringOrRawBytes : StringOrRawBytes]) + case custom([StringOrRawBytes : StringOrRawBytes]) + } + + internal let config: Configuration + + init(config: Configuration) { + self.config = config + } + /// Child process should inherit the same environment + /// values from its parent process. + public static var inherit: Self { + return .init(config: .inherit([:])) + } + /// Override the provided `newValue` in the existing `Environment` + public func updating(_ newValue: [String : String]) -> Self { + return .init(config: .inherit(newValue.wrapToStringOrRawBytes())) + } + /// Use custom environment variables + public static func custom(_ newValue: [String : String]) -> Self { + return .init(config: .custom(newValue.wrapToStringOrRawBytes())) + } + +#if !os(Windows) + /// Override the provided `newValue` in the existing `Environment` + public func updating(_ newValue: [Data : Data]) -> Self { + return .init(config: .inherit(newValue.wrapToStringOrRawBytes())) + } + /// Use custom environment variables + public static func custom(_ newValue: [Data : Data]) -> Self { + return .init(config: .custom(newValue.wrapToStringOrRawBytes())) + } +#endif + } +} + +extension Subprocess.Environment : CustomStringConvertible, CustomDebugStringConvertible { + public var description: String { + switch self.config { + case .custom(let customDictionary): + return customDictionary.dictionaryDescription + case .inherit(let updateValue): + return "Inherting current environment with updates: \(updateValue.dictionaryDescription)" + } + } + + public var debugDescription: String { + return self.description + } +} + +fileprivate extension Dictionary where Key == String, Value == String { + func wrapToStringOrRawBytes() -> [Subprocess.StringOrRawBytes : Subprocess.StringOrRawBytes] { + var result = Dictionary< + Subprocess.StringOrRawBytes, + Subprocess.StringOrRawBytes + >(minimumCapacity: self.count) + for (key, value) in self { + result[.string(key)] = .string(value) + } + return result + } +} + +fileprivate extension Dictionary where Key == Data, Value == Data { + func wrapToStringOrRawBytes() -> [Subprocess.StringOrRawBytes : Subprocess.StringOrRawBytes] { + var result = Dictionary< + Subprocess.StringOrRawBytes, + Subprocess.StringOrRawBytes + >(minimumCapacity: self.count) + for (key, value) in self { + result[.rawBytes(key.toArray())] = .rawBytes(value.toArray()) + } + return result + } +} + +fileprivate extension Dictionary where Key == Subprocess.StringOrRawBytes, Value == Subprocess.StringOrRawBytes { + var dictionaryDescription: String { + var result = "[\n" + for (key, value) in self { + result += "\t\(key.description) : \(value.description),\n" + } + result += "]" + return result + } +} + +fileprivate extension Data { + func toArray() -> [T] { + return self.withUnsafeBytes { ptr in + return Array(ptr.bindMemory(to: T.self)) + } + } +} + +// MARK: - TerminationStatus +extension Subprocess { + /// An exit status of a subprocess. + @frozen + public enum TerminationStatus: Sendable, Hashable, Codable { + #if canImport(WinSDK) + public typealias Code = DWORD + #else + public typealias Code = CInt + #endif + + /// The subprocess was existed with the given code + case exited(Code) + /// The subprocess was signalled with given exception value + case unhandledException(Code) + /// Whether the current TerminationStatus is successful. + public var isSuccess: Bool { + switch self { + case .exited(let exitCode): + return exitCode == 0 + case .unhandledException(_): + return false + } + } + } +} + +extension Subprocess.TerminationStatus : CustomStringConvertible, CustomDebugStringConvertible { + public var description: String { + switch self { + case .exited(let code): + return "exited(\(code))" + case .unhandledException(let code): + return "unhandledException(\(code))" + } + } + + public var debugDescription: String { + return self.description + } +} + +// MARK: - Internal +extension Subprocess { + internal enum StringOrRawBytes: Sendable, Hashable { + case string(String) + case rawBytes([CChar]) + + // Return value needs to be deallocated manually by callee + func createRawBytes() -> UnsafeMutablePointer { + switch self { + case .string(let string): + return strdup(string) + case .rawBytes(let rawBytes): + return strdup(rawBytes) + } + } + + var stringValue: String? { + switch self { + case .string(let string): + return string + case .rawBytes(let rawBytes): + return String(validatingUTF8: rawBytes) + } + } + + var description: String { + switch self { + case .string(let string): + return string + case .rawBytes(let bytes): + return bytes.description + } + } + + var count: Int { + switch self { + case .string(let string): + return string.count + case .rawBytes(let rawBytes): + return strnlen(rawBytes, Int.max) + } + } + + func hash(into hasher: inout Hasher) { + // If Raw bytes is valid UTF8, hash it as so + switch self { + case .string(let string): + hasher.combine(string) + case .rawBytes(let bytes): + if let stringValue = self.stringValue { + hasher.combine(stringValue) + } else { + hasher.combine(bytes) + } + } + } + } +} + +extension FilePath { + static var currentWorkingDirectory: Self { + let path = getcwd(nil, 0)! + defer { free(path) } + return .init(String(cString: path)) + } +} + +extension Optional where Wrapped : Collection { + func withOptionalUnsafeBufferPointer(_ body: ((UnsafeBufferPointer)?) throws -> R) rethrows -> R { + switch self { + case .some(let wrapped): + guard let array: Array = wrapped as? Array else { + return try body(nil) + } + return try array.withUnsafeBufferPointer { ptr in + return try body(ptr) + } + case .none: + return try body(nil) + } + } +} + +extension Optional where Wrapped == String { + func withOptionalCString(_ body: ((UnsafePointer)?) throws -> R) rethrows -> R { + switch self { + case .none: + return try body(nil) + case .some(let wrapped): + return try wrapped.withCString { + return try body($0) + } + } + } + + var stringValue: String { + return self ?? "nil" + } +} + +// MARK: - Stubs for the one from Foundation +public enum QualityOfService: Int, Sendable { + case userInteractive = 0x21 + case userInitiated = 0x19 + case utility = 0x11 + case background = 0x09 + case `default` = -1 +} + +internal func withAsyncTaskCancellationHandler( + _ body: sending @escaping () async throws -> R, + onCancel handler: sending @escaping () async -> Void +) async rethrows -> R { + return try await withThrowingTaskGroup( + of: R?.self, + returning: R.self + ) { group in + group.addTask { + return try await body() + } + group.addTask { + // wait until cancelled + do { while true { try await Task.sleep(nanoseconds: 1_000_000_000) } } catch {} + // Run task cancel handler + await handler() + return nil + } + + while let result = try await group.next() { + if let result = result { + // As soon as the body finishes, cancel the group + group.cancelAll() + return result + } + } + fatalError("Unreachable") + } +} + diff --git a/Sources/_Subprocess/Subprocess+IO.swift b/Sources/_Subprocess/Subprocess+IO.swift new file mode 100644 index 00000000..800d92d3 --- /dev/null +++ b/Sources/_Subprocess/Subprocess+IO.swift @@ -0,0 +1,435 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// +//===----------------------------------------------------------------------===// + +#if canImport(FoundationEssentials) +import FoundationEssentials +#elseif canImport(Foundation) +import Foundation +#endif + +import Dispatch +import SystemPackage +import Synchronization + +// Naive Mutex so we don't have to update the macOS dependency +final class _Mutex: Sendable { + let lock = NSLock() + + var value: Value + + init(_ value: Value) { + self.value = value + } + + func withLock(_ body: (inout Value) throws -> R) rethrows -> R { + self.lock.lock() + defer { self.lock.unlock() } + return try body(&self.value) + } +} + +// MARK: - Input +extension Subprocess { + /// `InputMethod` defines how should the standard input + /// of the subprocess receive inputs. + public struct InputMethod: Sendable, Hashable { + internal enum Storage: Sendable, Hashable { + case noInput + case fileDescriptor(FileDescriptor, Bool) + } + + internal let method: Storage + + internal init(method: Storage) { + self.method = method + } + + internal func createExecutionInput() throws -> ExecutionInput { + switch self.method { + case .noInput: + let devnull: FileDescriptor = try .openDevNull(withAcessMode: .readOnly) + return .init(storage: .noInput(devnull)) + case .fileDescriptor(let fileDescriptor, let closeWhenDone): + return .init(storage: .fileDescriptor(fileDescriptor, closeWhenDone)) + } + } + + /// Subprocess should read no input. This option is equivalent + /// to bind the stanard input to `/dev/null`. + public static var noInput: Self { + return .init(method: .noInput) + } + + /// Subprocess should read input from a given file descriptor. + /// - Parameters: + /// - fd: the file descriptor to read from + /// - closeAfterSpawningProcess: whether the file descriptor + /// should be automatically closed after subprocess is spawned. + public static func readFrom( + _ fd: FileDescriptor, + closeAfterSpawningProcess: Bool + ) -> Self { + return .init(method: .fileDescriptor(fd, closeAfterSpawningProcess)) + } + } +} + +extension Subprocess { + /// `CollectedOutputMethod` defines how should Subprocess collect + /// output from child process' standard output and standard error + public struct CollectedOutputMethod: Sendable, Hashable { + internal enum Storage: Sendable, Hashable { + case discarded + case fileDescriptor(FileDescriptor, Bool) + case collected(Int) + } + + internal let method: Storage + + internal init(method: Storage) { + self.method = method + } + + /// Subprocess shold dicard the child process output. + /// This option is equivalent to binding the child process + /// output to `/dev/null`. + public static var discard: Self { + return .init(method: .discarded) + } + /// Subprocess should write the child process output + /// to the file descriptor specified. + /// - Parameters: + /// - fd: the file descriptor to write to + /// - closeAfterSpawningProcess: whether to close the + /// file descriptor once the process is spawned. + public static func writeTo(_ fd: FileDescriptor, closeAfterSpawningProcess: Bool) -> Self { + return .init(method: .fileDescriptor(fd, closeAfterSpawningProcess)) + } + /// Subprocess should collect the child process output + /// as `Data` with the given limit in bytes. The default + /// limit is 128kb. + public static func collect(upTo limit: Int = 128 * 1024) -> Self { + return .init(method: .collected(limit)) + } + + internal func createExecutionOutput() throws -> ExecutionOutput { + switch self.method { + case .discarded: + // Bind to /dev/null + let devnull: FileDescriptor = try .openDevNull(withAcessMode: .writeOnly) + return .init(storage: .discarded(devnull)) + case .fileDescriptor(let fileDescriptor, let closeWhenDone): + return .init(storage: .fileDescriptor(fileDescriptor, closeWhenDone)) + case .collected(let limit): + let (readFd, writeFd) = try FileDescriptor.pipe() + return .init(storage: .collected(limit, readFd, writeFd)) + } + } + } + + /// `CollectedOutputMethod` defines how should Subprocess redirect + /// output from child process' standard output and standard error. + public struct RedirectedOutputMethod: Sendable, Hashable { + typealias Storage = CollectedOutputMethod.Storage + + internal let method: Storage + + internal init(method: Storage) { + self.method = method + } + + /// Subprocess shold dicard the child process output. + /// This option is equivalent to binding the child process + /// output to `/dev/null`. + public static var discard: Self { + return .init(method: .discarded) + } + /// Subprocess should redirect the child process output + /// to `Subprocess.standardOutput` or `Subprocess.standardError` + /// so they can be consumed as an AsyncSequence + public static var redirectToSequence: Self { + return .init(method: .collected(128 * 1024)) + } + /// Subprocess shold write the child process output + /// to the file descriptor specified. + /// - Parameters: + /// - fd: the file descriptor to write to + /// - closeAfterSpawningProcess: whether to close the + /// file descriptor once the process is spawned. + public static func writeTo( + _ fd: FileDescriptor, + closeAfterSpawningProcess: Bool + ) -> Self { + return .init(method: .fileDescriptor(fd, closeAfterSpawningProcess)) + } + + internal func createExecutionOutput() throws -> ExecutionOutput { + switch self.method { + case .discarded: + // Bind to /dev/null + let devnull: FileDescriptor = try .openDevNull(withAcessMode: .writeOnly) + return .init(storage: .discarded(devnull)) + case .fileDescriptor(let fileDescriptor, let closeWhenDone): + return .init(storage: .fileDescriptor(fileDescriptor, closeWhenDone)) + case .collected(let limit): + let (readFd, writeFd) = try FileDescriptor.pipe() + return .init(storage: .collected(limit, readFd, writeFd)) + } + } + } +} + +// MARK: - Execution IO +extension Subprocess { + internal final class ExecutionInput: Sendable, Hashable { + + + internal enum Storage: Sendable, Hashable { + case noInput(FileDescriptor?) + case customWrite(FileDescriptor?, FileDescriptor?) + case fileDescriptor(FileDescriptor?, Bool) + } + + let storage: _Mutex + + internal init(storage: Storage) { + self.storage = .init(storage) + } + + internal func getReadFileDescriptor() -> FileDescriptor? { + return self.storage.withLock { + switch $0 { + case .noInput(let readFd): + return readFd + case .customWrite(let readFd, _): + return readFd + case .fileDescriptor(let readFd, _): + return readFd + } + } + } + + internal func getWriteFileDescriptor() -> FileDescriptor? { + return self.storage.withLock { + switch $0 { + case .noInput(_), .fileDescriptor(_, _): + return nil + case .customWrite(_, let writeFd): + return writeFd + } + } + } + + internal func closeChildSide() throws { + try self.storage.withLock { + switch $0 { + case .noInput(let devnull): + try devnull?.close() + $0 = .noInput(nil) + case .customWrite(let readFd, let writeFd): + try readFd?.close() + $0 = .customWrite(nil, writeFd) + case .fileDescriptor(let fd, let closeWhenDone): + // User passed in fd + if closeWhenDone { + try fd?.close() + $0 = .fileDescriptor(nil, closeWhenDone) + } + } + } + } + + internal func closeParentSide() throws { + try self.storage.withLock { + switch $0 { + case .noInput(_), .fileDescriptor(_, _): + break + case .customWrite(let readFd, let writeFd): + // The parent fd should have been closed + // in the `body` when writer.finish() is called + // But in case it isn't call it agian + try writeFd?.close() + $0 = .customWrite(readFd, nil) + } + } + } + + internal func closeAll() throws { + try self.storage.withLock { + switch $0 { + case .noInput(let readFd): + try readFd?.close() + $0 = .noInput(nil) + case .customWrite(let readFd, let writeFd): + var readFdCloseError: Error? + var writeFdCloseError: Error? + do { + try readFd?.close() + } catch { + readFdCloseError = error + } + do { + try writeFd?.close() + } catch { + writeFdCloseError = error + } + $0 = .customWrite(nil, nil) + if let readFdCloseError { + throw readFdCloseError + } + if let writeFdCloseError { + throw writeFdCloseError + } + case .fileDescriptor(let fd, let closeWhenDone): + if closeWhenDone { + try fd?.close() + $0 = .fileDescriptor(nil, closeWhenDone) + } + } + } + } + + public func hash(into hasher: inout Hasher) { + self.storage.withLock { + hasher.combine($0) + } + } + + public static func == ( + lhs: Subprocess.ExecutionInput, + rhs: Subprocess.ExecutionInput + ) -> Bool { + return lhs.storage.withLock { lhsStorage in + rhs.storage.withLock { rhsStorage in + return lhsStorage == rhsStorage + } + } + } + } + + internal final class ExecutionOutput: Sendable { + internal enum Storage: Sendable { + case discarded(FileDescriptor?) + case fileDescriptor(FileDescriptor?, Bool) + case collected(Int, FileDescriptor?, FileDescriptor?) + } + + private let storage: _Mutex + + internal init(storage: Storage) { + self.storage = .init(storage) + } + + internal func getWriteFileDescriptor() -> FileDescriptor? { + return self.storage.withLock { + switch $0 { + case .discarded(let writeFd): + return writeFd + case .fileDescriptor(let writeFd, _): + return writeFd + case .collected(_, _, let writeFd): + return writeFd + } + } + } + + internal func getReadFileDescriptor() -> FileDescriptor? { + return self.storage.withLock { + switch $0 { + case .discarded(_), .fileDescriptor(_, _): + return nil + case .collected(_, let readFd, _): + return readFd + } + } + } + + internal func consumeCollectedFileDescriptor() -> (limit: Int, fd: FileDescriptor?)? { + return self.storage.withLock { + switch $0 { + case .discarded(_), .fileDescriptor(_, _): + // The output has been written somewhere else + return nil + case .collected(let limit, let readFd, let writeFd): + $0 = .collected(limit, nil, writeFd) + return (limit, readFd) + } + } + } + + internal func closeChildSide() throws { + try self.storage.withLock { + switch $0 { + case .discarded(let writeFd): + try writeFd?.close() + $0 = .discarded(nil) + case .fileDescriptor(let fd, let closeWhenDone): + // User passed fd + if closeWhenDone { + try fd?.close() + $0 = .fileDescriptor(nil, closeWhenDone) + } + case .collected(let limit, let readFd, let writeFd): + try writeFd?.close() + $0 = .collected(limit, readFd, nil) + } + } + } + + internal func closeParentSide() throws { + try self.storage.withLock { + switch $0 { + case .discarded(_), .fileDescriptor(_, _): + break + case .collected(let limit, let readFd, let writeFd): + try readFd?.close() + $0 = .collected(limit, nil, writeFd) + } + } + } + + internal func closeAll() throws { + try self.storage.withLock { + switch $0 { + case .discarded(let writeFd): + try writeFd?.close() + $0 = .discarded(nil) + case .fileDescriptor(let fd, let closeWhenDone): + if closeWhenDone { + try fd?.close() + $0 = .fileDescriptor(nil, closeWhenDone) + } + case .collected(let limit, let readFd, let writeFd): + var readFdCloseError: Error? + var writeFdCloseError: Error? + do { + try readFd?.close() + } catch { + readFdCloseError = error + } + do { + try writeFd?.close() + } catch { + writeFdCloseError = error + } + $0 = .collected(limit, nil, nil) + if let readFdCloseError { + throw readFdCloseError + } + if let writeFdCloseError { + throw writeFdCloseError + } + } + } + } + } +} + diff --git a/Sources/_Subprocess/Subprocess+Teardown.swift b/Sources/_Subprocess/Subprocess+Teardown.swift new file mode 100644 index 00000000..ee4b7333 --- /dev/null +++ b/Sources/_Subprocess/Subprocess+Teardown.swift @@ -0,0 +1,118 @@ +// +// Suubprocess+Teardown.swift +// SwiftExperimentalSubprocess +// +// Created by Charles Hu on 12/6/24. +// + +#if canImport(Darwin) || canImport(Glibc) + +#if canImport(Darwin) +import Darwin +#elseif canImport(Glibc) +import Glibc +#endif + +#if canImport(FoundationEssentials) +import FoundationEssentials +#elseif canImport(Foundation) +import Foundation +#endif + +extension Subprocess { + /// A step in the graceful shutdown teardown sequence. + /// It consists of a signal to send to the child process and the + /// number of nanoseconds allowed for the child process to exit + /// before proceeding to the next step. + public struct TeardownStep: Sendable, Hashable { + internal enum Storage: Sendable, Hashable { + case sendSignal(Signal, allowedNanoseconds: UInt64) + case kill + } + var storage: Storage + + /// Sends `signal` to the process and provides `allowedNanoSecondsToExit` + /// nanoseconds for the process to exit before proceeding to the next step. + /// The final step in the sequence will always send a `.kill` signal. + public static func sendSignal( + _ signal: Signal, + allowedNanoSecondsToExit: UInt64 + ) -> Self { + return Self( + storage: .sendSignal( + signal, + allowedNanoseconds: allowedNanoSecondsToExit + ) + ) + } + } +} + +extension Subprocess { + internal func runTeardownSequence(_ sequence: [TeardownStep]) async { + // First insert the `.kill` step + let finalSequence = sequence + [TeardownStep(storage: .kill)] + for step in finalSequence { + enum TeardownStepCompletion { + case processHasExited + case processStillAlive + case killedTheProcess + } + let stepCompletion: TeardownStepCompletion + + guard self.isAlive() else { + return + } + + switch step.storage { + case .sendSignal(let signal, let allowedNanoseconds): + stepCompletion = await withTaskGroup(of: TeardownStepCompletion.self) { group in + group.addTask { + do { + try await Task.sleep(nanoseconds: allowedNanoseconds) + return .processStillAlive + } catch { + // teardown(using:) cancells this task + // when process has exited + return .processHasExited + } + } + try? self.send(signal, toProcessGroup: false) + return await group.next()! + } + case .kill: + try? self.send(.kill, toProcessGroup: false) + stepCompletion = .killedTheProcess + } + + switch stepCompletion { + case .killedTheProcess, .processHasExited: + return + case .processStillAlive: + // Continue to next step + break + } + } + } +} + +extension Subprocess { + private func isAlive() -> Bool { + return kill(self.processIdentifier.value, 0) == 0 + } +} + +func withUncancelledTask( + returning: R.Type = R.self, + _ body: @Sendable @escaping () async -> R +) async -> R { + // This looks unstructured but it isn't, please note that we `await` `.value` of this task. + // The reason we need this separate `Task` is that in general, we cannot assume that code performs to our + // expectations if the task we run it on is already cancelled. However, in some cases we need the code to + // run regardless -- even if our task is already cancelled. Therefore, we create a new, uncancelled task here. + await Task { + await body() + }.value +} + +#endif // canImport(Darwin) || canImport(Glibc) diff --git a/Sources/_Subprocess/Subprocess.swift b/Sources/_Subprocess/Subprocess.swift new file mode 100644 index 00000000..8c66ed03 --- /dev/null +++ b/Sources/_Subprocess/Subprocess.swift @@ -0,0 +1,312 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// +//===----------------------------------------------------------------------===// + +import SystemPackage + +#if canImport(FoundationEssentials) +import FoundationEssentials +#elseif canImport(Foundation) +import Foundation +#endif + +/// An object that represents a subprocess of the current process. +/// +/// Using `Subprocess`, your program can run another program as a subprocess +/// and can monitor that program’s execution. A `Subprocess` object creates a +/// **separate executable** entity; it’s different from `Thread` because it doesn’t +/// share memory space with the process that creates it. +public struct Subprocess: Sendable { + /// The process identifier of the current subprocess + public let processIdentifier: ProcessIdentifier + + internal let executionInput: ExecutionInput + internal let executionOutput: ExecutionOutput + internal let executionError: ExecutionOutput +#if os(Windows) + internal let consoleBehavior: PlatformOptions.ConsoleBehavior +#endif + + /// The standard output of the subprocess. + /// Accessing this property will **fatalError** if + /// - `.output` wasn't set to `.redirectToSequence` when the subprocess was spawned; + /// - This property was accessed multiple times. Subprocess communicates with + /// parent process via pipe under the hood and each pipe can only be consumed ones. + public var standardOutput: some _AsyncSequence { + guard let (_, fd) = self.executionOutput + .consumeCollectedFileDescriptor() else { + fatalError("The standard output was not redirected") + } + guard let fd = fd else { + fatalError("The standard output has already been closed") + } + return AsyncDataSequence(fileDescriptor: fd) + } + + /// The standard error of the subprocess. + /// Accessing this property will **fatalError** if + /// - `.error` wasn't set to `.redirectToSequence` when the subprocess was spawned; + /// - This property was accessed multiple times. Subprocess communicates with + /// parent process via pipe under the hood and each pipe can only be consumed ones. + public var standardError: some _AsyncSequence { + guard let (_, fd) = self.executionError + .consumeCollectedFileDescriptor() else { + fatalError("The standard error was not redirected") + } + guard let fd = fd else { + fatalError("The standard error has already been closed") + } + return AsyncDataSequence(fileDescriptor: fd) + } +} + +// MARK: - Teardown +#if canImport(Darwin) || canImport(Glibc) +extension Subprocess { + /// Performs a sequence of teardown steps on the Subprocess. + /// Teardown sequence always ends with a `.kill` signal + /// - Parameter sequence: The steps to perform. + public func teardown(using sequence: [TeardownStep]) async { + await withUncancelledTask { + await self.runTeardownSequence(sequence) + } + } +} +#endif + +// MARK: - StandardInputWriter +extension Subprocess { + /// A writer that writes to the standard input of the subprocess. + public struct StandardInputWriter { + + private let input: ExecutionInput + + init(input: ExecutionInput) { + self.input = input + } + + /// Write a sequence of UInt8 to the standard input of the subprocess. + /// - Parameter sequence: The sequence of bytes to write. + public func write(_ sequence: S) async throws where S : Sequence, S.Element == UInt8 { + guard let fd: FileDescriptor = self.input.getWriteFileDescriptor() else { + fatalError("Attempting to write to a file descriptor that's already closed") + } + try await fd.write(sequence) + } + + /// Write a sequence of CChar to the standard input of the subprocess. + /// - Parameter sequence: The sequence of bytes to write. + public func write(_ sequence: S) async throws where S : Sequence, S.Element == CChar { + try await self.write(sequence.map { UInt8($0) }) + } + + /// Write a AsyncSequence of CChar to the standard input of the subprocess. + /// - Parameter sequence: The sequence of bytes to write. + public func write(_ asyncSequence: S) async throws where S.Element == CChar { + let sequence = try await Array(asyncSequence).map { UInt8($0) } + try await self.write(sequence) + } + + /// Write a AsyncSequence of UInt8 to the standard input of the subprocess. + /// - Parameter sequence: The sequence of bytes to write. + public func write(_ asyncSequence: S) async throws where S.Element == UInt8 { + let sequence = try await Array(asyncSequence) + try await self.write(sequence) + } + + /// Signal all writes are finished + public func finish() async throws { + try self.input.closeParentSide() + } + } +} + +@available(macOS, unavailable) +@available(iOS, unavailable) +@available(tvOS, unavailable) +@available(watchOS, unavailable) +@available(*, unavailable) +extension Subprocess.StandardInputWriter : Sendable {} + +// MARK: - Result +extension Subprocess { + /// A simple wrapper around the generic result returned by the + /// `run` closures with the corresponding `TerminationStatus` + /// of the child process. + public struct ExecutionResult: Sendable { + /// The termination status of the child process + public let terminationStatus: TerminationStatus + /// The result returned by the closure passed to `.run` methods + public let value: T + + internal init(terminationStatus: TerminationStatus, value: T) { + self.terminationStatus = terminationStatus + self.value = value + } + } + + /// The result of a subprocess execution with its collected + /// standard output and standard error. + public struct CollectedResult: Sendable, Hashable, Codable { + /// The process identifier for the executed subprocess + public let processIdentifier: ProcessIdentifier + /// The termination status of the executed subprocess + public let terminationStatus: TerminationStatus + private let _standardOutput: Data? + private let _standardError: Data? + + /// The collected standard output value for the subprocess. + /// Accessing this property will *fatalError* if the + /// corresponding `CollectedOutputMethod` is not set to + /// `.collect` or `.collect(upTo:)` + public var standardOutput: Data { + guard let output = self._standardOutput else { + fatalError("standardOutput is only available if the Subprocess was ran with .collect as output") + } + return output + } + /// The collected standard error value for the subprocess. + /// Accessing this property will *fatalError* if the + /// corresponding `CollectedOutputMethod` is not set to + /// `.collect` or `.collect(upTo:)` + public var standardError: Data { + guard let output = self._standardError else { + fatalError("standardError is only available if the Subprocess was ran with .collect as error ") + } + return output + } + + internal init( + processIdentifier: ProcessIdentifier, + terminationStatus: TerminationStatus, + standardOutput: Data?, + standardError: Data?) { + self.processIdentifier = processIdentifier + self.terminationStatus = terminationStatus + self._standardOutput = standardOutput + self._standardError = standardError + } + } +} + +extension Subprocess.ExecutionResult: Equatable where T : Equatable {} + +extension Subprocess.ExecutionResult: Hashable where T : Hashable {} + +extension Subprocess.ExecutionResult: Codable where T : Codable {} + +extension Subprocess.ExecutionResult: CustomStringConvertible where T : CustomStringConvertible { + public var description: String { + return """ +Subprocess.ExecutionResult( + terminationStatus: \(self.terminationStatus.description), + value: \(self.value.description) +) +""" + } +} + +extension Subprocess.ExecutionResult: CustomDebugStringConvertible where T : CustomDebugStringConvertible { + public var debugDescription: String { + return """ +Subprocess.ExecutionResult( + terminationStatus: \(self.terminationStatus.debugDescription), + value: \(self.value.debugDescription) +) +""" + } +} + +extension Subprocess.CollectedResult : CustomStringConvertible, CustomDebugStringConvertible { + public var description: String { + return """ +Subprocess.CollectedResult( + processIdentifier: \(self.processIdentifier.description), + terminationStatus: \(self.terminationStatus.description), + standardOutput: \(self._standardOutput?.description ?? "not captured"), + standardError: \(self._standardError?.description ?? "not captured") +) +""" + } + + public var debugDescription: String { + return """ +Subprocess.CollectedResult( + processIdentifier: \(self.processIdentifier.debugDescription), + terminationStatus: \(self.terminationStatus.debugDescription), + standardOutput: \(self._standardOutput?.debugDescription ?? "not captured"), + standardError: \(self._standardError?.debugDescription ?? "not captured") +) +""" + } +} + +// MARK: - Internal +extension Subprocess { + internal enum OutputCapturingState { + case standardOutputCaptured(Data?) + case standardErrorCaptured(Data?) + } + + internal typealias CapturedIOs = (standardOutput: Data?, standardError: Data?) + + private func capture(fileDescriptor: FileDescriptor, maxLength: Int) async throws -> Data { + return try await fileDescriptor.readUntilEOF(upToLength: maxLength) + } + + internal func captureStandardOutput() async throws -> Data? { + guard let (limit, readFd) = self.executionOutput + .consumeCollectedFileDescriptor(), + let readFd = readFd else { + return nil + } + defer { + try? readFd.close() + } + return try await self.capture(fileDescriptor: readFd, maxLength: limit) + } + + internal func captureStandardError() async throws -> Data? { + guard let (limit, readFd) = self.executionError + .consumeCollectedFileDescriptor(), + let readFd = readFd else { + return nil + } + defer { + try? readFd.close() + } + return try await self.capture(fileDescriptor: readFd, maxLength: limit) + } + + internal func captureIOs() async throws -> CapturedIOs { + return try await withThrowingTaskGroup(of: OutputCapturingState.self) { group in + group.addTask { + let stdout = try await self.captureStandardOutput() + return .standardOutputCaptured(stdout) + } + group.addTask { + let stderr = try await self.captureStandardError() + return .standardErrorCaptured(stderr) + } + + var stdout: Data? + var stderror: Data? + while let state = try await group.next() { + switch state { + case .standardOutputCaptured(let output): + stdout = output + case .standardErrorCaptured(let error): + stderror = error + } + } + return (standardOutput: stdout, standardError: stderror) + } + } +} From 00928b259d4347f085d85bdb62aaf1249dfb3eab Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Wed, 11 Dec 2024 14:52:54 +0900 Subject: [PATCH 196/426] Attempt to use build-plugin to bootstrap dependency resolver dependency --- .../SwiftJavaBootstrapJavaPlugin.swift | 190 +++++++ .../_PluginsShared | 1 + .../JavaDependencySampleApp/ci-validate.sh | 4 +- .../Configuration.swift | 2 +- .../SwiftJavaBootstrapJavaTool.swift | 130 +++++ Sources/_Subprocess/Subprocess+IO.swift | 3 +- Sources/_Subprocess/_nio_locks.swift | 526 ++++++++++++++++++ 7 files changed, 852 insertions(+), 4 deletions(-) create mode 100644 Plugins/SwiftJavaBootstrapJavaPlugin/SwiftJavaBootstrapJavaPlugin.swift create mode 120000 Plugins/SwiftJavaBootstrapJavaPlugin/_PluginsShared create mode 100644 Sources/SwiftJavaBootstrapJavaTool/SwiftJavaBootstrapJavaTool.swift create mode 100644 Sources/_Subprocess/_nio_locks.swift diff --git a/Plugins/SwiftJavaBootstrapJavaPlugin/SwiftJavaBootstrapJavaPlugin.swift b/Plugins/SwiftJavaBootstrapJavaPlugin/SwiftJavaBootstrapJavaPlugin.swift new file mode 100644 index 00000000..7d614371 --- /dev/null +++ b/Plugins/SwiftJavaBootstrapJavaPlugin/SwiftJavaBootstrapJavaPlugin.swift @@ -0,0 +1,190 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import Foundation +import PackagePlugin + +fileprivate let SwiftJavaConfigFileName = "swift-java.config" + +@main +struct Java2SwiftBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin { + + var pluginName: String = "swift-java-bootstrap" + var verbose: Bool = getEnvironmentBool("SWIFT_JAVA_VERBOSE") + + func createBuildCommands(context: PluginContext, target: Target) throws -> [Command] { + log("Create build commands for target '\(target.name)'") + guard let sourceModule = target.sourceModule else { return [] } + + let executable = try context.tool(named: "SwiftJavaBootstrapJavaTool").url + var commands: [Command] = [] + + // Note: Target doesn't have a directoryURL counterpart to directory, + // so we cannot eliminate this deprecation warning. + let sourceDir = target.directory.string + + // The name of the configuration file JavaKit.config from the target for + // which we are generating Swift wrappers for Java classes. + let configFile = URL(filePath: sourceDir) + .appending(path: SwiftJavaConfigFileName) + let config = try readConfiguration(sourceDir: sourceDir) + + log("Config on path: \(configFile.path(percentEncoded: false))") + log("Config was: \(config)") + var javaDependencies = config.dependencies ?? [] + + /// Find the manifest files from other Java2Swift executions in any targets + /// this target depends on. + var dependentConfigFiles: [(String, URL)] = [] + func searchForConfigFiles(in target: any Target) { + // log("Search for config files in target: \(target.name)") + let dependencyURL = URL(filePath: target.directory.string) + + // Look for a config file within this target. + let dependencyConfigURL = dependencyURL + .appending(path: SwiftJavaConfigFileName) + let dependencyConfigString = dependencyConfigURL + .path(percentEncoded: false) + + if FileManager.default.fileExists(atPath: dependencyConfigString) { + dependentConfigFiles.append((target.name, dependencyConfigURL)) + } + } + + // Process direct dependencies of this target. + for dependency in target.dependencies { + switch dependency { + case .target(let target): + searchForConfigFiles(in: target) + + case .product(let product): + for target in product.targets { + searchForConfigFiles(in: target) + } + + @unknown default: + break + } + } + + // Process indirect target dependencies. + for dependency in target.recursiveTargetDependencies { + searchForConfigFiles(in: dependency) + } + + var arguments: [String] = [] + arguments += argumentsModuleName(sourceModule: sourceModule) + arguments += argumentsOutputDirectory(context: context) + + arguments += dependentConfigFiles.flatMap { moduleAndConfigFile in + let (moduleName, configFile) = moduleAndConfigFile + return [ + "--depends-on", + "\(moduleName)=\(configFile.path(percentEncoded: false))" + ] + } + arguments.append(configFile.path(percentEncoded: false)) + + let classes = config.classes ?? [:] + print("Classes to wrap: \(classes.map(\.key))") + + /// Determine the set of Swift files that will be emitted by the Java2Swift tool. + // TODO: this is not precise and won't work with more advanced Java files, e.g. lambdas etc. + let outputDirectoryGenerated = self.outputDirectory(context: context, generated: true) + let outputSwiftFiles = classes.map { (javaClassName, swiftName) in + let swiftNestedName = swiftName.replacingOccurrences(of: ".", with: "+") + return outputDirectoryGenerated.appending(path: "\(swiftNestedName).swift") + } + + arguments += [ + "--cache-directory", + context.pluginWorkDirectoryURL.path(percentEncoded: false) + ] + + // Find the Java .class files generated from prior plugins. + let compiledClassFiles = sourceModule.pluginGeneratedResources.filter { url in + url.pathExtension == "class" + } + + if let firstClassFile = compiledClassFiles.first { + // Keep stripping off parts of the path until we hit the "Java" part. + // That's where the class path starts. + var classpath = firstClassFile + while classpath.lastPathComponent != "Java" { + classpath.deleteLastPathComponent() + } + arguments += ["--classpath", classpath.path()] + } + + var fetchDependenciesOutputFiles: [URL] = [] + if let dependencies = config.dependencies, !dependencies.isEmpty { + let displayName = "Fetch (Java) dependencies for Swift target \(sourceModule.name)" + log("Prepared: \(displayName)") + + let arguments = [ + "--fetch", configFile.path(percentEncoded: false), + "--module-name", sourceModule.name, + "--output-directory", outputDirectory(context: context, generated: false).path(percentEncoded: false) + ] + + log("Command: \(executable) \(arguments.joined(separator: " "))") + + fetchDependenciesOutputFiles += [ + outputFilePath(context: context, generated: false, filename: "\(sourceModule.name).swift-java.classpath") + ] + + commands += [ + .buildCommand( + displayName: displayName, + executable: executable, + arguments: arguments, + inputFiles: [configFile], + outputFiles: fetchDependenciesOutputFiles + ) + ] + } else { + log("No dependencies to fetch for target \(sourceModule.name)") + } + + return commands + } +} + +extension Java2SwiftBuildToolPlugin { + func argumentsModuleName(sourceModule: Target) -> [String] { + return [ + "--module-name", sourceModule.name + ] + } + + func argumentsOutputDirectory(context: PluginContext, generated: Bool = true) -> [String] { + return [ + "--output-directory", + outputDirectory(context: context, generated: generated).path(percentEncoded: false) + ] + } + + func outputDirectory(context: PluginContext, generated: Bool = true) -> URL { + let dir = context.pluginWorkDirectoryURL + if generated { + return dir.appending(path: "generated") + } else { + return dir + } + } + + func outputFilePath(context: PluginContext, generated: Bool, filename: String) -> URL { + outputDirectory(context: context, generated: generated).appending(path: filename) + } +} diff --git a/Plugins/SwiftJavaBootstrapJavaPlugin/_PluginsShared b/Plugins/SwiftJavaBootstrapJavaPlugin/_PluginsShared new file mode 120000 index 00000000..de623a5e --- /dev/null +++ b/Plugins/SwiftJavaBootstrapJavaPlugin/_PluginsShared @@ -0,0 +1 @@ +../PluginsShared \ No newline at end of file diff --git a/Samples/JavaDependencySampleApp/ci-validate.sh b/Samples/JavaDependencySampleApp/ci-validate.sh index 207aa343..4125fde1 100755 --- a/Samples/JavaDependencySampleApp/ci-validate.sh +++ b/Samples/JavaDependencySampleApp/ci-validate.sh @@ -3,8 +3,10 @@ set -e set -x +# TODO: this is a workaround for build plugins getting stuck running the bootstrap plugin +cd ../../ swift build --product SwiftJavaBootstrapJavaTool -.build/arm64-apple-macosx/debug/SwiftJavaBootstrapJavaTool --fetch /Users/ktoso/code/swift-java/Sources/JavaKitDependencyResolver/swift-java.config --module-name JavaKitDependencyResolver --output-directory && .build/plugins/outputs/swift-java/JavaKitDependencyResolver/destination/SwiftJavaBootstrapJavaPlugin +.build/arm64-apple-macosx/debug/SwiftJavaBootstrapJavaTool --fetch Sources/JavaKitDependencyResolver/swift-java.config --module-name JavaKitDependencyResolver --output-directory .build/plugins/outputs/swift-java/JavaKitDependencyResolver/destination/SwiftJavaBootstrapJavaPlugin cd - swift run --disable-sandbox diff --git a/Sources/JavaKitConfigurationShared/Configuration.swift b/Sources/JavaKitConfigurationShared/Configuration.swift index 2078c544..d401c657 100644 --- a/Sources/JavaKitConfigurationShared/Configuration.swift +++ b/Sources/JavaKitConfigurationShared/Configuration.swift @@ -116,7 +116,7 @@ public func readConfiguration(configPath: URL, file: String = #fileID, line: UIn let configData = try Data(contentsOf: configPath) return try JSONDecoder().decode(Configuration.self, from: configData) } catch { - throw ConfigurationError(message: "Failed to parse SwiftJava configuration at '\(configPath)'!", error: error, + throw ConfigurationError(message: "Failed to parse SwiftJava configuration at '\(configPath.absoluteURL)'!", error: error, file: file, line: line) } } diff --git a/Sources/SwiftJavaBootstrapJavaTool/SwiftJavaBootstrapJavaTool.swift b/Sources/SwiftJavaBootstrapJavaTool/SwiftJavaBootstrapJavaTool.swift new file mode 100644 index 00000000..ecc87dd3 --- /dev/null +++ b/Sources/SwiftJavaBootstrapJavaTool/SwiftJavaBootstrapJavaTool.swift @@ -0,0 +1,130 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import Foundation +import Synchronization +import JavaKitConfigurationShared +import Dispatch +import _Subprocess + +@available(macOS 15.0, *) +@main +final class SwiftJavaBootstrapJavaTool { + + let SwiftJavaClasspathPrefix = "SWIFT_JAVA_CLASSPATH:" + + // We seem to have weird "hang" issues with Gradle launched from Process(), workaround it by existing once we get the classpath + let printRuntimeClasspathTaskName = "printRuntimeClasspath" + + let out = Synchronization.Mutex(Data()) + let err = Synchronization.Mutex(Data()) + + static func main() async throws { + try await SwiftJavaBootstrapJavaTool().run() + } + + func run() async throws { + print("RUN SwiftJavaBootstrapJavaTool: \(CommandLine.arguments)") + + var args = CommandLine.arguments + _ = args.removeFirst() // executable + + assert(args.removeFirst() == "--fetch") + let configPath = args.removeFirst() + + assert(args.removeFirst() == "--module-name") + let moduleName = args.removeFirst() + + assert(args.removeFirst() == "--output-directory") + let outputDirectoryPath = args.removeFirst() + + let config = try readConfiguration(configPath: URL(fileURLWithPath: configPath)) + + // We only support a single dependency right now. + let localGradleProjectDependencyName = (config.dependencies ?? []).filter { + $0.artifactID.hasPrefix(":") + }.map { + $0.artifactID + }.first! + + let process = try await Subprocess.run( + .at("./gradlew"), + arguments: [ + "--no-daemon", + "--rerun-tasks", + // "--debug", + // "\(localGradleProjectDependencyName):jar", + "\(localGradleProjectDependencyName):\(printRuntimeClasspathTaskName)", + ], + workingDirectory: "/Users/ktoso/code/swift-java" + ) + + let outString = String( + data: process.standardOutput, + encoding: .utf8 + ) + let errString = String( + data: process.standardError, + encoding: .utf8 + ) + + print("OUT ==== \(outString?.count) ::: \(outString ?? "")") + print("ERR ==== \(errString?.count) ::: \(errString ?? "")") + + let classpathOutput: String + if let found = outString?.split(separator: "\n").first(where: { $0.hasPrefix(self.SwiftJavaClasspathPrefix) }) { + classpathOutput = String(found) + } else if let found = errString?.split(separator: "\n").first(where: { $0.hasPrefix(self.SwiftJavaClasspathPrefix) }) { + classpathOutput = String(found) + } else { + let suggestDisablingSandbox = "It may be that the Sandbox has prevented dependency fetching, please re-run with '--disable-sandbox'." + fatalError("Gradle output had no SWIFT_JAVA_CLASSPATH! \(suggestDisablingSandbox). \n" + + "Output was:<<<\(outString ?? "")>>>; Err was:<<<\(errString ?? "")>>>") + } + + let classpathString = String(classpathOutput.dropFirst(self.SwiftJavaClasspathPrefix.count)) + + let classpathOutputURL = + URL(fileURLWithPath: outputDirectoryPath) + .appendingPathComponent("\(moduleName).swift-java.classpath", isDirectory: false) + + try! classpathString.write(to: classpathOutputURL, atomically: true, encoding: .utf8) + + print("[swift-java-bootstrap] Done, written classpath to: \(classpathOutputURL)") + } + + func writeBuildGradle(directory: URL) { + // """ + // plugins { id 'java-library' } + // repositories { mavenCentral() } + // + // dependencies { + // implementation("dev.gradleplugins:gradle-api:8.10.1") + // } + // + // task \(printRuntimeClasspathTaskName) { + // def runtimeClasspath = sourceSets.main.runtimeClasspath + // inputs.files(runtimeClasspath) + // doLast { + // println("CLASSPATH:${runtimeClasspath.asPath}") + // } + // } + // """.write(to: URL(fileURLWithPath: tempDir.appendingPathComponent("build.gradle")).path(percentEncoded: false), atomically: true, encoding: .utf8) + // + // """ + // rootProject.name = "swift-java-resolve-temp-project" + // """.write(to: URL(fileURLWithPath: tempDir.appendingPathComponent("settings.gradle.kts")).path(percentEncoded: false), atomically: true, encoding: .utf8) + } + +} diff --git a/Sources/_Subprocess/Subprocess+IO.swift b/Sources/_Subprocess/Subprocess+IO.swift index 800d92d3..48e8754e 100644 --- a/Sources/_Subprocess/Subprocess+IO.swift +++ b/Sources/_Subprocess/Subprocess+IO.swift @@ -17,11 +17,10 @@ import Foundation import Dispatch import SystemPackage -import Synchronization // Naive Mutex so we don't have to update the macOS dependency final class _Mutex: Sendable { - let lock = NSLock() + let lock = Lock() var value: Value diff --git a/Sources/_Subprocess/_nio_locks.swift b/Sources/_Subprocess/_nio_locks.swift new file mode 100644 index 00000000..49053d04 --- /dev/null +++ b/Sources/_Subprocess/_nio_locks.swift @@ -0,0 +1,526 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the SwiftNIO open source project +// +// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of SwiftNIO project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +#if canImport(Darwin) +import Darwin +#elseif os(Windows) +import ucrt +import WinSDK +#elseif canImport(Glibc) +import Glibc +#elseif canImport(Musl) +import Musl +#else +#error("The concurrency lock module was unable to identify your C library.") +#endif + +/// A threading lock based on `libpthread` instead of `libdispatch`. +/// +/// This object provides a lock on top of a single `pthread_mutex_t`. This kind +/// of lock is safe to use with `libpthread`-based threading models, such as the +/// one used by NIO. On Windows, the lock is based on the substantially similar +/// `SRWLOCK` type. +@available(*, deprecated, renamed: "NIOLock") +public final class Lock { +#if os(Windows) + fileprivate let mutex: UnsafeMutablePointer = + UnsafeMutablePointer.allocate(capacity: 1) +#else + fileprivate let mutex: UnsafeMutablePointer = + UnsafeMutablePointer.allocate(capacity: 1) +#endif + + /// Create a new lock. + public init() { +#if os(Windows) + InitializeSRWLock(self.mutex) +#else + var attr = pthread_mutexattr_t() + pthread_mutexattr_init(&attr) + debugOnly { + pthread_mutexattr_settype(&attr, .init(PTHREAD_MUTEX_ERRORCHECK)) + } + + let err = pthread_mutex_init(self.mutex, &attr) + precondition(err == 0, "\(#function) failed in pthread_mutex with error \(err)") +#endif + } + + deinit { +#if os(Windows) + // SRWLOCK does not need to be free'd +#else + let err = pthread_mutex_destroy(self.mutex) + precondition(err == 0, "\(#function) failed in pthread_mutex with error \(err)") +#endif + mutex.deallocate() + } + + /// Acquire the lock. + /// + /// Whenever possible, consider using `withLock` instead of this method and + /// `unlock`, to simplify lock handling. + public func lock() { +#if os(Windows) + AcquireSRWLockExclusive(self.mutex) +#else + let err = pthread_mutex_lock(self.mutex) + precondition(err == 0, "\(#function) failed in pthread_mutex with error \(err)") +#endif + } + + /// Release the lock. + /// + /// Whenever possible, consider using `withLock` instead of this method and + /// `lock`, to simplify lock handling. + public func unlock() { +#if os(Windows) + ReleaseSRWLockExclusive(self.mutex) +#else + let err = pthread_mutex_unlock(self.mutex) + precondition(err == 0, "\(#function) failed in pthread_mutex with error \(err)") +#endif + } + + /// Acquire the lock for the duration of the given block. + /// + /// This convenience method should be preferred to `lock` and `unlock` in + /// most situations, as it ensures that the lock will be released regardless + /// of how `body` exits. + /// + /// - Parameter body: The block to execute while holding the lock. + /// - Returns: The value returned by the block. + @inlinable + public func withLock(_ body: () throws -> T) rethrows -> T { + self.lock() + defer { + self.unlock() + } + return try body() + } + + // specialise Void return (for performance) + @inlinable + public func withLockVoid(_ body: () throws -> Void) rethrows -> Void { + try self.withLock(body) + } +} + +/// A `Lock` with a built-in state variable. +/// +/// This class provides a convenience addition to `Lock`: it provides the ability to wait +/// until the state variable is set to a specific value to acquire the lock. +public final class ConditionLock { + private var _value: T + private let mutex: NIOLock +#if os(Windows) + private let cond: UnsafeMutablePointer = + UnsafeMutablePointer.allocate(capacity: 1) +#else + private let cond: UnsafeMutablePointer = + UnsafeMutablePointer.allocate(capacity: 1) +#endif + + /// Create the lock, and initialize the state variable to `value`. + /// + /// - Parameter value: The initial value to give the state variable. + public init(value: T) { + self._value = value + self.mutex = NIOLock() +#if os(Windows) + InitializeConditionVariable(self.cond) +#else + let err = pthread_cond_init(self.cond, nil) + precondition(err == 0, "\(#function) failed in pthread_cond with error \(err)") +#endif + } + + deinit { +#if os(Windows) + // condition variables do not need to be explicitly destroyed +#else + let err = pthread_cond_destroy(self.cond) + precondition(err == 0, "\(#function) failed in pthread_cond with error \(err)") +#endif + self.cond.deallocate() + } + + /// Acquire the lock, regardless of the value of the state variable. + public func lock() { + self.mutex.lock() + } + + /// Release the lock, regardless of the value of the state variable. + public func unlock() { + self.mutex.unlock() + } + + /// The value of the state variable. + /// + /// Obtaining the value of the state variable requires acquiring the lock. + /// This means that it is not safe to access this property while holding the + /// lock: it is only safe to use it when not holding it. + public var value: T { + self.lock() + defer { + self.unlock() + } + return self._value + } + + /// Acquire the lock when the state variable is equal to `wantedValue`. + /// + /// - Parameter wantedValue: The value to wait for the state variable + /// to have before acquiring the lock. + public func lock(whenValue wantedValue: T) { + self.lock() + while true { + if self._value == wantedValue { + break + } + self.mutex.withLockPrimitive { mutex in +#if os(Windows) + let result = SleepConditionVariableSRW(self.cond, mutex, INFINITE, 0) + precondition(result, "\(#function) failed in SleepConditionVariableSRW with error \(GetLastError())") +#else + let err = pthread_cond_wait(self.cond, mutex) + precondition(err == 0, "\(#function) failed in pthread_cond with error \(err)") +#endif + } + } + } + + /// Acquire the lock when the state variable is equal to `wantedValue`, + /// waiting no more than `timeoutSeconds` seconds. + /// + /// - Parameter wantedValue: The value to wait for the state variable + /// to have before acquiring the lock. + /// - Parameter timeoutSeconds: The number of seconds to wait to acquire + /// the lock before giving up. + /// - Returns: `true` if the lock was acquired, `false` if the wait timed out. + public func lock(whenValue wantedValue: T, timeoutSeconds: Double) -> Bool { + precondition(timeoutSeconds >= 0) + +#if os(Windows) + var dwMilliseconds: DWORD = DWORD(timeoutSeconds * 1000) + + self.lock() + while true { + if self._value == wantedValue { + return true + } + + let dwWaitStart = timeGetTime() + if !SleepConditionVariableSRW(self.cond, self.mutex._storage.mutex, + dwMilliseconds, 0) { + let dwError = GetLastError() + if (dwError == ERROR_TIMEOUT) { + self.unlock() + return false + } + fatalError("SleepConditionVariableSRW: \(dwError)") + } + + // NOTE: this may be a spurious wakeup, adjust the timeout accordingly + dwMilliseconds = dwMilliseconds - (timeGetTime() - dwWaitStart) + } +#else + let nsecPerSec: Int64 = 1000000000 + self.lock() + /* the timeout as a (seconds, nano seconds) pair */ + let timeoutNS = Int64(timeoutSeconds * Double(nsecPerSec)) + + var curTime = timeval() + gettimeofday(&curTime, nil) + + let allNSecs: Int64 = timeoutNS + Int64(curTime.tv_usec) * 1000 + var timeoutAbs = timespec(tv_sec: curTime.tv_sec + Int((allNSecs / nsecPerSec)), + tv_nsec: Int(allNSecs % nsecPerSec)) + assert(timeoutAbs.tv_nsec >= 0 && timeoutAbs.tv_nsec < Int(nsecPerSec)) + assert(timeoutAbs.tv_sec >= curTime.tv_sec) + return self.mutex.withLockPrimitive { mutex -> Bool in + while true { + if self._value == wantedValue { + return true + } + switch pthread_cond_timedwait(self.cond, mutex, &timeoutAbs) { + case 0: + continue + case ETIMEDOUT: + self.unlock() + return false + case let e: + fatalError("caught error \(e) when calling pthread_cond_timedwait") + } + } + } +#endif + } + + /// Release the lock, setting the state variable to `newValue`. + /// + /// - Parameter newValue: The value to give to the state variable when we + /// release the lock. + public func unlock(withValue newValue: T) { + self._value = newValue + self.unlock() +#if os(Windows) + WakeAllConditionVariable(self.cond) +#else + let err = pthread_cond_broadcast(self.cond) + precondition(err == 0, "\(#function) failed in pthread_cond with error \(err)") +#endif + } +} + +/// A utility function that runs the body code only in debug builds, without +/// emitting compiler warnings. +/// +/// This is currently the only way to do this in Swift: see +/// https://forums.swift.org/t/support-debug-only-code/11037 for a discussion. +@inlinable +internal func debugOnly(_ body: () -> Void) { + assert({ body(); return true }()) +} + +@available(*, deprecated) +extension Lock: @unchecked Sendable {} +extension ConditionLock: @unchecked Sendable {} + +#if os(Windows) +@usableFromInline +typealias LockPrimitive = SRWLOCK +#else +@usableFromInline +typealias LockPrimitive = pthread_mutex_t +#endif + +@usableFromInline +enum LockOperations { } + +extension LockOperations { + @inlinable + static func create(_ mutex: UnsafeMutablePointer) { + mutex.assertValidAlignment() + +#if os(Windows) + InitializeSRWLock(mutex) +#else + var attr = pthread_mutexattr_t() + pthread_mutexattr_init(&attr) + debugOnly { + pthread_mutexattr_settype(&attr, .init(PTHREAD_MUTEX_ERRORCHECK)) + } + + let err = pthread_mutex_init(mutex, &attr) + precondition(err == 0, "\(#function) failed in pthread_mutex with error \(err)") +#endif + } + + @inlinable + static func destroy(_ mutex: UnsafeMutablePointer) { + mutex.assertValidAlignment() + +#if os(Windows) + // SRWLOCK does not need to be free'd +#else + let err = pthread_mutex_destroy(mutex) + precondition(err == 0, "\(#function) failed in pthread_mutex with error \(err)") +#endif + } + + @inlinable + static func lock(_ mutex: UnsafeMutablePointer) { + mutex.assertValidAlignment() + +#if os(Windows) + AcquireSRWLockExclusive(mutex) +#else + let err = pthread_mutex_lock(mutex) + precondition(err == 0, "\(#function) failed in pthread_mutex with error \(err)") +#endif + } + + @inlinable + static func unlock(_ mutex: UnsafeMutablePointer) { + mutex.assertValidAlignment() + +#if os(Windows) + ReleaseSRWLockExclusive(mutex) +#else + let err = pthread_mutex_unlock(mutex) + precondition(err == 0, "\(#function) failed in pthread_mutex with error \(err)") +#endif + } +} + +// Tail allocate both the mutex and a generic value using ManagedBuffer. +// Both the header pointer and the elements pointer are stable for +// the class's entire lifetime. +// +// However, for safety reasons, we elect to place the lock in the "elements" +// section of the buffer instead of the head. The reasoning here is subtle, +// so buckle in. +// +// _As a practical matter_, the implementation of ManagedBuffer ensures that +// the pointer to the header is stable across the lifetime of the class, and so +// each time you call `withUnsafeMutablePointers` or `withUnsafeMutablePointerToHeader` +// the value of the header pointer will be the same. This is because ManagedBuffer uses +// `Builtin.addressOf` to load the value of the header, and that does ~magic~ to ensure +// that it does not invoke any weird Swift accessors that might copy the value. +// +// _However_, the header is also available via the `.header` field on the ManagedBuffer. +// This presents a problem! The reason there's an issue is that `Builtin.addressOf` and friends +// do not interact with Swift's exclusivity model. That is, the various `with` functions do not +// conceptually trigger a mutating access to `.header`. For elements this isn't a concern because +// there's literally no other way to perform the access, but for `.header` it's entirely possible +// to accidentally recursively read it. +// +// Our implementation is free from these issues, so we don't _really_ need to worry about it. +// However, out of an abundance of caution, we store the Value in the header, and the LockPrimitive +// in the trailing elements. We still don't use `.header`, but it's better to be safe than sorry, +// and future maintainers will be happier that we were cautious. +// +// See also: https://github.com/apple/swift/pull/40000 +@usableFromInline +final class LockStorage: ManagedBuffer { + + @inlinable + static func create(value: Value) -> Self { + let buffer = Self.create(minimumCapacity: 1) { _ in + return value + } + let storage = unsafeDowncast(buffer, to: Self.self) + + storage.withUnsafeMutablePointers { _, lockPtr in + LockOperations.create(lockPtr) + } + + return storage + } + + @inlinable + func lock() { + self.withUnsafeMutablePointerToElements { lockPtr in + LockOperations.lock(lockPtr) + } + } + + @inlinable + func unlock() { + self.withUnsafeMutablePointerToElements { lockPtr in + LockOperations.unlock(lockPtr) + } + } + + @inlinable + deinit { + self.withUnsafeMutablePointerToElements { lockPtr in + LockOperations.destroy(lockPtr) + } + } + + @inlinable + func withLockPrimitive(_ body: (UnsafeMutablePointer) throws -> T) rethrows -> T { + try self.withUnsafeMutablePointerToElements { lockPtr in + return try body(lockPtr) + } + } + + @inlinable + func withLockedValue(_ mutate: (inout Value) throws -> T) rethrows -> T { + try self.withUnsafeMutablePointers { valuePtr, lockPtr in + LockOperations.lock(lockPtr) + defer { LockOperations.unlock(lockPtr) } + return try mutate(&valuePtr.pointee) + } + } +} + +extension LockStorage: @unchecked Sendable { } + +/// A threading lock based on `libpthread` instead of `libdispatch`. +/// +/// - note: ``NIOLock`` has reference semantics. +/// +/// This object provides a lock on top of a single `pthread_mutex_t`. This kind +/// of lock is safe to use with `libpthread`-based threading models, such as the +/// one used by NIO. On Windows, the lock is based on the substantially similar +/// `SRWLOCK` type. +public struct NIOLock { + @usableFromInline + internal let _storage: LockStorage + + /// Create a new lock. + @inlinable + public init() { + self._storage = .create(value: ()) + } + + /// Acquire the lock. + /// + /// Whenever possible, consider using `withLock` instead of this method and + /// `unlock`, to simplify lock handling. + @inlinable + public func lock() { + self._storage.lock() + } + + /// Release the lock. + /// + /// Whenever possible, consider using `withLock` instead of this method and + /// `lock`, to simplify lock handling. + @inlinable + public func unlock() { + self._storage.unlock() + } + + @inlinable + internal func withLockPrimitive(_ body: (UnsafeMutablePointer) throws -> T) rethrows -> T { + return try self._storage.withLockPrimitive(body) + } +} + +extension NIOLock { + /// Acquire the lock for the duration of the given block. + /// + /// This convenience method should be preferred to `lock` and `unlock` in + /// most situations, as it ensures that the lock will be released regardless + /// of how `body` exits. + /// + /// - Parameter body: The block to execute while holding the lock. + /// - Returns: The value returned by the block. + @inlinable + public func withLock(_ body: () throws -> T) rethrows -> T { + self.lock() + defer { + self.unlock() + } + return try body() + } + + @inlinable + public func withLockVoid(_ body: () throws -> Void) rethrows -> Void { + try self.withLock(body) + } +} + +extension NIOLock: Sendable {} + +extension UnsafeMutablePointer { + @inlinable + func assertValidAlignment() { + assert(UInt(bitPattern: self) % UInt(MemoryLayout.alignment) == 0) + } +} From 6485e9ab4be7172340fd7fcbe9f41d5418d5ac33 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Wed, 11 Dec 2024 15:34:12 +0900 Subject: [PATCH 197/426] fix license headers in vendored code (just wording) --- .licenseignore | 3 ++- Sources/_CShims/include/_CShimsTargetConditionals.h | 10 ++++++---- Sources/_CShims/include/process_shims.h | 9 ++++++--- Sources/_CShims/process_shims.c | 9 ++++++--- Sources/_Subprocess/LockedState.swift | 10 ++++++---- .../_Subprocess/Platforms/Subprocess+Darwin.swift | 9 ++++++--- .../_Subprocess/Platforms/Subprocess+Linux.swift | 9 ++++++--- Sources/_Subprocess/Platforms/Subprocess+Unix.swift | 9 ++++++--- .../_Subprocess/Platforms/Subprocess+Windows.swift | 9 ++++++--- Sources/_Subprocess/Subprocess+API.swift | 9 ++++++--- .../_Subprocess/Subprocess+AsyncDataSequence.swift | 9 ++++++--- Sources/_Subprocess/Subprocess+Configuration.swift | 10 ++++++---- Sources/_Subprocess/Subprocess+Teardown.swift | 13 ++++++++++--- Sources/_Subprocess/Subprocess.swift | 9 ++++++--- 14 files changed, 84 insertions(+), 43 deletions(-) diff --git a/.licenseignore b/.licenseignore index 5f93c9a6..585ab5a4 100644 --- a/.licenseignore +++ b/.licenseignore @@ -43,4 +43,5 @@ gradlew.bat **/DO_NOT_EDIT.txt Plugins/**/_PluginsShared Plugins/**/0_PLEASE_SYMLINK* -Plugins/PluginsShared/JavaKitConfigurationShared \ No newline at end of file +Plugins/PluginsShared/JavaKitConfigurationShared +Sources/_Subprocess/_nio_locks.swift \ No newline at end of file diff --git a/Sources/_CShims/include/_CShimsTargetConditionals.h b/Sources/_CShims/include/_CShimsTargetConditionals.h index fef2eaf2..9e1d80cb 100644 --- a/Sources/_CShims/include/_CShimsTargetConditionals.h +++ b/Sources/_CShims/include/_CShimsTargetConditionals.h @@ -2,11 +2,13 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2021 - 2022 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 // -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// diff --git a/Sources/_CShims/include/process_shims.h b/Sources/_CShims/include/process_shims.h index 3b03d103..563b517f 100644 --- a/Sources/_CShims/include/process_shims.h +++ b/Sources/_CShims/include/process_shims.h @@ -2,10 +2,13 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2024 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 // -// See https://swift.org/LICENSE.txt for license information +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// diff --git a/Sources/_CShims/process_shims.c b/Sources/_CShims/process_shims.c index 2d7d4a4a..fe96c675 100644 --- a/Sources/_CShims/process_shims.c +++ b/Sources/_CShims/process_shims.c @@ -2,10 +2,13 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2024 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 // -// See https://swift.org/LICENSE.txt for license information +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// diff --git a/Sources/_Subprocess/LockedState.swift b/Sources/_Subprocess/LockedState.swift index 0cde3b94..e095668c 100644 --- a/Sources/_Subprocess/LockedState.swift +++ b/Sources/_Subprocess/LockedState.swift @@ -2,11 +2,13 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2022 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 // -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// diff --git a/Sources/_Subprocess/Platforms/Subprocess+Darwin.swift b/Sources/_Subprocess/Platforms/Subprocess+Darwin.swift index 2d02cd1d..4ac2276e 100644 --- a/Sources/_Subprocess/Platforms/Subprocess+Darwin.swift +++ b/Sources/_Subprocess/Platforms/Subprocess+Darwin.swift @@ -2,10 +2,13 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2024 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 // -// See https://swift.org/LICENSE.txt for license information +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// diff --git a/Sources/_Subprocess/Platforms/Subprocess+Linux.swift b/Sources/_Subprocess/Platforms/Subprocess+Linux.swift index 10d39e94..9debf2e3 100644 --- a/Sources/_Subprocess/Platforms/Subprocess+Linux.swift +++ b/Sources/_Subprocess/Platforms/Subprocess+Linux.swift @@ -2,10 +2,13 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2024 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 // -// See https://swift.org/LICENSE.txt for license information +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// diff --git a/Sources/_Subprocess/Platforms/Subprocess+Unix.swift b/Sources/_Subprocess/Platforms/Subprocess+Unix.swift index 3155743c..bd110301 100644 --- a/Sources/_Subprocess/Platforms/Subprocess+Unix.swift +++ b/Sources/_Subprocess/Platforms/Subprocess+Unix.swift @@ -2,10 +2,13 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2024 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 // -// See https://swift.org/LICENSE.txt for license information +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// diff --git a/Sources/_Subprocess/Platforms/Subprocess+Windows.swift b/Sources/_Subprocess/Platforms/Subprocess+Windows.swift index 98ec40bf..978cb139 100644 --- a/Sources/_Subprocess/Platforms/Subprocess+Windows.swift +++ b/Sources/_Subprocess/Platforms/Subprocess+Windows.swift @@ -2,10 +2,13 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2024 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 // -// See https://swift.org/LICENSE.txt for license information +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// diff --git a/Sources/_Subprocess/Subprocess+API.swift b/Sources/_Subprocess/Subprocess+API.swift index b202fedf..f9c8b1ec 100644 --- a/Sources/_Subprocess/Subprocess+API.swift +++ b/Sources/_Subprocess/Subprocess+API.swift @@ -2,10 +2,13 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2024 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 // -// See https://swift.org/LICENSE.txt for license information +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// diff --git a/Sources/_Subprocess/Subprocess+AsyncDataSequence.swift b/Sources/_Subprocess/Subprocess+AsyncDataSequence.swift index d2026fef..a3a3e393 100644 --- a/Sources/_Subprocess/Subprocess+AsyncDataSequence.swift +++ b/Sources/_Subprocess/Subprocess+AsyncDataSequence.swift @@ -2,10 +2,13 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2024 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 // -// See https://swift.org/LICENSE.txt for license information +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// diff --git a/Sources/_Subprocess/Subprocess+Configuration.swift b/Sources/_Subprocess/Subprocess+Configuration.swift index 68915eea..0b785790 100644 --- a/Sources/_Subprocess/Subprocess+Configuration.swift +++ b/Sources/_Subprocess/Subprocess+Configuration.swift @@ -2,16 +2,18 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2024 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 // -// See https://swift.org/LICENSE.txt for license information +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// @preconcurrency import SystemPackage - #if canImport(Darwin) import Darwin #elseif canImport(Glibc) diff --git a/Sources/_Subprocess/Subprocess+Teardown.swift b/Sources/_Subprocess/Subprocess+Teardown.swift index ee4b7333..8b9af32d 100644 --- a/Sources/_Subprocess/Subprocess+Teardown.swift +++ b/Sources/_Subprocess/Subprocess+Teardown.swift @@ -1,9 +1,16 @@ +//===----------------------------------------------------------------------===// // -// Suubprocess+Teardown.swift -// SwiftExperimentalSubprocess +// This source file is part of the Swift.org open source project // -// Created by Charles Hu on 12/6/24. +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 // +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// #if canImport(Darwin) || canImport(Glibc) diff --git a/Sources/_Subprocess/Subprocess.swift b/Sources/_Subprocess/Subprocess.swift index 8c66ed03..35f4a2c2 100644 --- a/Sources/_Subprocess/Subprocess.swift +++ b/Sources/_Subprocess/Subprocess.swift @@ -2,10 +2,13 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2024 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 // -// See https://swift.org/LICENSE.txt for license information +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// From e9ffca56646888f5cae278c1bad362ce1785ad08 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Wed, 11 Dec 2024 15:36:06 +0900 Subject: [PATCH 198/426] ignore the Subprocess files since APIs use process "kill" internally --- .unacceptablelanguageignore | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 .unacceptablelanguageignore diff --git a/.unacceptablelanguageignore b/.unacceptablelanguageignore new file mode 100644 index 00000000..0310d1c3 --- /dev/null +++ b/.unacceptablelanguageignore @@ -0,0 +1,17 @@ +Sources/SwiftJavaBootstrapJavaTool/SwiftJavaBootstrapJavaTool.swift +Sources/_Subprocess/Platforms/Subprocess+Darwin.swift +Sources/_Subprocess/Platforms/Subprocess+Linux.swift +Sources/_Subprocess/Platforms/Subprocess+Unix.swift +Sources/_Subprocess/Platforms/Subprocess+Unix.swift +Sources/_Subprocess/Platforms/Subprocess+Unix.swift +Sources/_Subprocess/Platforms/Subprocess+Unix.swift +Sources/_Subprocess/Platforms/Subprocess+Unix.swift +Sources/_Subprocess/Platforms/Subprocess+Unix.swift +Sources/_Subprocess/Subprocess+Teardown.swift +Sources/_Subprocess/Subprocess+Teardown.swift +Sources/_Subprocess/Subprocess+Teardown.swift +Sources/_Subprocess/Subprocess+Teardown.swift +Sources/_Subprocess/Subprocess+Teardown.swift +Sources/_Subprocess/Subprocess+Teardown.swift +Sources/_Subprocess/Subprocess+Teardown.swift +Sources/_Subprocess/Subprocess.swift \ No newline at end of file From 9844e3122dd1f678c466428b22e0a7ba84de0c89 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Wed, 11 Dec 2024 15:46:29 +0900 Subject: [PATCH 199/426] debugging CI paths --- .github/workflows/pull_request.yml | 2 +- Samples/JavaDependencySampleApp/ci-validate.sh | 2 +- .../SwiftJavaBootstrapJavaTool.swift | 13 +++++++------ 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index d289296d..2aaa845b 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -60,7 +60,7 @@ jobs: - name: Prepare CI Environment uses: ./.github/actions/prepare_env - name: Swift Build - run: "swift build --build-tests" + run: "swift build --build-tests --disable-sandbox" - name: Swift Test run: "swift test" diff --git a/Samples/JavaDependencySampleApp/ci-validate.sh b/Samples/JavaDependencySampleApp/ci-validate.sh index 4125fde1..b21d19d4 100755 --- a/Samples/JavaDependencySampleApp/ci-validate.sh +++ b/Samples/JavaDependencySampleApp/ci-validate.sh @@ -6,7 +6,7 @@ set -x # TODO: this is a workaround for build plugins getting stuck running the bootstrap plugin cd ../../ swift build --product SwiftJavaBootstrapJavaTool -.build/arm64-apple-macosx/debug/SwiftJavaBootstrapJavaTool --fetch Sources/JavaKitDependencyResolver/swift-java.config --module-name JavaKitDependencyResolver --output-directory .build/plugins/outputs/swift-java/JavaKitDependencyResolver/destination/SwiftJavaBootstrapJavaPlugin +.build/debug/SwiftJavaBootstrapJavaTool --fetch Sources/JavaKitDependencyResolver/swift-java.config --module-name JavaKitDependencyResolver --output-directory .build/plugins/outputs/swift-java/JavaKitDependencyResolver/destination/SwiftJavaBootstrapJavaPlugin cd - swift run --disable-sandbox diff --git a/Sources/SwiftJavaBootstrapJavaTool/SwiftJavaBootstrapJavaTool.swift b/Sources/SwiftJavaBootstrapJavaTool/SwiftJavaBootstrapJavaTool.swift index ecc87dd3..d37e8b08 100644 --- a/Sources/SwiftJavaBootstrapJavaTool/SwiftJavaBootstrapJavaTool.swift +++ b/Sources/SwiftJavaBootstrapJavaTool/SwiftJavaBootstrapJavaTool.swift @@ -35,7 +35,7 @@ final class SwiftJavaBootstrapJavaTool { } func run() async throws { - print("RUN SwiftJavaBootstrapJavaTool: \(CommandLine.arguments)") + print("[debug][swift-java-bootstrap] RUN SwiftJavaBootstrapJavaTool: \(CommandLine.arguments.joined(separator: " "))") var args = CommandLine.arguments _ = args.removeFirst() // executable @@ -48,8 +48,10 @@ final class SwiftJavaBootstrapJavaTool { assert(args.removeFirst() == "--output-directory") let outputDirectoryPath = args.removeFirst() - - let config = try readConfiguration(configPath: URL(fileURLWithPath: configPath)) + + let configPathURL = URL(fileURLWithPath: configPath) + print("[debug][swift-java-bootstrap] Load config: \(configPathURL.absoluteString)") + let config = try readConfiguration(configPath: configPathURL) // We only support a single dependency right now. let localGradleProjectDependencyName = (config.dependencies ?? []).filter { @@ -65,9 +67,8 @@ final class SwiftJavaBootstrapJavaTool { "--rerun-tasks", // "--debug", // "\(localGradleProjectDependencyName):jar", - "\(localGradleProjectDependencyName):\(printRuntimeClasspathTaskName)", - ], - workingDirectory: "/Users/ktoso/code/swift-java" + "\(localGradleProjectDependencyName):\(printRuntimeClasspathTaskName)" + ] ) let outString = String( From a738449fdbc0b5056195a2be2078de9a7383cfcf Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Wed, 11 Dec 2024 16:15:50 +0900 Subject: [PATCH 200/426] ignore .unacceptablelanguageignore from license checks --- .licenseignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.licenseignore b/.licenseignore index 585ab5a4..8b9d0933 100644 --- a/.licenseignore +++ b/.licenseignore @@ -14,6 +14,7 @@ Package.resolved README.md SECURITY.md scripts/unacceptable-language.txt +.unacceptablelanguageignore docker/* **/*.docc/* **/.gitignore From e54b5121d25d3291f025f5e51bd992b74d61dc7e Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Wed, 11 Dec 2024 16:33:35 +0900 Subject: [PATCH 201/426] workaround: disable bootstrap plugin --- Package.swift | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Package.swift b/Package.swift index 50b5da2a..8cda1aed 100644 --- a/Package.swift +++ b/Package.swift @@ -186,10 +186,12 @@ let package = Package( swiftSettings: [ .swiftLanguageMode(.v5), .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]), - ], - plugins: [ - "SwiftJavaBootstrapJavaPlugin", ] +// // FIXME: when the tool is run from plugin it hangs even if sandbox is disabled +// , +// plugins: [ +// "SwiftJavaBootstrapJavaPlugin", +// ] ), .target( From a7dbb90f9e20ba13ed26a7eb70e2de9d7092fae1 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Wed, 11 Dec 2024 16:42:33 +0900 Subject: [PATCH 202/426] create intermediate directories for output file --- .../SwiftJavaBootstrapJavaTool.swift | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Sources/SwiftJavaBootstrapJavaTool/SwiftJavaBootstrapJavaTool.swift b/Sources/SwiftJavaBootstrapJavaTool/SwiftJavaBootstrapJavaTool.swift index d37e8b08..96042a1e 100644 --- a/Sources/SwiftJavaBootstrapJavaTool/SwiftJavaBootstrapJavaTool.swift +++ b/Sources/SwiftJavaBootstrapJavaTool/SwiftJavaBootstrapJavaTool.swift @@ -95,7 +95,13 @@ final class SwiftJavaBootstrapJavaTool { } let classpathString = String(classpathOutput.dropFirst(self.SwiftJavaClasspathPrefix.count)) - + + _ = try? FileManager.default.createDirectory( + at: outputDirectoryPath, + withIntermediateDirectories: true, + attributes: nil + ) + let classpathOutputURL = URL(fileURLWithPath: outputDirectoryPath) .appendingPathComponent("\(moduleName).swift-java.classpath", isDirectory: false) From 5ca3e7fa860a81e30e0893cba1bcb554c26593a5 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Wed, 11 Dec 2024 16:46:02 +0900 Subject: [PATCH 203/426] license header fix --- Sources/_Subprocess/Subprocess+IO.swift | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Sources/_Subprocess/Subprocess+IO.swift b/Sources/_Subprocess/Subprocess+IO.swift index 48e8754e..1b43e421 100644 --- a/Sources/_Subprocess/Subprocess+IO.swift +++ b/Sources/_Subprocess/Subprocess+IO.swift @@ -2,10 +2,13 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2024 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 // -// See https://swift.org/LICENSE.txt for license information +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// From f15661911bbaf0766fabfc78b91753bc7da53390 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Wed, 11 Dec 2024 16:46:10 +0900 Subject: [PATCH 204/426] use try! since we get better error location from it --- .../SwiftJavaBootstrapJavaTool.swift | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Sources/SwiftJavaBootstrapJavaTool/SwiftJavaBootstrapJavaTool.swift b/Sources/SwiftJavaBootstrapJavaTool/SwiftJavaBootstrapJavaTool.swift index 96042a1e..11f26a67 100644 --- a/Sources/SwiftJavaBootstrapJavaTool/SwiftJavaBootstrapJavaTool.swift +++ b/Sources/SwiftJavaBootstrapJavaTool/SwiftJavaBootstrapJavaTool.swift @@ -30,11 +30,11 @@ final class SwiftJavaBootstrapJavaTool { let out = Synchronization.Mutex(Data()) let err = Synchronization.Mutex(Data()) - static func main() async throws { - try await SwiftJavaBootstrapJavaTool().run() + static func main() async { + await SwiftJavaBootstrapJavaTool().run() } - func run() async throws { + func run() async { print("[debug][swift-java-bootstrap] RUN SwiftJavaBootstrapJavaTool: \(CommandLine.arguments.joined(separator: " "))") var args = CommandLine.arguments @@ -51,7 +51,7 @@ final class SwiftJavaBootstrapJavaTool { let configPathURL = URL(fileURLWithPath: configPath) print("[debug][swift-java-bootstrap] Load config: \(configPathURL.absoluteString)") - let config = try readConfiguration(configPath: configPathURL) + let config = try! readConfiguration(configPath: configPathURL) // We only support a single dependency right now. let localGradleProjectDependencyName = (config.dependencies ?? []).filter { @@ -60,7 +60,7 @@ final class SwiftJavaBootstrapJavaTool { $0.artifactID }.first! - let process = try await Subprocess.run( + let process = try! await Subprocess.run( .at("./gradlew"), arguments: [ "--no-daemon", @@ -97,7 +97,7 @@ final class SwiftJavaBootstrapJavaTool { let classpathString = String(classpathOutput.dropFirst(self.SwiftJavaClasspathPrefix.count)) _ = try? FileManager.default.createDirectory( - at: outputDirectoryPath, + at: URL(fileURLWithPath: outputDirectoryPath), withIntermediateDirectories: true, attributes: nil ) From 626e06bf410e6943fba9b3f045f80b0c37fd152c Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Wed, 11 Dec 2024 18:23:31 +0900 Subject: [PATCH 205/426] Reimplement dependency fetching with just swift processes; require gradlew --- .licenseignore | 3 +- JavaKit/build.gradle | 72 ----- JavaKit/gradlew.bat | 1 - .../javakit/annotations/UsedFromSwift.java | 28 -- .../dependencies/DependencyResolver.java | 303 ------------------ .../SwiftJavaBootstrapException.java | 25 -- Package.swift | 47 +-- .../JExtractSwiftPlugin.swift | 0 .../_PluginsShared | 0 .../Java2SwiftPlugin/Java2SwiftPlugin.swift | 4 +- .../SwiftJavaBootstrapJavaPlugin.swift | 190 ----------- Plugins/SwiftJavaPlugin/_PluginsShared | 1 - Samples/JavaDependencySampleApp/Package.swift | 1 + .../Sources/JavaDependencySample/main.swift | 6 +- .../JavaDependencySampleApp/ci-validate.sh | 6 - Samples/JavaDependencySampleApp/gradle | 1 + Samples/JavaDependencySampleApp/gradlew | 1 + Samples/JavaDependencySampleApp/gradlew.bat | 1 + .../SwiftAndJavaJarSampleLib/Package.swift | 2 +- Samples/SwiftKitSampleApp/Package.swift | 2 +- Samples/gradle | 1 + {JavaKit => Samples}/gradlew | 0 .../JavaToSwift+EmitConfiguration.swift | 1 - .../JavaToSwift+FetchDependencies.swift | 176 +++++++--- .../JavaToSwift+GenerateWrappers.swift | 3 +- Sources/Java2Swift/JavaToSwift.swift | 48 +-- Sources/Java2Swift/String+Extensions.swift | 1 - .../Configuration.swift | 11 + .../SwiftJavaBootstrapJavaTool.swift | 137 -------- settings.gradle | 1 - 30 files changed, 179 insertions(+), 894 deletions(-) delete mode 100644 JavaKit/build.gradle delete mode 120000 JavaKit/gradlew.bat delete mode 100644 JavaKit/src/main/java/org/swift/javakit/annotations/UsedFromSwift.java delete mode 100644 JavaKit/src/main/java/org/swift/javakit/dependencies/DependencyResolver.java delete mode 100644 JavaKit/src/main/java/org/swift/javakit/dependencies/SwiftJavaBootstrapException.java rename Plugins/{SwiftJavaPlugin => JExtractSwiftPlugin}/JExtractSwiftPlugin.swift (100%) rename Plugins/{SwiftJavaBootstrapJavaPlugin => JExtractSwiftPlugin}/_PluginsShared (100%) delete mode 100644 Plugins/SwiftJavaBootstrapJavaPlugin/SwiftJavaBootstrapJavaPlugin.swift delete mode 120000 Plugins/SwiftJavaPlugin/_PluginsShared create mode 120000 Samples/JavaDependencySampleApp/gradle create mode 120000 Samples/JavaDependencySampleApp/gradlew create mode 120000 Samples/JavaDependencySampleApp/gradlew.bat create mode 120000 Samples/gradle rename {JavaKit => Samples}/gradlew (100%) delete mode 100644 Sources/SwiftJavaBootstrapJavaTool/SwiftJavaBootstrapJavaTool.swift diff --git a/.licenseignore b/.licenseignore index 8b9d0933..ada8e1de 100644 --- a/.licenseignore +++ b/.licenseignore @@ -45,4 +45,5 @@ gradlew.bat Plugins/**/_PluginsShared Plugins/**/0_PLEASE_SYMLINK* Plugins/PluginsShared/JavaKitConfigurationShared -Sources/_Subprocess/_nio_locks.swift \ No newline at end of file +Samples/JavaDependencySampleApp/gradle +Sources/_Subprocess/_nio_locks.swift diff --git a/JavaKit/build.gradle b/JavaKit/build.gradle deleted file mode 100644 index 70982e90..00000000 --- a/JavaKit/build.gradle +++ /dev/null @@ -1,72 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of Swift.org project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -plugins { - id("build-logic.java-library-conventions") -} - -group = "org.swift.javakit" -version = "1.0-SNAPSHOT" - -repositories { - mavenCentral() -} - -java { - toolchain { - languageVersion.set(JavaLanguageVersion.of(22)) - } -} - -dependencies { - implementation("dev.gradleplugins:gradle-api:8.10.1") - - testImplementation(platform("org.junit:junit-bom:5.10.0")) - testImplementation("org.junit.jupiter:junit-jupiter") -} - -tasks.test { - useJUnitPlatform() - testLogging { - events("passed", "skipped", "failed") - } -} - -// Copy the gradle wrapper we're using into the resulting jar's resources. -// We'll use it to bootstrap dependencies (and gradle!) if there is none yet. -tasks.processResources { - from('gradlew') { - into 'gradle/' - } - from('gradlew.bat') { - into 'gradle/' - } - from('../gradle/wrapper/gradle-wrapper.jar') { - into 'gradle/wrapper/' - } - from('../gradle/wrapper/gradle-wrapper.properties') { - into 'gradle/wrapper/' - } -} - -// Task necessary to bootstrap and EXIT, this is to prevent hangs when used via SwiftPM plugin. -tasks.register('printRuntimeClasspath') { - dependsOn 'jar' - - def runtimeClasspath = sourceSets.main.runtimeClasspath - inputs.files(runtimeClasspath) - doLast { - println("SWIFT_JAVA_CLASSPATH:${runtimeClasspath.asPath}") - } -} diff --git a/JavaKit/gradlew.bat b/JavaKit/gradlew.bat deleted file mode 120000 index 28401328..00000000 --- a/JavaKit/gradlew.bat +++ /dev/null @@ -1 +0,0 @@ -../gradlew.bat \ No newline at end of file diff --git a/JavaKit/src/main/java/org/swift/javakit/annotations/UsedFromSwift.java b/JavaKit/src/main/java/org/swift/javakit/annotations/UsedFromSwift.java deleted file mode 100644 index ad9e7918..00000000 --- a/JavaKit/src/main/java/org/swift/javakit/annotations/UsedFromSwift.java +++ /dev/null @@ -1,28 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of Swift.org project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -package org.swift.javakit.annotations; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -/** - * Since some public methods may not appear as used in Java source code, but are used by Swift, - * we can use this source annotation to mark such entry points to not accidentally remove them with - * "safe delete" refactorings in Java IDEs which would be unaware of the usages from Swift. - */ -@SuppressWarnings("unused") // used from Swift -@Retention(RetentionPolicy.SOURCE) -public @interface UsedFromSwift { -} diff --git a/JavaKit/src/main/java/org/swift/javakit/dependencies/DependencyResolver.java b/JavaKit/src/main/java/org/swift/javakit/dependencies/DependencyResolver.java deleted file mode 100644 index 0e801525..00000000 --- a/JavaKit/src/main/java/org/swift/javakit/dependencies/DependencyResolver.java +++ /dev/null @@ -1,303 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of Swift.org project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -package org.swift.javakit.dependencies; - -import org.gradle.tooling.GradleConnector; -import org.swift.javakit.annotations.UsedFromSwift; - -import java.io.*; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.StandardOpenOption; -import java.util.Arrays; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -/** - * Fetches dependencies using the Gradle resolver and returns the resulting classpath which includes - * the fetched dependency and all of its dependencies. - */ -@UsedFromSwift -@SuppressWarnings("unused") -public class DependencyResolver { - - private static final String COMMAND_OUTPUT_LINE_PREFIX_CLASSPATH = "SWIFT_JAVA_CLASSPATH:"; - private static final String CLASSPATH_CACHE_FILENAME = "JavaKitDependencyResolver.swift-java.classpath"; - - public static String GRADLE_API_DEPENDENCY = "dev.gradleplugins:gradle-api:8.10.1"; - public static String[] BASE_DEPENDENCIES = { - GRADLE_API_DEPENDENCY - }; - - /** - * May throw runtime exceptions including {@link org.gradle.api.internal.artifacts.ivyservice.TypedResolveException} - * if unable to resolve a dependency. - */ - @UsedFromSwift - @SuppressWarnings("unused") - public static String resolveDependenciesToClasspath(String projectBaseDirectoryString, String[] dependencies) throws IOException { - try { - simpleLog("Fetch dependencies: " + Arrays.toString(dependencies)); - simpleLog("Classpath: " + System.getProperty("java.class.path")); - var projectBasePath = new File(projectBaseDirectoryString).toPath(); - - File projectDir = Files.createTempDirectory("java-swift-dependencies").toFile(); - projectDir.mkdirs(); - - if (hasDependencyResolverDependenciesLoaded()) { - // === Resolve dependencies using Gradle API in-process - simpleLog("Gradle API runtime dependency is available, resolve dependencies..."); - return resolveDependenciesUsingAPI(projectDir, dependencies); - } - - // === Bootstrap the resolver dependencies and cache them - simpleLog("Gradle API not available on classpath, bootstrap %s dependencies: %s" - .formatted(DependencyResolver.class.getSimpleName(), Arrays.toString(BASE_DEPENDENCIES))); - String dependencyResolverDependenciesClasspath = bootstrapDependencyResolverClasspath(); - writeDependencyResolverClasspath(projectBasePath, dependencyResolverDependenciesClasspath); - - // --- Resolve dependencies using sub-process process - // TODO: it would be nice to just add the above classpath to the system classloader and here call the API - // immediately, but that's challenging and not a stable API we can rely on (hacks exist to add paths - // to system classloader but are not reliable). - printBuildFiles(projectDir, dependencies); - return resolveDependenciesWithSubprocess(projectDir); - } catch (Exception e) { - e.printStackTrace(); - throw e; - } - } - - - /** - * Use an external {@code gradle} invocation in order to download dependencies such that we can use `gradle-api` - * next time we want to resolve dependencies. This uses an external process and is slightly worse than using the API - * directly. - * - * @return classpath obtained for the dependencies - * @throws IOException if file IO failed during mock project creation - * @throws SwiftJavaBootstrapException if the resolve failed for some other reason - */ - private static String bootstrapDependencyResolverClasspath() throws IOException, SwiftJavaBootstrapException { - var dependencies = BASE_DEPENDENCIES; - simpleLog("Bootstrap gradle-api for DependencyResolver: " + Arrays.toString(dependencies)); - - File bootstrapDir = Files.createTempDirectory("swift-java-dependency-resolver").toFile(); - bootstrapDir.mkdirs(); - simpleLog("Bootstrap dependencies using project at: %s".formatted(bootstrapDir)); - - printBuildFiles(bootstrapDir, dependencies); - - var bootstrapClasspath = resolveDependenciesWithSubprocess(bootstrapDir); - simpleLog("Prepared dependency resolver bootstrap classpath: " + bootstrapClasspath.split(":").length + " entries"); - - return bootstrapClasspath; - - } - - private static String resolveDependenciesWithSubprocess(File gradleProjectDir) throws IOException { - if (!gradleProjectDir.isDirectory()) { - throw new IllegalArgumentException("Gradle project directory is not a directory: " + gradleProjectDir); - } - - File stdoutFile = File.createTempFile("swift-java-bootstrap", ".stdout", gradleProjectDir); - stdoutFile.deleteOnExit(); - File stderrFile = File.createTempFile("swift-java-bootstrap", ".stderr", gradleProjectDir); - stderrFile.deleteOnExit(); - - try { - ProcessBuilder gradleBuilder = new ProcessBuilder("./gradlew", ":printRuntimeClasspath"); - gradleBuilder.directory(gradleProjectDir); - gradleBuilder.redirectOutput(stdoutFile); - gradleBuilder.redirectError(stderrFile); - Process gradleProcess = gradleBuilder.start(); - gradleProcess.waitFor(10, TimeUnit.MINUTES); // TODO: must be configurable - - if (gradleProcess.exitValue() != 0) { - throw new SwiftJavaBootstrapException("Failed to resolve bootstrap dependencies, exit code: " + gradleProcess.exitValue()); - } - - Stream lines = Files.readAllLines(stdoutFile.toPath()).stream(); - var bootstrapClasspath = getClasspathFromGradleCommandOutput(lines); - return bootstrapClasspath; - } catch (Exception ex) { - simpleLog("stdoutFile = " + stdoutFile); - simpleLog("stderrFile = " + stderrFile); - - ex.printStackTrace(); - throw new SwiftJavaBootstrapException("Failed to bootstrap dependencies necessary for " + - DependencyResolver.class.getCanonicalName() + "! " + - "Make sure to invoke SwiftPM with --disable-sandbox because " + - "swift-java needs network access to fetch java dependencies.", ex); - } - } - - private static void writeDependencyResolverClasspath(Path projectBasePath, String dependencyResolverDependenciesClasspath) throws IOException { - File swiftBuildDirectory = new File(String.valueOf(projectBasePath), ".build"); - swiftBuildDirectory.mkdirs(); - - File dependencyResolverClasspathCacheFile = new File(swiftBuildDirectory, CLASSPATH_CACHE_FILENAME); - dependencyResolverClasspathCacheFile.createNewFile(); - simpleLog("Cache %s dependencies classpath at: '%s'. Subsequent dependency resolutions will use gradle-api." - .formatted(DependencyResolver.class.getSimpleName(), dependencyResolverClasspathCacheFile.toPath())); - - Files.writeString( - dependencyResolverClasspathCacheFile.toPath(), - dependencyResolverDependenciesClasspath, - StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING); - } - - /** - * Detect if we have the necessary dependencies loaded. - */ - @UsedFromSwift - public static boolean hasDependencyResolverDependenciesLoaded() { - return hasDependencyResolverDependenciesLoaded(DependencyResolver.class.getClassLoader()); - } - - /** - * Resolve dependencies in the passed project directory and return the resulting classpath. - * - * @return classpath which was resolved for the dependencies - */ - private static String resolveDependenciesUsingAPI(File projectDir, String[] dependencies) throws IOException { - printBuildFiles(projectDir, dependencies); - - var connection = GradleConnector.newConnector() - .forProjectDirectory(projectDir) - .connect(); - - try (connection) { - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - PrintStream printStream = new PrintStream(outputStream); - - connection.newBuild().forTasks(":printRuntimeClasspath") - .setStandardError(new NoopOutputStream()) - .setStandardOutput(printStream) - .run(); - - var all = outputStream.toString(); - var classpathString = Arrays.stream(all.split("\n")) - .filter(s -> s.startsWith(COMMAND_OUTPUT_LINE_PREFIX_CLASSPATH)) - .map(s -> s.substring(COMMAND_OUTPUT_LINE_PREFIX_CLASSPATH.length())) - .findFirst().orElseThrow(() -> new RuntimeException("Could not find classpath output from ':printRuntimeClasspath' task.")); - - // remove output directories of the project we used for the dependency resolution - var classpath = Arrays.stream(classpathString - .split(":")) - .filter(s -> !s.startsWith(projectDir.getAbsolutePath())) - .collect(Collectors.joining(":")); - - - return classpath; - } - } - - private static String getClasspathFromGradleCommandOutput(Stream lines) { - return lines.filter(s -> s.startsWith(COMMAND_OUTPUT_LINE_PREFIX_CLASSPATH)) - .map(s -> s.substring(COMMAND_OUTPUT_LINE_PREFIX_CLASSPATH.length())) - .findFirst().orElseThrow(() -> new RuntimeException("Could not find classpath output from gradle command output task.")); - } - - - private static boolean hasDependencyResolverDependenciesLoaded(ClassLoader classLoader) { - try { - classLoader.loadClass("org.gradle.tooling.GradleConnector"); - return true; - } catch (ClassNotFoundException e) { - return false; - } - } - - private static void printBuildFiles(File projectDir, String[] dependencies) throws IOException { - // === build.gradle - File buildFile = new File(projectDir, "build.gradle"); - try (PrintWriter writer = new PrintWriter(buildFile)) { - writer.println("plugins { id 'java-library' }"); - writer.println("repositories { mavenCentral() }"); - - writer.println("dependencies {"); - for (String dependency : dependencies) { - writer.println("implementation(\"" + dependency + "\")"); - } - writer.println("}"); - - writer.println(""" - tasks.register("printRuntimeClasspath") { - def runtimeClasspath = sourceSets.main.runtimeClasspath - inputs.files(runtimeClasspath) - doLast { - println("SWIFT_JAVA_CLASSPATH:${runtimeClasspath.asPath}") - } - } - """); - } - - // === settings.gradle - File settingsFile = new File(projectDir, "settings.gradle.kts"); - try (PrintWriter writer = new PrintWriter(settingsFile)) { - writer.println(""" - rootProject.name = "swift-java-resolve-temp-project" - """); - } - - // === gradle wrapper files, so we can even download gradle when necessary to bootstrap - File gradlew = new File(projectDir, "gradlew"); - writeResourceToFile("/gradle/gradlew", gradlew); - gradlew.setExecutable(true); - - File gradlewBat = new File(projectDir, "gradlew.bat"); - writeResourceToFile("/gradle/gradlew.bat", gradlewBat); - gradlew.setExecutable(true); - - File gradleDir = new File(projectDir, "gradle"); - File gradleWrapperDir = new File(gradleDir, "wrapper"); - gradleWrapperDir.mkdirs(); - - File gradleWrapperJar = new File(gradleWrapperDir, "gradle-wrapper.jar"); - writeResourceToFile("/gradle/wrapper/gradle-wrapper.jar", gradleWrapperJar); - File gradleWrapperProps = new File(gradleWrapperDir, "gradle-wrapper.properties"); - writeResourceToFile("/gradle/wrapper/gradle-wrapper.properties", gradleWrapperProps); - } - - private static void writeResourceToFile(String resource, File target) throws IOException { - try (PrintWriter writer = new PrintWriter(target)) { - try (InputStream inputStream = DependencyResolver.class.getResourceAsStream(resource)) { - if (inputStream == null) { - throw new FileNotFoundException("Not found: gradlew wrapper in resources!"); - } - try (var os = new BufferedOutputStream(new FileOutputStream(target))) { - byte[] buffer = new byte[8192]; // Buffer size of 8 KB - int bytesRead; - while ((bytesRead = inputStream.read(buffer)) != -1) { - os.write(buffer, 0, bytesRead); - } - } - } - } - } - - private static void simpleLog(String message) { - System.err.println("[info][swift-java/" + DependencyResolver.class.getSimpleName() + "] " + message); - } - - private static class NoopOutputStream extends OutputStream { - @Override - public void write(int b) throws IOException { - // ignore - } - } -} diff --git a/JavaKit/src/main/java/org/swift/javakit/dependencies/SwiftJavaBootstrapException.java b/JavaKit/src/main/java/org/swift/javakit/dependencies/SwiftJavaBootstrapException.java deleted file mode 100644 index 3c8d475a..00000000 --- a/JavaKit/src/main/java/org/swift/javakit/dependencies/SwiftJavaBootstrapException.java +++ /dev/null @@ -1,25 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of Swift.org project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -package org.swift.javakit.dependencies; - -public class SwiftJavaBootstrapException extends RuntimeException { - public SwiftJavaBootstrapException(String message) { - super(message); - } - - public SwiftJavaBootstrapException(String message, Exception ex) { - super(message, ex); - } -} diff --git a/Package.swift b/Package.swift index 8cda1aed..72a95155 100644 --- a/Package.swift +++ b/Package.swift @@ -128,9 +128,9 @@ let package = Package( // ==== Plugin for wrapping Java classes in Swift .plugin( - name: "SwiftJavaPlugin", + name: "JExtractSwiftPlugin", targets: [ - "SwiftJavaPlugin" + "JExtractSwiftPlugin" ] ), .plugin( @@ -175,25 +175,6 @@ let package = Package( ] ), - .target( - name: "JavaKitDependencyResolver", - dependencies: [ - "JavaKit", - ], - exclude: [ - "swift-java.config", - ], - swiftSettings: [ - .swiftLanguageMode(.v5), - .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]), - ] -// // FIXME: when the tool is run from plugin it hangs even if sandbox is disabled -// , -// plugins: [ -// "SwiftJavaBootstrapJavaPlugin", -// ] - ), - .target( name: "JavaKit", dependencies: [ @@ -329,7 +310,7 @@ let package = Package( "JavaTypes", "JavaKitShared", "JavaKitConfigurationShared", - "JavaKitDependencyResolver", + "_Subprocess", // using process spawning ], swiftSettings: [ .swiftLanguageMode(.v5), @@ -349,7 +330,6 @@ let package = Package( "JavaKitJar", "JavaKitNetwork", "Java2SwiftLib", - "JavaKitDependencyResolver", "JavaKitShared", ], @@ -386,27 +366,8 @@ let package = Package( ] ), - .executableTarget( - name: "SwiftJavaBootstrapJavaTool", - dependencies: [ - "JavaKitConfigurationShared", // for Configuration reading at runtime - "_Subprocess", - ], - swiftSettings: [ - .swiftLanguageMode(.v5) - ] - ), - - .plugin( - name: "SwiftJavaBootstrapJavaPlugin", - capability: .buildTool(), - dependencies: [ - "SwiftJavaBootstrapJavaTool" - ] - ), - .plugin( - name: "SwiftJavaPlugin", + name: "JExtractSwiftPlugin", capability: .buildTool(), dependencies: [ "JExtractSwiftTool" diff --git a/Plugins/SwiftJavaPlugin/JExtractSwiftPlugin.swift b/Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift similarity index 100% rename from Plugins/SwiftJavaPlugin/JExtractSwiftPlugin.swift rename to Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift diff --git a/Plugins/SwiftJavaBootstrapJavaPlugin/_PluginsShared b/Plugins/JExtractSwiftPlugin/_PluginsShared similarity index 100% rename from Plugins/SwiftJavaBootstrapJavaPlugin/_PluginsShared rename to Plugins/JExtractSwiftPlugin/_PluginsShared diff --git a/Plugins/Java2SwiftPlugin/Java2SwiftPlugin.swift b/Plugins/Java2SwiftPlugin/Java2SwiftPlugin.swift index d932ee97..88507f2e 100644 --- a/Plugins/Java2SwiftPlugin/Java2SwiftPlugin.swift +++ b/Plugins/Java2SwiftPlugin/Java2SwiftPlugin.swift @@ -156,11 +156,11 @@ struct Java2SwiftBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin { if let dependencies = config.dependencies, !dependencies.isEmpty { let displayName = "Fetch (Java) dependencies for Swift target \(sourceModule.name)" log("Prepared: \(displayName)") - + fetchDependenciesOutputFiles += [ outputFilePath(context: context, generated: false, filename: "\(sourceModule.name).swift-java.classpath") ] - + commands += [ .buildCommand( displayName: displayName, diff --git a/Plugins/SwiftJavaBootstrapJavaPlugin/SwiftJavaBootstrapJavaPlugin.swift b/Plugins/SwiftJavaBootstrapJavaPlugin/SwiftJavaBootstrapJavaPlugin.swift deleted file mode 100644 index 7d614371..00000000 --- a/Plugins/SwiftJavaBootstrapJavaPlugin/SwiftJavaBootstrapJavaPlugin.swift +++ /dev/null @@ -1,190 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of Swift.org project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -import Foundation -import PackagePlugin - -fileprivate let SwiftJavaConfigFileName = "swift-java.config" - -@main -struct Java2SwiftBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin { - - var pluginName: String = "swift-java-bootstrap" - var verbose: Bool = getEnvironmentBool("SWIFT_JAVA_VERBOSE") - - func createBuildCommands(context: PluginContext, target: Target) throws -> [Command] { - log("Create build commands for target '\(target.name)'") - guard let sourceModule = target.sourceModule else { return [] } - - let executable = try context.tool(named: "SwiftJavaBootstrapJavaTool").url - var commands: [Command] = [] - - // Note: Target doesn't have a directoryURL counterpart to directory, - // so we cannot eliminate this deprecation warning. - let sourceDir = target.directory.string - - // The name of the configuration file JavaKit.config from the target for - // which we are generating Swift wrappers for Java classes. - let configFile = URL(filePath: sourceDir) - .appending(path: SwiftJavaConfigFileName) - let config = try readConfiguration(sourceDir: sourceDir) - - log("Config on path: \(configFile.path(percentEncoded: false))") - log("Config was: \(config)") - var javaDependencies = config.dependencies ?? [] - - /// Find the manifest files from other Java2Swift executions in any targets - /// this target depends on. - var dependentConfigFiles: [(String, URL)] = [] - func searchForConfigFiles(in target: any Target) { - // log("Search for config files in target: \(target.name)") - let dependencyURL = URL(filePath: target.directory.string) - - // Look for a config file within this target. - let dependencyConfigURL = dependencyURL - .appending(path: SwiftJavaConfigFileName) - let dependencyConfigString = dependencyConfigURL - .path(percentEncoded: false) - - if FileManager.default.fileExists(atPath: dependencyConfigString) { - dependentConfigFiles.append((target.name, dependencyConfigURL)) - } - } - - // Process direct dependencies of this target. - for dependency in target.dependencies { - switch dependency { - case .target(let target): - searchForConfigFiles(in: target) - - case .product(let product): - for target in product.targets { - searchForConfigFiles(in: target) - } - - @unknown default: - break - } - } - - // Process indirect target dependencies. - for dependency in target.recursiveTargetDependencies { - searchForConfigFiles(in: dependency) - } - - var arguments: [String] = [] - arguments += argumentsModuleName(sourceModule: sourceModule) - arguments += argumentsOutputDirectory(context: context) - - arguments += dependentConfigFiles.flatMap { moduleAndConfigFile in - let (moduleName, configFile) = moduleAndConfigFile - return [ - "--depends-on", - "\(moduleName)=\(configFile.path(percentEncoded: false))" - ] - } - arguments.append(configFile.path(percentEncoded: false)) - - let classes = config.classes ?? [:] - print("Classes to wrap: \(classes.map(\.key))") - - /// Determine the set of Swift files that will be emitted by the Java2Swift tool. - // TODO: this is not precise and won't work with more advanced Java files, e.g. lambdas etc. - let outputDirectoryGenerated = self.outputDirectory(context: context, generated: true) - let outputSwiftFiles = classes.map { (javaClassName, swiftName) in - let swiftNestedName = swiftName.replacingOccurrences(of: ".", with: "+") - return outputDirectoryGenerated.appending(path: "\(swiftNestedName).swift") - } - - arguments += [ - "--cache-directory", - context.pluginWorkDirectoryURL.path(percentEncoded: false) - ] - - // Find the Java .class files generated from prior plugins. - let compiledClassFiles = sourceModule.pluginGeneratedResources.filter { url in - url.pathExtension == "class" - } - - if let firstClassFile = compiledClassFiles.first { - // Keep stripping off parts of the path until we hit the "Java" part. - // That's where the class path starts. - var classpath = firstClassFile - while classpath.lastPathComponent != "Java" { - classpath.deleteLastPathComponent() - } - arguments += ["--classpath", classpath.path()] - } - - var fetchDependenciesOutputFiles: [URL] = [] - if let dependencies = config.dependencies, !dependencies.isEmpty { - let displayName = "Fetch (Java) dependencies for Swift target \(sourceModule.name)" - log("Prepared: \(displayName)") - - let arguments = [ - "--fetch", configFile.path(percentEncoded: false), - "--module-name", sourceModule.name, - "--output-directory", outputDirectory(context: context, generated: false).path(percentEncoded: false) - ] - - log("Command: \(executable) \(arguments.joined(separator: " "))") - - fetchDependenciesOutputFiles += [ - outputFilePath(context: context, generated: false, filename: "\(sourceModule.name).swift-java.classpath") - ] - - commands += [ - .buildCommand( - displayName: displayName, - executable: executable, - arguments: arguments, - inputFiles: [configFile], - outputFiles: fetchDependenciesOutputFiles - ) - ] - } else { - log("No dependencies to fetch for target \(sourceModule.name)") - } - - return commands - } -} - -extension Java2SwiftBuildToolPlugin { - func argumentsModuleName(sourceModule: Target) -> [String] { - return [ - "--module-name", sourceModule.name - ] - } - - func argumentsOutputDirectory(context: PluginContext, generated: Bool = true) -> [String] { - return [ - "--output-directory", - outputDirectory(context: context, generated: generated).path(percentEncoded: false) - ] - } - - func outputDirectory(context: PluginContext, generated: Bool = true) -> URL { - let dir = context.pluginWorkDirectoryURL - if generated { - return dir.appending(path: "generated") - } else { - return dir - } - } - - func outputFilePath(context: PluginContext, generated: Bool, filename: String) -> URL { - outputDirectory(context: context, generated: generated).appending(path: filename) - } -} diff --git a/Plugins/SwiftJavaPlugin/_PluginsShared b/Plugins/SwiftJavaPlugin/_PluginsShared deleted file mode 120000 index de623a5e..00000000 --- a/Plugins/SwiftJavaPlugin/_PluginsShared +++ /dev/null @@ -1 +0,0 @@ -../PluginsShared \ No newline at end of file diff --git a/Samples/JavaDependencySampleApp/Package.swift b/Samples/JavaDependencySampleApp/Package.swift index 3d210e36..a90cd255 100644 --- a/Samples/JavaDependencySampleApp/Package.swift +++ b/Samples/JavaDependencySampleApp/Package.swift @@ -93,6 +93,7 @@ let package = Package( .swiftLanguageMode(.v5), ], plugins: [ +// .plugin(name: "SwiftJavaBootstrapJavaPlugin", package: "swift-java"), .plugin(name: "Java2SwiftPlugin", package: "swift-java"), ] ), diff --git a/Samples/JavaDependencySampleApp/Sources/JavaDependencySample/main.swift b/Samples/JavaDependencySampleApp/Sources/JavaDependencySample/main.swift index 86770ee8..16c2f4a9 100644 --- a/Samples/JavaDependencySampleApp/Sources/JavaDependencySample/main.swift +++ b/Samples/JavaDependencySampleApp/Sources/JavaDependencySample/main.swift @@ -25,10 +25,8 @@ print("") print("-----------------------------------------------------------------------") print("Start Sample app...") -// Make sure we have the classpath loaded -// TODO: this is more complex than that, need to account for dependencies of our module -let currentDir = FileManager.default.currentDirectoryPath -let swiftJavaClasspath = findSwiftJavaClasspaths() +// TODO: locating the classpath is more complex, need to account for dependencies of our module +let swiftJavaClasspath = findSwiftJavaClasspaths() // scans for .classpath files // 1) Start a JVM with appropriate classpath let jvm = try JavaVirtualMachine.shared(classpath: swiftJavaClasspath) diff --git a/Samples/JavaDependencySampleApp/ci-validate.sh b/Samples/JavaDependencySampleApp/ci-validate.sh index b21d19d4..7012b841 100755 --- a/Samples/JavaDependencySampleApp/ci-validate.sh +++ b/Samples/JavaDependencySampleApp/ci-validate.sh @@ -3,10 +3,4 @@ set -e set -x -# TODO: this is a workaround for build plugins getting stuck running the bootstrap plugin -cd ../../ -swift build --product SwiftJavaBootstrapJavaTool -.build/debug/SwiftJavaBootstrapJavaTool --fetch Sources/JavaKitDependencyResolver/swift-java.config --module-name JavaKitDependencyResolver --output-directory .build/plugins/outputs/swift-java/JavaKitDependencyResolver/destination/SwiftJavaBootstrapJavaPlugin - -cd - swift run --disable-sandbox diff --git a/Samples/JavaDependencySampleApp/gradle b/Samples/JavaDependencySampleApp/gradle new file mode 120000 index 00000000..fc7fc3b4 --- /dev/null +++ b/Samples/JavaDependencySampleApp/gradle @@ -0,0 +1 @@ +../../gradle/ \ No newline at end of file diff --git a/Samples/JavaDependencySampleApp/gradlew b/Samples/JavaDependencySampleApp/gradlew new file mode 120000 index 00000000..343e0d2c --- /dev/null +++ b/Samples/JavaDependencySampleApp/gradlew @@ -0,0 +1 @@ +../../gradlew \ No newline at end of file diff --git a/Samples/JavaDependencySampleApp/gradlew.bat b/Samples/JavaDependencySampleApp/gradlew.bat new file mode 120000 index 00000000..cb5a9464 --- /dev/null +++ b/Samples/JavaDependencySampleApp/gradlew.bat @@ -0,0 +1 @@ +../../gradlew.bat \ No newline at end of file diff --git a/Samples/SwiftAndJavaJarSampleLib/Package.swift b/Samples/SwiftAndJavaJarSampleLib/Package.swift index a1212fd7..5f132239 100644 --- a/Samples/SwiftAndJavaJarSampleLib/Package.swift +++ b/Samples/SwiftAndJavaJarSampleLib/Package.swift @@ -70,7 +70,7 @@ let package = Package( .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) ], plugins: [ - .plugin(name: "SwiftJavaPlugin", package: "swift-java"), + .plugin(name: "JExtractSwiftPlugin", package: "swift-java"), ] ), ] diff --git a/Samples/SwiftKitSampleApp/Package.swift b/Samples/SwiftKitSampleApp/Package.swift index bfd3ecbe..f12ecfd6 100644 --- a/Samples/SwiftKitSampleApp/Package.swift +++ b/Samples/SwiftKitSampleApp/Package.swift @@ -70,7 +70,7 @@ let package = Package( .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) ], plugins: [ - .plugin(name: "SwiftJavaPlugin", package: "swift-java"), + .plugin(name: "JExtractSwiftPlugin", package: "swift-java"), ] ), ] diff --git a/Samples/gradle b/Samples/gradle new file mode 120000 index 00000000..3337596a --- /dev/null +++ b/Samples/gradle @@ -0,0 +1 @@ +../gradle \ No newline at end of file diff --git a/JavaKit/gradlew b/Samples/gradlew similarity index 100% rename from JavaKit/gradlew rename to Samples/gradlew diff --git a/Sources/Java2Swift/JavaToSwift+EmitConfiguration.swift b/Sources/Java2Swift/JavaToSwift+EmitConfiguration.swift index fd567234..6754d381 100644 --- a/Sources/Java2Swift/JavaToSwift+EmitConfiguration.swift +++ b/Sources/Java2Swift/JavaToSwift+EmitConfiguration.swift @@ -18,7 +18,6 @@ import Java2SwiftLib import JavaKit import JavaKitJar import Java2SwiftLib -import JavaKitDependencyResolver import JavaKitConfigurationShared extension JavaToSwift { diff --git a/Sources/Java2Swift/JavaToSwift+FetchDependencies.swift b/Sources/Java2Swift/JavaToSwift+FetchDependencies.swift index 391abb27..60100fca 100644 --- a/Sources/Java2Swift/JavaToSwift+FetchDependencies.swift +++ b/Sources/Java2Swift/JavaToSwift+FetchDependencies.swift @@ -18,62 +18,105 @@ import JavaKit import Foundation import JavaKitJar import Java2SwiftLib -import JavaKitDependencyResolver import JavaKitConfigurationShared import JavaKitShared +import _Subprocess extension JavaToSwift { - /// Must be the same as `DependencyResolver#CLASSPATH_CACHE_FILENAME` on the java side. - var JavaKitDependencyResolverClasspathCacheFilename: String { - "JavaKitDependencyResolver.swift-java.classpath" - } - var JavaKitDependencyResolverClasspathCacheFilePath: String { - ".build/\(JavaKitDependencyResolverClasspathCacheFilename)" - } + var SwiftJavaClasspathPrefix: String { "SWIFT_JAVA_CLASSPATH:" } - func fetchDependenciesCachedClasspath() -> [String]? { - let cachedClasspathURL = URL( - fileURLWithPath: FileManager.default.currentDirectoryPath + "/" + JavaKitDependencyResolverClasspathCacheFilePath) - - guard FileManager.default.fileExists(atPath: cachedClasspathURL.path) else { - return [] - } - - guard let javaKitDependencyResolverCachedClasspath = try? String(contentsOf: cachedClasspathURL) else { - return [] - } - - print("[debug][swift-java] Cached dependency resolver classpath: \(javaKitDependencyResolverCachedClasspath)") - return javaKitDependencyResolverCachedClasspath.split(separator: ":").map(String.init) - } + var printRuntimeClasspathTaskName: String { "printRuntimeClasspath" } func fetchDependencies(moduleName: String, - dependencies: [JavaDependencyDescriptor], - baseClasspath: [String], - environment: JNIEnvironment) throws -> ResolvedDependencyClasspath { + dependencies: [JavaDependencyDescriptor]) async throws -> ResolvedDependencyClasspath { let deps = dependencies.map { $0.descriptionGradleStyle } print("[debug][swift-java] Resolve and fetch dependencies for: \(deps)") - let resolverClass = try JavaClass(environment: environment) - let fullClasspath = try resolverClass.resolveDependenciesToClasspath( - projectBaseDirectory: URL(fileURLWithPath: ".").path, - dependencies: deps) - .split(separator: ":") + let dependenciesClasspath = await resolveDependencies(dependencies: dependencies) + let classpathEntries = dependenciesClasspath.split(separator: ":") - let classpathEntries = fullClasspath.filter { - $0.hasSuffix(".jar") - } - let classpath = classpathEntries.joined(separator: ":") print("[info][swift-java] Resolved classpath for \(deps.count) dependencies of '\(moduleName)', classpath entries: \(classpathEntries.count), ", terminator: "") print("done.".green) - return ResolvedDependencyClasspath(for: dependencies, classpath: classpath) + return ResolvedDependencyClasspath(for: dependencies, classpath: dependenciesClasspath) + } + + func resolveDependencies(dependencies: [JavaDependencyDescriptor]) async -> String { + let workDir = URL(fileURLWithPath: FileManager.default.currentDirectoryPath) + .appendingPathComponent(".build") + let resolverDir = try! createTemporaryDirectory(in: workDir) + + try! copyGradlew(to: resolverDir) + + try! printGradleProject(directory: resolverDir, dependencies: dependencies) + + let process = try! await Subprocess.run( + .at(.init(resolverDir.appendingPathComponent("gradlew").path)), + arguments: [ + "--no-daemon", + "--rerun-tasks", + "\(printRuntimeClasspathTaskName)", + ], + workingDirectory: .init(platformString: resolverDir.path) + ) + + let outString = String( + data: process.standardOutput, + encoding: .utf8 + ) + let errString = String( + data: process.standardError, + encoding: .utf8 + ) + + let classpathOutput: String + if let found = outString?.split(separator: "\n").first(where: { $0.hasPrefix(self.SwiftJavaClasspathPrefix) }) { + classpathOutput = String(found) + } else if let found = errString?.split(separator: "\n").first(where: { $0.hasPrefix(self.SwiftJavaClasspathPrefix) }) { + classpathOutput = String(found) + } else { + let suggestDisablingSandbox = "It may be that the Sandbox has prevented dependency fetching, please re-run with '--disable-sandbox'." + fatalError("Gradle output had no SWIFT_JAVA_CLASSPATH! \(suggestDisablingSandbox). \n" + + "Output was:<<<\(outString ?? "")>>>; Err was:<<<\(errString ?? "")>>>") + } + + return String(classpathOutput.dropFirst(SwiftJavaClasspathPrefix.count)) + } + + func printGradleProject(directory: URL, dependencies: [JavaDependencyDescriptor]) throws { + let buildGradle = directory + .appendingPathComponent("build.gradle", isDirectory: false) + + let buildGradleText = + """ + plugins { id 'java-library' } + repositories { mavenCentral() } + + dependencies { + \(dependencies.map({ dep in "implementation(\"\(dep.descriptionGradleStyle)\")" }).joined(separator: ",\n")) + } + + tasks.register("printRuntimeClasspath") { + def runtimeClasspath = sourceSets.main.runtimeClasspath + inputs.files(runtimeClasspath) + doLast { + println("\(SwiftJavaClasspathPrefix)${runtimeClasspath.asPath}") + } + } + """ + try buildGradleText.write(to: buildGradle, atomically: true, encoding: .utf8) + + let settingsGradle = directory + .appendingPathComponent("settings.gradle.kts", isDirectory: false) + let settingsGradleText = + """ + rootProject.name = "swift-java-resolve-temp-project" + """ + try settingsGradleText.write(to: settingsGradle, atomically: true, encoding: .utf8) } -} -extension JavaToSwift { mutating func writeFetchedDependenciesClasspath( moduleName: String, cacheDir: String, @@ -98,6 +141,62 @@ extension JavaToSwift { let camelCased = components.map { $0.capitalized }.joined() return camelCased } + + func copyGradlew(to resolverWorkDirectory: URL) throws { + var searchDir = URL(fileURLWithPath: FileManager.default.currentDirectoryPath) + + while searchDir.pathComponents.count > 1 { + print("[COPY] Search dir: \(searchDir)") + + let gradlewFile = searchDir.appendingPathComponent("gradlew") + let gradlewExists = FileManager.default.fileExists(atPath: gradlewFile.path) + guard gradlewExists else { + searchDir = searchDir.deletingLastPathComponent() + continue + } + + let gradleDir = searchDir.appendingPathComponent("gradle") + let gradleDirExists = FileManager.default.fileExists(atPath: gradleDir.path) + guard gradleDirExists else { + searchDir = searchDir.deletingLastPathComponent() + continue + } +// +// let gradleWrapperDir = gradleDir.appendingPathComponent("wrapper") +// let gradleWrapperDirExists = FileManager.default.fileExists(atPath: gradleWrapperDir.path) +// guard gradleWrapperDirExists else { +// searchDir = searchDir.deletingLastPathComponent() +// continue +// } +// +// let gradleWrapperJarFile = gradleWrapperDir.appendingPathComponent("gradle-wrapper.jar") +// let gradleWrapperJarFileExists = FileManager.default.fileExists(atPath: gradleWrapperJarFile.path) +// guard gradleWrapperJarFileExists else { +// searchDir = searchDir.deletingLastPathComponent() +// continue +// } + + print("COPY: \(gradlewFile) -> \(resolverWorkDirectory)") + print("COPY: \(gradleDir) -> \(resolverWorkDirectory)") + try? FileManager.default.copyItem( + at: gradlewFile, + to: resolverWorkDirectory.appendingPathComponent("gradlew")) + try? FileManager.default.copyItem( + at: gradleDir, + to: resolverWorkDirectory.appendingPathComponent("gradle")) + return + } + } + + func createTemporaryDirectory(in directory: URL) throws -> URL { + let uuid = UUID().uuidString + let resolverDirectoryURL = directory.appendingPathComponent("swift-java-dependencies-\(uuid)") + + try FileManager.default.createDirectory(at: resolverDirectoryURL, withIntermediateDirectories: true, attributes: nil) + + return resolverDirectoryURL + } + } struct ResolvedDependencyClasspath: CustomStringConvertible { @@ -120,3 +219,4 @@ struct ResolvedDependencyClasspath: CustomStringConvertible { "JavaClasspath(for: \(rootDependencies), classpath: \(classpath))" } } + diff --git a/Sources/Java2Swift/JavaToSwift+GenerateWrappers.swift b/Sources/Java2Swift/JavaToSwift+GenerateWrappers.swift index 99f83b4e..67aa3f9c 100644 --- a/Sources/Java2Swift/JavaToSwift+GenerateWrappers.swift +++ b/Sources/Java2Swift/JavaToSwift+GenerateWrappers.swift @@ -18,7 +18,6 @@ import Java2SwiftLib import JavaKit import JavaKitJar import Java2SwiftLib -import JavaKitDependencyResolver import JavaKitConfigurationShared extension JavaToSwift { @@ -142,4 +141,4 @@ extension JavaToSwift { ) } } -} \ No newline at end of file +} diff --git a/Sources/Java2Swift/JavaToSwift.swift b/Sources/Java2Swift/JavaToSwift.swift index 0d196933..536b3fd1 100644 --- a/Sources/Java2Swift/JavaToSwift.swift +++ b/Sources/Java2Swift/JavaToSwift.swift @@ -26,7 +26,7 @@ import JavaKitShared /// Command-line utility to drive the export of Java classes into Swift types. @main -struct JavaToSwift: ParsableCommand { +struct JavaToSwift: AsyncParsableCommand { static var _commandName: String { "Java2Swift" } @Option(help: "The name of the Swift module into which the resulting Swift types will be generated.") @@ -159,14 +159,13 @@ struct JavaToSwift: ParsableCommand { /// Generate Swift wrappers for Java classes based on the given /// configuration. - case classWrappers // (Configuration) + case classWrappers /// Fetch dependencies for a module - case fetchDependencies // (Configuration) - // FIXME each mode should have its own config? + case fetchDependencies } - mutating func run() { + mutating func run() async { print("[info][swift-java] Run: \(CommandLine.arguments.joined(separator: " "))") do { let config: Configuration @@ -246,25 +245,16 @@ struct JavaToSwift: ParsableCommand { // if we have already fetched dependencies for the dependency loader, // let's use them so we can in-process resolve rather than forking a new // gradle process. - if let dependencyResolverClasspath = fetchDependenciesCachedClasspath() { - print("[debug][swift-java] Found cached dependency resolver classpath: \(dependencyResolverClasspath)") - classpathEntries += dependencyResolverClasspath - } + print("[debug][swift-java] Add classpath from .classpath files") + classpathEntries += findSwiftJavaClasspaths(in: FileManager.default.currentDirectoryPath) +// if let dependencyResolverClasspath = fetchDependenciesCachedClasspath() { +// print("[debug][swift-java] Found cached dependency resolver classpath: \(dependencyResolverClasspath)") +// classpathEntries += dependencyResolverClasspath +// } case .classWrappers: break; } - // Add extra classpath entries which are specific to building the JavaKit project and samples - let classpathBuildJavaKitEntries = [ // FIXME: THIS IS A TRICK UNTIL WE FIGURE OUT HOW TO BOOTSTRAP THIS PART - FileManager.default.currentDirectoryPath, - FileManager.default.currentDirectoryPath + "/.build", - FileManager.default.currentDirectoryPath + "/JavaKit/build/libs", - URL(fileURLWithPath: FileManager.default.currentDirectoryPath) - .deletingLastPathComponent() - .deletingLastPathComponent().absoluteURL.path + "/JavaKit/build/libs/JavaKit-1.0-SNAPSHOT.jar" - ] - classpathEntries += classpathBuildJavaKitEntries - // Bring up the Java VM. // TODO: print only in verbose mode let classpath = classpathEntries.joined(separator: ":") @@ -272,18 +262,6 @@ struct JavaToSwift: ParsableCommand { let jvm = try JavaVirtualMachine.shared(classpath: classpathEntries) - // FIXME: we should resolve dependencies here perhaps - // if let dependencies = config.dependencies { - // print("[info][swift-java] Resolve dependencies...") - // let dependencyClasspath = try fetchDependencies( - // moduleName: moduleName, - // dependencies: dependencies, - // baseClasspath: classpathOptionEntries, - // environment: jvm.environment() - // ) - // classpathEntries += dependencyClasspath.classpathEntries - // } - // * Classespaths from all dependent configuration files for (_, config) in dependentConfigs { // TODO: may need to resolve the dependent configs rather than just get their configs @@ -323,11 +301,9 @@ struct JavaToSwift: ParsableCommand { print("[debug][swift-java] Base classpath to fetch dependencies: \(classpathOptionEntries)") - let dependencyClasspath = try fetchDependencies( + let dependencyClasspath = try await fetchDependencies( moduleName: moduleName, - dependencies: dependencies, - baseClasspath: classpathOptionEntries, - environment: jvm.environment() + dependencies: dependencies ) try writeFetchedDependenciesClasspath( diff --git a/Sources/Java2Swift/String+Extensions.swift b/Sources/Java2Swift/String+Extensions.swift index ba26f892..26a20241 100644 --- a/Sources/Java2Swift/String+Extensions.swift +++ b/Sources/Java2Swift/String+Extensions.swift @@ -18,7 +18,6 @@ import Java2SwiftLib import JavaKit import JavaKitJar import Java2SwiftLib -import JavaKitDependencyResolver import JavaKitConfigurationShared extension String { diff --git a/Sources/JavaKitConfigurationShared/Configuration.swift b/Sources/JavaKitConfigurationShared/Configuration.swift index d401c657..13c7fd9b 100644 --- a/Sources/JavaKitConfigurationShared/Configuration.swift +++ b/Sources/JavaKitConfigurationShared/Configuration.swift @@ -121,6 +121,17 @@ public func readConfiguration(configPath: URL, file: String = #fileID, line: UIn } } +public func findSwiftJavaClasspaths(moduleName: String) -> [String] { + let basePath: String = FileManager.default.currentDirectoryPath + let pluginOutputsDir = URL(fileURLWithPath: basePath) + .appendingPathComponent(".build", isDirectory: true) + .appendingPathComponent("plugins", isDirectory: true) + .appendingPathComponent("outputs", isDirectory: true) + .appendingPathComponent(moduleName, isDirectory: true) + + return findSwiftJavaClasspaths(in: pluginOutputsDir.path) +} + public func findSwiftJavaClasspaths(in basePath: String = FileManager.default.currentDirectoryPath) -> [String] { let fileManager = FileManager.default diff --git a/Sources/SwiftJavaBootstrapJavaTool/SwiftJavaBootstrapJavaTool.swift b/Sources/SwiftJavaBootstrapJavaTool/SwiftJavaBootstrapJavaTool.swift deleted file mode 100644 index 11f26a67..00000000 --- a/Sources/SwiftJavaBootstrapJavaTool/SwiftJavaBootstrapJavaTool.swift +++ /dev/null @@ -1,137 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of Swift.org project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -import Foundation -import Synchronization -import JavaKitConfigurationShared -import Dispatch -import _Subprocess - -@available(macOS 15.0, *) -@main -final class SwiftJavaBootstrapJavaTool { - - let SwiftJavaClasspathPrefix = "SWIFT_JAVA_CLASSPATH:" - - // We seem to have weird "hang" issues with Gradle launched from Process(), workaround it by existing once we get the classpath - let printRuntimeClasspathTaskName = "printRuntimeClasspath" - - let out = Synchronization.Mutex(Data()) - let err = Synchronization.Mutex(Data()) - - static func main() async { - await SwiftJavaBootstrapJavaTool().run() - } - - func run() async { - print("[debug][swift-java-bootstrap] RUN SwiftJavaBootstrapJavaTool: \(CommandLine.arguments.joined(separator: " "))") - - var args = CommandLine.arguments - _ = args.removeFirst() // executable - - assert(args.removeFirst() == "--fetch") - let configPath = args.removeFirst() - - assert(args.removeFirst() == "--module-name") - let moduleName = args.removeFirst() - - assert(args.removeFirst() == "--output-directory") - let outputDirectoryPath = args.removeFirst() - - let configPathURL = URL(fileURLWithPath: configPath) - print("[debug][swift-java-bootstrap] Load config: \(configPathURL.absoluteString)") - let config = try! readConfiguration(configPath: configPathURL) - - // We only support a single dependency right now. - let localGradleProjectDependencyName = (config.dependencies ?? []).filter { - $0.artifactID.hasPrefix(":") - }.map { - $0.artifactID - }.first! - - let process = try! await Subprocess.run( - .at("./gradlew"), - arguments: [ - "--no-daemon", - "--rerun-tasks", - // "--debug", - // "\(localGradleProjectDependencyName):jar", - "\(localGradleProjectDependencyName):\(printRuntimeClasspathTaskName)" - ] - ) - - let outString = String( - data: process.standardOutput, - encoding: .utf8 - ) - let errString = String( - data: process.standardError, - encoding: .utf8 - ) - - print("OUT ==== \(outString?.count) ::: \(outString ?? "")") - print("ERR ==== \(errString?.count) ::: \(errString ?? "")") - - let classpathOutput: String - if let found = outString?.split(separator: "\n").first(where: { $0.hasPrefix(self.SwiftJavaClasspathPrefix) }) { - classpathOutput = String(found) - } else if let found = errString?.split(separator: "\n").first(where: { $0.hasPrefix(self.SwiftJavaClasspathPrefix) }) { - classpathOutput = String(found) - } else { - let suggestDisablingSandbox = "It may be that the Sandbox has prevented dependency fetching, please re-run with '--disable-sandbox'." - fatalError("Gradle output had no SWIFT_JAVA_CLASSPATH! \(suggestDisablingSandbox). \n" + - "Output was:<<<\(outString ?? "")>>>; Err was:<<<\(errString ?? "")>>>") - } - - let classpathString = String(classpathOutput.dropFirst(self.SwiftJavaClasspathPrefix.count)) - - _ = try? FileManager.default.createDirectory( - at: URL(fileURLWithPath: outputDirectoryPath), - withIntermediateDirectories: true, - attributes: nil - ) - - let classpathOutputURL = - URL(fileURLWithPath: outputDirectoryPath) - .appendingPathComponent("\(moduleName).swift-java.classpath", isDirectory: false) - - try! classpathString.write(to: classpathOutputURL, atomically: true, encoding: .utf8) - - print("[swift-java-bootstrap] Done, written classpath to: \(classpathOutputURL)") - } - - func writeBuildGradle(directory: URL) { - // """ - // plugins { id 'java-library' } - // repositories { mavenCentral() } - // - // dependencies { - // implementation("dev.gradleplugins:gradle-api:8.10.1") - // } - // - // task \(printRuntimeClasspathTaskName) { - // def runtimeClasspath = sourceSets.main.runtimeClasspath - // inputs.files(runtimeClasspath) - // doLast { - // println("CLASSPATH:${runtimeClasspath.asPath}") - // } - // } - // """.write(to: URL(fileURLWithPath: tempDir.appendingPathComponent("build.gradle")).path(percentEncoded: false), atomically: true, encoding: .utf8) - // - // """ - // rootProject.name = "swift-java-resolve-temp-project" - // """.write(to: URL(fileURLWithPath: tempDir.appendingPathComponent("settings.gradle.kts")).path(percentEncoded: false), atomically: true, encoding: .utf8) - } - -} diff --git a/settings.gradle b/settings.gradle index c1168a68..fa0fa5bd 100644 --- a/settings.gradle +++ b/settings.gradle @@ -18,7 +18,6 @@ pluginManagement { rootProject.name = "swift-java" -include "JavaKit" include "SwiftKit" // Include sample apps -- you can run them via `gradle Name:run` From 415525597d0128d439e1dc0eee3f9cc2766cf90a Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Fri, 13 Dec 2024 20:32:54 +0900 Subject: [PATCH 206/426] copy gradle.bat also --- .../JavaToSwift+FetchDependencies.swift | 25 +++++++------------ 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/Sources/Java2Swift/JavaToSwift+FetchDependencies.swift b/Sources/Java2Swift/JavaToSwift+FetchDependencies.swift index 60100fca..152ba871 100644 --- a/Sources/Java2Swift/JavaToSwift+FetchDependencies.swift +++ b/Sources/Java2Swift/JavaToSwift+FetchDependencies.swift @@ -155,32 +155,25 @@ extension JavaToSwift { continue } + let gradlewBatFile = searchDir.appendingPathComponent("gradlew.bat") + let gradlewBatExists = FileManager.default.fileExists(atPath: gradlewFile.path) + let gradleDir = searchDir.appendingPathComponent("gradle") let gradleDirExists = FileManager.default.fileExists(atPath: gradleDir.path) guard gradleDirExists else { searchDir = searchDir.deletingLastPathComponent() continue } -// -// let gradleWrapperDir = gradleDir.appendingPathComponent("wrapper") -// let gradleWrapperDirExists = FileManager.default.fileExists(atPath: gradleWrapperDir.path) -// guard gradleWrapperDirExists else { -// searchDir = searchDir.deletingLastPathComponent() -// continue -// } -// -// let gradleWrapperJarFile = gradleWrapperDir.appendingPathComponent("gradle-wrapper.jar") -// let gradleWrapperJarFileExists = FileManager.default.fileExists(atPath: gradleWrapperJarFile.path) -// guard gradleWrapperJarFileExists else { -// searchDir = searchDir.deletingLastPathComponent() -// continue -// } - print("COPY: \(gradlewFile) -> \(resolverWorkDirectory)") - print("COPY: \(gradleDir) -> \(resolverWorkDirectory)") + // TODO: gradle.bat as well try? FileManager.default.copyItem( at: gradlewFile, to: resolverWorkDirectory.appendingPathComponent("gradlew")) + if gradlewBatExists { + try? FileManager.default.copyItem( + at: gradlewBatFile, + to: resolverWorkDirectory.appendingPathComponent("gradlew.bat")) + } try? FileManager.default.copyItem( at: gradleDir, to: resolverWorkDirectory.appendingPathComponent("gradle")) From b48202c74939fe705feb5d2e0ba475b7336fd310 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Fri, 13 Dec 2024 20:36:59 +0900 Subject: [PATCH 207/426] cleanup after running fetch --- .licenseignore | 1 + Sources/Java2Swift/JavaToSwift+FetchDependencies.swift | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/.licenseignore b/.licenseignore index ada8e1de..bcafb671 100644 --- a/.licenseignore +++ b/.licenseignore @@ -47,3 +47,4 @@ Plugins/**/0_PLEASE_SYMLINK* Plugins/PluginsShared/JavaKitConfigurationShared Samples/JavaDependencySampleApp/gradle Sources/_Subprocess/_nio_locks.swift +Samples/gradle diff --git a/Sources/Java2Swift/JavaToSwift+FetchDependencies.swift b/Sources/Java2Swift/JavaToSwift+FetchDependencies.swift index 152ba871..9656c310 100644 --- a/Sources/Java2Swift/JavaToSwift+FetchDependencies.swift +++ b/Sources/Java2Swift/JavaToSwift+FetchDependencies.swift @@ -47,7 +47,13 @@ extension JavaToSwift { let workDir = URL(fileURLWithPath: FileManager.default.currentDirectoryPath) .appendingPathComponent(".build") let resolverDir = try! createTemporaryDirectory(in: workDir) + defer { + try? FileManager.default.removeItem(at: resolverDir) + } + // We try! because it's easier to track down errors like this than when we bubble up the errors, + // and don't get great diagnostics or backtraces due to how swiftpm plugin tools are executed. + try! copyGradlew(to: resolverDir) try! printGradleProject(directory: resolverDir, dependencies: dependencies) From 58070f53b76e012f121b595383bd8cf97b799013 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Fri, 13 Dec 2024 23:28:33 +0900 Subject: [PATCH 208/426] fix sample plugin name --- Samples/JavaKitSampleApp/Package.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Samples/JavaKitSampleApp/Package.swift b/Samples/JavaKitSampleApp/Package.swift index 46dfbd80..e51867cc 100644 --- a/Samples/JavaKitSampleApp/Package.swift +++ b/Samples/JavaKitSampleApp/Package.swift @@ -76,7 +76,7 @@ let package = Package( ], plugins: [ .plugin(name: "JavaCompilerPlugin", package: "swift-java"), - .plugin(name: "SwiftJavaPlugin", package: "swift-java"), + .plugin(name: "JExtractSwiftPlugin", package: "swift-java"), .plugin(name: "Java2SwiftPlugin", package: "swift-java"), ] ), From 860f2aa57a20d8e6132f1fe6dfc05ca97defa39a Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Mon, 16 Dec 2024 11:08:17 +0900 Subject: [PATCH 209/426] Fix JMH benchmark --- .../org/swift/swiftkit/JavaToSwiftBenchmark.java | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/JavaToSwiftBenchmark.java b/Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/JavaToSwiftBenchmark.java index 614697a3..a31aaaa0 100644 --- a/Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/JavaToSwiftBenchmark.java +++ b/Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/JavaToSwiftBenchmark.java @@ -36,19 +36,15 @@ public static class BenchmarkState { MySwiftClass obj; @Setup(Level.Trial) - public void beforeALl() { - System.loadLibrary("swiftCore"); - System.loadLibrary("ExampleSwiftLibrary"); - - // Tune down debug statements so they don't fill up stdout - System.setProperty("jextract.trace.downcalls", "false"); - + public void beforeAll() { obj = new MySwiftClass(1, 2); } } - @Benchmark @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.NANOSECONDS) - public void simpleSwiftApiCall(BenchmarkState state, Blackhole blackhole) { - blackhole.consume(state.obj.makeRandomIntMethod()); + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public long simpleSwiftApiCall(BenchmarkState state, Blackhole blackhole) { + return state.obj.makeRandomIntMethod(); } } From f61a5d2bf8e0aafa477009690d326ca9cc9fed36 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Mon, 16 Dec 2024 16:56:16 +0900 Subject: [PATCH 210/426] Implement passing Strings to Swift, with copying add benchmarks for String -> Swift and returning a count --- Samples/SwiftKitSampleApp/Package.swift | 2 + .../MySwiftLibrary/MySwiftLibrary.swift | 17 +++- .../jni/JNIImplementations.swift | 33 +++++++ Samples/SwiftKitSampleApp/build.gradle | 11 +++ .../swift/swiftkit/JavaToSwiftBenchmark.java | 48 +++++++---- .../swiftkit/StringPassingBenchmark.java | 86 +++++++++++++++++++ .../com/example/swift/HelloJava2Swift.java | 4 + .../com/example/swift/MySwiftLibraryTest.java | 21 +++++ Sources/JExtractSwift/ImportedDecls.swift | 12 +++ Sources/JExtractSwift/JavaTypes.swift | 5 ++ .../Swift2JavaTranslator+Printing.swift | 64 ++++++++++++-- Sources/JExtractSwift/Swift2JavaVisitor.swift | 2 +- .../JExtractSwift/SwiftThunkTranslator.swift | 61 ++++++++++--- Sources/JExtractSwift/TranslatedType.swift | 11 +++ .../BridgedValues/JavaValue+String.swift | 2 +- Sources/JavaTypes/JavaType+SwiftNames.swift | 12 +++ .../FuncCallbackImportTests.swift | 2 +- .../StringPassingTests.swift | 55 ++++++++++++ 18 files changed, 409 insertions(+), 39 deletions(-) create mode 100644 Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/jni/JNIImplementations.swift create mode 100644 Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/StringPassingBenchmark.java create mode 100644 Tests/JExtractSwiftTests/StringPassingTests.swift diff --git a/Samples/SwiftKitSampleApp/Package.swift b/Samples/SwiftKitSampleApp/Package.swift index bfd3ecbe..36d05878 100644 --- a/Samples/SwiftKitSampleApp/Package.swift +++ b/Samples/SwiftKitSampleApp/Package.swift @@ -60,6 +60,8 @@ let package = Package( .target( name: "MySwiftLibrary", dependencies: [ + .product(name: "JavaKit", package: "swift-java"), + .product(name: "JavaRuntime", package: "swift-java"), .product(name: "SwiftKitSwift", package: "swift-java"), ], exclude: [ diff --git a/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift b/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift index 84e4618f..ddb14569 100644 --- a/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift +++ b/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift @@ -31,6 +31,14 @@ public func globalTakeInt(i: Int) { p("i:\(i)") } +public func globalMakeInt() -> Int { + return 42 +} + +public func globalWriteString(string: String) -> Int { + return string.count +} + public func globalTakeIntInt(i: Int, j: Int) { p("i:\(i), j:\(j)") } @@ -79,6 +87,11 @@ public class MySwiftClass { return 12 } + public func writeString(string: String) -> Int { + p("echo -> \(string)") + return string.count + } + public func makeRandomIntMethod() -> Int { return Int.random(in: 1..<256) } @@ -87,8 +100,8 @@ public class MySwiftClass { // ==== Internal helpers private func p(_ msg: String, file: String = #fileID, line: UInt = #line, function: String = #function) { - print("[swift][\(file):\(line)](\(function)) \(msg)") - fflush(stdout) +// print("[swift][\(file):\(line)](\(function)) \(msg)") +// fflush(stdout) } #if os(Linux) diff --git a/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/jni/JNIImplementations.swift b/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/jni/JNIImplementations.swift new file mode 100644 index 00000000..90df0344 --- /dev/null +++ b/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/jni/JNIImplementations.swift @@ -0,0 +1,33 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaClass("com.example.swift.HelloJava2Swift") +open class HelloJava2Swift: JavaObject { +} + +extension JavaClass { +} + +/// Describes the Java `native` methods for ``HelloJava2Swift``. +/// +/// To implement all of the `native` methods for HelloSwift in Swift, +/// extend HelloSwift to conform to this protocol and mark each +/// implementation of the protocol requirement with `@JavaMethod`. +protocol HelloJava2SwiftNativeMethods { + func jniWriteString(_ message: String) -> Int32 + func jniGetInt() -> Int32 +} + +@JavaImplementation("com.example.swift.HelloJava2Swift") +extension HelloJava2Swift: HelloJava2SwiftNativeMethods { + @JavaMethod + func jniWriteString(_ message: String) -> Int32 { + return Int32(message.count) + } + + @JavaMethod + func jniGetInt() -> Int32 { + return 12 + } +} diff --git a/Samples/SwiftKitSampleApp/build.gradle b/Samples/SwiftKitSampleApp/build.gradle index ff9e1837..fdd38a11 100644 --- a/Samples/SwiftKitSampleApp/build.gradle +++ b/Samples/SwiftKitSampleApp/build.gradle @@ -145,10 +145,21 @@ application { ] } +String jmhIncludes = findProperty("jmhIncludes") + jmh { + if (jmhIncludes != null) { + includes = [jmhIncludes] + } + jvmArgsAppend = [ + "--enable-native-access=ALL-UNNAMED", + "-Djava.library.path=" + (BuildUtils.javaLibraryPaths(rootDir) + BuildUtils.javaLibraryPaths(project.projectDir)).join(":"), + + // Enable tracing downcalls (to Swift) + "-Djextract.trace.downcalls=false" ] } diff --git a/Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/JavaToSwiftBenchmark.java b/Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/JavaToSwiftBenchmark.java index a31aaaa0..18ced030 100644 --- a/Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/JavaToSwiftBenchmark.java +++ b/Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/JavaToSwiftBenchmark.java @@ -14,37 +14,51 @@ package org.swift.swiftkit; -import java.util.concurrent.TimeUnit; - -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.BenchmarkMode; -import org.openjdk.jmh.annotations.Level; -import org.openjdk.jmh.annotations.Mode; -import org.openjdk.jmh.annotations.OutputTimeUnit; -import org.openjdk.jmh.annotations.Scope; -import org.openjdk.jmh.annotations.Setup; -import org.openjdk.jmh.annotations.State; -import org.openjdk.jmh.infra.Blackhole; +import com.example.swift.HelloJava2Swift; +import com.example.swift.MySwiftLibrary; +import org.openjdk.jmh.annotations.*; import com.example.swift.MySwiftClass; -@SuppressWarnings("unused") +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.AverageTime) +@Warmup(iterations = 5, time = 200, timeUnit = TimeUnit.MILLISECONDS) +@Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@Fork(value = 3, jvmArgsAppend = { "--enable-native-access=ALL-UNNAMED" }) public class JavaToSwiftBenchmark { @State(Scope.Benchmark) public static class BenchmarkState { + ClosableSwiftArena arena; MySwiftClass obj; @Setup(Level.Trial) public void beforeAll() { - obj = new MySwiftClass(1, 2); + arena = SwiftArena.ofConfined(); + obj = new MySwiftClass(arena, 1, 2); + } + + @TearDown(Level.Trial) + public void afterAll() { + arena.close(); } } @Benchmark - @BenchmarkMode(Mode.AverageTime) - @OutputTimeUnit(TimeUnit.NANOSECONDS) - public long simpleSwiftApiCall(BenchmarkState state, Blackhole blackhole) { - return state.obj.makeRandomIntMethod(); + public long jextract_getInt_ffm(BenchmarkState state) { + return MySwiftLibrary.globalMakeInt(); } + + @Benchmark + public long getInt_global_jni(BenchmarkState state) { + return HelloJava2Swift.jniGetInt(); + } + + @Benchmark + public long getInt_member_ffi(BenchmarkState state) { + return state.obj.makeIntMethod(); + } + } diff --git a/Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/StringPassingBenchmark.java b/Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/StringPassingBenchmark.java new file mode 100644 index 00000000..1cc55e69 --- /dev/null +++ b/Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/StringPassingBenchmark.java @@ -0,0 +1,86 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package org.swift.swiftkit; + +import com.example.swift.HelloJava2Swift; +import com.example.swift.MySwiftClass; +import com.example.swift.MySwiftLibrary; +import org.openjdk.jmh.annotations.*; + +import java.lang.foreign.Arena; +import java.nio.charset.StandardCharsets; +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.AverageTime) +@Warmup(iterations = 5, time = 200, timeUnit = TimeUnit.MILLISECONDS) +@Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +@Fork(value = 2, jvmArgsAppend = {"--enable-native-access=ALL-UNNAMED"}) +public class StringPassingBenchmark { + + @Param({ + "5", + "10", + "100", + "200" + }) + public int stringLen; + public String string; + + ClosableSwiftArena arena; + MySwiftClass obj; + + @Setup(Level.Trial) + public void beforeAll() { + arena = SwiftArena.ofConfined(); + obj = new MySwiftClass(arena, 1, 2); + string = makeString(stringLen); + } + + @TearDown(Level.Trial) + public void afterAll() { + arena.close(); + } + + @Benchmark + public long writeString_global_fmm() { + return MySwiftLibrary.globalWriteString(string); + } + + @Benchmark + public long writeString_global_jni() { + return HelloJava2Swift.jniWriteString(string); + } + + @Benchmark + public long writeString_baseline() { + return string.length(); + } + + static String makeString(int size) { + var text = + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut in augue ullamcorper, mattis lacus tincidunt, " + + "accumsan massa. Morbi gravida purus ut porttitor iaculis. Vestibulum lacinia, mi in tincidunt hendrerit," + + "lectus est placerat magna, vitae vestibulum nulla ligula at massa. Pellentesque nibh quam, pulvinar eu " + + "nunc congue, molestie molestie augue. Nam convallis consectetur velit, at dictum risus ullamcorper iaculis. " + + "Vestibulum lacinia nisi in elit consectetur vulputate. Praesent id odio tristique, tincidunt arcu et, convallis velit. " + + "Sed vitae pulvinar arcu. Curabitur euismod mattis dui in suscipit. Morbi aliquet facilisis vulputate. Phasellus " + + "non lectus dapibus, semper magna eu, aliquet magna. Suspendisse vel enim at augue luctus gravida. Suspendisse " + + "venenatis justo non accumsan sollicitudin. Suspendisse vitae ornare odio, id blandit nibh. Nulla facilisi. " + + "Nulla nulla orci, finibus nec luctus et, faucibus et ligula."; + return text.substring(0, size); + } +} diff --git a/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java b/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java index 2a86e403..1fafaf0c 100644 --- a/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java +++ b/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java @@ -56,4 +56,8 @@ static void examples() { System.out.println("DONE."); } + + public static native long jniWriteString(String str); + public static native long jniGetInt(); + } diff --git a/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/MySwiftLibraryTest.java b/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/MySwiftLibraryTest.java index ffa90359..007b06bd 100644 --- a/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/MySwiftLibraryTest.java +++ b/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/MySwiftLibraryTest.java @@ -14,6 +14,7 @@ package com.example.swift; +import com.example.swift.MySwiftLibrary; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; @@ -27,6 +28,10 @@ public class MySwiftLibraryTest { + static { + System.loadLibrary(MySwiftLibrary.LIB_NAME); + } + @Test void call_helloWorld() { MySwiftLibrary.helloWorld(); @@ -41,6 +46,22 @@ void call_globalTakeInt() { assertNotNull(MySwiftLibrary.globalTakeInt$address()); } + @Test + void call_writeString_jextract() { + var string = "Hello Swift!"; + long reply = MySwiftLibrary.globalWriteString(string); + + assertEquals(string.length(), reply); + } + + @Test + void call_writeString_jni() { + var string = "Hello Swift!"; + long reply = HelloJava2Swift.jniWriteString(string); + + assertEquals(string.length(), reply); + } + @Test @Disabled("Upcalls not yet implemented in new scheme") @SuppressWarnings({"Convert2Lambda", "Convert2MethodRef"}) diff --git a/Sources/JExtractSwift/ImportedDecls.swift b/Sources/JExtractSwift/ImportedDecls.swift index cbff9969..794753aa 100644 --- a/Sources/JExtractSwift/ImportedDecls.swift +++ b/Sources/JExtractSwift/ImportedDecls.swift @@ -90,6 +90,10 @@ public struct ImportedParam { var effectiveName: String? { firstName ?? secondName } + + var effectiveValueName: String { + secondName ?? firstName ?? "_" + } // The Swift type as-is from the swift interface var swiftType: String { @@ -113,6 +117,14 @@ extension ImportedParam { } } +public enum ParameterVariant { + /// Used when declaring the "Swift thunks" we call through into Swift. + /// + /// Some types need to be represented as raw pointers and recovered into + /// Swift types inside the thunks when we do this. + case cDeclThunk +} + // TODO: this is used in different contexts and needs a cleanup // Perhaps this is "which parameter passing style"? public enum SelfParameterVariant { diff --git a/Sources/JExtractSwift/JavaTypes.swift b/Sources/JExtractSwift/JavaTypes.swift index 01a69aaf..633943ef 100644 --- a/Sources/JExtractSwift/JavaTypes.swift +++ b/Sources/JExtractSwift/JavaTypes.swift @@ -20,6 +20,11 @@ extension JavaType { .class(package: "java.lang.foreign", name: "MemorySegment") } + /// The description of the type java.lang.String. + static var javaLangString: JavaType { + .class(package: "java.lang", name: "String") + } + /// The description of the type java.lang.Runnable. static var javaLangRunnable: JavaType { .class(package: "java.lang", name: "Runnable") diff --git a/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift b/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift index 76721e46..d292467f 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift @@ -44,6 +44,19 @@ extension Swift2JavaTranslator { print("[swift-java] Generated: \(ty.javaClassName.bold).java (at \(outputFile))") } } + + do { + let filename = "\(self.swiftModuleName).java" + log.info("Printing contents: \(filename)") + printModule(&printer) + + if let outputFile = try printer.writeContents( + outputDirectory: outputDirectory, + javaPackagePath: javaPackagePath, + filename: filename) { + print("[swift-java] Generated: \(self.swiftModuleName).java (at \(outputFile)") + } + } } public func writeSwiftThunkSources(outputDirectory: String) throws { @@ -94,6 +107,13 @@ extension Swift2JavaTranslator { public func printGlobalSwiftThunkSources(_ printer: inout CodePrinter) throws { let stt = SwiftThunkTranslator(self) + printer.print( + """ + // Generated by swift-java + + import SwiftKitSwift + """) + for thunk in stt.renderGlobalThunks() { printer.print(thunk) printer.println() @@ -163,6 +183,7 @@ extension Swift2JavaTranslator { printModuleClass(&printer) { printer in // TODO: print all "static" methods for decl in importedGlobalFuncs { + self.log.trace("Print imported decl: \(decl)") printFunctionDowncallMethods(&printer, decl) } } @@ -711,9 +732,8 @@ extension Swift2JavaTranslator { var mh$ = \(decl.baseIdentifier).\(handleName); \(renderTry(withArena: needsArena)) """, - """ - \(renderUpcallHandles(decl)) - """, + renderUpcallHandles(decl), + renderParameterDowncallConversions(decl), """ if (SwiftKit.TRACE_DOWNCALLS) { SwiftKit.traceDowncall(\(renderForwardJavaParams(decl, paramPassingStyle: .memorySegment))); @@ -807,6 +827,10 @@ extension Swift2JavaTranslator { if p.type.javaType.isSwiftClosure { return true } + + if p.type.javaType.isString { + return true + } } return false @@ -814,7 +838,7 @@ extension Swift2JavaTranslator { public func renderTry(withArena: Bool) -> String { if withArena { - "try (Arena arena = Arena.ofConfined()) {" + "try (var arena = Arena.ofConfined()) {" } else { "try {" } @@ -839,7 +863,10 @@ extension Swift2JavaTranslator { } // TODO: these are stateless, find new place for them? - public func renderSwiftParamDecls(_ decl: ImportedFunc, paramPassingStyle: SelfParameterVariant?) -> String { + public func renderSwiftParamDecls( + _ decl: ImportedFunc, + paramPassingStyle: SelfParameterVariant?, + style: ParameterVariant? = nil) -> String { var ps: [String] = [] var pCounter = 0 @@ -853,7 +880,9 @@ extension Swift2JavaTranslator { let secondName = p.secondName ?? p.firstName ?? nextUniqueParamName() let paramTy: String = - if paramPassingStyle == .swiftThunkSelf { + if style == .cDeclThunk, p.type.javaType.isString { + "UnsafeMutablePointer" // TODO: is this ok? + } else if paramPassingStyle == .swiftThunkSelf { "\(p.type.cCompatibleSwiftType)" } else { p.type.swiftTypeName.description @@ -892,6 +921,21 @@ extension Swift2JavaTranslator { return printer.contents } + public func renderParameterDowncallConversions(_ decl: ImportedFunc) -> String { + var printer = CodePrinter() + for p in decl.parameters { + if p.type.javaType.isString { + printer.print( + """ + var \(p.effectiveValueName)$ = arena.allocateFrom(\(p.effectiveValueName)); + """ + ) + } + } + + return printer.contents + } + public func renderForwardJavaParams(_ decl: ImportedFunc, paramPassingStyle: SelfParameterVariant?) -> String { var ps: [String] = [] var pCounter = 0 @@ -907,6 +951,14 @@ extension Swift2JavaTranslator { if p.effectiveName == "self$" { precondition(paramPassingStyle == .memorySegment) param = "self$" + } else if p.type.javaType.isString { + // TODO: make this less one-off and maybe call it "was adapted"? + if paramPassingStyle == .wrapper { + // pass it raw, we're not performing adaptation here it seems as we're passing wrappers around + param = "\(p.effectiveValueName)" + } else { + param = "\(p.effectiveValueName)$" + } } else { param = "\(p.renderParameterForwarding() ?? nextUniqueParamName())" } diff --git a/Sources/JExtractSwift/Swift2JavaVisitor.swift b/Sources/JExtractSwift/Swift2JavaVisitor.swift index 3feceec3..44138018 100644 --- a/Sources/JExtractSwift/Swift2JavaVisitor.swift +++ b/Sources/JExtractSwift/Swift2JavaVisitor.swift @@ -94,7 +94,7 @@ final class Swift2JavaVisitor: SyntaxVisitor { params = try node.signature.parameterClause.parameters.map { param in // TODO: more robust parameter handling // TODO: More robust type handling - return ImportedParam( + ImportedParam( syntax: param, type: try cCompatibleType(for: param.type) ) diff --git a/Sources/JExtractSwift/SwiftThunkTranslator.swift b/Sources/JExtractSwift/SwiftThunkTranslator.swift index 5fc01279..c530be3b 100644 --- a/Sources/JExtractSwift/SwiftThunkTranslator.swift +++ b/Sources/JExtractSwift/SwiftThunkTranslator.swift @@ -50,6 +50,7 @@ struct SwiftThunkTranslator { decls.append(contentsOf: render(forFunc: decl)) } +// TODO: handle variables // for v in nominal.variables { // if let acc = v.accessorFunc(kind: .get) { // decls.append(contentsOf: render(forFunc: acc)) @@ -102,35 +103,73 @@ struct SwiftThunkTranslator { st.log.trace("Rendering thunks for: \(decl.baseIdentifier)") let thunkName = st.thunkNameRegistry.functionThunkName(module: st.swiftModuleName, decl: decl) + let returnArrowTy = + if decl.returnType.cCompatibleJavaMemoryLayout == .primitive(.void) { + "/* \(decl.returnType.swiftTypeName) */" + } else { + "-> \(decl.returnType.cCompatibleSwiftType) /* \(decl.returnType.swiftTypeName) */" + } + // Do we need to pass a self parameter? let paramPassingStyle: SelfParameterVariant? + let callBase: String let callBaseDot: String if let parent = decl.parent { paramPassingStyle = .swiftThunkSelf - callBaseDot = "unsafeBitCast(_self, to: \(parent.originalSwiftType).self)." - // callBaseDot = "(_self as! \(parent.originalSwiftType))." + callBase = "let self$ = unsafeBitCast(_self, to: \(parent.originalSwiftType).self)" + callBaseDot = "self$." } else { paramPassingStyle = nil + callBase = "" callBaseDot = "" } - let returnArrowTy = - if decl.returnType.cCompatibleJavaMemoryLayout == .primitive(.void) { - "/* \(decl.returnType.swiftTypeName) */" - } else { - "-> \(decl.returnType.cCompatibleSwiftType) /* \(decl.returnType.swiftTypeName) */" - } - // FIXME: handle in thunk: errors + let returnStatement: String + if decl.returnType.javaType.isString { + returnStatement = + """ + let adaptedReturnValue = fatalError("Not implemented: adapting return types in Swift thunks") + return adaptedReturnValue + """ + } else { + returnStatement = "return returnValue" + } + + let declParams = st.renderSwiftParamDecls( + decl, + paramPassingStyle: paramPassingStyle, + style: .cDeclThunk + ) return [ """ @_cdecl("\(raw: thunkName)") - public func \(raw: thunkName)(\(raw: st.renderSwiftParamDecls(decl, paramPassingStyle: paramPassingStyle))) \(raw: returnArrowTy) { - return \(raw: callBaseDot)\(raw: decl.baseIdentifier)(\(raw: st.renderForwardSwiftParams(decl, paramPassingStyle: paramPassingStyle))) + public func \(raw: thunkName)(\(raw: declParams)) \(raw: returnArrowTy) { + \(raw: adaptArgumentsInThunk(decl)) + \(raw: callBase) + let returnValue = \(raw: callBaseDot)\(raw: decl.baseIdentifier)(\(raw: st.renderForwardSwiftParams(decl, paramPassingStyle: paramPassingStyle))) + \(raw: returnStatement) } """ ] } + + func adaptArgumentsInThunk(_ decl: ImportedFunc) -> String { + var lines: [String] = [] + for p in decl.parameters { + if p.type.javaType.isString { + // FIXME: is there a way we can avoid the copying here? + let adaptedType = + """ + let \(p.effectiveValueName) = String(cString: \(p.effectiveValueName)) + """ + + lines += [adaptedType] + } + } + + return lines.joined(separator: "\n") + } } diff --git a/Sources/JExtractSwift/TranslatedType.swift b/Sources/JExtractSwift/TranslatedType.swift index 9dc12e07..eef4140d 100644 --- a/Sources/JExtractSwift/TranslatedType.swift +++ b/Sources/JExtractSwift/TranslatedType.swift @@ -116,6 +116,17 @@ extension Swift2JavaVisitor { ) } + // We special handle String types + if parent == nil, name == "String" { + return TranslatedType( + cCompatibleConvention: .direct, + originalSwiftType: "\(raw: name)", + cCompatibleSwiftType: "Swift.\(raw: name)", + cCompatibleJavaMemoryLayout: .heapObject, // FIXME: or specialize string? + javaType: .javaLangString + ) + } + // Identify the various pointer types from the standard library. if let (requiresArgument, _, hasCount) = name.isNameOfSwiftPointerType, !hasCount { // Dig out the pointee type if needed. diff --git a/Sources/JavaKit/BridgedValues/JavaValue+String.swift b/Sources/JavaKit/BridgedValues/JavaValue+String.swift index 5e98634d..213842cb 100644 --- a/Sources/JavaKit/BridgedValues/JavaValue+String.swift +++ b/Sources/JavaKit/BridgedValues/JavaValue+String.swift @@ -30,7 +30,7 @@ extension String: JavaValue { } let cString = environment.interface.GetStringUTFChars(environment, value, nil)! defer { environment.interface.ReleaseStringUTFChars(environment, value, cString) } - self = String(cString: cString) + self = String(cString: cString) // copy } public func getJNIValue(in environment: JNIEnvironment) -> JNIType { diff --git a/Sources/JavaTypes/JavaType+SwiftNames.swift b/Sources/JavaTypes/JavaType+SwiftNames.swift index e1604eaa..d01398b8 100644 --- a/Sources/JavaTypes/JavaType+SwiftNames.swift +++ b/Sources/JavaTypes/JavaType+SwiftNames.swift @@ -45,6 +45,18 @@ extension JavaType { } } + public var isString: Bool { + switch self { + case .boolean, .byte, .char, .short, .int, .long, .float, .double, .void, + .array: + return false + case .class(package: "java.lang", name: "String"): + return true + case .class: + return false + } + } + /// Produce the Swift type name for this Java type. public func swiftTypeName(resolver: JavaToSwiftClassNameResolver) rethrows -> String { switch self { diff --git a/Tests/JExtractSwiftTests/FuncCallbackImportTests.swift b/Tests/JExtractSwiftTests/FuncCallbackImportTests.swift index 2f2c8c8c..696c4b93 100644 --- a/Tests/JExtractSwiftTests/FuncCallbackImportTests.swift +++ b/Tests/JExtractSwiftTests/FuncCallbackImportTests.swift @@ -61,7 +61,7 @@ final class FuncCallbackImportTests { */ public static void callMe(java.lang.Runnable callback) { var mh$ = callMe.HANDLE; - try (Arena arena = Arena.ofConfined()) { + try (var arena = Arena.ofConfined()) { FunctionDescriptor callMe_callback_desc$ = FunctionDescriptor.ofVoid(); MethodHandle callMe_callback_handle$ = MethodHandles.lookup() .findVirtual(Runnable.class, "run", diff --git a/Tests/JExtractSwiftTests/StringPassingTests.swift b/Tests/JExtractSwiftTests/StringPassingTests.swift new file mode 100644 index 00000000..d377f166 --- /dev/null +++ b/Tests/JExtractSwiftTests/StringPassingTests.swift @@ -0,0 +1,55 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import JExtractSwift +import Testing + +final class StringPassingTests { + let class_interfaceFile = + """ + public func writeString(string: String) -> Int { + return string.count + } + """ + + @Test("Import: public func writeString(string: String) -> Int") + func method_helloWorld() throws { + let st = Swift2JavaTranslator( + javaPackage: "com.example.swift", + swiftModuleName: "__FakeModule" + ) + st.log.logLevel = .trace + + try assertOutput( + st, input: class_interfaceFile, .java, + detectChunkByInitialLines: 1, + expectedChunks: + [ + """ + public static long writeString(java.lang.String string) { + var mh$ = writeString.HANDLE; + try (var arena = Arena.ofConfined()) { + var string$ = arena.allocateFrom(string); + if (SwiftKit.TRACE_DOWNCALLS) { + SwiftKit.traceDowncall(); + } + return (long) mh$.invokeExact(string$); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + """ + ]) + } +} From b3039e522b55396976c0e1959aedce270e5fd6da Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Tue, 17 Dec 2024 14:48:26 +0900 Subject: [PATCH 211/426] fix license header --- .../MySwiftLibrary/jni/JNIImplementations.swift | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/jni/JNIImplementations.swift b/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/jni/JNIImplementations.swift index 90df0344..ef0e2e58 100644 --- a/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/jni/JNIImplementations.swift +++ b/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/jni/JNIImplementations.swift @@ -1,4 +1,17 @@ -// Auto-generated by Java-to-Swift wrapper generator. +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + import JavaKit import JavaRuntime From c57b70a3c50ecac73246ae5a86f139ff28852ab5 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Tue, 17 Dec 2024 17:39:40 +0900 Subject: [PATCH 212/426] adjust Swift tests to new source generation --- .../Swift2JavaTranslator+Printing.swift | 1 - Tests/JExtractSwiftTests/MethodImportTests.swift | 16 +++++----------- .../JExtractSwiftTests/StringPassingTests.swift | 2 +- 3 files changed, 6 insertions(+), 13 deletions(-) diff --git a/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift b/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift index d292467f..61d7e981 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift @@ -252,7 +252,6 @@ extension Swift2JavaTranslator { } public func printHeader(_ printer: inout CodePrinter) { - assert(printer.isEmpty) printer.print( """ // Generated by jextract-swift diff --git a/Tests/JExtractSwiftTests/MethodImportTests.swift b/Tests/JExtractSwiftTests/MethodImportTests.swift index c866cb60..67c7c210 100644 --- a/Tests/JExtractSwiftTests/MethodImportTests.swift +++ b/Tests/JExtractSwiftTests/MethodImportTests.swift @@ -38,7 +38,6 @@ final class MethodImportTests { public func globalTakeIntLongString(i32: Int32, l: Int64, s: String) extension MySwiftClass { - // MANGLED NAME: $s14MySwiftLibrary0aB5ClassC22helloMemberFunctionInExtension public func helloMemberInExtension() } @@ -54,12 +53,6 @@ final class MethodImportTests { @objc deinit } - - // FIXME: Hack to allow us to translate "String", even though it's not - // actually available - // MANGLED NAME: $ss - public class String { - } """ @Test("Import: public func helloWorld()") @@ -174,13 +167,14 @@ final class MethodImportTests { * public func globalTakeIntLongString(i32: Int32, l: Int64, s: String) * } */ - public static void globalTakeIntLongString(int i32, long l, com.example.swift.String s) { + public static void globalTakeIntLongString(int i32, long l, java.lang.String s) { var mh$ = globalTakeIntLongString.HANDLE; - try { + try (var arena = Arena.ofConfined()) { + var s$ = arena.allocateFrom(s); if (SwiftKit.TRACE_DOWNCALLS) { - SwiftKit.traceDowncall(i32, l, s.$memorySegment()); + SwiftKit.traceDowncall(i32, l, s$); } - mh$.invokeExact(i32, l, s.$memorySegment()); + mh$.invokeExact(i32, l, s$); } catch (Throwable ex$) { throw new AssertionError("should not reach here", ex$); } diff --git a/Tests/JExtractSwiftTests/StringPassingTests.swift b/Tests/JExtractSwiftTests/StringPassingTests.swift index d377f166..c51d3549 100644 --- a/Tests/JExtractSwiftTests/StringPassingTests.swift +++ b/Tests/JExtractSwiftTests/StringPassingTests.swift @@ -42,7 +42,7 @@ final class StringPassingTests { try (var arena = Arena.ofConfined()) { var string$ = arena.allocateFrom(string); if (SwiftKit.TRACE_DOWNCALLS) { - SwiftKit.traceDowncall(); + SwiftKit.traceDowncall(string$); } return (long) mh$.invokeExact(string$); } catch (Throwable ex$) { From b5c4a18234824599949067a58d42a2db164ddc81 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Wed, 15 Jan 2025 13:59:24 +0900 Subject: [PATCH 213/426] Simple step towards importing structs, add initializeWithCopy funcs (#206) --- .../Sources/MySwiftLibrary/MySwiftClass.swift | 58 +++++++++++++++ .../MySwiftLibrary/MySwiftLibrary.swift | 70 +++---------------- .../MySwiftLibrary/MySwiftStruct.swift | 44 ++++++++++++ .../MySwiftLibrary/_RuntimeWorkarounds.swift | 22 ++++++ .../com/example/swift/HelloJava2Swift.java | 3 + .../com/example/swift/MySwiftStructTest.java | 37 ++++++++++ .../org/swift/swiftkit/SwiftArenaTest.java | 4 ++ .../ExampleSwiftLibrary/MySwiftLibrary.swift | 11 +-- Sources/JExtractSwift/ImportedDecls.swift | 9 +++ .../Swift2JavaTranslator+Printing.swift | 13 +++- Sources/JExtractSwift/Swift2JavaVisitor.swift | 18 +++++ .../swiftkit/ConfinedSwiftMemorySession.java | 3 +- .../swiftkit/SwiftValueWitnessTable.java | 68 ++++++++++++++++++ 13 files changed, 286 insertions(+), 74 deletions(-) create mode 100644 Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftClass.swift create mode 100644 Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftStruct.swift create mode 100644 Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/_RuntimeWorkarounds.swift create mode 100644 Samples/SwiftKitSampleApp/src/test/java/com/example/swift/MySwiftStructTest.java diff --git a/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftClass.swift b/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftClass.swift new file mode 100644 index 00000000..1ae962a3 --- /dev/null +++ b/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftClass.swift @@ -0,0 +1,58 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +public class MySwiftClass { + + public var len: Int + public var cap: Int + + public init(len: Int, cap: Int) { + self.len = len + self.cap = cap + + p("\(MySwiftClass.self).len = \(self.len)") + p("\(MySwiftClass.self).cap = \(self.cap)") + let addr = unsafeBitCast(self, to: UInt64.self) + p("initializer done, self = 0x\(String(addr, radix: 16, uppercase: true))") + } + + deinit { + let addr = unsafeBitCast(self, to: UInt64.self) + p("Deinit, self = 0x\(String(addr, radix: 16, uppercase: true))") + } + + public var counter: Int32 = 0 + + public func voidMethod() { + p("") + } + + public func takeIntMethod(i: Int) { + p("i:\(i)") + } + + public func echoIntMethod(i: Int) -> Int { + p("i:\(i)") + return i + } + + public func makeIntMethod() -> Int { + p("make int -> 12") + return 12 + } + + public func makeRandomIntMethod() -> Int { + return Int.random(in: 1..<256) + } +} diff --git a/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift b/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift index ddb14569..2bd1905c 100644 --- a/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift +++ b/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift @@ -47,68 +47,18 @@ public func globalCallMeRunnable(run: () -> ()) { run() } -public class MySwiftClass { - - public var len: Int - public var cap: Int - - public init(len: Int, cap: Int) { - self.len = len - self.cap = cap - - p("\(MySwiftClass.self).len = \(self.len)") - p("\(MySwiftClass.self).cap = \(self.cap)") - let addr = unsafeBitCast(self, to: UInt64.self) - p("initializer done, self = 0x\(String(addr, radix: 16, uppercase: true))") - } - - deinit { - let addr = unsafeBitCast(self, to: UInt64.self) - p("Deinit, self = 0x\(String(addr, radix: 16, uppercase: true))") - } - - public var counter: Int32 = 0 - - public func voidMethod() { - p("") - } - - public func takeIntMethod(i: Int) { - p("i:\(i)") - } - - public func echoIntMethod(i: Int) -> Int { - p("i:\(i)") - return i - } - - public func makeIntMethod() -> Int { - p("make int -> 12") - return 12 - } - - public func writeString(string: String) -> Int { - p("echo -> \(string)") - return string.count - } - - public func makeRandomIntMethod() -> Int { - return Int.random(in: 1..<256) - } -} - // ==== Internal helpers -private func p(_ msg: String, file: String = #fileID, line: UInt = #line, function: String = #function) { -// print("[swift][\(file):\(line)](\(function)) \(msg)") -// fflush(stdout) +func p(_ msg: String, file: String = #fileID, line: UInt = #line, function: String = #function) { + print("[swift][\(file):\(line)](\(function)) \(msg)") + fflush(stdout) } -#if os(Linux) -// FIXME: why do we need this workaround? -@_silgen_name("_objc_autoreleaseReturnValue") -public func _objc_autoreleaseReturnValue(a: Any) {} + #if os(Linux) + // FIXME: why do we need this workaround? + @_silgen_name("_objc_autoreleaseReturnValue") + public func _objc_autoreleaseReturnValue(a: Any) {} -@_silgen_name("objc_autoreleaseReturnValue") -public func objc_autoreleaseReturnValue(a: Any) {} -#endif + @_silgen_name("objc_autoreleaseReturnValue") + public func objc_autoreleaseReturnValue(a: Any) {} + #endif diff --git a/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftStruct.swift b/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftStruct.swift new file mode 100644 index 00000000..85bcb4c7 --- /dev/null +++ b/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftStruct.swift @@ -0,0 +1,44 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +public struct MySwiftStruct { + + public var number: Int + + public init(number: Int) { + self.number = number + } + + public func voidMethod() { + p("") + } + + public func takeIntMethod(i: Int) { + p("i:\(i)") + } + + public func echoIntMethod(i: Int) -> Int { + p("i:\(i)") + return i + } + + public func makeIntMethod() -> Int { + p("make int -> 12") + return 12 + } + + public func makeRandomIntMethod() -> Int { + return Int.random(in: 1..<256) + } +} diff --git a/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/_RuntimeWorkarounds.swift b/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/_RuntimeWorkarounds.swift new file mode 100644 index 00000000..f3056973 --- /dev/null +++ b/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/_RuntimeWorkarounds.swift @@ -0,0 +1,22 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +#if os(Linux) +// FIXME: why do we need this workaround? +@_silgen_name("_objc_autoreleaseReturnValue") +public func _objc_autoreleaseReturnValue(a: Any) {} + +@_silgen_name("objc_autoreleaseReturnValue") +public func objc_autoreleaseReturnValue(a: Any) {} +#endif diff --git a/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java b/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java index 1fafaf0c..8c343ab5 100644 --- a/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java +++ b/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java @@ -52,6 +52,9 @@ static void examples() { obj.voidMethod(); obj.takeIntMethod(42); + + MySwiftStruct swiftValue = new MySwiftStruct(12); + } System.out.println("DONE."); diff --git a/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/MySwiftStructTest.java b/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/MySwiftStructTest.java new file mode 100644 index 00000000..27126587 --- /dev/null +++ b/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/MySwiftStructTest.java @@ -0,0 +1,37 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package com.example.swift; + +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.swift.swiftkit.SwiftArena; +import org.swift.swiftkit.SwiftKit; + +import java.io.File; +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class MySwiftStructTest { + + @Test + void test_MySwiftClass_voidMethod() { + try (var arena = SwiftArena.ofConfined()) { + MySwiftStruct o = new MySwiftStruct(12); +// o.voidMethod(); + } + } + +} diff --git a/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/SwiftArenaTest.java b/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/SwiftArenaTest.java index ad514e1b..1bf3c388 100644 --- a/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/SwiftArenaTest.java +++ b/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/SwiftArenaTest.java @@ -70,6 +70,10 @@ public void arena_releaseClassOnClose_class_leaked() { // The message should point out which objects "leaked": assertTrue(ex.getMessage().contains(memorySegmentDescription)); } + } + + @Test + public void arena_initializeWithCopy_struct() { } } diff --git a/Sources/ExampleSwiftLibrary/MySwiftLibrary.swift b/Sources/ExampleSwiftLibrary/MySwiftLibrary.swift index 8376d9b6..96afd331 100644 --- a/Sources/ExampleSwiftLibrary/MySwiftLibrary.swift +++ b/Sources/ExampleSwiftLibrary/MySwiftLibrary.swift @@ -97,16 +97,7 @@ public func _getTypeByMangledNameInEnvironment( // ==== Internal helpers -private func p(_ msg: String, file: String = #fileID, line: UInt = #line, function: String = #function) { +func p(_ msg: String, file: String = #fileID, line: UInt = #line, function: String = #function) { print("[swift][\(file):\(line)](\(function)) \(msg)") fflush(stdout) } - -#if os(Linux) -// FIXME: why do we need this workaround? -@_silgen_name("_objc_autoreleaseReturnValue") -public func _objc_autoreleaseReturnValue(a: Any) {} - -@_silgen_name("objc_autoreleaseReturnValue") -public func objc_autoreleaseReturnValue(a: Any) {} -#endif diff --git a/Sources/JExtractSwift/ImportedDecls.swift b/Sources/JExtractSwift/ImportedDecls.swift index 794753aa..6edc263c 100644 --- a/Sources/JExtractSwift/ImportedDecls.swift +++ b/Sources/JExtractSwift/ImportedDecls.swift @@ -49,6 +49,15 @@ public struct ImportedNominalType: ImportedDecl { javaType: javaType ) } + + public var isReferenceType: Bool { + switch self.kind { + case .class, .actor: + return true + case .enum, .struct: + return false + } + } /// The Java class name without the package. public var javaClassName: String { diff --git a/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift b/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift index 61d7e981..bac029ec 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift @@ -194,7 +194,7 @@ extension Swift2JavaTranslator { printPackage(&printer) printImports(&printer) - printClass(&printer, decl) { printer in + printNominal(&printer, decl) { printer in // Prepare type metadata, we're going to need these when invoking e.g. initializers so cache them in a static. // We call into source swift-java source generated accessors which give us the type of the Swift object: // TODO: seems we no longer need the mangled name per se, so avoiding such constant and downcall @@ -277,10 +277,17 @@ extension Swift2JavaTranslator { printer.print("") } - public func printClass( + public func printNominal( _ printer: inout CodePrinter, _ decl: ImportedNominalType, body: (inout CodePrinter) -> Void ) { - printer.printTypeDecl("public final class \(decl.javaClassName) implements SwiftHeapObject") { + let parentProtocol: String + if decl.isReferenceType { + parentProtocol = "SwiftHeapObject" + } else { + parentProtocol = "SwiftValue" + } + + printer.printTypeDecl("public final class \(decl.javaClassName) implements \(parentProtocol)") { printer in // ==== Storage of the class printClassSelfProperty(&printer, decl) diff --git a/Sources/JExtractSwift/Swift2JavaVisitor.swift b/Sources/JExtractSwift/Swift2JavaVisitor.swift index 44138018..b9ba3bd4 100644 --- a/Sources/JExtractSwift/Swift2JavaVisitor.swift +++ b/Sources/JExtractSwift/Swift2JavaVisitor.swift @@ -40,6 +40,7 @@ final class Swift2JavaVisitor: SyntaxVisitor { } override func visit(_ node: ClassDeclSyntax) -> SyntaxVisitorContinueKind { + log.debug("Visit \(node.kind): \(node)") guard let importedNominalType = translator.importedNominalType(node) else { return .skipChildren } @@ -54,7 +55,24 @@ final class Swift2JavaVisitor: SyntaxVisitor { currentTypeName = nil } } + + override func visit(_ node: StructDeclSyntax) -> SyntaxVisitorContinueKind { + log.debug("Visit \(node.kind): \(node)") + guard let importedNominalType = translator.importedNominalType(node) else { + return .skipChildren + } + + currentTypeName = importedNominalType.swiftTypeName + return .visitChildren + } + override func visitPost(_ node: StructDeclSyntax) { + if currentTypeName != nil { + log.debug("Completed import: \(node.kind) \(node.name)") + currentTypeName = nil + } + } + override func visit(_ node: ExtensionDeclSyntax) -> SyntaxVisitorContinueKind { // Resolve the extended type of the extension as an imported nominal, and // recurse if we found it. diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/ConfinedSwiftMemorySession.java b/SwiftKit/src/main/java/org/swift/swiftkit/ConfinedSwiftMemorySession.java index e727f5db..36d7be77 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/ConfinedSwiftMemorySession.java +++ b/SwiftKit/src/main/java/org/swift/swiftkit/ConfinedSwiftMemorySession.java @@ -36,7 +36,8 @@ public ConfinedSwiftMemorySession(Thread owner) { public void checkValid() throws RuntimeException { if (this.owner != null && this.owner != Thread.currentThread()) { - throw new WrongThreadException("ConfinedSwift arena is confined to %s but was closed from %s!".formatted(this.owner, Thread.currentThread())); + throw new WrongThreadException("ConfinedSwift arena is confined to %s but was closed from %s!" + .formatted(this.owner, Thread.currentThread())); } else if (this.state.get() < ACTIVE) { throw new RuntimeException("SwiftArena is already closed!"); } diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValueWitnessTable.java b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValueWitnessTable.java index 826a4fa2..d2f7d729 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValueWitnessTable.java +++ b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValueWitnessTable.java @@ -225,4 +225,72 @@ public static void destroy(SwiftAnyType type, MemorySegment object) { } } + /** + * {@snippet lang = C: + * /// T *(*initializeWithCopy)(T *dest, T *src, M *self); + * /// + * /// Given an invalid object of this type, initialize it as a copy of + * /// the source object. Returns the dest object. + * FUNCTION_VALUE_WITNESS(initializeWithCopy, + * InitializeWithCopy, + * MUTABLE_VALUE_TYPE, + * (MUTABLE_VALUE_TYPE, MUTABLE_VALUE_TYPE, TYPE_TYPE)) + *} + */ + private static class initializeWithCopy { + + static final long $offset = + $LAYOUT.byteOffset(MemoryLayout.PathElement.groupElement("initializeWithCopy")); + + static final FunctionDescriptor DESC = FunctionDescriptor.of( + /* -> */ ValueLayout.ADDRESS, // returns the destination object + ValueLayout.ADDRESS, // destination + ValueLayout.ADDRESS, // source + ValueLayout.ADDRESS // pointer to the witness table + ); + + /** + * Function pointer for the initializeWithCopy operation + */ + static MemorySegment addr(SwiftAnyType ty) { + // Get the value witness table of the type + final var vwt = SwiftValueWitnessTable.valueWitnessTable(ty.$memorySegment()); + + // Get the address of the function stored at the offset of the witness table + long funcAddress = getSwiftInt(vwt, initializeWithCopy.$offset); + return MemorySegment.ofAddress(funcAddress); + } + + static MethodHandle handle(SwiftAnyType ty) { + return Linker.nativeLinker().downcallHandle(addr(ty), DESC); + } + } + + + /** + * Given an invalid object of this type, initialize it as a copy of + * the source object. + *

+ * Returns the dest object. + */ + public static MemorySegment initializeWithCopy(SwiftAnyType type, MemorySegment dest, MemorySegment src) { + var fullTypeMetadata = fullTypeMetadata(type.$memorySegment()); + var wtable = valueWitnessTable(fullTypeMetadata); + + var mh = initializeWithCopy.handle(type); + + try (var arena = Arena.ofConfined()) { + // we need to make a pointer to the self pointer when calling witness table functions: + MemorySegment indirectDest = arena.allocate(SwiftValueLayout.SWIFT_POINTER); + MemorySegmentUtils.setSwiftPointerAddress(indirectDest, dest); + MemorySegment indirectSrc = arena.allocate(SwiftValueLayout.SWIFT_POINTER); + MemorySegmentUtils.setSwiftPointerAddress(indirectSrc, src); + + var returnedDest = (MemorySegment) mh.invokeExact(indirectDest, indirectSrc, wtable); + return returnedDest; + } catch (Throwable th) { + throw new AssertionError("Failed to initializeWithCopy '" + type + "' (" + dest + ", " + src + ")", th); + } + } + } From 6c4f77a99acf19b249a1a1ee5340ffd48e10bffc Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Tue, 21 Jan 2025 20:12:34 +0900 Subject: [PATCH 214/426] Prefer VarHandle to raw offset APIs A bit more idiomatic to use var handles rather than raw offsets. --- .../swiftkit/SwiftValueWitnessTable.java | 73 ++++++++----------- 1 file changed, 31 insertions(+), 42 deletions(-) diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValueWitnessTable.java b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValueWitnessTable.java index d2f7d729..8a092bc2 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValueWitnessTable.java +++ b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValueWitnessTable.java @@ -16,6 +16,7 @@ import java.lang.foreign.*; import java.lang.invoke.MethodHandle; +import java.lang.invoke.VarHandle; import static java.lang.foreign.ValueLayout.JAVA_BYTE; import static org.swift.swiftkit.SwiftKit.getSwiftInt; @@ -70,8 +71,7 @@ public static MemorySegment fullTypeMetadata(MemorySegment typeMetadata) { */ public static MemorySegment valueWitnessTable(MemorySegment typeMetadata) { return fullTypeMetadata(typeMetadata) - .get(SwiftValueLayout.SWIFT_POINTER, SwiftValueWitnessTable.fullTypeMetadata$vwt$offset); -// .get(ValueLayout.ADDRESS, SwiftValueWitnessTable.fullTypeMetadata$vwt$offset); + .get(SwiftValueLayout.SWIFT_POINTER, SwiftValueWitnessTable.fullTypeMetadata$vwt$offset); } @@ -81,22 +81,33 @@ public static MemorySegment valueWitnessTable(MemorySegment typeMetadata) { static final long $size$offset = $LAYOUT.byteOffset(MemoryLayout.PathElement.groupElement("size")); + /** + * Variable handle for the "stride" field within the value witness table. + */ + static final VarHandle $size$mh = + $LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("size")); + /** * Determine the size of a Swift type given its type metadata. * * @param typeMetadata the memory segment must point to a Swift metadata */ public static long sizeOfSwiftType(MemorySegment typeMetadata) { - return getSwiftInt(valueWitnessTable(typeMetadata), SwiftValueWitnessTable.$size$offset); + return getSwiftInt(valueWitnessTable(typeMetadata), $size$mh); } - /** * Offset for the "stride" field within the value witness table. */ static final long $stride$offset = $LAYOUT.byteOffset(MemoryLayout.PathElement.groupElement("stride")); + /** + * Variable handle for the "stride" field within the value witness table. + */ + static final VarHandle $stride$mh = + $LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("size")); + /** * Determine the stride of a Swift type given its type metadata, which is * how many bytes are between successive elements of this type within an @@ -107,7 +118,7 @@ public static long sizeOfSwiftType(MemorySegment typeMetadata) { * @param typeMetadata the memory segment must point to a Swift metadata */ public static long strideOfSwiftType(MemorySegment typeMetadata) { - return getSwiftInt(valueWitnessTable(typeMetadata), SwiftValueWitnessTable.$stride$offset); + return getSwiftInt(valueWitnessTable(typeMetadata), $stride$mh); } @@ -117,7 +128,7 @@ public static long strideOfSwiftType(MemorySegment typeMetadata) { * @param typeMetadata the memory segment must point to a Swift metadata */ public static long alignmentOfSwiftType(MemorySegment typeMetadata) { - long flags = getSwiftInt(valueWitnessTable(typeMetadata), SwiftValueWitnessTable.$flags$offset); + long flags = getSwiftInt(valueWitnessTable(typeMetadata), $flags$offset); return (flags & 0xFF) + 1; } @@ -161,9 +172,12 @@ public static MemoryLayout layoutOfSwiftType(MemorySegment typeMetadata) { static final long $flags$offset = $LAYOUT.byteOffset(MemoryLayout.PathElement.groupElement("flags")); + // ==== ------------------------------------------------------------------------------------------------------------ + // destroy + /** * {@snippet lang = C: - * ///void(*destroy)(T *object, witness_t *self); + * /// void(*destroy)(T *object, witness_t *self); * /// * /// Given a valid object of this type, destroy it, leaving it as an * /// invalid object. This is useful when generically destroying @@ -202,7 +216,6 @@ static MethodHandle handle(SwiftAnyType ty) { } } - /** * Destroy the value/object. *

@@ -225,6 +238,9 @@ public static void destroy(SwiftAnyType type, MemorySegment object) { } } + // ==== ------------------------------------------------------------------------------------------------------------ + // initializeWithCopy + /** * {@snippet lang = C: * /// T *(*initializeWithCopy)(T *dest, T *src, M *self); @@ -238,26 +254,23 @@ public static void destroy(SwiftAnyType type, MemorySegment object) { *} */ private static class initializeWithCopy { - static final long $offset = - $LAYOUT.byteOffset(MemoryLayout.PathElement.groupElement("initializeWithCopy")); + $LAYOUT.byteOffset(MemoryLayout.PathElement.groupElement("destroy")); - static final FunctionDescriptor DESC = FunctionDescriptor.of( - /* -> */ ValueLayout.ADDRESS, // returns the destination object - ValueLayout.ADDRESS, // destination - ValueLayout.ADDRESS, // source + static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( + ValueLayout.ADDRESS, // witness table functions expect a pointer to self pointer ValueLayout.ADDRESS // pointer to the witness table ); /** - * Function pointer for the initializeWithCopy operation + * Function pointer for the destroy operation */ static MemorySegment addr(SwiftAnyType ty) { // Get the value witness table of the type final var vwt = SwiftValueWitnessTable.valueWitnessTable(ty.$memorySegment()); - // Get the address of the function stored at the offset of the witness table - long funcAddress = getSwiftInt(vwt, initializeWithCopy.$offset); + // Get the address of the destroy function stored at the offset of the witness table + long funcAddress = getSwiftInt(vwt, destroy.$offset); return MemorySegment.ofAddress(funcAddress); } @@ -266,31 +279,7 @@ static MethodHandle handle(SwiftAnyType ty) { } } + public static void initializeWithCopy(SwiftAnyType type, MemorySegment from, MemorySegment target) { - /** - * Given an invalid object of this type, initialize it as a copy of - * the source object. - *

- * Returns the dest object. - */ - public static MemorySegment initializeWithCopy(SwiftAnyType type, MemorySegment dest, MemorySegment src) { - var fullTypeMetadata = fullTypeMetadata(type.$memorySegment()); - var wtable = valueWitnessTable(fullTypeMetadata); - - var mh = initializeWithCopy.handle(type); - - try (var arena = Arena.ofConfined()) { - // we need to make a pointer to the self pointer when calling witness table functions: - MemorySegment indirectDest = arena.allocate(SwiftValueLayout.SWIFT_POINTER); - MemorySegmentUtils.setSwiftPointerAddress(indirectDest, dest); - MemorySegment indirectSrc = arena.allocate(SwiftValueLayout.SWIFT_POINTER); - MemorySegmentUtils.setSwiftPointerAddress(indirectSrc, src); - - var returnedDest = (MemorySegment) mh.invokeExact(indirectDest, indirectSrc, wtable); - return returnedDest; - } catch (Throwable th) { - throw new AssertionError("Failed to initializeWithCopy '" + type + "' (" + dest + ", " + src + ")", th); - } } - } From 9c96f6550b4f0c4a91fa4c078b246769bcc1efcc Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Tue, 21 Jan 2025 21:08:08 +0900 Subject: [PATCH 215/426] Revert "Prefer VarHandle to raw offset APIs" (#208) This reverts commit 6c4f77a99acf19b249a1a1ee5340ffd48e10bffc. --- .../swiftkit/SwiftValueWitnessTable.java | 73 +++++++++++-------- 1 file changed, 42 insertions(+), 31 deletions(-) diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValueWitnessTable.java b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValueWitnessTable.java index 8a092bc2..d2f7d729 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValueWitnessTable.java +++ b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValueWitnessTable.java @@ -16,7 +16,6 @@ import java.lang.foreign.*; import java.lang.invoke.MethodHandle; -import java.lang.invoke.VarHandle; import static java.lang.foreign.ValueLayout.JAVA_BYTE; import static org.swift.swiftkit.SwiftKit.getSwiftInt; @@ -71,7 +70,8 @@ public static MemorySegment fullTypeMetadata(MemorySegment typeMetadata) { */ public static MemorySegment valueWitnessTable(MemorySegment typeMetadata) { return fullTypeMetadata(typeMetadata) - .get(SwiftValueLayout.SWIFT_POINTER, SwiftValueWitnessTable.fullTypeMetadata$vwt$offset); + .get(SwiftValueLayout.SWIFT_POINTER, SwiftValueWitnessTable.fullTypeMetadata$vwt$offset); +// .get(ValueLayout.ADDRESS, SwiftValueWitnessTable.fullTypeMetadata$vwt$offset); } @@ -81,33 +81,22 @@ public static MemorySegment valueWitnessTable(MemorySegment typeMetadata) { static final long $size$offset = $LAYOUT.byteOffset(MemoryLayout.PathElement.groupElement("size")); - /** - * Variable handle for the "stride" field within the value witness table. - */ - static final VarHandle $size$mh = - $LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("size")); - /** * Determine the size of a Swift type given its type metadata. * * @param typeMetadata the memory segment must point to a Swift metadata */ public static long sizeOfSwiftType(MemorySegment typeMetadata) { - return getSwiftInt(valueWitnessTable(typeMetadata), $size$mh); + return getSwiftInt(valueWitnessTable(typeMetadata), SwiftValueWitnessTable.$size$offset); } + /** * Offset for the "stride" field within the value witness table. */ static final long $stride$offset = $LAYOUT.byteOffset(MemoryLayout.PathElement.groupElement("stride")); - /** - * Variable handle for the "stride" field within the value witness table. - */ - static final VarHandle $stride$mh = - $LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("size")); - /** * Determine the stride of a Swift type given its type metadata, which is * how many bytes are between successive elements of this type within an @@ -118,7 +107,7 @@ public static long sizeOfSwiftType(MemorySegment typeMetadata) { * @param typeMetadata the memory segment must point to a Swift metadata */ public static long strideOfSwiftType(MemorySegment typeMetadata) { - return getSwiftInt(valueWitnessTable(typeMetadata), $stride$mh); + return getSwiftInt(valueWitnessTable(typeMetadata), SwiftValueWitnessTable.$stride$offset); } @@ -128,7 +117,7 @@ public static long strideOfSwiftType(MemorySegment typeMetadata) { * @param typeMetadata the memory segment must point to a Swift metadata */ public static long alignmentOfSwiftType(MemorySegment typeMetadata) { - long flags = getSwiftInt(valueWitnessTable(typeMetadata), $flags$offset); + long flags = getSwiftInt(valueWitnessTable(typeMetadata), SwiftValueWitnessTable.$flags$offset); return (flags & 0xFF) + 1; } @@ -172,12 +161,9 @@ public static MemoryLayout layoutOfSwiftType(MemorySegment typeMetadata) { static final long $flags$offset = $LAYOUT.byteOffset(MemoryLayout.PathElement.groupElement("flags")); - // ==== ------------------------------------------------------------------------------------------------------------ - // destroy - /** * {@snippet lang = C: - * /// void(*destroy)(T *object, witness_t *self); + * ///void(*destroy)(T *object, witness_t *self); * /// * /// Given a valid object of this type, destroy it, leaving it as an * /// invalid object. This is useful when generically destroying @@ -216,6 +202,7 @@ static MethodHandle handle(SwiftAnyType ty) { } } + /** * Destroy the value/object. *

@@ -238,9 +225,6 @@ public static void destroy(SwiftAnyType type, MemorySegment object) { } } - // ==== ------------------------------------------------------------------------------------------------------------ - // initializeWithCopy - /** * {@snippet lang = C: * /// T *(*initializeWithCopy)(T *dest, T *src, M *self); @@ -254,23 +238,26 @@ public static void destroy(SwiftAnyType type, MemorySegment object) { *} */ private static class initializeWithCopy { + static final long $offset = - $LAYOUT.byteOffset(MemoryLayout.PathElement.groupElement("destroy")); + $LAYOUT.byteOffset(MemoryLayout.PathElement.groupElement("initializeWithCopy")); - static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( - ValueLayout.ADDRESS, // witness table functions expect a pointer to self pointer + static final FunctionDescriptor DESC = FunctionDescriptor.of( + /* -> */ ValueLayout.ADDRESS, // returns the destination object + ValueLayout.ADDRESS, // destination + ValueLayout.ADDRESS, // source ValueLayout.ADDRESS // pointer to the witness table ); /** - * Function pointer for the destroy operation + * Function pointer for the initializeWithCopy operation */ static MemorySegment addr(SwiftAnyType ty) { // Get the value witness table of the type final var vwt = SwiftValueWitnessTable.valueWitnessTable(ty.$memorySegment()); - // Get the address of the destroy function stored at the offset of the witness table - long funcAddress = getSwiftInt(vwt, destroy.$offset); + // Get the address of the function stored at the offset of the witness table + long funcAddress = getSwiftInt(vwt, initializeWithCopy.$offset); return MemorySegment.ofAddress(funcAddress); } @@ -279,7 +266,31 @@ static MethodHandle handle(SwiftAnyType ty) { } } - public static void initializeWithCopy(SwiftAnyType type, MemorySegment from, MemorySegment target) { + /** + * Given an invalid object of this type, initialize it as a copy of + * the source object. + *

+ * Returns the dest object. + */ + public static MemorySegment initializeWithCopy(SwiftAnyType type, MemorySegment dest, MemorySegment src) { + var fullTypeMetadata = fullTypeMetadata(type.$memorySegment()); + var wtable = valueWitnessTable(fullTypeMetadata); + + var mh = initializeWithCopy.handle(type); + + try (var arena = Arena.ofConfined()) { + // we need to make a pointer to the self pointer when calling witness table functions: + MemorySegment indirectDest = arena.allocate(SwiftValueLayout.SWIFT_POINTER); + MemorySegmentUtils.setSwiftPointerAddress(indirectDest, dest); + MemorySegment indirectSrc = arena.allocate(SwiftValueLayout.SWIFT_POINTER); + MemorySegmentUtils.setSwiftPointerAddress(indirectSrc, src); + + var returnedDest = (MemorySegment) mh.invokeExact(indirectDest, indirectSrc, wtable); + return returnedDest; + } catch (Throwable th) { + throw new AssertionError("Failed to initializeWithCopy '" + type + "' (" + dest + ", " + src + ")", th); + } } + } From 4f6f7b500cea88c08be49dae1019b4fe59e71fdb Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Wed, 22 Jan 2025 23:42:30 -0800 Subject: [PATCH 216/426] Initial implementation of a new lowering from a Swift func to `@_cdecl` func Start implementing a more complete and formal lowering from an arbitrary Swift function to a `@_cdecl`-compatible thunk that calls that function. This is set up in stages more akin to what you'd see in a compiler: 1. Resolve the syntax trees for the function into a more semantic representation, for example resolving type names to nominal type declarations. This includes a simplistic implementation of a symbol table so we can resolve arbitrary type names. 2. Lower the semantic representation of each function parameter (including self). How we do this varies based on type: * Value types (struct / enum) are passed indirectly via Unsafe(Mutable)RawPointer, using a mutable pointer when the corresponding parameter is inout. * Class / actor types are passed directly via UnsafeRawPointer. * Swift types that map to primitive types (like Swift.Int32) in passed directly, no translation required. * Tuple types are recursively "exploded" into multiple parameters. * Unsafe*BufferPointer types are "exploded" into a pointer and count. * Typed unsafe pointers types are passed via their raw versions. 3. Lower returns similarly to parameters, using indirect mutable parameters for the return when we can't return directly. 4. Render the lowered declaration into a FunctionDeclSyntax node, which can be modified by the client. At present, we aren't rendering the bodies of these thunks, which need to effectively undo the transformations described in (3) and (4). For example, reconstituting a tuple from disparate arguments, appropriately re-typing and loading from indirectly-passed value types, and so on. The description of the lowered signature is intended to provide sufficient information for doing so, but will likely require tweaking. At present, this new code is not integrated in the main code path for jextract-swift. Once it hits feature parity, we'll enable it. --- .../JavaConstants/ForeignValueLayouts.swift | 22 +- .../JExtractSwift/NominalTypeResolution.swift | 4 +- ...wift2JavaTranslator+FunctionLowering.swift | 377 ++++++++++++++++++ .../JExtractSwift/Swift2JavaTranslator.swift | 42 +- .../SwiftTypes/SwiftFunctionSignature.swift | 118 ++++++ .../SwiftTypes/SwiftFunctionType.swift | 59 +++ .../SwiftTypes/SwiftModuleSymbolTable.swift | 39 ++ .../SwiftNominalTypeDeclaration.swift | 78 ++++ .../SwiftTypes/SwiftParameter.swift | 88 ++++ .../SwiftParsedModuleSymbolTable.swift | 120 ++++++ .../SwiftTypes/SwiftResult.swift | 25 ++ .../SwiftStandardLibraryTypes.swift | 208 ++++++++++ .../SwiftTypes/SwiftSymbolTable.swift | 117 ++++++ .../JExtractSwift/SwiftTypes/SwiftType.swift | 216 ++++++++++ Sources/JExtractSwift/TranslatedType.swift | 14 +- .../Asserts/LoweringAssertions.swift | 59 +++ .../FunctionLoweringTests.swift | 77 ++++ 17 files changed, 1641 insertions(+), 22 deletions(-) create mode 100644 Sources/JExtractSwift/Swift2JavaTranslator+FunctionLowering.swift create mode 100644 Sources/JExtractSwift/SwiftTypes/SwiftFunctionSignature.swift create mode 100644 Sources/JExtractSwift/SwiftTypes/SwiftFunctionType.swift create mode 100644 Sources/JExtractSwift/SwiftTypes/SwiftModuleSymbolTable.swift create mode 100644 Sources/JExtractSwift/SwiftTypes/SwiftNominalTypeDeclaration.swift create mode 100644 Sources/JExtractSwift/SwiftTypes/SwiftParameter.swift create mode 100644 Sources/JExtractSwift/SwiftTypes/SwiftParsedModuleSymbolTable.swift create mode 100644 Sources/JExtractSwift/SwiftTypes/SwiftResult.swift create mode 100644 Sources/JExtractSwift/SwiftTypes/SwiftStandardLibraryTypes.swift create mode 100644 Sources/JExtractSwift/SwiftTypes/SwiftSymbolTable.swift create mode 100644 Sources/JExtractSwift/SwiftTypes/SwiftType.swift create mode 100644 Tests/JExtractSwiftTests/Asserts/LoweringAssertions.swift create mode 100644 Tests/JExtractSwiftTests/FunctionLoweringTests.swift diff --git a/Sources/JExtractSwift/JavaConstants/ForeignValueLayouts.swift b/Sources/JExtractSwift/JavaConstants/ForeignValueLayouts.swift index 292b7182..190f9993 100644 --- a/Sources/JExtractSwift/JavaConstants/ForeignValueLayouts.swift +++ b/Sources/JExtractSwift/JavaConstants/ForeignValueLayouts.swift @@ -13,11 +13,12 @@ //===----------------------------------------------------------------------===// import Foundation +import JavaTypes /// Represents a value of a `java.lang.foreign.Self` that we want to render in generated Java code. /// /// This type may gain further methods for adjusting target layout, byte order, names etc. -public struct ForeignValueLayout: CustomStringConvertible { +public struct ForeignValueLayout: CustomStringConvertible, Equatable { var inlineComment: String? var value: String @@ -35,6 +36,20 @@ public struct ForeignValueLayout: CustomStringConvertible { self.needsMemoryLayoutCall = true } + public init?(javaType: JavaType) { + switch javaType { + case .boolean: self = .SwiftBool + case .byte: self = .SwiftInt8 + case .char: self = .SwiftUInt16 + case .short: self = .SwiftInt16 + case .int: self = .SwiftInt32 + case .long: self = .SwiftInt64 + case .float: self = .SwiftFloat + case .double: self = .SwiftDouble + case .array, .class, .void: return nil + } + } + public var description: String { var result = "" @@ -68,4 +83,9 @@ extension ForeignValueLayout { public static let SwiftFloat = Self(javaConstant: "SWIFT_FLOAT") public static let SwiftDouble = Self(javaConstant: "SWIFT_DOUBLE") + + var isPrimitive: Bool { + // FIXME: This is a hack, we need an enum to better describe this! + value != "SWIFT_POINTER" + } } diff --git a/Sources/JExtractSwift/NominalTypeResolution.swift b/Sources/JExtractSwift/NominalTypeResolution.swift index e3cc18a1..d2421a24 100644 --- a/Sources/JExtractSwift/NominalTypeResolution.swift +++ b/Sources/JExtractSwift/NominalTypeResolution.swift @@ -25,13 +25,13 @@ public class NominalTypeResolution { /// Mapping from extension declarations to the type declaration that they /// extend. - private var resolvedExtensions: [ExtensionDeclSyntax: NominalTypeDeclSyntaxNode] = [:] + var resolvedExtensions: [ExtensionDeclSyntax: NominalTypeDeclSyntaxNode] = [:] /// Extensions that have been encountered but not yet resolved to private var unresolvedExtensions: [ExtensionDeclSyntax] = [] /// Mapping from qualified nominal type names to their syntax nodes. - private var topLevelNominalTypes: [String: NominalTypeDeclSyntaxNode] = [:] + var topLevelNominalTypes: [String: NominalTypeDeclSyntaxNode] = [:] @_spi(Testing) public init() { } } diff --git a/Sources/JExtractSwift/Swift2JavaTranslator+FunctionLowering.swift b/Sources/JExtractSwift/Swift2JavaTranslator+FunctionLowering.swift new file mode 100644 index 00000000..6b49774f --- /dev/null +++ b/Sources/JExtractSwift/Swift2JavaTranslator+FunctionLowering.swift @@ -0,0 +1,377 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import JavaTypes +import SwiftSyntax + +extension Swift2JavaTranslator { + @_spi(Testing) + public func lowerFunctionSignature( + _ decl: FunctionDeclSyntax, + enclosingType: TypeSyntax? = nil + ) throws -> LoweredFunctionSignature { + let signature = try SwiftFunctionSignature( + decl, + enclosingType: try enclosingType.map { try SwiftType($0, symbolTable: symbolTable) }, + symbolTable: symbolTable + ) + + return try lowerFunctionSignature(signature) + } + + /// Lower the given Swift function signature to a Swift @_cdecl function signature, + /// which is C compatible, and the corresponding Java method signature. + /// + /// Throws an error if this function cannot be lowered for any reason. + func lowerFunctionSignature( + _ signature: SwiftFunctionSignature + ) throws -> LoweredFunctionSignature { + // Lower all of the parameters. + let loweredSelf = try signature.selfParameter.map { selfParameter in + try lowerParameter( + selfParameter.type, + convention: selfParameter.convention, parameterName: "self" + ) + } + + let loweredParameters = try signature.parameters.enumerated().map { (index, param) in + try lowerParameter( + param.type, + convention: param.convention, + parameterName: param.parameterName ?? "_\(index)" + ) + } + + // Lower the result. + var loweredResult = try lowerParameter( + signature.result.type, + convention: .byValue, + parameterName: "_result" + ) + + // If the result type doesn't lower to either empty (void) or a single + // primitive result, make it indirect. + let indirectResult: Bool + if !(loweredResult.javaFFMParameters.count == 0 || + (loweredResult.javaFFMParameters.count == 1 && + loweredResult.javaFFMParameters[0].isPrimitive)) { + loweredResult = try lowerParameter( + signature.result.type, + convention: .inout, + parameterName: "_result" + ) + indirectResult = true + } else { + indirectResult = false + } + + // Collect all of the lowered parameters for the @_cdecl function. + var allLoweredParameters: [LoweredParameters] = [] + var cdeclLoweredParameters: [SwiftParameter] = [] + if let loweredSelf { + allLoweredParameters.append(loweredSelf) + cdeclLoweredParameters.append(contentsOf: loweredSelf.cdeclParameters) + } + allLoweredParameters.append(contentsOf: loweredParameters) + cdeclLoweredParameters.append( + contentsOf: loweredParameters.flatMap { $0.cdeclParameters } + ) + + let cdeclResult: SwiftResult + if indirectResult { + cdeclLoweredParameters.append( + contentsOf: loweredResult.cdeclParameters + ) + cdeclResult = .init(convention: .direct, type: .tuple([])) + } else if loweredResult.cdeclParameters.count == 1, + let primitiveResult = loweredResult.cdeclParameters.first { + cdeclResult = .init(convention: .direct, type: primitiveResult.type) + } else if loweredResult.cdeclParameters.count == 0 { + cdeclResult = .init(convention: .direct, type: .tuple([])) + } else { + fatalError("Improper lowering of result for \(signature)") + } + + let cdeclSignature = SwiftFunctionSignature( + isStaticOrClass: false, + selfParameter: nil, + parameters: cdeclLoweredParameters, + result: cdeclResult + ) + + return LoweredFunctionSignature( + original: signature, + cdecl: cdeclSignature, + parameters: allLoweredParameters, + result: loweredResult + ) + } + + func lowerParameter( + _ type: SwiftType, + convention: SwiftParameterConvention, + parameterName: String + ) throws -> LoweredParameters { + switch type { + case .function, .metatype, .optional: + throw LoweringError.unhandledType(type) + + case .nominal(let nominal): + // Types from the Swift standard library that we know about. + if nominal.nominalTypeDecl.moduleName == "Swift", + nominal.nominalTypeDecl.parent == nil { + // Primitive types + if let loweredPrimitive = try lowerParameterPrimitive(nominal, convention: convention, parameterName: parameterName) { + return loweredPrimitive + } + + // Swift pointer types. + if let loweredPointers = try lowerParameterPointers(nominal, convention: convention, parameterName: parameterName) { + return loweredPointers + } + } + + let mutable = (convention == .inout) + let loweringStep: LoweringStep + switch nominal.nominalTypeDecl.kind { + case .actor, .class: loweringStep = .passDirectly(parameterName) + case .enum, .struct, .protocol: loweringStep = .passIndirectly(parameterName) + } + + return LoweredParameters( + cdeclToOriginal: loweringStep, + cdeclParameters: [ + SwiftParameter( + convention: .byValue, + parameterName: parameterName, + type: .nominal( + SwiftNominalType( + nominalTypeDecl: mutable + ? swiftStdlibTypes.unsafeMutableRawPointerDecl + : swiftStdlibTypes.unsafeRawPointerDecl + ) + ) + ) + ], + javaFFMParameters: [.SwiftPointer] + ) + + case .tuple(let tuple): + let parameterNames = tuple.indices.map { "\(parameterName)_\($0)" } + let loweredElements: [LoweredParameters] = try zip(tuple, parameterNames).map { element, name in + try lowerParameter(element, convention: convention, parameterName: name) + } + return LoweredParameters( + cdeclToOriginal: .tuplify(parameterNames.map { .passDirectly($0) }), + cdeclParameters: loweredElements.flatMap { $0.cdeclParameters }, + javaFFMParameters: loweredElements.flatMap { $0.javaFFMParameters } + ) + } + } + + func lowerParameterPrimitive( + _ nominal: SwiftNominalType, + convention: SwiftParameterConvention, + parameterName: String + ) throws -> LoweredParameters? { + let nominalName = nominal.nominalTypeDecl.name + let type = SwiftType.nominal(nominal) + + // Swift types that map directly to Java primitive types. + if let primitiveType = JavaType(swiftTypeName: nominalName) { + // We cannot handle inout on primitive types. + if convention == .inout { + throw LoweringError.inoutNotSupported(type) + } + + return LoweredParameters( + cdeclToOriginal: .passDirectly(parameterName), + cdeclParameters: [ + SwiftParameter( + convention: convention, + parameterName: parameterName, + type: type + ) + ], + javaFFMParameters: [ + ForeignValueLayout(javaType: primitiveType)! + ] + ) + } + + // The Swift "Int" type, which maps to whatever the pointer-sized primitive + // integer type is in Java (int for 32-bit, long for 64-bit). + if nominalName == "Int" { + // We cannot handle inout on primitive types. + if convention == .inout { + throw LoweringError.inoutNotSupported(type) + } + + return LoweredParameters( + cdeclToOriginal: .passDirectly(parameterName), + cdeclParameters: [ + SwiftParameter( + convention: convention, + parameterName: parameterName, + type: type + ) + ], + javaFFMParameters: [ + .SwiftInt + ] + ) + } + + return nil + } + + func lowerParameterPointers( + _ nominal: SwiftNominalType, + convention: SwiftParameterConvention, + parameterName: String + ) throws -> LoweredParameters? { + let nominalName = nominal.nominalTypeDecl.name + let type = SwiftType.nominal(nominal) + + guard let (requiresArgument, mutable, hasCount) = nominalName.isNameOfSwiftPointerType else { + return nil + } + + // At the @_cdecl level, make everything a raw pointer. + let cdeclPointerType = mutable + ? swiftStdlibTypes.unsafeMutableRawPointerDecl + : swiftStdlibTypes.unsafeRawPointerDecl + var cdeclToOriginal: LoweringStep + switch (requiresArgument, hasCount) { + case (false, false): + cdeclToOriginal = .passDirectly(parameterName) + + case (true, false): + // FIXME: Generic arguments, ugh + cdeclToOriginal = .suffixed( + .passDirectly(parameterName), + ".assumingMemoryBound(to: \(nominal.genericArguments![0]).self)" + ) + + case (false, true): + cdeclToOriginal = .initialize(type, arguments: [ + LabeledArgument(label: "start", argument: .passDirectly(parameterName + "_pointer")), + LabeledArgument(label: "count", argument: .passDirectly(parameterName + "_count")) + ]) + + case (true, true): + cdeclToOriginal = .initialize( + type, + arguments: [ + LabeledArgument(label: "start", + argument: .suffixed( + .passDirectly(parameterName + "_pointer"), + ".assumingMemoryBound(to: \(nominal.genericArguments![0]).self")), + LabeledArgument(label: "count", + argument: .passDirectly(parameterName + "_count")) + ] + ) + } + + let lowered: [(SwiftParameter, ForeignValueLayout)] + if hasCount { + lowered = [ + ( + SwiftParameter( + convention: convention, + parameterName: parameterName + "_pointer", + type: SwiftType.nominal( + SwiftNominalType(nominalTypeDecl: cdeclPointerType) + ) + ), + .SwiftPointer + ), + ( + SwiftParameter( + convention: convention, + parameterName: parameterName + "_count", + type: SwiftType.nominal( + SwiftNominalType(nominalTypeDecl: swiftStdlibTypes.intDecl) + ) + ), + .SwiftInt + ) + ] + } else { + lowered = [ + ( + SwiftParameter( + convention: convention, + parameterName: parameterName + "_pointer", + type: SwiftType.nominal( + SwiftNominalType(nominalTypeDecl: cdeclPointerType) + ) + ), + .SwiftPointer + ), + ] + } + + return LoweredParameters( + cdeclToOriginal: cdeclToOriginal, + cdeclParameters: lowered.map(\.0), + javaFFMParameters: lowered.map(\.1) + ) + } +} + +struct LabeledArgument { + var label: String? + var argument: Element +} + +extension LabeledArgument: Equatable where Element: Equatable { } + +/// How to lower the Swift parameter +enum LoweringStep: Equatable { + case passDirectly(String) + case passIndirectly(String) + indirect case suffixed(LoweringStep, String) + case initialize(SwiftType, arguments: [LabeledArgument]) + case tuplify([LoweringStep]) +} + +struct LoweredParameters: Equatable { + /// The steps needed to get from the @_cdecl parameter to the original function + /// parameter. + var cdeclToOriginal: LoweringStep + + /// The lowering of the parameters at the C level in Swift. + var cdeclParameters: [SwiftParameter] + + /// The lowerung of the parmaeters at the C level as expressed for Java's + /// foreign function and memory interface. + /// + /// The elements in this array match up with those of 'cdeclParameters'. + var javaFFMParameters: [ForeignValueLayout] +} + +enum LoweringError: Error { + case inoutNotSupported(SwiftType) + case unhandledType(SwiftType) +} + +@_spi(Testing) +public struct LoweredFunctionSignature: Equatable { + var original: SwiftFunctionSignature + public var cdecl: SwiftFunctionSignature + + var parameters: [LoweredParameters] + var result: LoweredParameters +} diff --git a/Sources/JExtractSwift/Swift2JavaTranslator.swift b/Sources/JExtractSwift/Swift2JavaTranslator.swift index 9894244b..bf1d72a2 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator.swift @@ -24,9 +24,6 @@ public final class Swift2JavaTranslator { package var log = Logger(label: "translator", logLevel: .info) - // ==== Input configuration - let swiftModuleName: String - // ==== Output configuration let javaPackage: String @@ -42,16 +39,29 @@ public final class Swift2JavaTranslator { /// type representation. package var importedTypes: [String: ImportedNominalType] = [:] + var swiftStdlibTypes: SwiftStandardLibraryTypes + + let symbolTable: SwiftSymbolTable let nominalResolution: NominalTypeResolution = NominalTypeResolution() var thunkNameRegistry: ThunkNameRegistry = ThunkNameRegistry() + /// The name of the Swift module being translated. + var swiftModuleName: String { + symbolTable.moduleName + } + public init( javaPackage: String, swiftModuleName: String ) { self.javaPackage = javaPackage - self.swiftModuleName = swiftModuleName + self.symbolTable = SwiftSymbolTable(parsedModuleName: swiftModuleName) + + // Create a mock of the Swift standard library. + var parsedSwiftModule = SwiftParsedModuleSymbolTable(moduleName: "Swift") + self.swiftStdlibTypes = SwiftStandardLibraryTypes(into: &parsedSwiftModule) + self.symbolTable.importedModules.append(parsedSwiftModule.symbolTable) } } @@ -87,9 +97,8 @@ extension Swift2JavaTranslator { package func analyzeSwiftInterface(interfaceFilePath: String, text: String) throws { let sourceFileSyntax = Parser.parse(source: text) - // Find all of the types and extensions, then bind the extensions. - nominalResolution.addSourceFile(sourceFileSyntax) - nominalResolution.bindExtensions() + addSourceFile(sourceFileSyntax) + prepareForTranslation() let visitor = Swift2JavaVisitor( moduleName: self.swiftModuleName, @@ -99,6 +108,25 @@ extension Swift2JavaTranslator { visitor.walk(sourceFileSyntax) } + package func addSourceFile(_ sourceFile: SourceFileSyntax) { + nominalResolution.addSourceFile(sourceFile) + } + + package func prepareForTranslation() { + nominalResolution.bindExtensions() + + for (_, node) in nominalResolution.topLevelNominalTypes { + symbolTable.parsedModule.addNominalTypeDeclaration(node, parent: nil) + } + + for (ext, nominalNode) in nominalResolution.resolvedExtensions { + guard let nominalDecl = symbolTable.parsedModule.lookup(nominalNode) else { + continue + } + + symbolTable.parsedModule.addExtension(ext, extending: nominalDecl) + } + } } // ===== -------------------------------------------------------------------------------------------------------------- diff --git a/Sources/JExtractSwift/SwiftTypes/SwiftFunctionSignature.swift b/Sources/JExtractSwift/SwiftTypes/SwiftFunctionSignature.swift new file mode 100644 index 00000000..187c18a6 --- /dev/null +++ b/Sources/JExtractSwift/SwiftTypes/SwiftFunctionSignature.swift @@ -0,0 +1,118 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import SwiftSyntax +import SwiftSyntaxBuilder + +/// Provides a complete signature for a Swift function, which includes its +/// parameters and return type. +@_spi(Testing) +public struct SwiftFunctionSignature: Equatable { + var isStaticOrClass: Bool + var selfParameter: SwiftParameter? + var parameters: [SwiftParameter] + var result: SwiftResult +} + +extension SwiftFunctionSignature { + /// Create a function declaration with the given name that has this + /// signature. + package func createFunctionDecl(_ name: String) -> FunctionDeclSyntax { + let parametersStr = parameters.map(\.description).joined(separator: ", ") + let resultStr = result.type.description + let decl: DeclSyntax = """ + func \(raw: name)(\(raw: parametersStr)) -> \(raw: resultStr) { + // implementation + } + """ + return decl.cast(FunctionDeclSyntax.self) + } +} + +extension SwiftFunctionSignature { + init( + _ node: FunctionDeclSyntax, + enclosingType: SwiftType?, + symbolTable: SwiftSymbolTable + ) throws { + // If this is a member of a type, so we will have a self parameter. Figure out the + // type and convention for the self parameter. + if let enclosingType { + var isMutating = false + var isConsuming = false + var isStaticOrClass = false + for modifier in node.modifiers { + switch modifier.name { + case .keyword(.mutating): isMutating = true + case .keyword(.static), .keyword(.class): isStaticOrClass = true + case .keyword(.consuming): isConsuming = true + default: break + } + } + + if isStaticOrClass { + self.selfParameter = SwiftParameter( + convention: .byValue, + type: .metatype( + enclosingType + ) + ) + } else { + self.selfParameter = SwiftParameter( + convention: isMutating ? .inout : isConsuming ? .consuming : .byValue, + type: enclosingType + ) + } + + self.isStaticOrClass = isStaticOrClass + } else { + self.selfParameter = nil + self.isStaticOrClass = false + } + + // Translate the parameters. + self.parameters = try node.signature.parameterClause.parameters.map { param in + try SwiftParameter(param, symbolTable: symbolTable) + } + + // Translate the result type. + if let resultType = node.signature.returnClause?.type { + self.result = try SwiftResult( + convention: .direct, + type: SwiftType(resultType, symbolTable: symbolTable) + ) + } else { + self.result = SwiftResult(convention: .direct, type: .tuple([])) + } + + // FIXME: Prohibit effects for now. + if let throwsClause = node.signature.effectSpecifiers?.throwsClause { + throw SwiftFunctionTranslationError.throws(throwsClause) + } + if let asyncSpecifier = node.signature.effectSpecifiers?.asyncSpecifier { + throw SwiftFunctionTranslationError.async(asyncSpecifier) + } + + // Prohibit generics for now. + if let generics = node.genericParameterClause { + throw SwiftFunctionTranslationError.generic(generics) + } + } +} + +enum SwiftFunctionTranslationError: Error { + case `throws`(ThrowsClauseSyntax) + case async(TokenSyntax) + case generic(GenericParameterClauseSyntax) +} diff --git a/Sources/JExtractSwift/SwiftTypes/SwiftFunctionType.swift b/Sources/JExtractSwift/SwiftTypes/SwiftFunctionType.swift new file mode 100644 index 00000000..1e5637e3 --- /dev/null +++ b/Sources/JExtractSwift/SwiftTypes/SwiftFunctionType.swift @@ -0,0 +1,59 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import SwiftSyntax + +struct SwiftFunctionType: Equatable { + enum Convention: Equatable { + case swift + case c + } + + var convention: Convention + var parameters: [SwiftParameter] + var resultType: SwiftType +} + +extension SwiftFunctionType: CustomStringConvertible { + var description: String { + return "(\(parameters.map { $0.descriptionInType } )) -> \(resultType.description)" + } +} + +extension SwiftFunctionType { + init( + _ node: FunctionTypeSyntax, + convention: Convention, + symbolTable: SwiftSymbolTable + ) throws { + self.convention = convention + self.parameters = try node.parameters.map { param in + let isInout = param.inoutKeyword != nil + return SwiftParameter( + convention: isInout ? .inout : .byValue, + type: try SwiftType(param.type, symbolTable: symbolTable) + ) + } + + self.resultType = try SwiftType(node.returnClause.type, symbolTable: symbolTable) + + // check for effect specifiers + if let throwsClause = node.effectSpecifiers?.throwsClause { + throw SwiftFunctionTranslationError.throws(throwsClause) + } + if let asyncSpecifier = node.effectSpecifiers?.asyncSpecifier { + throw SwiftFunctionTranslationError.async(asyncSpecifier) + } + } +} diff --git a/Sources/JExtractSwift/SwiftTypes/SwiftModuleSymbolTable.swift b/Sources/JExtractSwift/SwiftTypes/SwiftModuleSymbolTable.swift new file mode 100644 index 00000000..f1bbaa12 --- /dev/null +++ b/Sources/JExtractSwift/SwiftTypes/SwiftModuleSymbolTable.swift @@ -0,0 +1,39 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import SwiftSyntax +import SwiftSyntaxBuilder + +struct SwiftModuleSymbolTable: SwiftSymbolTableProtocol { + /// The name of this module. + let moduleName: String + + /// The top-level nominal types, found by name. + var topLevelTypes: [String: SwiftNominalTypeDeclaration] = [:] + + /// The nested types defined within this module. The map itself is indexed by the + /// identifier of the nominal type declaration, and each entry is a map from the nested + /// type name to the nominal type declaration. + var nestedTypes: [SwiftNominalTypeDeclaration: [String: SwiftNominalTypeDeclaration]] = [:] + + /// Look for a top-level type with the given name. + func lookupTopLevelNominalType(_ name: String) -> SwiftNominalTypeDeclaration? { + topLevelTypes[name] + } + + // Look for a nested type with the given name. + func lookupNestedType(_ name: String, parent: SwiftNominalTypeDeclaration) -> SwiftNominalTypeDeclaration? { + nestedTypes[parent]?[name] + } +} diff --git a/Sources/JExtractSwift/SwiftTypes/SwiftNominalTypeDeclaration.swift b/Sources/JExtractSwift/SwiftTypes/SwiftNominalTypeDeclaration.swift new file mode 100644 index 00000000..cf017f98 --- /dev/null +++ b/Sources/JExtractSwift/SwiftTypes/SwiftNominalTypeDeclaration.swift @@ -0,0 +1,78 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import SwiftSyntax + +/// Describes a nominal type declaration, which can be of any kind (class, struct, etc.) +/// and has a name, parent type (if nested), and owning module. +class SwiftNominalTypeDeclaration { + enum Kind { + case actor + case `class` + case `enum` + case `protocol` + case `struct` + } + + /// The kind of nominal type. + var kind: Kind + + /// The parent nominal type when this nominal type is nested inside another type, e.g., + /// MyCollection.Iterator. + var parent: SwiftNominalTypeDeclaration? + + /// The module in which this nominal type is defined. If this is a nested type, the + /// module might be different from that of the parent type, if this nominal type + /// is defined in an extension within another module. + var moduleName: String + + /// The name of this nominal type, e.g., 'MyCollection'. + var name: String + + // TODO: Generic parameters. + + /// Create a nominal type declaration from the syntax node for a nominal type + /// declaration. + init( + moduleName: String, + parent: SwiftNominalTypeDeclaration?, + node: NominalTypeDeclSyntaxNode + ) { + self.moduleName = moduleName + self.parent = parent + self.name = node.name.text + + // Determine the kind from the syntax node. + switch Syntax(node).as(SyntaxEnum.self) { + case .actorDecl: self.kind = .actor + case .classDecl: self.kind = .class + case .enumDecl: self.kind = .enum + case .protocolDecl: self.kind = .protocol + case .structDecl: self.kind = .struct + default: fatalError("Not a nominal type declaration") + } + } +} + +extension SwiftNominalTypeDeclaration: Equatable { + static func ==(lhs: SwiftNominalTypeDeclaration, rhs: SwiftNominalTypeDeclaration) -> Bool { + lhs === rhs + } +} + +extension SwiftNominalTypeDeclaration: Hashable { + func hash(into hasher: inout Hasher) { + hasher.combine(ObjectIdentifier(self)) + } +} diff --git a/Sources/JExtractSwift/SwiftTypes/SwiftParameter.swift b/Sources/JExtractSwift/SwiftTypes/SwiftParameter.swift new file mode 100644 index 00000000..b7bc28fb --- /dev/null +++ b/Sources/JExtractSwift/SwiftTypes/SwiftParameter.swift @@ -0,0 +1,88 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import SwiftSyntax + +struct SwiftParameter: Equatable { + var convention: SwiftParameterConvention + var argumentLabel: String? + var parameterName: String? + var type: SwiftType +} + +extension SwiftParameter: CustomStringConvertible { + var description: String { + let argumentLabel = self.argumentLabel ?? "_" + let parameterName = self.parameterName ?? "_" + + return "\(argumentLabel) \(parameterName): \(descriptionInType)" + } + + var descriptionInType: String { + let conventionString: String + switch convention { + case .byValue: + conventionString = "" + + case .consuming: + conventionString = "consuming " + + case .inout: + conventionString = "inout " + } + + return conventionString + type.description + } +} + +/// Describes how a parameter is passed. +enum SwiftParameterConvention: Equatable { + /// The parameter is passed by-value or borrowed. + case byValue + /// The parameter is passed by-value but consumed. + case consuming + /// The parameter is passed indirectly via inout. + case `inout` +} + +extension SwiftParameter { + init(_ node: FunctionParameterSyntax, symbolTable: SwiftSymbolTable) throws { + // Determine the convention. The default is by-value, but modifiers can alter + // this. + var convention = SwiftParameterConvention.byValue + for modifier in node.modifiers { + switch modifier.name { + case .keyword(.consuming), .keyword(.__consuming), .keyword(.__owned): + convention = .consuming + case .keyword(.inout): + convention = .inout + default: + break + } + } + self.convention = convention + + // Determine the type. + self.type = try SwiftType(node.type, symbolTable: symbolTable) + + // FIXME: swift-syntax itself should have these utilities based on identifiers. + if let secondName = node.secondName { + self.argumentLabel = node.firstName.identifier?.name + self.parameterName = secondName.identifier?.name + } else { + self.argumentLabel = node.firstName.identifier?.name + self.parameterName = self.argumentLabel + } + } +} diff --git a/Sources/JExtractSwift/SwiftTypes/SwiftParsedModuleSymbolTable.swift b/Sources/JExtractSwift/SwiftTypes/SwiftParsedModuleSymbolTable.swift new file mode 100644 index 00000000..1eb37eac --- /dev/null +++ b/Sources/JExtractSwift/SwiftTypes/SwiftParsedModuleSymbolTable.swift @@ -0,0 +1,120 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import SwiftSyntax + +struct SwiftParsedModuleSymbolTable { + var symbolTable: SwiftModuleSymbolTable + + /// The nominal type declarations, indexed by the nominal type declaration syntax node. + var nominalTypeDeclarations: [SyntaxIdentifier: SwiftNominalTypeDeclaration] = [:] + + /// Mapping from the nominal type declarations in this module back to the syntax + /// node. This is the reverse mapping of 'nominalTypeDeclarations'. + var nominalTypeSyntaxNodes: [SwiftNominalTypeDeclaration: NominalTypeDeclSyntaxNode] = [:] + + init(moduleName: String) { + symbolTable = .init(moduleName: moduleName) + } +} + +extension SwiftParsedModuleSymbolTable: SwiftSymbolTableProtocol { + var moduleName: String { + symbolTable.moduleName + } + + func lookupTopLevelNominalType(_ name: String) -> SwiftNominalTypeDeclaration? { + symbolTable.lookupTopLevelNominalType(name) + } + + func lookupNestedType(_ name: String, parent: SwiftNominalTypeDeclaration) -> SwiftNominalTypeDeclaration? { + symbolTable.lookupNestedType(name, parent: parent) + } +} + +extension SwiftParsedModuleSymbolTable { + /// Look up a nominal type declaration based on its syntax node. + func lookup(_ node: NominalTypeDeclSyntaxNode) -> SwiftNominalTypeDeclaration? { + nominalTypeDeclarations[node.id] + } + + /// Add a nominal type declaration and all of the nested types within it to the symbol + /// table. + @discardableResult + mutating func addNominalTypeDeclaration( + _ node: NominalTypeDeclSyntaxNode, + parent: SwiftNominalTypeDeclaration? + ) -> SwiftNominalTypeDeclaration { + // If we have already recorded this nominal type declaration, we're done. + if let existingNominal = nominalTypeDeclarations[node.id] { + return existingNominal + } + + // Otherwise, create the nominal type declaration. + let nominalTypeDecl = SwiftNominalTypeDeclaration( + moduleName: moduleName, + parent: parent, + node: node + ) + + // Ensure that we can find this nominal type declaration again based on the syntax + // node, and vice versa. + nominalTypeDeclarations[node.id] = nominalTypeDecl + nominalTypeSyntaxNodes[nominalTypeDecl] = node + + if let parent { + // For nested types, make them discoverable from the parent type. + symbolTable.nestedTypes[parent, default: [:]][node.name.text] = nominalTypeDecl + } else { + // For top-level types, make them discoverable by name. + symbolTable.topLevelTypes[node.name.text] = nominalTypeDecl + } + + // Find any nested types within this nominal type and add them. + for member in node.memberBlock.members { + if let nominalMember = member.decl.asNominal { + addNominalTypeDeclaration(nominalMember, parent: nominalTypeDecl) + } + } + + return nominalTypeDecl + } + + /// Add any nested types within the given extension (with known extended nominal type + /// declaration) to the symbol table. + mutating func addExtension( + _ extensionNode: ExtensionDeclSyntax, + extending nominalTypeDecl: SwiftNominalTypeDeclaration + ) { + // Find any nested types within this extension and add them. + for member in extensionNode.memberBlock.members { + if let nominalMember = member.decl.asNominal { + addNominalTypeDeclaration(nominalMember, parent: nominalTypeDecl) + } + } + } +} + +extension DeclSyntaxProtocol { + var asNominal: NominalTypeDeclSyntaxNode? { + switch DeclSyntax(self).as(DeclSyntaxEnum.self) { + case .actorDecl(let actorDecl): actorDecl + case .classDecl(let classDecl): classDecl + case .enumDecl(let enumDecl): enumDecl + case .protocolDecl(let protocolDecl): protocolDecl + case .structDecl(let structDecl): structDecl + default: nil + } + } +} diff --git a/Sources/JExtractSwift/SwiftTypes/SwiftResult.swift b/Sources/JExtractSwift/SwiftTypes/SwiftResult.swift new file mode 100644 index 00000000..4ca14815 --- /dev/null +++ b/Sources/JExtractSwift/SwiftTypes/SwiftResult.swift @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import SwiftSyntax + +struct SwiftResult: Equatable { + var convention: SwiftResultConvention + var type: SwiftType +} + +enum SwiftResultConvention: Equatable { + case direct + case indirect +} diff --git a/Sources/JExtractSwift/SwiftTypes/SwiftStandardLibraryTypes.swift b/Sources/JExtractSwift/SwiftTypes/SwiftStandardLibraryTypes.swift new file mode 100644 index 00000000..57a5865f --- /dev/null +++ b/Sources/JExtractSwift/SwiftTypes/SwiftStandardLibraryTypes.swift @@ -0,0 +1,208 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import SwiftSyntax + +/// Captures many types from the Swift standard library in their most basic +/// forms, so that the translator can reason about them in source code. +struct SwiftStandardLibraryTypes { + /// Swift.UnsafeRawPointer + var unsafeRawPointerDecl: SwiftNominalTypeDeclaration + + /// Swift.UnsafeMutableRawPointer + var unsafeMutableRawPointerDecl: SwiftNominalTypeDeclaration + + // Swift.UnsafePointer + var unsafePointerDecl: SwiftNominalTypeDeclaration + + // Swift.UnsafeMutablePointer + var unsafeMutablePointerDecl: SwiftNominalTypeDeclaration + + // Swift.UnsafeBufferPointer + var unsafeBufferPointerDecl: SwiftNominalTypeDeclaration + + // Swift.UnsafeMutableBufferPointer + var unsafeMutableBufferPointerDecl: SwiftNominalTypeDeclaration + + /// Swift.Bool + var boolDecl: SwiftNominalTypeDeclaration + + /// Swift.Int8 + var int8Decl: SwiftNominalTypeDeclaration + + /// Swift.Int16 + var int16Decl: SwiftNominalTypeDeclaration + + /// Swift.UInt16 + var uint16Decl: SwiftNominalTypeDeclaration + + /// Swift.Int32 + var int32Decl: SwiftNominalTypeDeclaration + + /// Swift.Int64 + var int64Decl: SwiftNominalTypeDeclaration + + /// Swift.Int + var intDecl: SwiftNominalTypeDeclaration + + /// Swift.Float + var floatDecl: SwiftNominalTypeDeclaration + + /// Swift.Double + var doubleDecl: SwiftNominalTypeDeclaration + + /// Swift.String + var stringDecl: SwiftNominalTypeDeclaration + + init(into parsedModule: inout SwiftParsedModuleSymbolTable) { + // Pointer types + self.unsafeRawPointerDecl = parsedModule.addNominalTypeDeclaration( + StructDeclSyntax( + name: .identifier("UnsafeRawPointer"), + memberBlock: .init(members: []) + ), + parent: nil + ) + + self.unsafeMutableRawPointerDecl = parsedModule.addNominalTypeDeclaration( + StructDeclSyntax( + name: .identifier("UnsafeMutableRawPointer"), + memberBlock: .init(members: []) + ), + parent: nil + ) + + self.unsafePointerDecl = parsedModule.addNominalTypeDeclaration( + StructDeclSyntax( + name: .identifier("UnsafePointer"), + genericParameterClause: .init( + parameters: [GenericParameterSyntax(name: .identifier("Element"))] + ), + memberBlock: .init(members: []) + ), + parent: nil + ) + + self.unsafeMutablePointerDecl = parsedModule.addNominalTypeDeclaration( + StructDeclSyntax( + name: .identifier("UnsafeMutablePointer"), + genericParameterClause: .init( + parameters: [GenericParameterSyntax(name: .identifier("Element"))] + ), + memberBlock: .init(members: []) + ), + parent: nil + ) + + self.unsafeBufferPointerDecl = parsedModule.addNominalTypeDeclaration( + StructDeclSyntax( + name: .identifier("UnsafeBufferPointer"), + genericParameterClause: .init( + parameters: [GenericParameterSyntax(name: .identifier("Element"))] + ), + memberBlock: .init(members: []) + ), + parent: nil + ) + + self.unsafeMutableBufferPointerDecl = parsedModule.addNominalTypeDeclaration( + StructDeclSyntax( + name: .identifier("UnsafeMutableBufferPointer"), + genericParameterClause: .init( + parameters: [GenericParameterSyntax(name: .identifier("Element"))] + ), + memberBlock: .init(members: []) + ), + parent: nil + ) + + self.boolDecl = parsedModule.addNominalTypeDeclaration( + StructDeclSyntax( + name: .identifier("Bool"), + memberBlock: .init(members: []) + ), + parent: nil + ) + self.intDecl = parsedModule.addNominalTypeDeclaration( + StructDeclSyntax( + name: .identifier("Int"), + memberBlock: .init(members: []) + ), + parent: nil + ) + self.int8Decl = parsedModule.addNominalTypeDeclaration( + StructDeclSyntax( + name: .identifier("Int8"), + memberBlock: .init(members: []) + ), + parent: nil + ) + self.int16Decl = parsedModule.addNominalTypeDeclaration( + StructDeclSyntax( + name: .identifier("Int16"), + memberBlock: .init(members: []) + ), + parent: nil + ) + self.uint16Decl = parsedModule.addNominalTypeDeclaration( + StructDeclSyntax( + name: .identifier("UInt16"), + memberBlock: .init(members: []) + ), + parent: nil + ) + self.int32Decl = parsedModule.addNominalTypeDeclaration( + StructDeclSyntax( + name: .identifier("Int32"), + memberBlock: .init(members: []) + ), + parent: nil + ) + self.int64Decl = parsedModule.addNominalTypeDeclaration( + StructDeclSyntax( + name: .identifier("Int64"), + memberBlock: .init(members: []) + ), + parent: nil + ) + self.floatDecl = parsedModule.addNominalTypeDeclaration( + StructDeclSyntax( + name: .identifier("Float"), + memberBlock: .init(members: []) + ), + parent: nil + ) + self.doubleDecl = parsedModule.addNominalTypeDeclaration( + StructDeclSyntax( + name: .identifier("Double"), + memberBlock: .init(members: []) + ), + parent: nil + ) + self.intDecl = parsedModule.addNominalTypeDeclaration( + StructDeclSyntax( + name: .identifier("Int"), + memberBlock: .init(members: []) + ), + parent: nil + ) + self.stringDecl = parsedModule.addNominalTypeDeclaration( + StructDeclSyntax( + name: .identifier("String"), + memberBlock: .init(members: []) + ), + parent: nil + ) + } +} diff --git a/Sources/JExtractSwift/SwiftTypes/SwiftSymbolTable.swift b/Sources/JExtractSwift/SwiftTypes/SwiftSymbolTable.swift new file mode 100644 index 00000000..bb3c2f5f --- /dev/null +++ b/Sources/JExtractSwift/SwiftTypes/SwiftSymbolTable.swift @@ -0,0 +1,117 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import SwiftSyntax + +protocol SwiftSymbolTableProtocol { + /// The module name that this symbol table describes. + var moduleName: String { get } + + /// Look for a top-level nominal type with the given name. This should only + /// return nominal types within this module. + func lookupTopLevelNominalType(_ name: String) -> SwiftNominalTypeDeclaration? + + // Look for a nested type with the given name. + func lookupNestedType(_ name: String, parent: SwiftNominalTypeDeclaration) -> SwiftNominalTypeDeclaration? +} + +extension SwiftSymbolTableProtocol { + /// Look for a type + func lookupType(_ name: String, parent: SwiftNominalTypeDeclaration?) -> SwiftNominalTypeDeclaration? { + if let parent { + return lookupNestedType(name, parent: parent) + } + + return lookupTopLevelNominalType(name) + } +} + +class SwiftSymbolTable { + var importedModules: [SwiftModuleSymbolTable] = [] + var parsedModule: SwiftParsedModuleSymbolTable + + init(parsedModuleName: String) { + self.parsedModule = SwiftParsedModuleSymbolTable(moduleName: parsedModuleName) + } + + func addImportedModule(symbolTable: SwiftModuleSymbolTable) { + importedModules.append(symbolTable) + } + + func addTopLevelNominalTypeDeclarations(_ sourceFile: SourceFileSyntax) { + // Find top-level nominal type declarations. + for statement in sourceFile.statements { + // We only care about declarations. + guard case .decl(let decl) = statement.item, + let nominalTypeNode = decl.asNominal else { + continue + } + + parsedModule.addNominalTypeDeclaration(nominalTypeNode, parent: nil) + } + } + + func addExtensions( + _ sourceFile: SourceFileSyntax, + nominalResolution: NominalTypeResolution + ) { + // Find extensions. + for statement in sourceFile.statements { + // We only care about declarations. + guard case .decl(let decl) = statement.item, + let extNode = decl.as(ExtensionDeclSyntax.self), + let extendedTypeNode = nominalResolution.extendedType(of: extNode), + let extendedTypeDecl = parsedModule.nominalTypeDeclarations[extendedTypeNode.id] else { + continue + } + + parsedModule.addExtension(extNode, extending: extendedTypeDecl) + } + } +} + +extension SwiftSymbolTable: SwiftSymbolTableProtocol { + var moduleName: String { parsedModule.moduleName } + + /// Look for a top-level nominal type with the given name. This should only + /// return nominal types within this module. + func lookupTopLevelNominalType(_ name: String) -> SwiftNominalTypeDeclaration? { + if let parsedResult = parsedModule.lookupTopLevelNominalType(name) { + return parsedResult + } + + for importedModule in importedModules { + if let result = importedModule.lookupTopLevelNominalType(name) { + return result + } + } + + return nil + } + + // Look for a nested type with the given name. + func lookupNestedType(_ name: String, parent: SwiftNominalTypeDeclaration) -> SwiftNominalTypeDeclaration? { + if let parsedResult = parsedModule.lookupNestedType(name, parent: parent) { + return parsedResult + } + + for importedModule in importedModules { + if let result = importedModule.lookupNestedType(name, parent: parent) { + return result + } + } + + return nil + } +} diff --git a/Sources/JExtractSwift/SwiftTypes/SwiftType.swift b/Sources/JExtractSwift/SwiftTypes/SwiftType.swift new file mode 100644 index 00000000..4eef607a --- /dev/null +++ b/Sources/JExtractSwift/SwiftTypes/SwiftType.swift @@ -0,0 +1,216 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import SwiftSyntax + +/// Describes a type in the Swift type system. +enum SwiftType: Equatable { + indirect case function(SwiftFunctionType) + indirect case metatype(SwiftType) + case nominal(SwiftNominalType) + indirect case optional(SwiftType) + case tuple([SwiftType]) + + var asNominalType: SwiftNominalType? { + switch self { + case .nominal(let nominal): nominal + case .tuple(let elements): elements.count == 1 ? elements[0].asNominalType : nil + case .function, .metatype, .optional: nil + } + } + + var asNominalTypeDeclaration: SwiftNominalTypeDeclaration? { + asNominalType?.nominalTypeDecl + } +} + +extension SwiftType: CustomStringConvertible { + var description: String { + switch self { + case .nominal(let nominal): return nominal.description + case .function(let functionType): return functionType.description + case .metatype(let instanceType): + return "(\(instanceType.description)).Type" + case .optional(let wrappedType): + return "\(wrappedType.description)?" + case .tuple(let elements): + return "(\(elements.map(\.description).joined(separator: ", ")))" + } + } +} + +struct SwiftNominalType: Equatable { + enum Parent: Equatable { + indirect case nominal(SwiftNominalType) + } + + private var storedParent: Parent? + var nominalTypeDecl: SwiftNominalTypeDeclaration + var genericArguments: [SwiftType]? + + init( + parent: SwiftNominalType? = nil, + nominalTypeDecl: SwiftNominalTypeDeclaration, + genericArguments: [SwiftType]? = nil + ) { + self.storedParent = parent.map { .nominal($0) } + self.nominalTypeDecl = nominalTypeDecl + self.genericArguments = genericArguments + } + + var parent: SwiftNominalType? { + if case .nominal(let parent) = storedParent ?? .none { + return parent + } + + return nil + } +} + +extension SwiftNominalType: CustomStringConvertible { + var description: String { + var resultString: String + if let parent { + resultString = parent.description + "." + } else { + resultString = "" + } + + resultString += nominalTypeDecl.name + + if let genericArguments { + resultString += "<\(genericArguments.map(\.description).joined(separator: ", "))>" + } + + return resultString + } +} + +extension SwiftType { + init(_ type: TypeSyntax, symbolTable: SwiftSymbolTable) throws { + switch type.as(TypeSyntaxEnum.self) { + case .arrayType, .classRestrictionType, .compositionType, + .dictionaryType, .missingType, .namedOpaqueReturnType, + .packElementType, .packExpansionType, .someOrAnyType, + .suppressedType: + throw TypeTranslationError.unimplementedType(type) + + case .attributedType(let attributedType): + // Only recognize the "@convention(c)" and "@convention(swift)" attributes, and + // then only on function types. + // FIXME: This string matching is a horrible hack. + switch attributedType.trimmedDescription { + case "@convention(c)", "@convention(swift)": + let innerType = try SwiftType(attributedType.baseType, symbolTable: symbolTable) + switch innerType { + case .function(var functionType): + let isConventionC = attributedType.trimmedDescription == "@convention(c)" + let convention: SwiftFunctionType.Convention = isConventionC ? .c : .swift + functionType.convention = convention + self = .function(functionType) + default: + throw TypeTranslationError.unimplementedType(type) + } + default: + throw TypeTranslationError.unimplementedType(type) + } + + case .functionType(let functionType): + self = .function( + try SwiftFunctionType(functionType, convention: .swift, symbolTable: symbolTable) + ) + + case .identifierType(let identifierType): + // Translate the generic arguments. + let genericArgs = try identifierType.genericArgumentClause.map { genericArgumentClause in + try genericArgumentClause.arguments.map { argument in + try SwiftType(argument.argument, symbolTable: symbolTable) + } + } + + // Resolve the type by name. + self = try SwiftType( + originalType: type, + parent: nil, + name: identifierType.name.text, + genericArguments: genericArgs, + symbolTable: symbolTable + ) + + case .implicitlyUnwrappedOptionalType(let optionalType): + self = .optional(try SwiftType(optionalType.wrappedType, symbolTable: symbolTable)) + + case .memberType(let memberType): + // If the parent type isn't a known module, translate it. + // FIXME: Need a more reasonable notion of which names are module names + // for this to work. What can we query for this information? + let parentType: SwiftType? + if memberType.baseType.trimmedDescription == "Swift" { + parentType = nil + } else { + parentType = try SwiftType(memberType.baseType, symbolTable: symbolTable) + } + + // Translate the generic arguments. + let genericArgs = try memberType.genericArgumentClause.map { genericArgumentClause in + try genericArgumentClause.arguments.map { argument in + try SwiftType(argument.argument, symbolTable: symbolTable) + } + } + + self = try SwiftType( + originalType: type, + parent: parentType, + name: memberType.name.text, + genericArguments: genericArgs, + symbolTable: symbolTable + ) + + case .metatypeType(let metatypeType): + self = .metatype(try SwiftType(metatypeType.baseType, symbolTable: symbolTable)) + + case .optionalType(let optionalType): + self = .optional(try SwiftType(optionalType.wrappedType, symbolTable: symbolTable)) + + case .tupleType(let tupleType): + self = try .tuple(tupleType.elements.map { element in + try SwiftType(element.type, symbolTable: symbolTable) + }) + } + } + + init( + originalType: TypeSyntax, + parent: SwiftType?, + name: String, + genericArguments: [SwiftType]?, + symbolTable: SwiftSymbolTable + ) throws { + // Look up the imported types by name to resolve it to a nominal type. + guard let nominalTypeDecl = symbolTable.lookupType( + name, + parent: parent?.asNominalTypeDeclaration + ) else { + throw TypeTranslationError.unknown(originalType) + } + + self = .nominal( + SwiftNominalType( + parent: parent?.asNominalType, + nominalTypeDecl: nominalTypeDecl, + genericArguments: genericArguments + ) + ) + } +} diff --git a/Sources/JExtractSwift/TranslatedType.swift b/Sources/JExtractSwift/TranslatedType.swift index eef4140d..be0be1b8 100644 --- a/Sources/JExtractSwift/TranslatedType.swift +++ b/Sources/JExtractSwift/TranslatedType.swift @@ -176,7 +176,7 @@ extension String { /// 2. Whether the memory referenced by the pointer is mutable. /// 3. Whether the pointer type has a `count` property describing how /// many elements it points to. - fileprivate var isNameOfSwiftPointerType: (requiresArgument: Bool, mutable: Bool, hasCount: Bool)? { + var isNameOfSwiftPointerType: (requiresArgument: Bool, mutable: Bool, hasCount: Bool)? { switch self { case "COpaquePointer", "UnsafeRawPointer": return (requiresArgument: false, mutable: true, hasCount: false) @@ -280,17 +280,7 @@ extension TranslatedType { var foreignValueLayout: ForeignValueLayout { switch cCompatibleJavaMemoryLayout { case .primitive(let javaType): - switch javaType { - case .boolean: return .SwiftBool - case .byte: return .SwiftInt8 - case .char: return .SwiftUInt16 - case .short: return .SwiftInt16 - case .int: return .SwiftInt32 - case .long: return .SwiftInt64 - case .float: return .SwiftFloat - case .double: return .SwiftDouble - case .array, .class, .void: fatalError("Not a primitive type: \(cCompatibleJavaMemoryLayout) in \(self)") - } + return ForeignValueLayout(javaType: javaType)! case .int: return .SwiftInt diff --git a/Tests/JExtractSwiftTests/Asserts/LoweringAssertions.swift b/Tests/JExtractSwiftTests/Asserts/LoweringAssertions.swift new file mode 100644 index 00000000..ca101133 --- /dev/null +++ b/Tests/JExtractSwiftTests/Asserts/LoweringAssertions.swift @@ -0,0 +1,59 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +@_spi(Testing) import JExtractSwift +import SwiftSyntax +import Testing + +/// Assert that the lowering of the function function declaration to a @_cdecl +/// entrypoint matches the expected form. +func assertLoweredFunction( + _ inputDecl: DeclSyntax, + javaPackage: String = "org.swift.mypackage", + swiftModuleName: String = "MyModule", + sourceFile: SourceFileSyntax? = nil, + enclosingType: TypeSyntax? = nil, + expectedCDecl: DeclSyntax, + fileID: String = #fileID, + filePath: String = #filePath, + line: Int = #line, + column: Int = #column +) throws { + let translator = Swift2JavaTranslator( + javaPackage: javaPackage, + swiftModuleName: swiftModuleName + ) + + if let sourceFile { + translator.addSourceFile(sourceFile) + } + + translator.prepareForTranslation() + + let inputFunction = inputDecl.cast(FunctionDeclSyntax.self) + let loweredFunction = try translator.lowerFunctionSignature( + inputFunction, + enclosingType: enclosingType + ) + let loweredCDecl = loweredFunction.cdecl.createFunctionDecl(inputFunction.name.text) + #expect( + loweredCDecl.description == expectedCDecl.description, + sourceLocation: Testing.SourceLocation( + fileID: fileID, + filePath: filePath, + line: line, + column: column + ) + ) +} diff --git a/Tests/JExtractSwiftTests/FunctionLoweringTests.swift b/Tests/JExtractSwiftTests/FunctionLoweringTests.swift new file mode 100644 index 00000000..fd909565 --- /dev/null +++ b/Tests/JExtractSwiftTests/FunctionLoweringTests.swift @@ -0,0 +1,77 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import JExtractSwift +import SwiftSyntax +import SwiftSyntaxBuilder +import Testing + +final class FunctionLoweringTests { + @Test("Lowering buffer pointers") + func loweringBufferPointers() throws { + try assertLoweredFunction(""" + func f(x: Int, y: Swift.Float, z: UnsafeBufferPointer) { } + """, + expectedCDecl: """ + func f(_ x: Int, _ y: Float, _ z_pointer: UnsafeRawPointer, _ z_count: Int) -> () { + // implementation + } + """ + ) + } + + @Test("Lowering tuples") + func loweringTuples() throws { + try assertLoweredFunction(""" + func f(t: (Int, (Float, Double)), z: UnsafePointer) { } + """, + expectedCDecl: """ + func f(_ t_0: Int, _ t_1_0: Float, _ t_1_1: Double, _ z_pointer: UnsafeRawPointer) -> () { + // implementation + } + """ + ) + } + + @Test("Lowering methods") + func loweringMethods() throws { + try assertLoweredFunction(""" + func shifted(by delta: (Double, Double)) -> Point { } + """, + sourceFile: """ + struct Point { } + """, + enclosingType: "Point", + expectedCDecl: """ + func shifted(_ self: UnsafeRawPointer, _ delta_0: Double, _ delta_1: Double, _ _result: UnsafeMutableRawPointer) -> () { + // implementation + } + """ + ) + } + + @Test("Lowering metatypes", .disabled("Metatypes are not yet lowered")) + func lowerMetatype() throws { + try assertLoweredFunction(""" + func f(t: Int.Type) { } + """, + expectedCDecl: """ + func f(t: RawPointerType) -> () { + // implementation + } + """ + ) + } +} + From 831397dc400de26455e0616bda26d559295215c3 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Tue, 28 Jan 2025 17:13:01 +0000 Subject: [PATCH 217/426] jextract: Indirect returns and more value type support (#211) * ignore .index-build directory * Implement SwiftValue cleanup * SourceGen: Handle init() of value types with indirect return * Followups for handling value inits, various helper funcs * SwiftArena is now a segment allocator * Add $destroyed flag to wrapper types to prevent use-after-free bugs * Use varHandle instead of offset for reading data off VWT * testing: skip empty lines in output matching * gitignore vscode build outputs * test fixups * more tests for protecting access to destroyed objects * remove commented out code * fix formatting --- .gitignore | 2 + .../MySwiftLibrary/MySwiftStruct.swift | 22 +++- .../com/example/swift/HelloJava2Swift.java | 20 ++-- .../com/example/swift/MySwiftClassTest.java | 1 - .../swift/swiftkit}/MySwiftStructTest.java | 20 ++-- .../org/swift/swiftkit/SwiftArenaTest.java | 39 ++++++- .../Convenience/SwiftSyntax+Extensions.swift | 26 +++-- Sources/JExtractSwift/ImportedDecls.swift | 62 ++++++++--- .../Swift2JavaTranslator+MemoryLayouts.swift | 16 ++- .../Swift2JavaTranslator+Printing.swift | 102 +++++++++++++----- .../JExtractSwift/Swift2JavaTranslator.swift | 1 + Sources/JExtractSwift/Swift2JavaVisitor.swift | 27 ++--- .../JExtractSwift/SwiftThunkTranslator.swift | 85 ++++++++++----- Sources/JExtractSwift/TranslatedType.swift | 45 ++++++-- .../swiftkit/AutoSwiftMemorySession.java | 23 +++- .../swiftkit/ConfinedSwiftMemorySession.java | 28 ++++- .../java/org/swift/swiftkit/SwiftAnyType.java | 10 +- .../java/org/swift/swiftkit/SwiftArena.java | 4 +- .../org/swift/swiftkit/SwiftInstance.java | 10 ++ .../swift/swiftkit/SwiftInstanceCleanup.java | 25 +++-- .../java/org/swift/swiftkit/SwiftKit.java | 9 ++ .../swiftkit/SwiftValueWitnessTable.java | 8 +- .../org/swift/swiftkit/AutoArenaTest.java | 27 +++-- .../Asserts/TextAssertions.swift | 12 ++- .../ClassPrintingTests.swift | 1 - .../FuncCallbackImportTests.swift | 1 + .../FunctionDescriptorImportTests.swift | 18 ++-- .../MethodImportTests.swift | 86 ++++++++++++++- .../JExtractSwiftTests/MethodThunkTests.swift | 6 +- .../StringPassingTests.swift | 3 +- .../VariableImportTests.swift | 26 +++-- 31 files changed, 580 insertions(+), 185 deletions(-) rename Samples/SwiftKitSampleApp/src/test/java/{com/example/swift => org/swift/swiftkit}/MySwiftStructTest.java (69%) diff --git a/.gitignore b/.gitignore index 11bbeceb..6712182f 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,8 @@ DerivedData/ *.class bin/ BuildLogic/out/ +.index-build +.build-vscode # Ignore gradle build artifacts .gradle diff --git a/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftStruct.swift b/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftStruct.swift index 85bcb4c7..8feb3d2b 100644 --- a/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftStruct.swift +++ b/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftStruct.swift @@ -14,10 +14,12 @@ public struct MySwiftStruct { - public var number: Int + private var cap: Int + private var len: Int - public init(number: Int) { - self.number = number + public init(cap: Int, len: Int) { + self.cap = cap + self.len = len } public func voidMethod() { @@ -38,6 +40,20 @@ public struct MySwiftStruct { return 12 } + public func getCapacity() -> Int { + self.cap + } + + public func getLength() -> Int { + self.len + } + + public mutating func increaseCap(by value: Int) -> Int { + precondition(value > 0) + self.cap += value + return self.cap + } + public func makeRandomIntMethod() -> Int { return Int.random(in: 1..<256) } diff --git a/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java b/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java index 8c343ab5..81c6dd0f 100644 --- a/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java +++ b/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java @@ -24,15 +24,13 @@ import org.swift.swiftkit.SwiftKit; import org.swift.swiftkit.SwiftValueWitnessTable; -import java.util.Arrays; - public class HelloJava2Swift { public static void main(String[] args) { boolean traceDowncalls = Boolean.getBoolean("jextract.trace.downcalls"); System.out.println("Property: jextract.trace.downcalls = " + traceDowncalls); - System.out.print("Property: java.library.path = " +SwiftKit.getJavaLibraryPath()); + System.out.print("Property: java.library.path = " + SwiftKit.getJavaLibraryPath()); examples(); } @@ -44,23 +42,23 @@ static void examples() { // Example of using an arena; MyClass.deinit is run at end of scope try (var arena = SwiftArena.ofConfined()) { - MySwiftClass obj = new MySwiftClass(arena, 2222, 7777); - - // just checking retains/releases work - SwiftKit.retain(obj.$memorySegment()); - SwiftKit.release(obj.$memorySegment()); + MySwiftClass obj = new MySwiftClass(arena, 2222, 7777); - obj.voidMethod(); - obj.takeIntMethod(42); + // just checking retains/releases work + SwiftKit.retain(obj.$memorySegment()); + SwiftKit.release(obj.$memorySegment()); - MySwiftStruct swiftValue = new MySwiftStruct(12); + obj.voidMethod(); + obj.takeIntMethod(42); + MySwiftStruct swiftValue = new MySwiftStruct(arena, 2222, 1111); } System.out.println("DONE."); } public static native long jniWriteString(String str); + public static native long jniGetInt(); } diff --git a/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/MySwiftClassTest.java b/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/MySwiftClassTest.java index fa17ef1a..f0a45c62 100644 --- a/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/MySwiftClassTest.java +++ b/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/MySwiftClassTest.java @@ -28,7 +28,6 @@ public class MySwiftClassTest { void checkPaths(Throwable throwable) { var paths = SwiftKit.getJavaLibraryPath().split(":"); for (var path : paths) { - System.out.println("CHECKING PATH: " + path); Stream.of(new File(path).listFiles()) .filter(file -> !file.isDirectory()) .forEach((file) -> { diff --git a/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/MySwiftStructTest.java b/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/MySwiftStructTest.java similarity index 69% rename from Samples/SwiftKitSampleApp/src/test/java/com/example/swift/MySwiftStructTest.java rename to Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/MySwiftStructTest.java index 27126587..b48e28d3 100644 --- a/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/MySwiftStructTest.java +++ b/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/MySwiftStructTest.java @@ -12,26 +12,24 @@ // //===----------------------------------------------------------------------===// -package com.example.swift; +package org.swift.swiftkit; -import org.junit.jupiter.api.Disabled; +import com.example.swift.MySwiftStruct; import org.junit.jupiter.api.Test; -import org.swift.swiftkit.SwiftArena; -import org.swift.swiftkit.SwiftKit; - -import java.io.File; -import java.util.stream.Stream; import static org.junit.jupiter.api.Assertions.assertEquals; public class MySwiftStructTest { @Test - void test_MySwiftClass_voidMethod() { + void create_struct() { try (var arena = SwiftArena.ofConfined()) { - MySwiftStruct o = new MySwiftStruct(12); -// o.voidMethod(); + long cap = 12; + long len = 34; + var struct = new MySwiftStruct(arena, cap, len); + + assertEquals(cap, struct.getCapacity()); + assertEquals(len, struct.getLength()); } } - } diff --git a/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/SwiftArenaTest.java b/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/SwiftArenaTest.java index 1bf3c388..d9b7bebd 100644 --- a/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/SwiftArenaTest.java +++ b/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/SwiftArenaTest.java @@ -15,6 +15,7 @@ package org.swift.swiftkit; import com.example.swift.MySwiftClass; +import com.example.swift.MySwiftStruct; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.DisabledIf; @@ -47,8 +48,44 @@ public void arena_releaseClassOnClose_class_ok() { release(obj.$memorySegment()); assertEquals(1, retainCount(obj.$memorySegment())); } + } + + // FIXME: The destroy witness table call hangs on x86_64 platforms during the destroy witness table call + // See: https://github.com/swiftlang/swift-java/issues/97 + @Test + public void arena_markAsDestroyed_preventUseAfterFree_class() { + MySwiftClass unsafelyEscapedOutsideArenaScope = null; + + try (var arena = SwiftArena.ofConfined()) { + var obj = new MySwiftClass(arena,1, 2); + unsafelyEscapedOutsideArenaScope = obj; + } + + try { + unsafelyEscapedOutsideArenaScope.echoIntMethod(1); + fail("Expected exception to be thrown! Object was suposed to be dead."); + } catch (IllegalStateException ex) { + return; + } + } + + // FIXME: The destroy witness table call hangs on x86_64 platforms during the destroy witness table call + // See: https://github.com/swiftlang/swift-java/issues/97 + @Test + public void arena_markAsDestroyed_preventUseAfterFree_struct() { + MySwiftStruct unsafelyEscapedOutsideArenaScope = null; - // TODO: should we zero out the $memorySegment perhaps? + try (var arena = SwiftArena.ofConfined()) { + var s = new MySwiftStruct(arena,1, 2); + unsafelyEscapedOutsideArenaScope = s; + } + + try { + unsafelyEscapedOutsideArenaScope.echoIntMethod(1); + fail("Expected exception to be thrown! Object was suposed to be dead."); + } catch (IllegalStateException ex) { + return; + } } @Test diff --git a/Sources/JExtractSwift/Convenience/SwiftSyntax+Extensions.swift b/Sources/JExtractSwift/Convenience/SwiftSyntax+Extensions.swift index 0a8f5533..6b814f8a 100644 --- a/Sources/JExtractSwift/Convenience/SwiftSyntax+Extensions.swift +++ b/Sources/JExtractSwift/Convenience/SwiftSyntax+Extensions.swift @@ -52,13 +52,22 @@ extension ImplicitlyUnwrappedOptionalTypeSyntax { } } -extension TypeSyntax { - fileprivate var isActorSystem: Bool { - self.trimmedDescription == "ActorSystem" +extension SyntaxProtocol { + + var asNominalTypeKind: NominalTypeKind { + if isClass { + .class + } else if isActor { + .actor + } else if isStruct { + .struct + } else if isEnum { + .enum + } else { + fatalError("Unknown nominal kind: \(self)") + } } -} -extension DeclSyntaxProtocol { var isClass: Bool { return self.is(ClassDeclSyntax.self) } @@ -79,11 +88,8 @@ extension DeclSyntaxProtocol { extension DeclModifierSyntax { var isAccessControl: Bool { switch self.name.tokenKind { - case .keyword(.private): fallthrough - case .keyword(.fileprivate): fallthrough - case .keyword(.internal): fallthrough - case .keyword(.package): fallthrough - case .keyword(.public): + case .keyword(.private), .keyword(.fileprivate), .keyword(.internal), .keyword(.package), + .keyword(.public): return true default: return false diff --git a/Sources/JExtractSwift/ImportedDecls.swift b/Sources/JExtractSwift/ImportedDecls.swift index 6edc263c..72204e66 100644 --- a/Sources/JExtractSwift/ImportedDecls.swift +++ b/Sources/JExtractSwift/ImportedDecls.swift @@ -44,18 +44,19 @@ public struct ImportedNominalType: ImportedDecl { TranslatedType( cCompatibleConvention: .direct, originalSwiftType: "\(raw: swiftTypeName)", + originalSwiftTypeKind: self.kind, cCompatibleSwiftType: "UnsafeRawPointer", cCompatibleJavaMemoryLayout: .heapObject, javaType: javaType ) } - + public var isReferenceType: Bool { switch self.kind { case .class, .actor: - return true - case .enum, .struct: - return false + true + default: + false } } @@ -68,11 +69,40 @@ public struct ImportedNominalType: ImportedDecl { } } +// TODO: replace this with `SwiftNominalTypeDeclaration.Kind` public enum NominalTypeKind { case `actor` case `class` case `enum` case `struct` + case `void` // TODO: NOT NOMINAL, BUT... + case function // TODO: NOT NOMINAL, BUT... + case primitive // TODO: NOT NOMINAL, BUT... + + var isReferenceType: Bool { + switch self { + case .actor, .class: true + case .enum, .struct: false + case .void, .function, .primitive: false + } + } + + var isValueType: Bool { + switch self { + case .actor, .class: false + case .enum, .struct: true + case .void, .function, .primitive: false + } + } + + var isVoid: Bool { + switch self { + case .actor, .class: false + case .enum, .struct: false + case .void: true + case .function, .primitive: false + } + } } public struct ImportedParam { @@ -99,7 +129,7 @@ public struct ImportedParam { var effectiveName: String? { firstName ?? secondName } - + var effectiveValueName: String { secondName ?? firstName ?? "_" } @@ -199,13 +229,13 @@ public struct ImportedFunc: ImportedDecl, CustomStringConvertible { case nil, .wrapper: break - case .pointer: + case .pointer where !isInit: let selfParam: FunctionParameterSyntax = "self$: $swift_pointer" params.append( ImportedParam(syntax: selfParam, type: parent) ) - case .memorySegment: + case .memorySegment where !isInit: let selfParam: FunctionParameterSyntax = "self$: $java_lang_foreign_MemorySegment" var parentForSelf = parent parentForSelf.javaType = .javaForeignMemorySegment @@ -215,6 +245,9 @@ public struct ImportedFunc: ImportedDecl, CustomStringConvertible { case .swiftThunkSelf: break + + default: + break } // TODO: add any metadata for generics and other things we may need to add here @@ -233,6 +266,11 @@ public struct ImportedFunc: ImportedDecl, CustomStringConvertible { public var isInit: Bool = false + public var isIndirectReturn: Bool { + returnType.isValueType || + (isInit && (parent?.isValueType ?? false)) + } + public init( module: String, decl: any DeclSyntaxProtocol, @@ -269,9 +307,9 @@ extension ImportedFunc: Hashable { self.swiftDecl.id.hash(into: &hasher) } - public static func ==(lhs: ImportedFunc, rhs: ImportedFunc) -> Swift.Bool { - lhs.parent?.originalSwiftType.id == rhs.parent?.originalSwiftType.id && - lhs.swiftDecl.id == rhs.swiftDecl.id + public static func == (lhs: ImportedFunc, rhs: ImportedFunc) -> Swift.Bool { + lhs.parent?.originalSwiftType.id == rhs.parent?.originalSwiftType.id + && lhs.swiftDecl.id == rhs.swiftDecl.id } } @@ -394,8 +432,8 @@ public struct ImportedVariable: ImportedDecl, CustomStringConvertible { ) case nil, - .wrapper, - .swiftThunkSelf: + .wrapper, + .swiftThunkSelf: break } } diff --git a/Sources/JExtractSwift/Swift2JavaTranslator+MemoryLayouts.swift b/Sources/JExtractSwift/Swift2JavaTranslator+MemoryLayouts.swift index 21d6946b..fa5b6318 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator+MemoryLayouts.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator+MemoryLayouts.swift @@ -18,6 +18,7 @@ import SwiftParser import SwiftSyntax extension Swift2JavaTranslator { + public func javaMemoryLayoutDescriptors( forParametersOf decl: ImportedFunc, paramPassingStyle: SelfParameterVariant? @@ -25,16 +26,21 @@ extension Swift2JavaTranslator { var layouts: [ForeignValueLayout] = [] layouts.reserveCapacity(decl.parameters.count + 1) - // // When the method is `init()` it does not accept a self (well, unless allocating init but we don't import those) - // let paramPassingStyle: SelfParameterVariant? = - // decl.isInit ? nil : .wrapper - for param in decl.effectiveParameters(paramPassingStyle: paramPassingStyle) { if param.type.cCompatibleJavaMemoryLayout == CCompatibleJavaMemoryLayout.primitive(.void) { continue } - layouts.append(param.type.foreignValueLayout) + var layout = param.type.foreignValueLayout + layout.inlineComment = "\(param.effectiveValueName)" + layouts.append(layout) + } + + // an indirect return passes the buffer as the last parameter to our thunk + if decl.isIndirectReturn { + var layout = ForeignValueLayout.SwiftPointer + layout.inlineComment = "indirect return buffer" + layouts.append(layout) } return layouts diff --git a/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift b/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift index bac029ec..af85a214 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift @@ -53,7 +53,8 @@ extension Swift2JavaTranslator { if let outputFile = try printer.writeContents( outputDirectory: outputDirectory, javaPackagePath: javaPackagePath, - filename: filename) { + filename: filename) + { print("[swift-java] Generated: \(self.swiftModuleName).java (at \(outputFile)") } } @@ -76,7 +77,8 @@ extension Swift2JavaTranslator { if let outputFile = try printer.writeContents( outputDirectory: outputDirectory, javaPackagePath: nil, - filename: moduleFilename) { + filename: moduleFilename) + { print("[swift-java] Generated: \(moduleFilenameBase.bold).swift (at \(outputFile)") } } catch { @@ -95,7 +97,8 @@ extension Swift2JavaTranslator { if let outputFile = try printer.writeContents( outputDirectory: outputDirectory, javaPackagePath: nil, - filename: filename) { + filename: filename) + { print("[swift-java] Generated: \(fileNameBase.bold).swift (at \(outputFile)") } } catch { @@ -133,12 +136,12 @@ extension Swift2JavaTranslator { let stt = SwiftThunkTranslator(self) printer.print( - """ - // Generated by swift-java + """ + // Generated by swift-java - import SwiftKitSwift + import SwiftKitSwift - """ + """ ) for thunk in stt.renderThunks(forType: ty) { @@ -291,6 +294,7 @@ extension Swift2JavaTranslator { printer in // ==== Storage of the class printClassSelfProperty(&printer, decl) + printStatusFlagsField(&printer, decl) // Constants printClassConstants(printer: &printer) @@ -412,6 +416,21 @@ extension Swift2JavaTranslator { ) } + private func printStatusFlagsField(_ printer: inout CodePrinter, _ decl: ImportedNominalType) { + printer.print( + """ + // TODO: make this a flagset integer and/or use a field updater + /** Used to track additional state of the underlying object, e.g. if it was explicitly destroyed. */ + private final AtomicBoolean $state$destroyed = new AtomicBoolean(false); + + @Override + public final AtomicBoolean $statusDestroyedFlag() { + return this.$state$destroyed; + } + """ + ) + } + private func printClassMemoryLayout(_ printer: inout CodePrinter, _ decl: ImportedNominalType) { printer.print( """ @@ -476,10 +495,10 @@ extension Swift2JavaTranslator { printMethodDowncallHandleForAddrDesc(&printer) } - printClassInitializerConstructors(&printer, decl, parentName: parentName) + printNominalInitializerConstructors(&printer, decl, parentName: parentName) } - public func printClassInitializerConstructors( + public func printNominalInitializerConstructors( _ printer: inout CodePrinter, _ decl: ImportedFunc, parentName: TranslatedType @@ -499,6 +518,25 @@ extension Swift2JavaTranslator { """ ) + let initializeMemorySegment = + if let parent = decl.parent, + parent.isReferenceType + { + """ + this.selfMemorySegment = (MemorySegment) mh$.invokeExact( + \(renderForwardJavaParams(decl, paramPassingStyle: nil)) + ); + """ + } else { + """ + this.selfMemorySegment = arena.allocate($layout()); + mh$.invokeExact( + \(renderForwardJavaParams(decl, paramPassingStyle: nil)), + /* indirect return buffer */this.selfMemorySegment + ); + """ + } + printer.print( """ /** @@ -514,7 +552,8 @@ extension Swift2JavaTranslator { SwiftKit.traceDowncall(\(renderForwardJavaParams(decl, paramPassingStyle: nil))); } - this.selfMemorySegment = (MemorySegment) mh$.invokeExact(\(renderForwardJavaParams(decl, paramPassingStyle: nil)), TYPE_METADATA.$memorySegment()); + \(initializeMemorySegment) + if (arena != null) { arena.register(this); } @@ -666,9 +705,6 @@ extension Swift2JavaTranslator { _ printer: inout CodePrinter, _ decl: ImportedFunc, accessorKind: VariableAccessorKind? = nil ) { -// var thunkName = SwiftKitPrinting.Names.functionThunk( -// thunkNameRegistry: &self.thunkNameRegistry, -// module: self.swiftModuleName, function: decl) let thunkName = thunkNameRegistry.functionThunkName(module: self.swiftModuleName, decl: decl) printer.print( """ @@ -716,11 +752,21 @@ extension Swift2JavaTranslator { let identifier = accessorKind.renderMethodName(decl) if paramPassingStyle == SelfParameterVariant.wrapper { + let guardFromDestroyedObjectCalls: String = + if decl.hasParent { + """ + if (this.$state$destroyed.get()) { + throw new IllegalStateException("Attempted to call method on already destroyed instance of " + getClass().getSimpleName() + "!"); + } + """ + } else { "" } + // delegate to the MemorySegment "self" accepting overload printer.print( """ \(javaDocComment) public \(returnTy) \(identifier)(\(renderJavaParamDecls(decl, paramPassingStyle: .wrapper))) { + \(guardFromDestroyedObjectCalls) \(maybeReturnCast) \(identifier)(\(renderForwardJavaParams(decl, paramPassingStyle: .wrapper))); } """ @@ -872,7 +918,8 @@ extension Swift2JavaTranslator { public func renderSwiftParamDecls( _ decl: ImportedFunc, paramPassingStyle: SelfParameterVariant?, - style: ParameterVariant? = nil) -> String { + style: ParameterVariant? = nil + ) -> String { var ps: [String] = [] var pCounter = 0 @@ -887,7 +934,7 @@ extension Swift2JavaTranslator { let paramTy: String = if style == .cDeclThunk, p.type.javaType.isString { - "UnsafeMutablePointer" // TODO: is this ok? + "UnsafeMutablePointer" // TODO: is this ok? } else if paramPassingStyle == .swiftThunkSelf { "\(p.type.cCompatibleSwiftType)" } else { @@ -906,7 +953,6 @@ extension Swift2JavaTranslator { if paramPassingStyle == .swiftThunkSelf { ps.append("_self: UnsafeMutableRawPointer") -// ps.append("_self: Any") } let res = ps.joined(separator: ", ") @@ -942,7 +988,9 @@ extension Swift2JavaTranslator { return printer.contents } - public func renderForwardJavaParams(_ decl: ImportedFunc, paramPassingStyle: SelfParameterVariant?) -> String { + public func renderForwardJavaParams( + _ decl: ImportedFunc, paramPassingStyle: SelfParameterVariant? + ) -> String { var ps: [String] = [] var pCounter = 0 @@ -980,20 +1028,16 @@ extension Swift2JavaTranslator { } // TODO: these are stateless, find new place for them? - public func renderForwardSwiftParams(_ decl: ImportedFunc, paramPassingStyle: SelfParameterVariant?) -> String { + public func renderForwardSwiftParams( + _ decl: ImportedFunc, paramPassingStyle: SelfParameterVariant? + ) -> String { var ps: [String] = [] - var pCounter = 0 - - func nextUniqueParamName() -> String { - pCounter += 1 - return "p\(pCounter)" - } for p in decl.effectiveParameters(paramPassingStyle: paramPassingStyle) { if let firstName = p.firstName { - ps.append("\(firstName): \(p.effectiveName ?? nextUniqueParamName())") + ps.append("\(firstName): \(p.effectiveValueName)") } else { - ps.append("\(p.effectiveName ?? nextUniqueParamName())") + ps.append("\(p.effectiveValueName)") } } @@ -1008,12 +1052,14 @@ extension Swift2JavaTranslator { let fieldName = accessorKind.renderDescFieldName printer.start("public static final FunctionDescriptor \(fieldName) = ") - let parameterLayoutDescriptors = javaMemoryLayoutDescriptors( + let isIndirectReturn = decl.isIndirectReturn + + var parameterLayoutDescriptors: [ForeignValueLayout] = javaMemoryLayoutDescriptors( forParametersOf: decl, paramPassingStyle: .pointer ) - if decl.returnType.javaType == .void { + if decl.returnType.javaType == .void || isIndirectReturn { printer.print("FunctionDescriptor.ofVoid(") printer.indent() } else { diff --git a/Sources/JExtractSwift/Swift2JavaTranslator.swift b/Sources/JExtractSwift/Swift2JavaTranslator.swift index bf1d72a2..ff81ef16 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator.swift @@ -147,6 +147,7 @@ extension Swift2JavaTranslator { "java.lang.invoke.*", "java.util.Arrays", "java.util.stream.Collectors", + "java.util.concurrent.atomic.*", "java.nio.charset.StandardCharsets", ] diff --git a/Sources/JExtractSwift/Swift2JavaVisitor.swift b/Sources/JExtractSwift/Swift2JavaVisitor.swift index b9ba3bd4..5b577589 100644 --- a/Sources/JExtractSwift/Swift2JavaVisitor.swift +++ b/Sources/JExtractSwift/Swift2JavaVisitor.swift @@ -26,8 +26,10 @@ final class Swift2JavaVisitor: SyntaxVisitor { /// store this along with type names as we import them. let targetJavaPackage: String + var currentType: ImportedNominalType? = nil + /// The current type name as a nested name like A.B.C. - var currentTypeName: String? = nil + var currentTypeName: String? { self.currentType?.swiftTypeName } var log: Logger { translator.log } @@ -45,34 +47,34 @@ final class Swift2JavaVisitor: SyntaxVisitor { return .skipChildren } - currentTypeName = importedNominalType.swiftTypeName + self.currentType = importedNominalType return .visitChildren } override func visitPost(_ node: ClassDeclSyntax) { - if currentTypeName != nil { + if currentType != nil { log.debug("Completed import: \(node.kind) \(node.name)") - currentTypeName = nil + self.currentType = nil } } - + override func visit(_ node: StructDeclSyntax) -> SyntaxVisitorContinueKind { log.debug("Visit \(node.kind): \(node)") guard let importedNominalType = translator.importedNominalType(node) else { return .skipChildren } - currentTypeName = importedNominalType.swiftTypeName + self.currentType = importedNominalType return .visitChildren } override func visitPost(_ node: StructDeclSyntax) { - if currentTypeName != nil { + if currentType != nil { log.debug("Completed import: \(node.kind) \(node.name)") - currentTypeName = nil + self.currentType = nil } } - + override func visit(_ node: ExtensionDeclSyntax) -> SyntaxVisitorContinueKind { // Resolve the extended type of the extension as an imported nominal, and // recurse if we found it. @@ -82,13 +84,13 @@ final class Swift2JavaVisitor: SyntaxVisitor { return .skipChildren } - currentTypeName = importedNominalType.swiftTypeName + self.currentType = importedNominalType return .visitChildren } override func visitPost(_ node: ExtensionDeclSyntax) { - if currentTypeName != nil { - currentTypeName = nil + if currentType != nil { + self.currentType = nil } } @@ -266,6 +268,7 @@ extension InitializerDeclSyntax { } // Ok, import it + log.warning("Import initializer: \(self)") return true } } diff --git a/Sources/JExtractSwift/SwiftThunkTranslator.swift b/Sources/JExtractSwift/SwiftThunkTranslator.swift index c530be3b..2676ef2e 100644 --- a/Sources/JExtractSwift/SwiftThunkTranslator.swift +++ b/Sources/JExtractSwift/SwiftThunkTranslator.swift @@ -50,15 +50,15 @@ struct SwiftThunkTranslator { decls.append(contentsOf: render(forFunc: decl)) } -// TODO: handle variables -// for v in nominal.variables { -// if let acc = v.accessorFunc(kind: .get) { -// decls.append(contentsOf: render(forFunc: acc)) -// } -// if let acc = v.accessorFunc(kind: .set) { -// decls.append(contentsOf: render(forFunc: acc)) -// } -// } + // TODO: handle variables + // for v in nominal.variables { + // if let acc = v.accessorFunc(kind: .get) { + // decls.append(contentsOf: render(forFunc: acc)) + // } + // if let acc = v.accessorFunc(kind: .set) { + // decls.append(contentsOf: render(forFunc: acc)) + // } + // } return decls } @@ -80,23 +80,45 @@ struct SwiftThunkTranslator { func renderSwiftInitAccessor(_ function: ImportedFunc) -> [DeclSyntax] { guard let parent = function.parent else { - fatalError("Cannot render initializer accessor if init function has no parent! Was: \(function)") + fatalError( + "Cannot render initializer accessor if init function has no parent! Was: \(function)") } let thunkName = self.st.thunkNameRegistry.functionThunkName( module: st.swiftModuleName, decl: function) - return - [ + let cDecl = + """ + @_cdecl("\(thunkName)") + """ + let typeName = "\(parent.swiftTypeName)" + + if parent.isReferenceType { + return [ """ - @_cdecl("\(raw: thunkName)") - public func \(raw: thunkName)(\(raw: st.renderSwiftParamDecls(function, paramPassingStyle: nil))) -> UnsafeMutableRawPointer /* \(raw: parent.swiftTypeName) */ { - let _self = \(raw: parent.swiftTypeName)(\(raw: st.renderForwardSwiftParams(function, paramPassingStyle: nil))) + \(raw: cDecl) + public func \(raw: thunkName)(\(raw: st.renderSwiftParamDecls(function, paramPassingStyle: nil))) -> UnsafeMutableRawPointer /* \(raw: typeName) */ { + var _self = \(raw: typeName)(\(raw: st.renderForwardSwiftParams(function, paramPassingStyle: nil))) let self$ = unsafeBitCast(_self, to: UnsafeMutableRawPointer.self) - return _swiftjava_swift_retain(object: self$) + _swiftjava_swift_retain(object: self$) + return self$ + } + """ + ] + } else { + return [ + """ + \(raw: cDecl) + public func \(raw: thunkName)( + \(raw: st.renderSwiftParamDecls(function, paramPassingStyle: nil)), + resultBuffer: /* \(raw: typeName) */ UnsafeMutableRawPointer + ) { + var _self = \(raw: typeName)(\(raw: st.renderForwardSwiftParams(function, paramPassingStyle: nil))) + resultBuffer.assumingMemoryBound(to: \(raw: typeName).self).initialize(to: _self) } """ ] + } } func render(forFunc decl: ImportedFunc) -> [DeclSyntax] { @@ -109,20 +131,25 @@ struct SwiftThunkTranslator { } else { "-> \(decl.returnType.cCompatibleSwiftType) /* \(decl.returnType.swiftTypeName) */" } - + // Do we need to pass a self parameter? let paramPassingStyle: SelfParameterVariant? let callBase: String let callBaseDot: String - if let parent = decl.parent { - paramPassingStyle = .swiftThunkSelf - callBase = "let self$ = unsafeBitCast(_self, to: \(parent.originalSwiftType).self)" - callBaseDot = "self$." - } else { - paramPassingStyle = nil - callBase = "" - callBaseDot = "" - } + if let parent = decl.parent, parent.isReferenceType { + paramPassingStyle = .swiftThunkSelf + callBase = "let self$ = unsafeBitCast(_self, to: \(parent.originalSwiftType).self)" + callBaseDot = "self$." + } else if let parent = decl.parent, !parent.isReferenceType { + paramPassingStyle = .swiftThunkSelf + callBase = + "var self$ = _self.assumingMemoryBound(to: \(parent.originalSwiftType).self).pointee" + callBaseDot = "self$." + } else { + paramPassingStyle = nil + callBase = "" + callBaseDot = "" + } // FIXME: handle in thunk: errors @@ -155,7 +182,7 @@ struct SwiftThunkTranslator { """ ] } - + func adaptArgumentsInThunk(_ decl: ImportedFunc) -> String { var lines: [String] = [] for p in decl.parameters { @@ -165,11 +192,11 @@ struct SwiftThunkTranslator { """ let \(p.effectiveValueName) = String(cString: \(p.effectiveValueName)) """ - + lines += [adaptedType] } } - + return lines.joined(separator: "\n") } } diff --git a/Sources/JExtractSwift/TranslatedType.swift b/Sources/JExtractSwift/TranslatedType.swift index be0be1b8..b36d7e77 100644 --- a/Sources/JExtractSwift/TranslatedType.swift +++ b/Sources/JExtractSwift/TranslatedType.swift @@ -21,10 +21,10 @@ extension Swift2JavaVisitor { func cCompatibleType(for type: TypeSyntax) throws -> TranslatedType { switch type.as(TypeSyntaxEnum.self) { case .arrayType, .attributedType, .classRestrictionType, .compositionType, - .dictionaryType, .implicitlyUnwrappedOptionalType, .metatypeType, - .missingType, .namedOpaqueReturnType, - .optionalType, .packElementType, .packExpansionType, .someOrAnyType, - .suppressedType, .tupleType: + .dictionaryType, .implicitlyUnwrappedOptionalType, .metatypeType, + .missingType, .namedOpaqueReturnType, + .optionalType, .packElementType, .packExpansionType, .someOrAnyType, + .suppressedType, .tupleType: throw TypeTranslationError.unimplementedType(type) case .functionType(let functionType): @@ -33,6 +33,7 @@ extension Swift2JavaVisitor { return TranslatedType( cCompatibleConvention: .direct, originalSwiftType: type, + originalSwiftTypeKind: .function, cCompatibleSwiftType: "@convention(c) () -> Void", cCompatibleJavaMemoryLayout: .cFunction, javaType: .javaLangRunnable @@ -64,6 +65,7 @@ extension Swift2JavaVisitor { for: type, parent: parentType, name: memberType.name.text, + kind: nil, genericArguments: genericArgs ) @@ -80,6 +82,7 @@ extension Swift2JavaVisitor { for: type, parent: nil, name: identifierType.name.text, + kind: nil, genericArguments: genericArgs ) } @@ -90,6 +93,7 @@ extension Swift2JavaVisitor { for type: TypeSyntax, parent: TranslatedType?, name: String, + kind: NominalTypeKind?, genericArguments: [TranslatedType]? ) throws -> TranslatedType { // Look for a primitive type with this name. @@ -97,6 +101,7 @@ extension Swift2JavaVisitor { return TranslatedType( cCompatibleConvention: .direct, originalSwiftType: "\(raw: name)", + originalSwiftTypeKind: .primitive, cCompatibleSwiftType: "Swift.\(raw: name)", cCompatibleJavaMemoryLayout: .primitive(primitiveType), javaType: primitiveType @@ -110,6 +115,7 @@ extension Swift2JavaVisitor { return TranslatedType( cCompatibleConvention: .direct, originalSwiftType: "\(raw: name)", + originalSwiftTypeKind: .primitive, cCompatibleSwiftType: "Swift.\(raw: name)", cCompatibleJavaMemoryLayout: .int, javaType: translator.javaPrimitiveForSwiftInt @@ -121,8 +127,9 @@ extension Swift2JavaVisitor { return TranslatedType( cCompatibleConvention: .direct, originalSwiftType: "\(raw: name)", + originalSwiftTypeKind: kind, cCompatibleSwiftType: "Swift.\(raw: name)", - cCompatibleJavaMemoryLayout: .heapObject, // FIXME: or specialize string? + cCompatibleJavaMemoryLayout: .heapObject, // FIXME: or specialize string? javaType: .javaLangString ) } @@ -157,9 +164,10 @@ extension Swift2JavaVisitor { } // Look up the imported types by name to resolve it to a nominal type. - let swiftTypeName = type.trimmedDescription // FIXME: This is a hack. + let swiftTypeName = type.trimmedDescription // FIXME: This is a hack. guard let resolvedNominal = translator.nominalResolution.resolveNominalType(swiftTypeName), - let importedNominal = translator.importedNominalType(resolvedNominal) else { + let importedNominal = translator.importedNominalType(resolvedNominal) + else { throw TypeTranslationError.unknown(type) } @@ -220,6 +228,9 @@ public struct TranslatedType { /// The original Swift type, as written in the source. var originalSwiftType: TypeSyntax + /// + var originalSwiftTypeKind: NominalTypeKind? + /// The C-compatible Swift type that should be used in any C -> Swift thunks /// emitted in Swift. var cCompatibleSwiftType: TypeSyntax @@ -239,10 +250,18 @@ public struct TranslatedType { /// Produce the "unqualified" Java type name. var unqualifiedJavaTypeName: String { switch javaType { - case .class(package: _, name: let name): name + case .class(package: _, let name): name default: javaType.description } } + + var isReferenceType: Bool { + originalSwiftTypeKind == .class || originalSwiftTypeKind == .actor + } + + var isValueType: Bool { + originalSwiftTypeKind == .struct || originalSwiftTypeKind == .enum + } } extension TranslatedType { @@ -250,6 +269,7 @@ extension TranslatedType { TranslatedType( cCompatibleConvention: .direct, originalSwiftType: "Void", + originalSwiftTypeKind: .void, cCompatibleSwiftType: "Swift.Void", cCompatibleJavaMemoryLayout: .primitive(.void), javaType: JavaType.void) @@ -274,6 +294,15 @@ enum CCompatibleJavaMemoryLayout: Hashable { case cFunction } +enum SwiftTypeKind { + case `class` + case `actor` + case `enum` + case `struct` + case primitive + case `void` +} + extension TranslatedType { /// Determine the foreign value layout to use for the translated type with /// the Java Foreign Function and Memory API. diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/AutoSwiftMemorySession.java b/SwiftKit/src/main/java/org/swift/swiftkit/AutoSwiftMemorySession.java index 9d25ad12..2de79393 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/AutoSwiftMemorySession.java +++ b/SwiftKit/src/main/java/org/swift/swiftkit/AutoSwiftMemorySession.java @@ -14,6 +14,7 @@ package org.swift.swiftkit; +import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; import java.lang.ref.Cleaner; import java.util.Objects; @@ -38,15 +39,24 @@ */ final class AutoSwiftMemorySession implements SwiftArena { + private final Arena arena; private final Cleaner cleaner; public AutoSwiftMemorySession(ThreadFactory cleanerThreadFactory) { this.cleaner = Cleaner.create(cleanerThreadFactory); + this.arena = Arena.ofAuto(); } @Override public void register(SwiftHeapObject object) { - SwiftHeapObjectCleanup cleanupAction = new SwiftHeapObjectCleanup(object.$memorySegment(), object.$swiftType()); + var statusDestroyedFlag = object.$statusDestroyedFlag(); + Runnable markAsDestroyed = () -> statusDestroyedFlag.set(true); + + SwiftHeapObjectCleanup cleanupAction = new SwiftHeapObjectCleanup( + object.$memorySegment(), + object.$swiftType(), + markAsDestroyed + ); register(object, cleanupAction); } @@ -62,9 +72,18 @@ void register(SwiftHeapObject object, SwiftHeapObjectCleanup cleanupAction) { @Override public void register(SwiftValue value) { Objects.requireNonNull(value, "value"); + + // We're doing this dance to avoid keeping a strong reference to the value itself + var statusDestroyedFlag = value.$statusDestroyedFlag(); + Runnable markAsDestroyed = () -> statusDestroyedFlag.set(true); + MemorySegment resource = value.$memorySegment(); - var cleanupAction = new SwiftValueCleanup(resource); + var cleanupAction = new SwiftValueCleanup(resource, value.$swiftType(), markAsDestroyed); cleaner.register(value, cleanupAction); } + @Override + public MemorySegment allocate(long byteSize, long byteAlignment) { + return arena.allocate(byteSize, byteAlignment); + } } diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/ConfinedSwiftMemorySession.java b/SwiftKit/src/main/java/org/swift/swiftkit/ConfinedSwiftMemorySession.java index 36d7be77..317ebcd4 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/ConfinedSwiftMemorySession.java +++ b/SwiftKit/src/main/java/org/swift/swiftkit/ConfinedSwiftMemorySession.java @@ -14,6 +14,8 @@ package org.swift.swiftkit; +import java.lang.foreign.Arena; +import java.lang.foreign.MemorySegment; import java.util.LinkedList; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; @@ -26,12 +28,15 @@ final class ConfinedSwiftMemorySession implements ClosableSwiftArena { final Thread owner; final AtomicInteger state; + final Arena arena; final ConfinedResourceList resources; public ConfinedSwiftMemorySession(Thread owner) { this.owner = owner; this.state = new AtomicInteger(ACTIVE); this.resources = new ConfinedResourceList(); + + this.arena = Arena.ofConfined(); } public void checkValid() throws RuntimeException { @@ -51,13 +56,20 @@ public void close() { if (this.state.compareAndExchange(ACTIVE, CLOSED) == ACTIVE) { this.resources.runCleanup(); } // else, was already closed; do nothing + + this.arena.close(); } @Override public void register(SwiftHeapObject object) { checkValid(); - var cleanup = new SwiftHeapObjectCleanup(object.$memorySegment(), object.$swiftType()); + var statusDestroyedFlag = object.$statusDestroyedFlag(); + Runnable markAsDestroyed = () -> statusDestroyedFlag.set(true); + + var cleanup = new SwiftHeapObjectCleanup( + object.$memorySegment(), object.$swiftType(), + markAsDestroyed); this.resources.add(cleanup); } @@ -65,10 +77,21 @@ public void register(SwiftHeapObject object) { public void register(SwiftValue value) { checkValid(); - var cleanup = new SwiftValueCleanup(value.$memorySegment()); + var statusDestroyedFlag = value.$statusDestroyedFlag(); + Runnable markAsDestroyed = () -> statusDestroyedFlag.set(true); + + var cleanup = new SwiftValueCleanup( + value.$memorySegment(), + value.$swiftType(), + markAsDestroyed); this.resources.add(cleanup); } + @Override + public MemorySegment allocate(long byteSize, long byteAlignment) { + return arena.allocate(byteSize, byteAlignment); + } + static final class ConfinedResourceList implements SwiftResourceList { // TODO: Could use intrusive linked list to avoid one indirection here final List resourceCleanups = new LinkedList<>(); @@ -82,6 +105,7 @@ public void runCleanup() { for (SwiftInstanceCleanup cleanup : resourceCleanups) { cleanup.run(); } + resourceCleanups.clear(); } } } diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftAnyType.java b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftAnyType.java index cf7cc238..8b2d94de 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftAnyType.java +++ b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftAnyType.java @@ -56,11 +56,19 @@ public SwiftAnyType(SwiftHeapObject object) { return $LAYOUT; } + /** + * Get the human-readable Swift type name of this type. + */ + public String getSwiftName() { + return SwiftKit.nameOfSwiftType(memorySegment, true); + } + @Override public String toString() { return "AnySwiftType{" + - "name=" + SwiftKit.nameOfSwiftType(memorySegment, true) + + "name=" + getSwiftName() + ", memorySegment=" + memorySegment + '}'; } + } diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftArena.java b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftArena.java index 02c1b599..fa89fd1b 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftArena.java +++ b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftArena.java @@ -14,6 +14,7 @@ package org.swift.swiftkit; +import java.lang.foreign.SegmentAllocator; import java.util.concurrent.ThreadFactory; /** @@ -23,7 +24,7 @@ *

A confined arena has an associated owner thread that confines some operations to * associated owner thread such as {@link ClosableSwiftArena#close()}. */ -public interface SwiftArena { +public interface SwiftArena extends SegmentAllocator { static ClosableSwiftArena ofConfined() { return new ConfinedSwiftMemorySession(Thread.currentThread()); @@ -65,4 +66,3 @@ public UnexpectedRetainCountException(Object resource, long retainCount, int exp ).formatted(resource, expectedRetainCount, retainCount)); } } - diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftInstance.java b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftInstance.java index 08cce158..de642a78 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftInstance.java +++ b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftInstance.java @@ -16,6 +16,7 @@ import java.lang.foreign.GroupLayout; import java.lang.foreign.MemorySegment; +import java.util.concurrent.atomic.AtomicBoolean; public interface SwiftInstance { @@ -39,4 +40,13 @@ public interface SwiftInstance { default boolean isReferenceType() { return this instanceof SwiftHeapObject; } + + /** + * Exposes a boolean value which can be used to indicate if the object was destroyed. + *

+ * This is exposing the object, rather than performing the action because we don't want to accidentally + * form a strong reference to the {@code SwiftInstance} which could prevent the cleanup from running, + * if using an GC managed instance (e.g. using an {@link AutoSwiftMemorySession}. + */ + AtomicBoolean $statusDestroyedFlag(); } diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftInstanceCleanup.java b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftInstanceCleanup.java index 8ac62793..4dc22127 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftInstanceCleanup.java +++ b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftInstanceCleanup.java @@ -31,18 +31,21 @@ interface SwiftInstanceCleanup extends Runnable { // non-final for testing class SwiftHeapObjectCleanup implements SwiftInstanceCleanup { - final MemorySegment selfPointer; - final SwiftAnyType selfType; + private final MemorySegment selfPointer; + private final SwiftAnyType selfType; + private final Runnable markAsDestroyed; /** * This constructor on purpose does not just take a {@link SwiftHeapObject} in order to make it very * clear that it does not take ownership of it, but we ONLY manage the native resource here. - * + *

* This is important for {@link AutoSwiftMemorySession} which relies on the wrapper type to be GC-able, * when no longer "in use" on the Java side. */ - SwiftHeapObjectCleanup(MemorySegment selfPointer, SwiftAnyType selfType) { + SwiftHeapObjectCleanup(MemorySegment selfPointer, + SwiftAnyType selfType, Runnable markAsDestroyed) { this.selfPointer = selfPointer; + this.markAsDestroyed = markAsDestroyed; this.selfType = selfType; } @@ -54,6 +57,8 @@ public void run() throws UnexpectedRetainCountException { throw new UnexpectedRetainCountException(selfPointer, retainedCount, 1); } + this.markAsDestroyed.run(); + // Destroy (and deinit) the object: SwiftValueWitnessTable.destroy(selfType, selfPointer); @@ -62,9 +67,17 @@ public void run() throws UnexpectedRetainCountException { } } -record SwiftValueCleanup(MemorySegment resource) implements SwiftInstanceCleanup { +record SwiftValueCleanup( + MemorySegment selfPointer, + SwiftAnyType selfType, + Runnable markAsDestroyed +) implements SwiftInstanceCleanup { + @Override public void run() { - throw new RuntimeException("not implemented yet"); + System.out.println("[debug] Destroy swift value [" + selfType.getSwiftName() + "]: " + selfPointer); + + markAsDestroyed.run(); + SwiftValueWitnessTable.destroy(selfType, selfPointer); } } diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftKit.java b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftKit.java index 858f5500..dadb87ff 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftKit.java +++ b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftKit.java @@ -20,6 +20,7 @@ import java.io.IOException; import java.lang.foreign.*; import java.lang.invoke.MethodHandle; +import java.lang.invoke.VarHandle; import java.nio.file.CopyOption; import java.nio.file.FileSystems; import java.nio.file.Files; @@ -437,6 +438,14 @@ public static long getSwiftInt(MemorySegment memorySegment, long offset) { } } + public static long getSwiftInt(MemorySegment memorySegment, VarHandle handle) { + if (SwiftValueLayout.SWIFT_INT == ValueLayout.JAVA_LONG) { + return (long) handle.get(memorySegment, 0); + } else { + return (int) handle.get(memorySegment, 0); + } + } + private static class swift_getTypeName { diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValueWitnessTable.java b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValueWitnessTable.java index d2f7d729..4bc86786 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValueWitnessTable.java +++ b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValueWitnessTable.java @@ -15,7 +15,7 @@ package org.swift.swiftkit; import java.lang.foreign.*; -import java.lang.invoke.MethodHandle; +import java.lang.invoke.*; import static java.lang.foreign.ValueLayout.JAVA_BYTE; import static org.swift.swiftkit.SwiftKit.getSwiftInt; @@ -97,6 +97,12 @@ public static long sizeOfSwiftType(MemorySegment typeMetadata) { static final long $stride$offset = $LAYOUT.byteOffset(MemoryLayout.PathElement.groupElement("stride")); + /** + * Variable handle for the "stride" field within the value witness table. + */ + static final VarHandle $stride$mh = + $LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("stride")); + /** * Determine the stride of a Swift type given its type metadata, which is * how many bytes are between successive elements of this type within an diff --git a/SwiftKit/src/test/java/org/swift/swiftkit/AutoArenaTest.java b/SwiftKit/src/test/java/org/swift/swiftkit/AutoArenaTest.java index 7ba215ab..c57daf16 100644 --- a/SwiftKit/src/test/java/org/swift/swiftkit/AutoArenaTest.java +++ b/SwiftKit/src/test/java/org/swift/swiftkit/AutoArenaTest.java @@ -18,12 +18,11 @@ import java.lang.foreign.GroupLayout; import java.lang.foreign.MemorySegment; -import java.lang.ref.Cleaner; import java.util.concurrent.CountDownLatch; +import java.util.concurrent.atomic.AtomicBoolean; public class AutoArenaTest { - @Test @SuppressWarnings("removal") // System.runFinalization() will be removed public void cleaner_releases_native_resource() { @@ -34,16 +33,21 @@ public void cleaner_releases_native_resource() { // we're retaining the `object`, register it with the arena: AutoSwiftMemorySession arena = (AutoSwiftMemorySession) SwiftArena.ofAuto(); - arena.register(object, new SwiftHeapObjectCleanup(object.$memorySegment(), object.$swiftType()) { - @Override - public void run() throws UnexpectedRetainCountException { - cleanupLatch.countDown(); - } - }); + + var statusDestroyedFlag = object.$statusDestroyedFlag(); + Runnable markAsDestroyed = () -> statusDestroyedFlag.set(true); + + arena.register(object, + new SwiftHeapObjectCleanup(object.$memorySegment(), object.$swiftType(), markAsDestroyed) { + @Override + public void run() throws UnexpectedRetainCountException { + cleanupLatch.countDown(); + } + }); // Release the object and hope it gets GC-ed soon - //noinspection UnusedAssignment + // noinspection UnusedAssignment object = null; var i = 1_000; @@ -76,5 +80,10 @@ public FakeSwiftHeapObject() { public SwiftAnyType $swiftType() { return null; } + + @Override + public AtomicBoolean $statusDestroyedFlag() { + return new AtomicBoolean(); + } } } diff --git a/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift b/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift index 0efff0c7..1686f0ab 100644 --- a/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift +++ b/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift @@ -45,7 +45,9 @@ func assertOutput( } output = printer.finalize() - let gotLines = output.split(separator: "\n") + let gotLines = output.split(separator: "\n").filter { l in + l.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines).count > 0 + } for expected in expectedChunks { let expectedLines = expected.split(separator: "\n") @@ -131,8 +133,12 @@ func assertOutput( line: Int = #line, column: Int = #column ) { - let gotLines = got.split(separator: "\n") - let expectedLines = expected.split(separator: "\n") + let gotLines = got.split(separator: "\n").filter { l in + l.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines).count > 0 + } + let expectedLines = expected.split(separator: "\n").filter { l in + l.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines).count > 0 + } var diffLineNumbers: [Int] = [] diff --git a/Tests/JExtractSwiftTests/ClassPrintingTests.swift b/Tests/JExtractSwiftTests/ClassPrintingTests.swift index 57c06f7e..768f1480 100644 --- a/Tests/JExtractSwiftTests/ClassPrintingTests.swift +++ b/Tests/JExtractSwiftTests/ClassPrintingTests.swift @@ -54,7 +54,6 @@ struct ClassPrintingTests { return TYPE_METADATA; } - private static final GroupLayout $LAYOUT = (GroupLayout) SwiftValueWitnessTable.layoutOfSwiftType(TYPE_METADATA.$memorySegment()); public final GroupLayout $layout() { return $LAYOUT; diff --git a/Tests/JExtractSwiftTests/FuncCallbackImportTests.swift b/Tests/JExtractSwiftTests/FuncCallbackImportTests.swift index 696c4b93..739cbb79 100644 --- a/Tests/JExtractSwiftTests/FuncCallbackImportTests.swift +++ b/Tests/JExtractSwiftTests/FuncCallbackImportTests.swift @@ -72,6 +72,7 @@ final class FuncCallbackImportTests { if (SwiftKit.TRACE_DOWNCALLS) { SwiftKit.traceDowncall(callback$); } + mh$.invokeExact(callback$); } catch (Throwable ex$) { throw new AssertionError("should not reach here", ex$); diff --git a/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift b/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift index 3160d55f..734d9eab 100644 --- a/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift +++ b/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift @@ -48,8 +48,8 @@ final class FunctionDescriptorTests { // #MySwiftClass.counter!getter: (MySwiftClass) -> () -> Int32 : @$s14MySwiftLibrary0aB5ClassC7counters5Int32Vvg\t// MySwiftClass.counter.getter // #MySwiftClass.counter!setter: (MySwiftClass) -> (Int32) -> () : @$s14MySwiftLibrary0aB5ClassC7counters5Int32Vvs\t// MySwiftClass.counter.setter - // #MySwiftClass.counter!modify: (MySwiftClass) -> () -> () : @$s14MySwiftLibrary0aB5ClassC7counters5Int32VvM\t// MySwiftClass.counter.modify - var counter: Int32 + // #MySwiftClass.counter!modify: (MySwiftClass) -> () -> () : @$s14MySwiftLibrary0aB5ClassC7counters5Int32VvM\t// MySwiftClass.counter.modify + var counter: Int32 } """ @@ -61,7 +61,7 @@ final class FunctionDescriptorTests { expected: """ public static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( - SWIFT_INT + /*i*/SWIFT_INT ); """ ) @@ -76,8 +76,8 @@ final class FunctionDescriptorTests { expected: """ public static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( - SWIFT_INT64, - SWIFT_INT32 + /*l*/SWIFT_INT64, + /*i32*/SWIFT_INT32 ); """ ) @@ -93,7 +93,7 @@ final class FunctionDescriptorTests { """ public static final FunctionDescriptor DESC = FunctionDescriptor.of( /* -> */SWIFT_INT, - SWIFT_INT + /*i*/SWIFT_INT ); """ ) @@ -109,7 +109,7 @@ final class FunctionDescriptorTests { """ public static final FunctionDescriptor DESC_GET = FunctionDescriptor.of( /* -> */SWIFT_INT32, - SWIFT_POINTER + /*self$*/SWIFT_POINTER ); """ ) @@ -123,8 +123,8 @@ final class FunctionDescriptorTests { expected: """ public static final FunctionDescriptor DESC_SET = FunctionDescriptor.ofVoid( - SWIFT_INT32, - SWIFT_POINTER + /*newValue*/SWIFT_INT32, + /*self$*/SWIFT_POINTER ); """ ) diff --git a/Tests/JExtractSwiftTests/MethodImportTests.swift b/Tests/JExtractSwiftTests/MethodImportTests.swift index 67c7c210..39d72dc0 100644 --- a/Tests/JExtractSwiftTests/MethodImportTests.swift +++ b/Tests/JExtractSwiftTests/MethodImportTests.swift @@ -53,6 +53,10 @@ final class MethodImportTests { @objc deinit } + + public struct MySwiftStruct { + public init(len: Swift.Int, cap: Swift.Int) {} + } """ @Test("Import: public func helloWorld()") @@ -87,6 +91,7 @@ final class MethodImportTests { if (SwiftKit.TRACE_DOWNCALLS) { SwiftKit.traceDowncall(); } + mh$.invokeExact(); } catch (Throwable ex$) { throw new AssertionError("should not reach here", ex$); @@ -128,8 +133,9 @@ final class MethodImportTests { var mh$ = globalTakeInt.HANDLE; try { if (SwiftKit.TRACE_DOWNCALLS) { - SwiftKit.traceDowncall(i); + SwiftKit.traceDowncall(i); } + mh$.invokeExact(i); } catch (Throwable ex$) { throw new AssertionError("should not reach here", ex$); @@ -158,6 +164,7 @@ final class MethodImportTests { } assertOutput( + dump: true, output, expected: """ @@ -174,6 +181,7 @@ final class MethodImportTests { if (SwiftKit.TRACE_DOWNCALLS) { SwiftKit.traceDowncall(i32, l, s$); } + mh$.invokeExact(i32, l, s$); } catch (Throwable ex$) { throw new AssertionError("should not reach here", ex$); @@ -341,6 +349,9 @@ final class MethodImportTests { * } */ public void helloMemberFunction() { + if (this.$state$destroyed.get()) { + throw new IllegalStateException("Attempted to call method on already destroyed instance of " + getClass().getSimpleName() + "!") + } helloMemberFunction($memorySegment()); } """ @@ -376,6 +387,10 @@ final class MethodImportTests { * } */ public long makeInt() { + if (this.$state$destroyed.get()) { + throw new IllegalStateException("Attempted to call method on already destroyed instance of " + getClass().getSimpleName() + "!") + } + return (long) makeInt($memorySegment()); } """ @@ -397,7 +412,7 @@ final class MethodImportTests { }! let output = CodePrinter.toString { printer in - st.printClassInitializerConstructors(&printer, initDecl, parentName: initDecl.parent!) + st.printNominalInitializerConstructors(&printer, initDecl, parentName: initDecl.parent!) } assertOutput( @@ -428,7 +443,72 @@ final class MethodImportTests { if (SwiftKit.TRACE_DOWNCALLS) { SwiftKit.traceDowncall(len, cap); } - this.selfMemorySegment = (MemorySegment) mh$.invokeExact(len, cap, TYPE_METADATA.$memorySegment()); + this.selfMemorySegment = (MemorySegment) mh$.invokeExact( + len, cap + ); + if (arena != null) { + arena.register(this); + } + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + """ + ) + } + + @Test + func struct_constructor() throws { + let st = Swift2JavaTranslator( + javaPackage: "com.example.swift", + swiftModuleName: "__FakeModule" + ) + st.log.logLevel = .info + + try st.analyze(file: "Fake.swift", text: class_interfaceFile) + + let initDecl: ImportedFunc = st.importedTypes["MySwiftStruct"]!.initializers.first { + $0.identifier == "init(len:cap:)" + }! + + let output = CodePrinter.toString { printer in + st.printNominalInitializerConstructors(&printer, initDecl, parentName: initDecl.parent!) + } + + assertOutput( + output, + expected: + """ + /** + * Create an instance of {@code MySwiftStruct}. + * + * {@snippet lang=swift : + * public init(len: Swift.Int, cap: Swift.Int) {} + * } + */ + public MySwiftStruct(long len, long cap) { + this(/*arena=*/null, len, cap); + } + /** + * Create an instance of {@code MySwiftStruct}. + * This instance is managed by the passed in {@link SwiftArena} and may not outlive the arena's lifetime. + * + * {@snippet lang=swift : + * public init(len: Swift.Int, cap: Swift.Int) {} + * } + */ + + public MySwiftStruct(SwiftArena arena, long len, long cap) { + var mh$ = init_len_cap.HANDLE; + try { + if (SwiftKit.TRACE_DOWNCALLS) { + SwiftKit.traceDowncall(len, cap); + } + this.selfMemorySegment = arena.allocate($layout()); + mh$.invokeExact( + len, cap, + /* indirect return buffer */this.selfMemorySegment + ); if (arena != null) { arena.register(this); } diff --git a/Tests/JExtractSwiftTests/MethodThunkTests.swift b/Tests/JExtractSwiftTests/MethodThunkTests.swift index 56eedfa5..7de47816 100644 --- a/Tests/JExtractSwiftTests/MethodThunkTests.swift +++ b/Tests/JExtractSwiftTests/MethodThunkTests.swift @@ -40,13 +40,15 @@ final class MethodThunkTests { """ @_cdecl("swiftjava_FakeModule_globalFunc_a_b") public func swiftjava_FakeModule_globalFunc_a_b(a: Int32, b: Int64) /* Void */ { - return globalFunc(a: a, b: b) + let returnValue = globalFunc(a: a, b: b) + return returnValue } """, """ @_cdecl("swiftjava_FakeModule_globalFunc_a_b$1") public func swiftjava_FakeModule_globalFunc_a_b$1(a: Double, b: Int64) /* Void */ { - return globalFunc(a: a, b: b) + let returnValue = globalFunc(a: a, b: b) + return returnValue } """ ] diff --git a/Tests/JExtractSwiftTests/StringPassingTests.swift b/Tests/JExtractSwiftTests/StringPassingTests.swift index c51d3549..cc488dfc 100644 --- a/Tests/JExtractSwiftTests/StringPassingTests.swift +++ b/Tests/JExtractSwiftTests/StringPassingTests.swift @@ -34,8 +34,7 @@ final class StringPassingTests { try assertOutput( st, input: class_interfaceFile, .java, detectChunkByInitialLines: 1, - expectedChunks: - [ + expectedChunks: [ """ public static long writeString(java.lang.String string) { var mh$ = writeString.HANDLE; diff --git a/Tests/JExtractSwiftTests/VariableImportTests.swift b/Tests/JExtractSwiftTests/VariableImportTests.swift index ee562cbd..0d45b08b 100644 --- a/Tests/JExtractSwiftTests/VariableImportTests.swift +++ b/Tests/JExtractSwiftTests/VariableImportTests.swift @@ -44,21 +44,20 @@ final class VariableImportTests { try assertOutput( st, input: class_interfaceFile, .java, detectChunkByInitialLines: 7, - expectedChunks: - [ + expectedChunks: [ """ private static class counterInt { public static final FunctionDescriptor DESC_GET = FunctionDescriptor.of( /* -> */SWIFT_INT, - SWIFT_POINTER + /*self$*/SWIFT_POINTER ); public static final MemorySegment ADDR_GET = FakeModule.findOrThrow("swiftjava_FakeModule_MySwiftClass_counterInt"); public static final MethodHandle HANDLE_GET = Linker.nativeLinker().downcallHandle(ADDR_GET, DESC_GET); public static final FunctionDescriptor DESC_SET = FunctionDescriptor.ofVoid( - SWIFT_INT, - SWIFT_POINTER + /*newValue*/SWIFT_INT, + /*self$*/SWIFT_POINTER ); public static final MemorySegment ADDR_SET = FakeModule.findOrThrow("swiftjava_FakeModule_MySwiftClass_counterInt"); @@ -109,8 +108,7 @@ final class VariableImportTests { public static FunctionDescriptor counterInt$set$descriptor() { return counterInt.DESC_SET; } - """ - , + """, """ /** * Downcall method handle for: @@ -160,6 +158,9 @@ final class VariableImportTests { * } */ public long getCounterInt() { + if (this.$state$destroyed.get()) { + throw new IllegalStateException("Attempted to call method on already destroyed instance of " + getClass(). + } return (long) getCounterInt($memorySegment()); } """, @@ -174,9 +175,9 @@ final class VariableImportTests { var mh$ = counterInt.HANDLE_SET; try { if (SwiftKit.TRACE_DOWNCALLS) { - SwiftKit.traceDowncall(newValue, self$); + SwiftKit.traceDowncall(newValue, self$); } - mh$.invokeExact(newValue, self$); + mh$.invokeExact(newValue, self$); } catch (Throwable ex$) { throw new AssertionError("should not reach here", ex$); } @@ -190,9 +191,12 @@ final class VariableImportTests { * } */ public void setCounterInt(long newValue) { - setCounterInt(newValue, $memorySegment()); + if (this.$state$destroyed.get()) { + throw new IllegalStateException("Attempted to call method on already destroyed instance of " + getClass().getSimpleName() + "!"); + } + setCounterInt(newValue, $memorySegment()); } - """ + """, ] ) } From 464475ea0bdfbdd9ccdfbe5984d89f55e8508930 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Wed, 29 Jan 2025 17:14:23 -0800 Subject: [PATCH 218/426] Implement function bodies for lowered @_cdecl thunks Improve the handling of lowering Swift declarations down to C thunks to more clearly model the mapping between the C parameters and the Swift parameters, and start generating code within the body of these C thunks. Provide tests and fixes for lowering of methods of structs and classes, including mutating methods, as well as inout parameters, direct and indirect returns, and so on. --- ...wift2JavaTranslator+FunctionLowering.swift | 188 ++++++++++++++++-- .../SwiftTypes/SwiftFunctionSignature.swift | 14 +- .../SwiftTypes/SwiftParameter.swift | 33 ++- .../JExtractSwift/SwiftTypes/SwiftType.swift | 31 ++- .../Asserts/LoweringAssertions.swift | 3 +- .../FunctionLoweringTests.swift | 72 ++++++- 6 files changed, 303 insertions(+), 38 deletions(-) diff --git a/Sources/JExtractSwift/Swift2JavaTranslator+FunctionLowering.swift b/Sources/JExtractSwift/Swift2JavaTranslator+FunctionLowering.swift index 6b49774f..4ab81e39 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator+FunctionLowering.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator+FunctionLowering.swift @@ -16,6 +16,9 @@ import JavaTypes import SwiftSyntax extension Swift2JavaTranslator { + /// Lower the given function declaration to a C-compatible entrypoint, + /// providing all of the mappings between the parameter and result types + /// of the original function and its `@_cdecl` counterpart. @_spi(Testing) public func lowerFunctionSignature( _ decl: FunctionDeclSyntax, @@ -145,8 +148,12 @@ extension Swift2JavaTranslator { let mutable = (convention == .inout) let loweringStep: LoweringStep switch nominal.nominalTypeDecl.kind { - case .actor, .class: loweringStep = .passDirectly(parameterName) - case .enum, .struct, .protocol: loweringStep = .passIndirectly(parameterName) + case .actor, .class: + loweringStep = + .unsafeCastPointer(.passDirectly(parameterName), swiftType: type) + case .enum, .struct, .protocol: + loweringStep = + .passIndirectly(.pointee( .typedPointer(.passDirectly(parameterName), swiftType: type))) } return LoweredParameters( @@ -173,7 +180,7 @@ extension Swift2JavaTranslator { try lowerParameter(element, convention: convention, parameterName: name) } return LoweredParameters( - cdeclToOriginal: .tuplify(parameterNames.map { .passDirectly($0) }), + cdeclToOriginal: .tuplify(loweredElements.map { $0.cdeclToOriginal }), cdeclParameters: loweredElements.flatMap { $0.cdeclParameters }, javaFFMParameters: loweredElements.flatMap { $0.javaFFMParameters } ) @@ -258,10 +265,9 @@ extension Swift2JavaTranslator { cdeclToOriginal = .passDirectly(parameterName) case (true, false): - // FIXME: Generic arguments, ugh - cdeclToOriginal = .suffixed( - .passDirectly(parameterName), - ".assumingMemoryBound(to: \(nominal.genericArguments![0]).self)" + cdeclToOriginal = .typedPointer( + .passDirectly(parameterName + "_pointer"), + swiftType: nominal.genericArguments![0] ) case (false, true): @@ -275,9 +281,9 @@ extension Swift2JavaTranslator { type, arguments: [ LabeledArgument(label: "start", - argument: .suffixed( + argument: .typedPointer( .passDirectly(parameterName + "_pointer"), - ".assumingMemoryBound(to: \(nominal.genericArguments![0]).self")), + swiftType: nominal.genericArguments![0])), LabeledArgument(label: "count", argument: .passDirectly(parameterName + "_count")) ] @@ -338,30 +344,113 @@ struct LabeledArgument { extension LabeledArgument: Equatable where Element: Equatable { } -/// How to lower the Swift parameter +/// Describes the transformation needed to take the parameters of a thunk +/// and map them to the corresponding parameter (or result value) of the +/// original function. enum LoweringStep: Equatable { + /// A direct reference to a parameter of the thunk. case passDirectly(String) - case passIndirectly(String) - indirect case suffixed(LoweringStep, String) + + /// Cast the pointer described by the lowering step to the given + /// Swift type using `unsafeBitCast(_:to:)`. + indirect case unsafeCastPointer(LoweringStep, swiftType: SwiftType) + + /// Assume at the untyped pointer described by the lowering step to the + /// given type, using `assumingMemoryBound(to:).` + indirect case typedPointer(LoweringStep, swiftType: SwiftType) + + /// The thing to which the pointer typed, which is the `pointee` property + /// of the `Unsafe(Mutable)Pointer` types in Swift. + indirect case pointee(LoweringStep) + + /// Pass this value indirectly, via & for explicit `inout` parameters. + indirect case passIndirectly(LoweringStep) + + /// Initialize a value of the given Swift type with the set of labeled + /// arguments. case initialize(SwiftType, arguments: [LabeledArgument]) + + /// Produce a tuple with the given elements. + /// + /// This is used for exploding Swift tuple arguments into multiple + /// elements, recursively. Note that this always produces unlabeled + /// tuples, which Swift will convert to the labeled tuple form. case tuplify([LoweringStep]) } struct LoweredParameters: Equatable { - /// The steps needed to get from the @_cdecl parameter to the original function + /// The steps needed to get from the @_cdecl parameters to the original function /// parameter. var cdeclToOriginal: LoweringStep /// The lowering of the parameters at the C level in Swift. var cdeclParameters: [SwiftParameter] - /// The lowerung of the parmaeters at the C level as expressed for Java's + /// The lowering of the parameters at the C level as expressed for Java's /// foreign function and memory interface. /// /// The elements in this array match up with those of 'cdeclParameters'. var javaFFMParameters: [ForeignValueLayout] } +extension LoweredParameters { + /// Produce an expression that computes the argument for this parameter + /// when calling the original function from the cdecl entrypoint. + func cdeclToOriginalArgumentExpr(isSelf: Bool)-> ExprSyntax { + cdeclToOriginal.asExprSyntax(isSelf: isSelf) + } +} + +extension LoweringStep { + func asExprSyntax(isSelf: Bool) -> ExprSyntax { + switch self { + case .passDirectly(let rawArgument): + return "\(raw: rawArgument)" + + case .unsafeCastPointer(let step, swiftType: let swiftType): + let untypedExpr = step.asExprSyntax(isSelf: false) + return "unsafeBitCast(\(untypedExpr), to: \(swiftType.metatypeReferenceExprSyntax))" + + case .typedPointer(let step, swiftType: let type): + let untypedExpr = step.asExprSyntax(isSelf: isSelf) + return "\(untypedExpr).assumingMemoryBound(to: \(type.metatypeReferenceExprSyntax))" + + case .pointee(let step): + let untypedExpr = step.asExprSyntax(isSelf: isSelf) + return "\(untypedExpr).pointee" + + case .passIndirectly(let step): + let innerExpr = step.asExprSyntax(isSelf: false) + return isSelf ? innerExpr : "&\(innerExpr)" + + case .initialize(let type, arguments: let arguments): + let renderedArguments: [String] = arguments.map { labeledArgument in + let renderedArg = labeledArgument.argument.asExprSyntax(isSelf: false) + if let argmentLabel = labeledArgument.label { + return "\(argmentLabel): \(renderedArg.description)" + } else { + return renderedArg.description + } + } + + // FIXME: Should be able to use structured initializers here instead + // of splatting out text. + let renderedArgumentList = renderedArguments.joined(separator: ", ") + return "\(raw: type.description)(\(raw: renderedArgumentList))" + + case .tuplify(let elements): + let renderedElements: [String] = elements.map { element in + element.asExprSyntax(isSelf: false).description + } + + // FIXME: Should be able to use structured initializers here instead + // of splatting out text. + let renderedElementList = renderedElements.joined(separator: ", ") + return "(\(raw: renderedElementList))" + } + } +} + enum LoweringError: Error { case inoutNotSupported(SwiftType) case unhandledType(SwiftType) @@ -375,3 +464,74 @@ public struct LoweredFunctionSignature: Equatable { var parameters: [LoweredParameters] var result: LoweredParameters } + +extension LoweredFunctionSignature { + /// Produce the `@_cdecl` thunk for this lowered function signature that will + /// call into the original function. + @_spi(Testing) + public func cdeclThunk(cName: String, inputFunction: FunctionDeclSyntax) -> FunctionDeclSyntax { + var loweredCDecl = cdecl.createFunctionDecl(cName) + + // Add the @_cdecl attribute. + let cdeclAttribute: AttributeSyntax = "@_cdecl(\(literal: cName))\n" + loweredCDecl.attributes.append(.attribute(cdeclAttribute)) + + // Create the body. + + // Lower "self", if there is one. + let parametersToLower: ArraySlice + let cdeclToOriginalSelf: ExprSyntax? + if original.selfParameter != nil { + cdeclToOriginalSelf = parameters[0].cdeclToOriginalArgumentExpr(isSelf: true) + parametersToLower = parameters[1...] + } else { + cdeclToOriginalSelf = nil + parametersToLower = parameters[...] + } + + // Lower the remaining arguments. + // FIXME: Should be able to use structured initializers here instead + // of splatting out text. + let cdeclToOriginalArguments = zip(parametersToLower, original.parameters).map { lowering, originalParam in + let cdeclToOriginalArg = lowering.cdeclToOriginalArgumentExpr(isSelf: false) + if let argumentLabel = originalParam.argumentLabel { + return "\(argumentLabel): \(cdeclToOriginalArg.description)" + } else { + return cdeclToOriginalArg.description + } + } + + // Form the call expression. + var callExpression: ExprSyntax = "\(inputFunction.name)(\(raw: cdeclToOriginalArguments.joined(separator: ", ")))" + if let cdeclToOriginalSelf { + callExpression = "\(cdeclToOriginalSelf).\(callExpression)" + } + + // Handle the return. + if cdecl.result.type.isVoid && original.result.type.isVoid { + // Nothing to return. + loweredCDecl.body = """ + { + \(callExpression) + } + """ + } else if cdecl.result.type.isVoid { + // Indirect return. This is a regular return in Swift that turns + // into a + loweredCDecl.body = """ + { + \(result.cdeclToOriginalArgumentExpr(isSelf: true)) = \(callExpression) + } + """ + } else { + // Direct return. + loweredCDecl.body = """ + { + return \(callExpression) + } + """ + } + + return loweredCDecl + } +} diff --git a/Sources/JExtractSwift/SwiftTypes/SwiftFunctionSignature.swift b/Sources/JExtractSwift/SwiftTypes/SwiftFunctionSignature.swift index 187c18a6..c2b626f2 100644 --- a/Sources/JExtractSwift/SwiftTypes/SwiftFunctionSignature.swift +++ b/Sources/JExtractSwift/SwiftTypes/SwiftFunctionSignature.swift @@ -19,6 +19,7 @@ import SwiftSyntaxBuilder /// parameters and return type. @_spi(Testing) public struct SwiftFunctionSignature: Equatable { + // FIXME: isStaticOrClass probably shouldn't be here? var isStaticOrClass: Bool var selfParameter: SwiftParameter? var parameters: [SwiftParameter] @@ -30,9 +31,16 @@ extension SwiftFunctionSignature { /// signature. package func createFunctionDecl(_ name: String) -> FunctionDeclSyntax { let parametersStr = parameters.map(\.description).joined(separator: ", ") - let resultStr = result.type.description + + let resultWithArrow: String + if result.type.isVoid { + resultWithArrow = "" + } else { + resultWithArrow = " -> \(result.type.description)" + } + let decl: DeclSyntax = """ - func \(raw: name)(\(raw: parametersStr)) -> \(raw: resultStr) { + func \(raw: name)(\(raw: parametersStr))\(raw: resultWithArrow) { // implementation } """ @@ -53,7 +61,7 @@ extension SwiftFunctionSignature { var isConsuming = false var isStaticOrClass = false for modifier in node.modifiers { - switch modifier.name { + switch modifier.name.tokenKind { case .keyword(.mutating): isMutating = true case .keyword(.static), .keyword(.class): isStaticOrClass = true case .keyword(.consuming): isConsuming = true diff --git a/Sources/JExtractSwift/SwiftTypes/SwiftParameter.swift b/Sources/JExtractSwift/SwiftTypes/SwiftParameter.swift index b7bc28fb..35b7a0e1 100644 --- a/Sources/JExtractSwift/SwiftTypes/SwiftParameter.swift +++ b/Sources/JExtractSwift/SwiftTypes/SwiftParameter.swift @@ -58,23 +58,34 @@ enum SwiftParameterConvention: Equatable { extension SwiftParameter { init(_ node: FunctionParameterSyntax, symbolTable: SwiftSymbolTable) throws { - // Determine the convention. The default is by-value, but modifiers can alter - // this. + // Determine the convention. The default is by-value, but there are + // specifiers on the type for other conventions (like `inout`). + var type = node.type var convention = SwiftParameterConvention.byValue - for modifier in node.modifiers { - switch modifier.name { - case .keyword(.consuming), .keyword(.__consuming), .keyword(.__owned): - convention = .consuming - case .keyword(.inout): - convention = .inout - default: - break + if let attributedType = type.as(AttributedTypeSyntax.self) { + for specifier in attributedType.specifiers { + guard case .simpleTypeSpecifier(let simple) = specifier else { + continue + } + + switch simple.specifier.tokenKind { + case .keyword(.consuming), .keyword(.__consuming), .keyword(.__owned): + convention = .consuming + case .keyword(.inout): + convention = .inout + default: + break + } } + + // Ignore anything else in the attributed type. + // FIXME: We might want to check for these and ignore them. + type = attributedType.baseType } self.convention = convention // Determine the type. - self.type = try SwiftType(node.type, symbolTable: symbolTable) + self.type = try SwiftType(type, symbolTable: symbolTable) // FIXME: swift-syntax itself should have these utilities based on identifiers. if let secondName = node.secondName { diff --git a/Sources/JExtractSwift/SwiftTypes/SwiftType.swift b/Sources/JExtractSwift/SwiftTypes/SwiftType.swift index 4eef607a..d83d5e63 100644 --- a/Sources/JExtractSwift/SwiftTypes/SwiftType.swift +++ b/Sources/JExtractSwift/SwiftTypes/SwiftType.swift @@ -33,15 +33,34 @@ enum SwiftType: Equatable { var asNominalTypeDeclaration: SwiftNominalTypeDeclaration? { asNominalType?.nominalTypeDecl } + + /// Whether this is the "Void" type, which is actually an empty + /// tuple. + var isVoid: Bool { + return self == .tuple([]) + } } extension SwiftType: CustomStringConvertible { + /// Whether forming a postfix type or expression to this Swift type + /// requires parentheses. + private var postfixRequiresParentheses: Bool { + switch self { + case .function: true + case .metatype, .nominal, .optional, .tuple: false + } + } + var description: String { switch self { case .nominal(let nominal): return nominal.description case .function(let functionType): return functionType.description case .metatype(let instanceType): - return "(\(instanceType.description)).Type" + var instanceTypeStr = instanceType.description + if instanceType.postfixRequiresParentheses { + instanceTypeStr = "(\(instanceTypeStr))" + } + return "\(instanceTypeStr).Type" case .optional(let wrappedType): return "\(wrappedType.description)?" case .tuple(let elements): @@ -213,4 +232,14 @@ extension SwiftType { ) ) } + + /// Produce an expression that creates the metatype for this type in + /// Swift source code. + var metatypeReferenceExprSyntax: ExprSyntax { + let type: ExprSyntax = "\(raw: description)" + if postfixRequiresParentheses { + return "(\(type)).self" + } + return "\(type).self" + } } diff --git a/Tests/JExtractSwiftTests/Asserts/LoweringAssertions.swift b/Tests/JExtractSwiftTests/Asserts/LoweringAssertions.swift index ca101133..b5304b71 100644 --- a/Tests/JExtractSwiftTests/Asserts/LoweringAssertions.swift +++ b/Tests/JExtractSwiftTests/Asserts/LoweringAssertions.swift @@ -46,7 +46,8 @@ func assertLoweredFunction( inputFunction, enclosingType: enclosingType ) - let loweredCDecl = loweredFunction.cdecl.createFunctionDecl(inputFunction.name.text) + let loweredCDecl = loweredFunction.cdeclThunk(cName: "c_\(inputFunction.name.text)", inputFunction: inputFunction) + #expect( loweredCDecl.description == expectedCDecl.description, sourceLocation: Testing.SourceLocation( diff --git a/Tests/JExtractSwiftTests/FunctionLoweringTests.swift b/Tests/JExtractSwiftTests/FunctionLoweringTests.swift index fd909565..60aa1a51 100644 --- a/Tests/JExtractSwiftTests/FunctionLoweringTests.swift +++ b/Tests/JExtractSwiftTests/FunctionLoweringTests.swift @@ -17,6 +17,7 @@ import SwiftSyntax import SwiftSyntaxBuilder import Testing +@Suite("Swift function lowering tests") final class FunctionLoweringTests { @Test("Lowering buffer pointers") func loweringBufferPointers() throws { @@ -24,8 +25,9 @@ final class FunctionLoweringTests { func f(x: Int, y: Swift.Float, z: UnsafeBufferPointer) { } """, expectedCDecl: """ - func f(_ x: Int, _ y: Float, _ z_pointer: UnsafeRawPointer, _ z_count: Int) -> () { - // implementation + @_cdecl("c_f") + func c_f(_ x: Int, _ y: Float, _ z_pointer: UnsafeRawPointer, _ z_count: Int) { + f(x: x, y: y, z: UnsafeBufferPointer(start: z_pointer.assumingMemoryBound(to: Bool.self), count: z_count)) } """ ) @@ -34,16 +36,33 @@ final class FunctionLoweringTests { @Test("Lowering tuples") func loweringTuples() throws { try assertLoweredFunction(""" - func f(t: (Int, (Float, Double)), z: UnsafePointer) { } + func f(t: (Int, (Float, Double)), z: UnsafePointer) -> Int { } """, expectedCDecl: """ - func f(_ t_0: Int, _ t_1_0: Float, _ t_1_1: Double, _ z_pointer: UnsafeRawPointer) -> () { - // implementation + @_cdecl("c_f") + func c_f(_ t_0: Int, _ t_1_0: Float, _ t_1_1: Double, _ z_pointer: UnsafeRawPointer) -> Int { + return f(t: (t_0, (t_1_0, t_1_1)), z: z_pointer.assumingMemoryBound(to: Int.self)) } """ ) } + @Test("Lowering functions involving inout") + func loweringInoutParameters() throws { + try assertLoweredFunction(""" + func shift(point: inout Point, by delta: (Double, Double)) { } + """, + sourceFile: """ + struct Point { } + """, + expectedCDecl: """ + @_cdecl("c_shift") + func c_shift(_ point: UnsafeMutableRawPointer, _ delta_0: Double, _ delta_1: Double) { + shift(point: &point.assumingMemoryBound(to: Point.self).pointee, by: (delta_0, delta_1)) + } + """ + ) + } @Test("Lowering methods") func loweringMethods() throws { try assertLoweredFunction(""" @@ -54,8 +73,45 @@ final class FunctionLoweringTests { """, enclosingType: "Point", expectedCDecl: """ - func shifted(_ self: UnsafeRawPointer, _ delta_0: Double, _ delta_1: Double, _ _result: UnsafeMutableRawPointer) -> () { - // implementation + @_cdecl("c_shifted") + func c_shifted(_ self: UnsafeRawPointer, _ delta_0: Double, _ delta_1: Double, _ _result: UnsafeMutableRawPointer) { + _result.assumingMemoryBound(to: Point.self).pointee = self.assumingMemoryBound(to: Point.self).pointee.shifted(by: (delta_0, delta_1)) + } + """ + ) + } + + @Test("Lowering mutating methods") + func loweringMutatingMethods() throws { + try assertLoweredFunction(""" + mutating func shift(by delta: (Double, Double)) { } + """, + sourceFile: """ + struct Point { } + """, + enclosingType: "Point", + expectedCDecl: """ + @_cdecl("c_shift") + func c_shift(_ self: UnsafeMutableRawPointer, _ delta_0: Double, _ delta_1: Double) { + self.assumingMemoryBound(to: Point.self).pointee.shift(by: (delta_0, delta_1)) + } + """ + ) + } + + @Test("Lowering instance methods of classes") + func loweringInstanceMethodsOfClass() throws { + try assertLoweredFunction(""" + func shift(by delta: (Double, Double)) { } + """, + sourceFile: """ + class Point { } + """, + enclosingType: "Point", + expectedCDecl: """ + @_cdecl("c_shift") + func c_shift(_ self: UnsafeRawPointer, _ delta_0: Double, _ delta_1: Double) { + unsafeBitCast(self, to: Point.self).shift(by: (delta_0, delta_1)) } """ ) @@ -67,7 +123,7 @@ final class FunctionLoweringTests { func f(t: Int.Type) { } """, expectedCDecl: """ - func f(t: RawPointerType) -> () { + func f(t: UnsafeRawPointer) -> () { // implementation } """ From 3d72f9f7c930508907180d2c37e561afebf3f30e Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Wed, 29 Jan 2025 17:24:10 -0800 Subject: [PATCH 219/426] Add support for lowering metatype parameters --- ...wift2JavaTranslator+FunctionLowering.swift | 22 ++++++++++++++++++- .../FunctionLoweringTests.swift | 7 +++--- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/Sources/JExtractSwift/Swift2JavaTranslator+FunctionLowering.swift b/Sources/JExtractSwift/Swift2JavaTranslator+FunctionLowering.swift index 4ab81e39..5e0c5b1c 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator+FunctionLowering.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator+FunctionLowering.swift @@ -127,9 +127,29 @@ extension Swift2JavaTranslator { parameterName: String ) throws -> LoweredParameters { switch type { - case .function, .metatype, .optional: + case .function, .optional: throw LoweringError.unhandledType(type) + case .metatype(let instanceType): + return LoweredParameters( + cdeclToOriginal: .unsafeCastPointer( + .passDirectly(parameterName), + swiftType: instanceType + ), + cdeclParameters: [ + SwiftParameter( + convention: .byValue, + parameterName: parameterName, + type: .nominal( + SwiftNominalType( + nominalTypeDecl: swiftStdlibTypes.unsafeRawPointerDecl + ) + ) + ) + ], + javaFFMParameters: [.SwiftPointer] + ) + case .nominal(let nominal): // Types from the Swift standard library that we know about. if nominal.nominalTypeDecl.moduleName == "Swift", diff --git a/Tests/JExtractSwiftTests/FunctionLoweringTests.swift b/Tests/JExtractSwiftTests/FunctionLoweringTests.swift index 60aa1a51..08187914 100644 --- a/Tests/JExtractSwiftTests/FunctionLoweringTests.swift +++ b/Tests/JExtractSwiftTests/FunctionLoweringTests.swift @@ -117,14 +117,15 @@ final class FunctionLoweringTests { ) } - @Test("Lowering metatypes", .disabled("Metatypes are not yet lowered")) + @Test("Lowering metatypes") func lowerMetatype() throws { try assertLoweredFunction(""" func f(t: Int.Type) { } """, expectedCDecl: """ - func f(t: UnsafeRawPointer) -> () { - // implementation + @_cdecl("c_f") + func c_f(_ t: UnsafeRawPointer) { + f(t: unsafeBitCast(t, to: Int.self)) } """ ) From 2ca6d55db815eadf6f09331e2cdf0f09a2491c8c Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Thu, 30 Jan 2025 16:24:03 -0800 Subject: [PATCH 220/426] C lowering: drop the Java FFM type from this lowering We're going to separate out the lowering of Swift declarations to C from the handling of those C declarations on the Java side. That's cleaner and more generalizable. --- ...wift2JavaTranslator+FunctionLowering.swift | 48 ++++++++----------- .../SwiftTypes/SwiftParameter.swift | 1 + 2 files changed, 21 insertions(+), 28 deletions(-) diff --git a/Sources/JExtractSwift/Swift2JavaTranslator+FunctionLowering.swift b/Sources/JExtractSwift/Swift2JavaTranslator+FunctionLowering.swift index 5e0c5b1c..ffb550b1 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator+FunctionLowering.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator+FunctionLowering.swift @@ -64,19 +64,22 @@ extension Swift2JavaTranslator { ) // If the result type doesn't lower to either empty (void) or a single - // primitive result, make it indirect. + // result, make it indirect. let indirectResult: Bool - if !(loweredResult.javaFFMParameters.count == 0 || - (loweredResult.javaFFMParameters.count == 1 && - loweredResult.javaFFMParameters[0].isPrimitive)) { + if loweredResult.cdeclParameters.count == 0 { + // void result type + indirectResult = false + } else if loweredResult.cdeclParameters.count == 1, + loweredResult.cdeclParameters[0].isPrimitive { + // Primitive result type + indirectResult = false + } else { loweredResult = try lowerParameter( signature.result.type, convention: .inout, parameterName: "_result" ) indirectResult = true - } else { - indirectResult = false } // Collect all of the lowered parameters for the @_cdecl function. @@ -146,8 +149,7 @@ extension Swift2JavaTranslator { ) ) ) - ], - javaFFMParameters: [.SwiftPointer] + ] ) case .nominal(let nominal): @@ -190,8 +192,7 @@ extension Swift2JavaTranslator { ) ) ) - ], - javaFFMParameters: [.SwiftPointer] + ] ) case .tuple(let tuple): @@ -201,8 +202,7 @@ extension Swift2JavaTranslator { } return LoweredParameters( cdeclToOriginal: .tuplify(loweredElements.map { $0.cdeclToOriginal }), - cdeclParameters: loweredElements.flatMap { $0.cdeclParameters }, - javaFFMParameters: loweredElements.flatMap { $0.javaFFMParameters } + cdeclParameters: loweredElements.flatMap { $0.cdeclParameters } ) } } @@ -217,6 +217,9 @@ extension Swift2JavaTranslator { // Swift types that map directly to Java primitive types. if let primitiveType = JavaType(swiftTypeName: nominalName) { + // FIXME: Should be using C types here, not Java types. + _ = primitiveType + // We cannot handle inout on primitive types. if convention == .inout { throw LoweringError.inoutNotSupported(type) @@ -228,11 +231,9 @@ extension Swift2JavaTranslator { SwiftParameter( convention: convention, parameterName: parameterName, - type: type + type: type, + isPrimitive: true ) - ], - javaFFMParameters: [ - ForeignValueLayout(javaType: primitiveType)! ] ) } @@ -251,11 +252,9 @@ extension Swift2JavaTranslator { SwiftParameter( convention: convention, parameterName: parameterName, - type: type + type: type, + isPrimitive: true ) - ], - javaFFMParameters: [ - .SwiftInt ] ) } @@ -351,8 +350,7 @@ extension Swift2JavaTranslator { return LoweredParameters( cdeclToOriginal: cdeclToOriginal, - cdeclParameters: lowered.map(\.0), - javaFFMParameters: lowered.map(\.1) + cdeclParameters: lowered.map(\.0) ) } } @@ -405,12 +403,6 @@ struct LoweredParameters: Equatable { /// The lowering of the parameters at the C level in Swift. var cdeclParameters: [SwiftParameter] - - /// The lowering of the parameters at the C level as expressed for Java's - /// foreign function and memory interface. - /// - /// The elements in this array match up with those of 'cdeclParameters'. - var javaFFMParameters: [ForeignValueLayout] } extension LoweredParameters { diff --git a/Sources/JExtractSwift/SwiftTypes/SwiftParameter.swift b/Sources/JExtractSwift/SwiftTypes/SwiftParameter.swift index 35b7a0e1..15b905a4 100644 --- a/Sources/JExtractSwift/SwiftTypes/SwiftParameter.swift +++ b/Sources/JExtractSwift/SwiftTypes/SwiftParameter.swift @@ -19,6 +19,7 @@ struct SwiftParameter: Equatable { var argumentLabel: String? var parameterName: String? var type: SwiftType + var isPrimitive = false } extension SwiftParameter: CustomStringConvertible { From 4fdef82f956753001f14357500e87f6e93ad9314 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Thu, 30 Jan 2025 20:36:13 -0800 Subject: [PATCH 221/426] Introduce a C type system for lowering purposes Swift functions are lowered into C-compatible thunks. Those thunks currently have their types represented in Swift, which is needed for the `@_cdecl` declaration. Introduce a representation of the C type system so that we can describe the specific C types that each parameter has. This intentionally represents C types in an abstract form that fits will with the mapping from Swift, for example representing integral types by the number of bits and their signedness, rather than the actual C primitive types like `int` or `unsigned long`. Implement printing of C types and functions, in case we decide that we want to render C declarations for consumption by humans or tools that want to bind to them. --- Sources/JExtractSwift/CTypes/CEnum.swift | 21 ++ Sources/JExtractSwift/CTypes/CFunction.swift | 72 +++++++ Sources/JExtractSwift/CTypes/CParameter.swift | 33 +++ Sources/JExtractSwift/CTypes/CStruct.swift | 22 ++ Sources/JExtractSwift/CTypes/CTag.swift | 29 +++ Sources/JExtractSwift/CTypes/CType.swift | 197 ++++++++++++++++++ Sources/JExtractSwift/CTypes/CUnion.swift | 21 ++ Tests/JExtractSwiftTests/CTypeTests.swift | 73 +++++++ 8 files changed, 468 insertions(+) create mode 100644 Sources/JExtractSwift/CTypes/CEnum.swift create mode 100644 Sources/JExtractSwift/CTypes/CFunction.swift create mode 100644 Sources/JExtractSwift/CTypes/CParameter.swift create mode 100644 Sources/JExtractSwift/CTypes/CStruct.swift create mode 100644 Sources/JExtractSwift/CTypes/CTag.swift create mode 100644 Sources/JExtractSwift/CTypes/CType.swift create mode 100644 Sources/JExtractSwift/CTypes/CUnion.swift create mode 100644 Tests/JExtractSwiftTests/CTypeTests.swift diff --git a/Sources/JExtractSwift/CTypes/CEnum.swift b/Sources/JExtractSwift/CTypes/CEnum.swift new file mode 100644 index 00000000..3caddb96 --- /dev/null +++ b/Sources/JExtractSwift/CTypes/CEnum.swift @@ -0,0 +1,21 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +/// Describes a C enum type. +public class CEnum { + public var name: String + public init(name: String) { + self.name = name + } +} diff --git a/Sources/JExtractSwift/CTypes/CFunction.swift b/Sources/JExtractSwift/CTypes/CFunction.swift new file mode 100644 index 00000000..9dc69e41 --- /dev/null +++ b/Sources/JExtractSwift/CTypes/CFunction.swift @@ -0,0 +1,72 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +/// Describes a C function. +public struct CFunction { + /// The result type of the function. + public var resultType: CType + + /// The name of the function. + public var name: String + + /// The parameters of the function. + public var parameters: [CParameter] + + /// Whether the function is variadic. + public var isVariadic: Bool + + public init(resultType: CType, name: String, parameters: [CParameter], isVariadic: Bool) { + self.resultType = resultType + self.name = name + self.parameters = parameters + self.isVariadic = isVariadic + } + + /// Produces the type of the function. + public var functionType: CType { + .function( + resultType: resultType, + parameters: parameters.map { $0.type }, + variadic: isVariadic + ) + } +} + +extension CFunction: CustomStringConvertible { + /// Print the declaration of this C function + public var description: String { + var result = "" + + resultType.printBefore(result: &result) + + // FIXME: parentheses when needed. + result += " " + result += name + + // Function parameters. + result += "(" + result += parameters.map { $0.description }.joined(separator: ", ") + CType.printFunctionParametersSuffix( + isVariadic: isVariadic, + hasZeroParameters: parameters.isEmpty, + to: &result + ) + result += ")" + + resultType.printAfter(result: &result) + + result += "" + return result + } +} diff --git a/Sources/JExtractSwift/CTypes/CParameter.swift b/Sources/JExtractSwift/CTypes/CParameter.swift new file mode 100644 index 00000000..500af4b9 --- /dev/null +++ b/Sources/JExtractSwift/CTypes/CParameter.swift @@ -0,0 +1,33 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +/// Describes a parameter to a C function. +public struct CParameter { + /// The name of the parameter, if provided. + public var name: String? + + /// The type of the parameter. + public var type: CType + + public init(name: String? = nil, type: CType) { + self.name = name + self.type = type + } +} + +extension CParameter: CustomStringConvertible { + public var description: String { + type.print(placeholder: name ?? "") + } +} diff --git a/Sources/JExtractSwift/CTypes/CStruct.swift b/Sources/JExtractSwift/CTypes/CStruct.swift new file mode 100644 index 00000000..c7e3ab68 --- /dev/null +++ b/Sources/JExtractSwift/CTypes/CStruct.swift @@ -0,0 +1,22 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +/// Describes a C struct type. +public class CStruct { + public var name: String + + public init(name: String) { + self.name = name + } +} diff --git a/Sources/JExtractSwift/CTypes/CTag.swift b/Sources/JExtractSwift/CTypes/CTag.swift new file mode 100644 index 00000000..3e26d2db --- /dev/null +++ b/Sources/JExtractSwift/CTypes/CTag.swift @@ -0,0 +1,29 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +/// Describes a tag type in C, which is either a struct or an enum. +public enum CTag { + case `struct`(CStruct) + case `enum`(CEnum) + case `union`(CUnion) + + public var name: String { + switch self { + case .struct(let cStruct): return cStruct.name + case .enum(let cEnum): return cEnum.name + case .union(let cUnion): return cUnion.name + } + } +} + diff --git a/Sources/JExtractSwift/CTypes/CType.swift b/Sources/JExtractSwift/CTypes/CType.swift new file mode 100644 index 00000000..54716b90 --- /dev/null +++ b/Sources/JExtractSwift/CTypes/CType.swift @@ -0,0 +1,197 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +/// Describes a type in the C type system as it is used for lowering of Swift +/// declarations to C. +/// +/// This description of the C type system only has to account for the types +/// that are used when providing C-compatible thunks from Swift code. It is +/// not a complete representation of the C type system, and leaves some +/// target-specific types (like the actual type that ptrdiff_t and size_t +/// map to) unresolved. +public enum CType { + /// A tag type, such as a struct or enum. + case tag(CTag) + + /// An integral type. + case integral(IntegralType) + + /// A floating-point type. + case floating(FloatingType) + + case void + + /// A qualiied type, such as 'const T'. + indirect case qualified(const: Bool, volatile: Bool, type: CType) + + /// A pointer to the given type. + indirect case pointer(CType) + + /// A function type. + indirect case function(resultType: CType, parameters: [CType], variadic: Bool) + + /// An integral type in C, described mostly in terms of the bit-sized + /// typedefs rather than actual C types (like int or long), because Swift + /// deals in bit-widths. + public enum IntegralType { + case bool + + /// A signed integer type stored with the given number of bits. This + /// corresponds to the intNNN_t types from . + case signed(bits: Int) + + /// An unsigned integer type stored with the given number of bits. This + /// corresponds to the uintNNN_t types from . + case unsigned(bits: Int) + + /// The ptrdiff_t type, which in C is a typedef for the signed integer + /// type that is the same size as a pointer. + case ptrdiff_t + + /// The size_t type, which in C is a typedef for the unsigned integer + /// type that is the same size as a pointer. + case size_t + } + + /// A floating point type in C. + public enum FloatingType { + case float + case double + } +} + +extension CType: CustomStringConvertible { + /// Print the part of this type that comes before the declarator, appending + /// it to the provided `result` string. + func printBefore(result: inout String) { + switch self { + case .floating(let floating): + switch floating { + case .float: result += "float" + case .double: result += "double" + } + + case .function(resultType: let resultType, parameters: _, variadic: _): + resultType.printBefore(result: &result) + + // FIXME: Clang inserts a parentheses in here if there's a non-empty + // placeholder, which is Very Stateful. How should I model that? + + case .integral(let integral): + switch integral { + case .bool: result += "_Bool" + case .signed(let bits): result += "int\(bits)_t" + case .unsigned(let bits): result += "uint\(bits)_t" + case .ptrdiff_t: result += "ptrdiff_t" + case .size_t: result += "size_t" + } + + case .pointer(let pointee): + pointee.printBefore(result: &result) + result += "*" + + case .qualified(const: let isConst, volatile: let isVolatile, type: let underlying): + underlying.printBefore(result: &result) + + // FIXME: "east const" is easier to print correctly, so do that. We could + // follow Clang and decide when it's correct to print "west const" by + // splitting the qualifiers before we get here. + if isConst { + result += " const" + } + if isVolatile { + result += " volatile" + } + + case .tag(let tag): + switch tag { + case .enum(let cEnum): result += "enum \(cEnum.name)" + case .struct(let cStruct): result += "struct \(cStruct.name)" + case .union(let cUnion): result += "union \(cUnion.name)" + } + + case .void: result += "void" + } + } + + /// Render an appropriate "suffix" to the parameter list of a function, + /// which goes just before the closing ")" of that function, appending + /// it to the string. This includes whether the function is variadic and + /// whether is had zero parameters. + static func printFunctionParametersSuffix( + isVariadic: Bool, + hasZeroParameters: Bool, + to result: inout String + ) { + // Take care of variadic parameters and empty parameter lists together, + // because the formatter of the former depends on the latter. + switch (isVariadic, hasZeroParameters) { + case (true, false): result += ", ..." + case (true, true): result += "..." + case (false, true): result += "void" + case (false, false): break + } + } + + /// Print the part of the type that comes after the declarator, appending + /// it to the provided `result` string. + func printAfter(result: inout String) { + switch self { + case .floating, .integral, .tag, .void: break + + case .function(resultType: let resultType, parameters: let parameters, variadic: let variadic): + // FIXME: Clang inserts a parentheses in here if there's a non-empty + // placeholder, which is Very Stateful. How should I model that? + + result += "(" + + // Render the parameter types. + result += parameters.map { $0.description }.joined(separator: ", ") + + CType.printFunctionParametersSuffix( + isVariadic: variadic, + hasZeroParameters: parameters.isEmpty, + to: &result + ) + + result += ")" + + resultType.printAfter(result: &result) + + case .pointer(let pointee): + pointee.printAfter(result: &result) + + case .qualified(const: _, volatile: _, type: let underlying): + underlying.printAfter(result: &result) + } + } + + /// Print this type into a string, with the given placeholder as the name + /// of the entity being declared. + public func print(placeholder: String?) -> String { + var result = "" + printBefore(result: &result) + if let placeholder { + result += " " + result += placeholder + } + printAfter(result: &result) + return result + } + + /// Render the C type into a string that represents the type in C. + public var description: String { + print(placeholder: nil) + } +} diff --git a/Sources/JExtractSwift/CTypes/CUnion.swift b/Sources/JExtractSwift/CTypes/CUnion.swift new file mode 100644 index 00000000..e8d68c15 --- /dev/null +++ b/Sources/JExtractSwift/CTypes/CUnion.swift @@ -0,0 +1,21 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +/// Describes a C union type. +public class CUnion { + public var name: String + public init(name: String) { + self.name = name + } +} diff --git a/Tests/JExtractSwiftTests/CTypeTests.swift b/Tests/JExtractSwiftTests/CTypeTests.swift new file mode 100644 index 00000000..c60a38b6 --- /dev/null +++ b/Tests/JExtractSwiftTests/CTypeTests.swift @@ -0,0 +1,73 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import JExtractSwift +import Testing + +@Suite("C type system tests") +struct CTypeTests { + @Test("Function declaration printing") + func testFunctionDeclarationPrint() { + let malloc = CFunction( + resultType: .pointer(.void), + name: "malloc", + parameters: [ + CParameter(name: "size", type: .integral(.size_t)) + ], + isVariadic: false + ) + #expect(malloc.description == "void* malloc(size_t size)") + + let free = CFunction( + resultType: .void, + name: "free", + parameters: [ + CParameter(name: "ptr", type: .pointer(.void)) + ], + isVariadic: false + ) + #expect(free.description == "void free(void* ptr)") + + let snprintf = CFunction( + resultType: .integral(.signed(bits: 32)), + name: "snprintf", + parameters: [ + CParameter(name: "str", type: .pointer(.integral(.signed(bits: 8)))), + CParameter(name: "size", type: .integral(.size_t)), + CParameter( + name: "format", + type: .pointer( + .qualified( + const: true, + volatile: false, + type: .integral(.signed(bits: 8)) + ) + ) + ) + ], + isVariadic: true + ) + #expect(snprintf.description == "int32_t snprintf(int8_t* str, size_t size, int8_t const* format, ...)") + #expect(snprintf.functionType.description == "int32_t(int8_t*, size_t, int8_t const*, ...)") + + let rand = CFunction( + resultType: .integral(.signed(bits: 32)), + name: "rand", + parameters: [], + isVariadic: false + ) + #expect(rand.description == "int32_t rand(void)") + #expect(rand.functionType.description == "int32_t(void)") + } +} From 68d48d4c3717949d1a6f85e0821ba0e95dc0edce Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Fri, 31 Jan 2025 13:55:53 +0000 Subject: [PATCH 222/426] Implement lowering of Swift cdecl functions to C functions Leverage the new C type system so that we can lower Swift cdecl functions down to their C representation. This could be used to generate C headers (albeit ugly ones) in the future, but for now is part of the validation of lowering Swift functions to cdecl thunks. --- Sources/JExtractSwift/CTypes/CType.swift | 13 + ...wift2JavaTranslator+FunctionLowering.swift | 39 ++- .../SwiftStandardLibraryTypes+CLowering.swift | 85 +++++++ .../SwiftStandardLibraryTypes.swift | 236 ++++++++---------- .../Asserts/LoweringAssertions.swift | 15 ++ .../FunctionLoweringTests.swift | 22 +- 6 files changed, 267 insertions(+), 143 deletions(-) create mode 100644 Sources/JExtractSwift/SwiftTypes/SwiftStandardLibraryTypes+CLowering.swift diff --git a/Sources/JExtractSwift/CTypes/CType.swift b/Sources/JExtractSwift/CTypes/CType.swift index 54716b90..e69e89f4 100644 --- a/Sources/JExtractSwift/CTypes/CType.swift +++ b/Sources/JExtractSwift/CTypes/CType.swift @@ -195,3 +195,16 @@ extension CType: CustomStringConvertible { print(placeholder: nil) } } + +extension CType { + /// Apply the rules for function parameter decay to produce the resulting + /// decayed type. For example, this will adjust a function type to a + /// pointer-to-function type. + var parameterDecay: CType { + switch self { + case .floating, .integral, .pointer, .qualified, .tag, .void: self + + case .function: .pointer(self) + } + } +} diff --git a/Sources/JExtractSwift/Swift2JavaTranslator+FunctionLowering.swift b/Sources/JExtractSwift/Swift2JavaTranslator+FunctionLowering.swift index ffb550b1..af168139 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator+FunctionLowering.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator+FunctionLowering.swift @@ -145,7 +145,7 @@ extension Swift2JavaTranslator { parameterName: parameterName, type: .nominal( SwiftNominalType( - nominalTypeDecl: swiftStdlibTypes.unsafeRawPointerDecl + nominalTypeDecl: swiftStdlibTypes[.unsafeRawPointer] ) ) ) @@ -187,8 +187,8 @@ extension Swift2JavaTranslator { type: .nominal( SwiftNominalType( nominalTypeDecl: mutable - ? swiftStdlibTypes.unsafeMutableRawPointerDecl - : swiftStdlibTypes.unsafeRawPointerDecl + ? swiftStdlibTypes[.unsafeMutableRawPointer] + : swiftStdlibTypes[.unsafeRawPointer] ) ) ) @@ -276,8 +276,8 @@ extension Swift2JavaTranslator { // At the @_cdecl level, make everything a raw pointer. let cdeclPointerType = mutable - ? swiftStdlibTypes.unsafeMutableRawPointerDecl - : swiftStdlibTypes.unsafeRawPointerDecl + ? swiftStdlibTypes[.unsafeMutableRawPointer] + : swiftStdlibTypes[.unsafeRawPointer] var cdeclToOriginal: LoweringStep switch (requiresArgument, hasCount) { case (false, false): @@ -327,7 +327,7 @@ extension Swift2JavaTranslator { convention: convention, parameterName: parameterName + "_count", type: SwiftType.nominal( - SwiftNominalType(nominalTypeDecl: swiftStdlibTypes.intDecl) + SwiftNominalType(nominalTypeDecl: swiftStdlibTypes[.int]) ) ), .SwiftInt @@ -353,6 +353,33 @@ extension Swift2JavaTranslator { cdeclParameters: lowered.map(\.0) ) } + + /// Given a Swift function signature that represents a @_cdecl function, + /// produce the equivalent C function with the given name. + /// + /// Lowering to a @_cdecl function should never produce a + @_spi(Testing) + public func cdeclToCFunctionLowering( + _ cdeclSignature: SwiftFunctionSignature, + cName: String + ) -> CFunction { + assert(cdeclSignature.selfParameter == nil) + + let cResultType = try! swiftStdlibTypes.cdeclToCLowering(cdeclSignature.result.type) + let cParameters = cdeclSignature.parameters.map { parameter in + CParameter( + name: parameter.parameterName, + type: try! swiftStdlibTypes.cdeclToCLowering(parameter.type).parameterDecay + ) + } + + return CFunction( + resultType: cResultType, + name: cName, + parameters: cParameters, + isVariadic: false + ) + } } struct LabeledArgument { diff --git a/Sources/JExtractSwift/SwiftTypes/SwiftStandardLibraryTypes+CLowering.swift b/Sources/JExtractSwift/SwiftTypes/SwiftStandardLibraryTypes+CLowering.swift new file mode 100644 index 00000000..3913f9cc --- /dev/null +++ b/Sources/JExtractSwift/SwiftTypes/SwiftStandardLibraryTypes+CLowering.swift @@ -0,0 +1,85 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +extension SwiftStandardLibraryTypes { + /// Lower the given Swift type down to a its corresponding C type. + /// + /// This operation only supports the subset of Swift types that are + /// representable in a Swift `@_cdecl` function. If lowering an arbitrary + /// Swift function, first go through Swift -> cdecl lowering. + func cdeclToCLowering(_ swiftType: SwiftType) throws -> CType { + switch swiftType { + case .nominal(let nominalType): + if let knownType = self[nominalType.nominalTypeDecl] { + return try knownType.loweredCType() + } + + throw CDeclToCLoweringError.invalidNominalType(nominalType.nominalTypeDecl) + + case .function(let functionType): + switch functionType.convention { + case .swift: + throw CDeclToCLoweringError.invalidFunctionConvention(functionType) + + case .c: + let resultType = try cdeclToCLowering(functionType.resultType) + let parameterTypes = try functionType.parameters.map { param in + try cdeclToCLowering(param.type) + } + + return .function( + resultType: resultType, + parameters: parameterTypes, + variadic: false + ) + } + + case .tuple([]): + return .void + + case .metatype, .optional, .tuple: + throw CDeclToCLoweringError.invalidCDeclType(swiftType) + } + } +} + +extension KnownStandardLibraryType { + func loweredCType() throws -> CType { + switch self { + case .bool: .integral(.bool) + case .int: .integral(.ptrdiff_t) + case .uint: .integral(.size_t) + case .int8: .integral(.signed(bits: 8)) + case .uint8: .integral(.unsigned(bits: 8)) + case .int16: .integral(.signed(bits: 16)) + case .uint16: .integral(.unsigned(bits: 16)) + case .int32: .integral(.signed(bits: 32)) + case .uint32: .integral(.unsigned(bits: 32)) + case .int64: .integral(.signed(bits: 64)) + case .uint64: .integral(.unsigned(bits: 64)) + case .float: .floating(.float) + case .double: .floating(.double) + case .unsafeMutableRawPointer: .pointer(.void) + case .unsafeRawPointer: .pointer( + .qualified(const: true, volatile: false, type: .void) + ) + } + } +} +enum CDeclToCLoweringError: Error { + case invalidCDeclType(SwiftType) + case invalidNominalType(SwiftNominalTypeDeclaration) + case invalidFunctionConvention(SwiftFunctionType) +} + diff --git a/Sources/JExtractSwift/SwiftTypes/SwiftStandardLibraryTypes.swift b/Sources/JExtractSwift/SwiftTypes/SwiftStandardLibraryTypes.swift index 57a5865f..b9689e9c 100644 --- a/Sources/JExtractSwift/SwiftTypes/SwiftStandardLibraryTypes.swift +++ b/Sources/JExtractSwift/SwiftTypes/SwiftStandardLibraryTypes.swift @@ -14,75 +14,101 @@ import SwiftSyntax +enum KnownStandardLibraryType: Int, Hashable, CaseIterable { + case bool = 0 + case int + case uint + case int8 + case uint8 + case int16 + case uint16 + case int32 + case uint32 + case int64 + case uint64 + case float + case double + case unsafeRawPointer + case unsafeMutableRawPointer + + var typeName: String { + switch self { + case .bool: return "Bool" + case .int: return "Int" + case .uint: return "UInt" + case .int8: return "Int8" + case .uint8: return "UInt8" + case .int16: return "Int16" + case .uint16: return "UInt16" + case .int32: return "Int32" + case .uint32: return "UInt32" + case .int64: return "Int64" + case .uint64: return "UInt64" + case .float: return "Float" + case .double: return "Double" + case .unsafeRawPointer: return "UnsafeRawPointer" + case .unsafeMutableRawPointer: return "UnsafeMutableRawPointer" + } + } + + var isGeneric: Bool { + false + } +} + /// Captures many types from the Swift standard library in their most basic /// forms, so that the translator can reason about them in source code. struct SwiftStandardLibraryTypes { - /// Swift.UnsafeRawPointer - var unsafeRawPointerDecl: SwiftNominalTypeDeclaration - - /// Swift.UnsafeMutableRawPointer - var unsafeMutableRawPointerDecl: SwiftNominalTypeDeclaration - // Swift.UnsafePointer - var unsafePointerDecl: SwiftNominalTypeDeclaration + let unsafePointerDecl: SwiftNominalTypeDeclaration // Swift.UnsafeMutablePointer - var unsafeMutablePointerDecl: SwiftNominalTypeDeclaration + let unsafeMutablePointerDecl: SwiftNominalTypeDeclaration // Swift.UnsafeBufferPointer - var unsafeBufferPointerDecl: SwiftNominalTypeDeclaration + let unsafeBufferPointerDecl: SwiftNominalTypeDeclaration // Swift.UnsafeMutableBufferPointer - var unsafeMutableBufferPointerDecl: SwiftNominalTypeDeclaration - - /// Swift.Bool - var boolDecl: SwiftNominalTypeDeclaration - - /// Swift.Int8 - var int8Decl: SwiftNominalTypeDeclaration - - /// Swift.Int16 - var int16Decl: SwiftNominalTypeDeclaration - - /// Swift.UInt16 - var uint16Decl: SwiftNominalTypeDeclaration - - /// Swift.Int32 - var int32Decl: SwiftNominalTypeDeclaration - - /// Swift.Int64 - var int64Decl: SwiftNominalTypeDeclaration - - /// Swift.Int - var intDecl: SwiftNominalTypeDeclaration - - /// Swift.Float - var floatDecl: SwiftNominalTypeDeclaration - - /// Swift.Double - var doubleDecl: SwiftNominalTypeDeclaration - - /// Swift.String - var stringDecl: SwiftNominalTypeDeclaration - - init(into parsedModule: inout SwiftParsedModuleSymbolTable) { - // Pointer types - self.unsafeRawPointerDecl = parsedModule.addNominalTypeDeclaration( - StructDeclSyntax( - name: .identifier("UnsafeRawPointer"), - memberBlock: .init(members: []) - ), - parent: nil - ) + let unsafeMutableBufferPointerDecl: SwiftNominalTypeDeclaration + + /// Mapping from known standard library types to their nominal type declaration. + let knownTypeToNominal: [KnownStandardLibraryType: SwiftNominalTypeDeclaration] + + /// Mapping from nominal type declarations to known types. + let nominalTypeDeclToKnownType: [SwiftNominalTypeDeclaration: KnownStandardLibraryType] + + private static func recordKnownType( + _ type: KnownStandardLibraryType, + _ syntax: NominalTypeDeclSyntaxNode, + knownTypeToNominal: inout [KnownStandardLibraryType: SwiftNominalTypeDeclaration], + nominalTypeDeclToKnownType: inout [SwiftNominalTypeDeclaration: KnownStandardLibraryType], + parsedModule: inout SwiftParsedModuleSymbolTable + ) { + let nominalDecl = parsedModule.addNominalTypeDeclaration(syntax, parent: nil) + knownTypeToNominal[type] = nominalDecl + nominalTypeDeclToKnownType[nominalDecl] = type + } - self.unsafeMutableRawPointerDecl = parsedModule.addNominalTypeDeclaration( + private static func recordKnownNonGenericStruct( + _ type: KnownStandardLibraryType, + knownTypeToNominal: inout [KnownStandardLibraryType: SwiftNominalTypeDeclaration], + nominalTypeDeclToKnownType: inout [SwiftNominalTypeDeclaration: KnownStandardLibraryType], + parsedModule: inout SwiftParsedModuleSymbolTable + ) { + recordKnownType( + type, StructDeclSyntax( - name: .identifier("UnsafeMutableRawPointer"), + name: .identifier(type.typeName), memberBlock: .init(members: []) ), - parent: nil + knownTypeToNominal: &knownTypeToNominal, + nominalTypeDeclToKnownType: &nominalTypeDeclToKnownType, + parsedModule: &parsedModule ) + } + init(into parsedModule: inout SwiftParsedModuleSymbolTable) { + // Pointer types self.unsafePointerDecl = parsedModule.addNominalTypeDeclaration( StructDeclSyntax( name: .identifier("UnsafePointer"), @@ -127,82 +153,32 @@ struct SwiftStandardLibraryTypes { parent: nil ) - self.boolDecl = parsedModule.addNominalTypeDeclaration( - StructDeclSyntax( - name: .identifier("Bool"), - memberBlock: .init(members: []) - ), - parent: nil - ) - self.intDecl = parsedModule.addNominalTypeDeclaration( - StructDeclSyntax( - name: .identifier("Int"), - memberBlock: .init(members: []) - ), - parent: nil - ) - self.int8Decl = parsedModule.addNominalTypeDeclaration( - StructDeclSyntax( - name: .identifier("Int8"), - memberBlock: .init(members: []) - ), - parent: nil - ) - self.int16Decl = parsedModule.addNominalTypeDeclaration( - StructDeclSyntax( - name: .identifier("Int16"), - memberBlock: .init(members: []) - ), - parent: nil - ) - self.uint16Decl = parsedModule.addNominalTypeDeclaration( - StructDeclSyntax( - name: .identifier("UInt16"), - memberBlock: .init(members: []) - ), - parent: nil - ) - self.int32Decl = parsedModule.addNominalTypeDeclaration( - StructDeclSyntax( - name: .identifier("Int32"), - memberBlock: .init(members: []) - ), - parent: nil - ) - self.int64Decl = parsedModule.addNominalTypeDeclaration( - StructDeclSyntax( - name: .identifier("Int64"), - memberBlock: .init(members: []) - ), - parent: nil - ) - self.floatDecl = parsedModule.addNominalTypeDeclaration( - StructDeclSyntax( - name: .identifier("Float"), - memberBlock: .init(members: []) - ), - parent: nil - ) - self.doubleDecl = parsedModule.addNominalTypeDeclaration( - StructDeclSyntax( - name: .identifier("Double"), - memberBlock: .init(members: []) - ), - parent: nil - ) - self.intDecl = parsedModule.addNominalTypeDeclaration( - StructDeclSyntax( - name: .identifier("Int"), - memberBlock: .init(members: []) - ), - parent: nil - ) - self.stringDecl = parsedModule.addNominalTypeDeclaration( - StructDeclSyntax( - name: .identifier("String"), - memberBlock: .init(members: []) - ), - parent: nil - ) + var knownTypeToNominal: [KnownStandardLibraryType: SwiftNominalTypeDeclaration] = [:] + var nominalTypeDeclToKnownType: [SwiftNominalTypeDeclaration: KnownStandardLibraryType] = [:] + + // Handle all of the non-generic types at once. + for knownType in KnownStandardLibraryType.allCases { + guard !knownType.isGeneric else { + continue + } + + Self.recordKnownNonGenericStruct( + knownType, + knownTypeToNominal: &knownTypeToNominal, + nominalTypeDeclToKnownType: &nominalTypeDeclToKnownType, + parsedModule: &parsedModule + ) + } + + self.knownTypeToNominal = knownTypeToNominal + self.nominalTypeDeclToKnownType = nominalTypeDeclToKnownType + } + + subscript(knownType: KnownStandardLibraryType) -> SwiftNominalTypeDeclaration { + knownTypeToNominal[knownType]! + } + + subscript(nominalType: SwiftNominalTypeDeclaration) -> KnownStandardLibraryType? { + nominalTypeDeclToKnownType[nominalType] } } diff --git a/Tests/JExtractSwiftTests/Asserts/LoweringAssertions.swift b/Tests/JExtractSwiftTests/Asserts/LoweringAssertions.swift index b5304b71..3be4931c 100644 --- a/Tests/JExtractSwiftTests/Asserts/LoweringAssertions.swift +++ b/Tests/JExtractSwiftTests/Asserts/LoweringAssertions.swift @@ -25,6 +25,7 @@ func assertLoweredFunction( sourceFile: SourceFileSyntax? = nil, enclosingType: TypeSyntax? = nil, expectedCDecl: DeclSyntax, + expectedCFunction: String, fileID: String = #fileID, filePath: String = #filePath, line: Int = #line, @@ -57,4 +58,18 @@ func assertLoweredFunction( column: column ) ) + + let cFunction = translator.cdeclToCFunctionLowering( + loweredFunction.cdecl, + cName: "c_\(inputFunction.name.text)" + ) + #expect( + cFunction.description == expectedCFunction, + sourceLocation: Testing.SourceLocation( + fileID: fileID, + filePath: filePath, + line: line, + column: column + ) + ) } diff --git a/Tests/JExtractSwiftTests/FunctionLoweringTests.swift b/Tests/JExtractSwiftTests/FunctionLoweringTests.swift index 08187914..e929a5fa 100644 --- a/Tests/JExtractSwiftTests/FunctionLoweringTests.swift +++ b/Tests/JExtractSwiftTests/FunctionLoweringTests.swift @@ -29,7 +29,8 @@ final class FunctionLoweringTests { func c_f(_ x: Int, _ y: Float, _ z_pointer: UnsafeRawPointer, _ z_count: Int) { f(x: x, y: y, z: UnsafeBufferPointer(start: z_pointer.assumingMemoryBound(to: Bool.self), count: z_count)) } - """ + """, + expectedCFunction: "void c_f(ptrdiff_t x, float y, void const* z_pointer, ptrdiff_t z_count)" ) } @@ -43,7 +44,8 @@ final class FunctionLoweringTests { func c_f(_ t_0: Int, _ t_1_0: Float, _ t_1_1: Double, _ z_pointer: UnsafeRawPointer) -> Int { return f(t: (t_0, (t_1_0, t_1_1)), z: z_pointer.assumingMemoryBound(to: Int.self)) } - """ + """, + expectedCFunction: "ptrdiff_t c_f(ptrdiff_t t_0, float t_1_0, double t_1_1, void const* z_pointer)" ) } @@ -60,9 +62,11 @@ final class FunctionLoweringTests { func c_shift(_ point: UnsafeMutableRawPointer, _ delta_0: Double, _ delta_1: Double) { shift(point: &point.assumingMemoryBound(to: Point.self).pointee, by: (delta_0, delta_1)) } - """ + """, + expectedCFunction: "void c_shift(void* point, double delta_0, double delta_1)" ) } + @Test("Lowering methods") func loweringMethods() throws { try assertLoweredFunction(""" @@ -77,7 +81,8 @@ final class FunctionLoweringTests { func c_shifted(_ self: UnsafeRawPointer, _ delta_0: Double, _ delta_1: Double, _ _result: UnsafeMutableRawPointer) { _result.assumingMemoryBound(to: Point.self).pointee = self.assumingMemoryBound(to: Point.self).pointee.shifted(by: (delta_0, delta_1)) } - """ + """, + expectedCFunction: "void c_shifted(void const* self, double delta_0, double delta_1, void* _result)" ) } @@ -95,7 +100,8 @@ final class FunctionLoweringTests { func c_shift(_ self: UnsafeMutableRawPointer, _ delta_0: Double, _ delta_1: Double) { self.assumingMemoryBound(to: Point.self).pointee.shift(by: (delta_0, delta_1)) } - """ + """, + expectedCFunction: "void c_shift(void* self, double delta_0, double delta_1)" ) } @@ -113,7 +119,8 @@ final class FunctionLoweringTests { func c_shift(_ self: UnsafeRawPointer, _ delta_0: Double, _ delta_1: Double) { unsafeBitCast(self, to: Point.self).shift(by: (delta_0, delta_1)) } - """ + """, + expectedCFunction: "void c_shift(void const* self, double delta_0, double delta_1)" ) } @@ -127,7 +134,8 @@ final class FunctionLoweringTests { func c_f(_ t: UnsafeRawPointer) { f(t: unsafeBitCast(t, to: Int.self)) } - """ + """, + expectedCFunction: "void c_f(void const* t)" ) } } From 169b2f0f4eacce80426fb138193fbf69518c250b Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Mon, 3 Feb 2025 12:09:22 +0100 Subject: [PATCH 223/426] Use placeholders rather than parameter names in cdecl-to-swift sequences --- ...wift2JavaTranslator+FunctionLowering.swift | 82 +++++++++++-------- 1 file changed, 46 insertions(+), 36 deletions(-) diff --git a/Sources/JExtractSwift/Swift2JavaTranslator+FunctionLowering.swift b/Sources/JExtractSwift/Swift2JavaTranslator+FunctionLowering.swift index af168139..99e8227b 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator+FunctionLowering.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator+FunctionLowering.swift @@ -44,7 +44,8 @@ extension Swift2JavaTranslator { let loweredSelf = try signature.selfParameter.map { selfParameter in try lowerParameter( selfParameter.type, - convention: selfParameter.convention, parameterName: "self" + convention: selfParameter.convention, + parameterName: selfParameter.parameterName ?? "self" ) } @@ -136,7 +137,7 @@ extension Swift2JavaTranslator { case .metatype(let instanceType): return LoweredParameters( cdeclToOriginal: .unsafeCastPointer( - .passDirectly(parameterName), + .value, swiftType: instanceType ), cdeclParameters: [ @@ -172,10 +173,10 @@ extension Swift2JavaTranslator { switch nominal.nominalTypeDecl.kind { case .actor, .class: loweringStep = - .unsafeCastPointer(.passDirectly(parameterName), swiftType: type) + .unsafeCastPointer(.value, swiftType: type) case .enum, .struct, .protocol: loweringStep = - .passIndirectly(.pointee( .typedPointer(.passDirectly(parameterName), swiftType: type))) + .passIndirectly(.pointee(.typedPointer(.value, swiftType: type))) } return LoweredParameters( @@ -226,7 +227,7 @@ extension Swift2JavaTranslator { } return LoweredParameters( - cdeclToOriginal: .passDirectly(parameterName), + cdeclToOriginal: .value, cdeclParameters: [ SwiftParameter( convention: convention, @@ -247,7 +248,7 @@ extension Swift2JavaTranslator { } return LoweredParameters( - cdeclToOriginal: .passDirectly(parameterName), + cdeclToOriginal: .value, cdeclParameters: [ SwiftParameter( convention: convention, @@ -281,30 +282,34 @@ extension Swift2JavaTranslator { var cdeclToOriginal: LoweringStep switch (requiresArgument, hasCount) { case (false, false): - cdeclToOriginal = .passDirectly(parameterName) + cdeclToOriginal = .value case (true, false): cdeclToOriginal = .typedPointer( - .passDirectly(parameterName + "_pointer"), + .explodedComponent(.value, component: "pointer"), swiftType: nominal.genericArguments![0] ) case (false, true): cdeclToOriginal = .initialize(type, arguments: [ - LabeledArgument(label: "start", argument: .passDirectly(parameterName + "_pointer")), - LabeledArgument(label: "count", argument: .passDirectly(parameterName + "_count")) + LabeledArgument(label: "start", argument: .explodedComponent(.value, component: "pointer")), + LabeledArgument(label: "count", argument: .explodedComponent(.value, component: "count")) ]) case (true, true): cdeclToOriginal = .initialize( type, arguments: [ - LabeledArgument(label: "start", - argument: .typedPointer( - .passDirectly(parameterName + "_pointer"), - swiftType: nominal.genericArguments![0])), - LabeledArgument(label: "count", - argument: .passDirectly(parameterName + "_count")) + LabeledArgument( + label: "start", + argument: .typedPointer( + .explodedComponent(.value, component: "pointer"), + swiftType: nominal.genericArguments![0]) + ), + LabeledArgument( + label: "count", + argument: .explodedComponent(.value, component: "count") + ) ] ) } @@ -393,8 +398,12 @@ extension LabeledArgument: Equatable where Element: Equatable { } /// and map them to the corresponding parameter (or result value) of the /// original function. enum LoweringStep: Equatable { - /// A direct reference to a parameter of the thunk. - case passDirectly(String) + /// The value being lowered. + case value + + /// A reference to a component in a value that has been exploded, such as + /// a tuple element or part of a buffer pointer. + indirect case explodedComponent(LoweringStep, component: String) /// Cast the pointer described by the lowering step to the given /// Swift type using `unsafeBitCast(_:to:)`. @@ -435,36 +444,39 @@ struct LoweredParameters: Equatable { extension LoweredParameters { /// Produce an expression that computes the argument for this parameter /// when calling the original function from the cdecl entrypoint. - func cdeclToOriginalArgumentExpr(isSelf: Bool)-> ExprSyntax { - cdeclToOriginal.asExprSyntax(isSelf: isSelf) + func cdeclToOriginalArgumentExpr(isSelf: Bool, value: String)-> ExprSyntax { + cdeclToOriginal.asExprSyntax(isSelf: isSelf, value: value) } } extension LoweringStep { - func asExprSyntax(isSelf: Bool) -> ExprSyntax { + func asExprSyntax(isSelf: Bool, value: String) -> ExprSyntax { switch self { - case .passDirectly(let rawArgument): - return "\(raw: rawArgument)" + case .value: + return "\(raw: value)" + + case .explodedComponent(let step, component: let component): + return step.asExprSyntax(isSelf: false, value: "\(value)_\(component)") case .unsafeCastPointer(let step, swiftType: let swiftType): - let untypedExpr = step.asExprSyntax(isSelf: false) + let untypedExpr = step.asExprSyntax(isSelf: false, value: value) return "unsafeBitCast(\(untypedExpr), to: \(swiftType.metatypeReferenceExprSyntax))" case .typedPointer(let step, swiftType: let type): - let untypedExpr = step.asExprSyntax(isSelf: isSelf) + let untypedExpr = step.asExprSyntax(isSelf: isSelf, value: value) return "\(untypedExpr).assumingMemoryBound(to: \(type.metatypeReferenceExprSyntax))" case .pointee(let step): - let untypedExpr = step.asExprSyntax(isSelf: isSelf) + let untypedExpr = step.asExprSyntax(isSelf: isSelf, value: value) return "\(untypedExpr).pointee" case .passIndirectly(let step): - let innerExpr = step.asExprSyntax(isSelf: false) + let innerExpr = step.asExprSyntax(isSelf: false, value: value) return isSelf ? innerExpr : "&\(innerExpr)" case .initialize(let type, arguments: let arguments): let renderedArguments: [String] = arguments.map { labeledArgument in - let renderedArg = labeledArgument.argument.asExprSyntax(isSelf: false) + let renderedArg = labeledArgument.argument.asExprSyntax(isSelf: false, value: value) if let argmentLabel = labeledArgument.label { return "\(argmentLabel): \(renderedArg.description)" } else { @@ -478,8 +490,8 @@ extension LoweringStep { return "\(raw: type.description)(\(raw: renderedArgumentList))" case .tuplify(let elements): - let renderedElements: [String] = elements.map { element in - element.asExprSyntax(isSelf: false).description + let renderedElements: [String] = elements.enumerated().map { (index, element) in + element.asExprSyntax(isSelf: false, value: "\(value)_\(index)").description } // FIXME: Should be able to use structured initializers here instead @@ -520,8 +532,8 @@ extension LoweredFunctionSignature { // Lower "self", if there is one. let parametersToLower: ArraySlice let cdeclToOriginalSelf: ExprSyntax? - if original.selfParameter != nil { - cdeclToOriginalSelf = parameters[0].cdeclToOriginalArgumentExpr(isSelf: true) + if let originalSelfParam = original.selfParameter { + cdeclToOriginalSelf = parameters[0].cdeclToOriginalArgumentExpr(isSelf: true, value: originalSelfParam.parameterName ?? "self") parametersToLower = parameters[1...] } else { cdeclToOriginalSelf = nil @@ -529,10 +541,8 @@ extension LoweredFunctionSignature { } // Lower the remaining arguments. - // FIXME: Should be able to use structured initializers here instead - // of splatting out text. let cdeclToOriginalArguments = zip(parametersToLower, original.parameters).map { lowering, originalParam in - let cdeclToOriginalArg = lowering.cdeclToOriginalArgumentExpr(isSelf: false) + let cdeclToOriginalArg = lowering.cdeclToOriginalArgumentExpr(isSelf: false, value: originalParam.parameterName ?? "FIXME") if let argumentLabel = originalParam.argumentLabel { return "\(argumentLabel): \(cdeclToOriginalArg.description)" } else { @@ -559,7 +569,7 @@ extension LoweredFunctionSignature { // into a loweredCDecl.body = """ { - \(result.cdeclToOriginalArgumentExpr(isSelf: true)) = \(callExpression) + \(result.cdeclToOriginalArgumentExpr(isSelf: true, value: "_result")) = \(callExpression) } """ } else { From aff35dd06844238197e69f2388c2a0a0155366ca Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Mon, 3 Feb 2025 12:20:14 +0100 Subject: [PATCH 224/426] Move "self" parameter to the end of the @_cdecl thunk This matches what we're doing elsewhere, and also the way that the Swift calling convention is lowered to LLVM IR by the compiler. --- ...wift2JavaTranslator+FunctionLowering.swift | 32 ++++++++++--------- .../FunctionLoweringTests.swift | 12 +++---- 2 files changed, 23 insertions(+), 21 deletions(-) diff --git a/Sources/JExtractSwift/Swift2JavaTranslator+FunctionLowering.swift b/Sources/JExtractSwift/Swift2JavaTranslator+FunctionLowering.swift index 99e8227b..6375b92f 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator+FunctionLowering.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator+FunctionLowering.swift @@ -41,14 +41,6 @@ extension Swift2JavaTranslator { _ signature: SwiftFunctionSignature ) throws -> LoweredFunctionSignature { // Lower all of the parameters. - let loweredSelf = try signature.selfParameter.map { selfParameter in - try lowerParameter( - selfParameter.type, - convention: selfParameter.convention, - parameterName: selfParameter.parameterName ?? "self" - ) - } - let loweredParameters = try signature.parameters.enumerated().map { (index, param) in try lowerParameter( param.type, @@ -83,13 +75,17 @@ extension Swift2JavaTranslator { indirectResult = true } + let loweredSelf = try signature.selfParameter.map { selfParameter in + try lowerParameter( + selfParameter.type, + convention: selfParameter.convention, + parameterName: selfParameter.parameterName ?? "self" + ) + } + // Collect all of the lowered parameters for the @_cdecl function. var allLoweredParameters: [LoweredParameters] = [] var cdeclLoweredParameters: [SwiftParameter] = [] - if let loweredSelf { - allLoweredParameters.append(loweredSelf) - cdeclLoweredParameters.append(contentsOf: loweredSelf.cdeclParameters) - } allLoweredParameters.append(contentsOf: loweredParameters) cdeclLoweredParameters.append( contentsOf: loweredParameters.flatMap { $0.cdeclParameters } @@ -110,6 +106,11 @@ extension Swift2JavaTranslator { fatalError("Improper lowering of result for \(signature)") } + if let loweredSelf { + allLoweredParameters.append(loweredSelf) + cdeclLoweredParameters.append(contentsOf: loweredSelf.cdeclParameters) + } + let cdeclSignature = SwiftFunctionSignature( isStaticOrClass: false, selfParameter: nil, @@ -532,9 +533,10 @@ extension LoweredFunctionSignature { // Lower "self", if there is one. let parametersToLower: ArraySlice let cdeclToOriginalSelf: ExprSyntax? - if let originalSelfParam = original.selfParameter { - cdeclToOriginalSelf = parameters[0].cdeclToOriginalArgumentExpr(isSelf: true, value: originalSelfParam.parameterName ?? "self") - parametersToLower = parameters[1...] + if let originalSelfParam = original.selfParameter, + let selfParameter = parameters.last { + cdeclToOriginalSelf = selfParameter.cdeclToOriginalArgumentExpr(isSelf: true, value: originalSelfParam.parameterName ?? "self") + parametersToLower = parameters.dropLast() } else { cdeclToOriginalSelf = nil parametersToLower = parameters[...] diff --git a/Tests/JExtractSwiftTests/FunctionLoweringTests.swift b/Tests/JExtractSwiftTests/FunctionLoweringTests.swift index e929a5fa..0c51ccf6 100644 --- a/Tests/JExtractSwiftTests/FunctionLoweringTests.swift +++ b/Tests/JExtractSwiftTests/FunctionLoweringTests.swift @@ -78,11 +78,11 @@ final class FunctionLoweringTests { enclosingType: "Point", expectedCDecl: """ @_cdecl("c_shifted") - func c_shifted(_ self: UnsafeRawPointer, _ delta_0: Double, _ delta_1: Double, _ _result: UnsafeMutableRawPointer) { + func c_shifted(_ delta_0: Double, _ delta_1: Double, _ _result: UnsafeMutableRawPointer, _ self: UnsafeRawPointer) { _result.assumingMemoryBound(to: Point.self).pointee = self.assumingMemoryBound(to: Point.self).pointee.shifted(by: (delta_0, delta_1)) } """, - expectedCFunction: "void c_shifted(void const* self, double delta_0, double delta_1, void* _result)" + expectedCFunction: "void c_shifted(double delta_0, double delta_1, void* _result, void const* self)" ) } @@ -97,11 +97,11 @@ final class FunctionLoweringTests { enclosingType: "Point", expectedCDecl: """ @_cdecl("c_shift") - func c_shift(_ self: UnsafeMutableRawPointer, _ delta_0: Double, _ delta_1: Double) { + func c_shift(_ delta_0: Double, _ delta_1: Double, _ self: UnsafeMutableRawPointer) { self.assumingMemoryBound(to: Point.self).pointee.shift(by: (delta_0, delta_1)) } """, - expectedCFunction: "void c_shift(void* self, double delta_0, double delta_1)" + expectedCFunction: "void c_shift(double delta_0, double delta_1, void* self)" ) } @@ -116,11 +116,11 @@ final class FunctionLoweringTests { enclosingType: "Point", expectedCDecl: """ @_cdecl("c_shift") - func c_shift(_ self: UnsafeRawPointer, _ delta_0: Double, _ delta_1: Double) { + func c_shift(_ delta_0: Double, _ delta_1: Double, _ self: UnsafeRawPointer) { unsafeBitCast(self, to: Point.self).shift(by: (delta_0, delta_1)) } """, - expectedCFunction: "void c_shift(void const* self, double delta_0, double delta_1)" + expectedCFunction: "void c_shift(double delta_0, double delta_1, void const* self)" ) } From 1873da5476c5627576719d1459cf7e10da824dfa Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Mon, 3 Feb 2025 12:27:47 +0100 Subject: [PATCH 225/426] Factor out the lowering step as a more general "ConversionStep" --- Sources/JExtractSwift/ConversionStep.swift | 106 ++++++++++++++++ ...wift2JavaTranslator+FunctionLowering.swift | 120 +++--------------- 2 files changed, 121 insertions(+), 105 deletions(-) create mode 100644 Sources/JExtractSwift/ConversionStep.swift diff --git a/Sources/JExtractSwift/ConversionStep.swift b/Sources/JExtractSwift/ConversionStep.swift new file mode 100644 index 00000000..cde2dc4f --- /dev/null +++ b/Sources/JExtractSwift/ConversionStep.swift @@ -0,0 +1,106 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import SwiftSyntax + +/// Describes the transformation needed to take the parameters of a thunk +/// and map them to the corresponding parameter (or result value) of the +/// original function. +enum ConversionStep: Equatable { + /// The value being lowered. + case placeholder + + /// A reference to a component in a value that has been exploded, such as + /// a tuple element or part of a buffer pointer. + indirect case explodedComponent(ConversionStep, component: String) + + /// Cast the pointer described by the lowering step to the given + /// Swift type using `unsafeBitCast(_:to:)`. + indirect case unsafeCastPointer(ConversionStep, swiftType: SwiftType) + + /// Assume at the untyped pointer described by the lowering step to the + /// given type, using `assumingMemoryBound(to:).` + indirect case typedPointer(ConversionStep, swiftType: SwiftType) + + /// The thing to which the pointer typed, which is the `pointee` property + /// of the `Unsafe(Mutable)Pointer` types in Swift. + indirect case pointee(ConversionStep) + + /// Pass this value indirectly, via & for explicit `inout` parameters. + indirect case passIndirectly(ConversionStep) + + /// Initialize a value of the given Swift type with the set of labeled + /// arguments. + case initialize(SwiftType, arguments: [LabeledArgument]) + + /// Produce a tuple with the given elements. + /// + /// This is used for exploding Swift tuple arguments into multiple + /// elements, recursively. Note that this always produces unlabeled + /// tuples, which Swift will convert to the labeled tuple form. + case tuplify([ConversionStep]) + + /// Convert the conversion step into an expression with the given + /// value as the placeholder value in the expression. + func asExprSyntax(isSelf: Bool, placeholder: String) -> ExprSyntax { + switch self { + case .placeholder: + return "\(raw: placeholder)" + + case .explodedComponent(let step, component: let component): + return step.asExprSyntax(isSelf: false, placeholder: "\(placeholder)_\(component)") + + case .unsafeCastPointer(let step, swiftType: let swiftType): + let untypedExpr = step.asExprSyntax(isSelf: false, placeholder: placeholder) + return "unsafeBitCast(\(untypedExpr), to: \(swiftType.metatypeReferenceExprSyntax))" + + case .typedPointer(let step, swiftType: let type): + let untypedExpr = step.asExprSyntax(isSelf: isSelf, placeholder: placeholder) + return "\(untypedExpr).assumingMemoryBound(to: \(type.metatypeReferenceExprSyntax))" + + case .pointee(let step): + let untypedExpr = step.asExprSyntax(isSelf: isSelf, placeholder: placeholder) + return "\(untypedExpr).pointee" + + case .passIndirectly(let step): + let innerExpr = step.asExprSyntax(isSelf: false, placeholder: placeholder) + return isSelf ? innerExpr : "&\(innerExpr)" + + case .initialize(let type, arguments: let arguments): + let renderedArguments: [String] = arguments.map { labeledArgument in + let renderedArg = labeledArgument.argument.asExprSyntax(isSelf: false, placeholder: placeholder) + if let argmentLabel = labeledArgument.label { + return "\(argmentLabel): \(renderedArg.description)" + } else { + return renderedArg.description + } + } + + // FIXME: Should be able to use structured initializers here instead + // of splatting out text. + let renderedArgumentList = renderedArguments.joined(separator: ", ") + return "\(raw: type.description)(\(raw: renderedArgumentList))" + + case .tuplify(let elements): + let renderedElements: [String] = elements.enumerated().map { (index, element) in + element.asExprSyntax(isSelf: false, placeholder: "\(placeholder)_\(index)").description + } + + // FIXME: Should be able to use structured initializers here instead + // of splatting out text. + let renderedElementList = renderedElements.joined(separator: ", ") + return "(\(raw: renderedElementList))" + } + } +} diff --git a/Sources/JExtractSwift/Swift2JavaTranslator+FunctionLowering.swift b/Sources/JExtractSwift/Swift2JavaTranslator+FunctionLowering.swift index 6375b92f..8143e3cd 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator+FunctionLowering.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator+FunctionLowering.swift @@ -138,7 +138,7 @@ extension Swift2JavaTranslator { case .metatype(let instanceType): return LoweredParameters( cdeclToOriginal: .unsafeCastPointer( - .value, + .placeholder, swiftType: instanceType ), cdeclParameters: [ @@ -170,14 +170,14 @@ extension Swift2JavaTranslator { } let mutable = (convention == .inout) - let loweringStep: LoweringStep + let loweringStep: ConversionStep switch nominal.nominalTypeDecl.kind { case .actor, .class: loweringStep = - .unsafeCastPointer(.value, swiftType: type) + .unsafeCastPointer(.placeholder, swiftType: type) case .enum, .struct, .protocol: loweringStep = - .passIndirectly(.pointee(.typedPointer(.value, swiftType: type))) + .passIndirectly(.pointee(.typedPointer(.placeholder, swiftType: type))) } return LoweredParameters( @@ -228,7 +228,7 @@ extension Swift2JavaTranslator { } return LoweredParameters( - cdeclToOriginal: .value, + cdeclToOriginal: .placeholder, cdeclParameters: [ SwiftParameter( convention: convention, @@ -249,7 +249,7 @@ extension Swift2JavaTranslator { } return LoweredParameters( - cdeclToOriginal: .value, + cdeclToOriginal: .placeholder, cdeclParameters: [ SwiftParameter( convention: convention, @@ -280,21 +280,21 @@ extension Swift2JavaTranslator { let cdeclPointerType = mutable ? swiftStdlibTypes[.unsafeMutableRawPointer] : swiftStdlibTypes[.unsafeRawPointer] - var cdeclToOriginal: LoweringStep + var cdeclToOriginal: ConversionStep switch (requiresArgument, hasCount) { case (false, false): - cdeclToOriginal = .value + cdeclToOriginal = .placeholder case (true, false): cdeclToOriginal = .typedPointer( - .explodedComponent(.value, component: "pointer"), + .explodedComponent(.placeholder, component: "pointer"), swiftType: nominal.genericArguments![0] ) case (false, true): cdeclToOriginal = .initialize(type, arguments: [ - LabeledArgument(label: "start", argument: .explodedComponent(.value, component: "pointer")), - LabeledArgument(label: "count", argument: .explodedComponent(.value, component: "count")) + LabeledArgument(label: "start", argument: .explodedComponent(.placeholder, component: "pointer")), + LabeledArgument(label: "count", argument: .explodedComponent(.placeholder, component: "count")) ]) case (true, true): @@ -304,12 +304,12 @@ extension Swift2JavaTranslator { LabeledArgument( label: "start", argument: .typedPointer( - .explodedComponent(.value, component: "pointer"), + .explodedComponent(.placeholder, component: "pointer"), swiftType: nominal.genericArguments![0]) ), LabeledArgument( label: "count", - argument: .explodedComponent(.value, component: "count") + argument: .explodedComponent(.placeholder, component: "count") ) ] ) @@ -395,48 +395,11 @@ struct LabeledArgument { extension LabeledArgument: Equatable where Element: Equatable { } -/// Describes the transformation needed to take the parameters of a thunk -/// and map them to the corresponding parameter (or result value) of the -/// original function. -enum LoweringStep: Equatable { - /// The value being lowered. - case value - - /// A reference to a component in a value that has been exploded, such as - /// a tuple element or part of a buffer pointer. - indirect case explodedComponent(LoweringStep, component: String) - - /// Cast the pointer described by the lowering step to the given - /// Swift type using `unsafeBitCast(_:to:)`. - indirect case unsafeCastPointer(LoweringStep, swiftType: SwiftType) - - /// Assume at the untyped pointer described by the lowering step to the - /// given type, using `assumingMemoryBound(to:).` - indirect case typedPointer(LoweringStep, swiftType: SwiftType) - - /// The thing to which the pointer typed, which is the `pointee` property - /// of the `Unsafe(Mutable)Pointer` types in Swift. - indirect case pointee(LoweringStep) - - /// Pass this value indirectly, via & for explicit `inout` parameters. - indirect case passIndirectly(LoweringStep) - - /// Initialize a value of the given Swift type with the set of labeled - /// arguments. - case initialize(SwiftType, arguments: [LabeledArgument]) - - /// Produce a tuple with the given elements. - /// - /// This is used for exploding Swift tuple arguments into multiple - /// elements, recursively. Note that this always produces unlabeled - /// tuples, which Swift will convert to the labeled tuple form. - case tuplify([LoweringStep]) -} struct LoweredParameters: Equatable { /// The steps needed to get from the @_cdecl parameters to the original function /// parameter. - var cdeclToOriginal: LoweringStep + var cdeclToOriginal: ConversionStep /// The lowering of the parameters at the C level in Swift. var cdeclParameters: [SwiftParameter] @@ -446,60 +409,7 @@ extension LoweredParameters { /// Produce an expression that computes the argument for this parameter /// when calling the original function from the cdecl entrypoint. func cdeclToOriginalArgumentExpr(isSelf: Bool, value: String)-> ExprSyntax { - cdeclToOriginal.asExprSyntax(isSelf: isSelf, value: value) - } -} - -extension LoweringStep { - func asExprSyntax(isSelf: Bool, value: String) -> ExprSyntax { - switch self { - case .value: - return "\(raw: value)" - - case .explodedComponent(let step, component: let component): - return step.asExprSyntax(isSelf: false, value: "\(value)_\(component)") - - case .unsafeCastPointer(let step, swiftType: let swiftType): - let untypedExpr = step.asExprSyntax(isSelf: false, value: value) - return "unsafeBitCast(\(untypedExpr), to: \(swiftType.metatypeReferenceExprSyntax))" - - case .typedPointer(let step, swiftType: let type): - let untypedExpr = step.asExprSyntax(isSelf: isSelf, value: value) - return "\(untypedExpr).assumingMemoryBound(to: \(type.metatypeReferenceExprSyntax))" - - case .pointee(let step): - let untypedExpr = step.asExprSyntax(isSelf: isSelf, value: value) - return "\(untypedExpr).pointee" - - case .passIndirectly(let step): - let innerExpr = step.asExprSyntax(isSelf: false, value: value) - return isSelf ? innerExpr : "&\(innerExpr)" - - case .initialize(let type, arguments: let arguments): - let renderedArguments: [String] = arguments.map { labeledArgument in - let renderedArg = labeledArgument.argument.asExprSyntax(isSelf: false, value: value) - if let argmentLabel = labeledArgument.label { - return "\(argmentLabel): \(renderedArg.description)" - } else { - return renderedArg.description - } - } - - // FIXME: Should be able to use structured initializers here instead - // of splatting out text. - let renderedArgumentList = renderedArguments.joined(separator: ", ") - return "\(raw: type.description)(\(raw: renderedArgumentList))" - - case .tuplify(let elements): - let renderedElements: [String] = elements.enumerated().map { (index, element) in - element.asExprSyntax(isSelf: false, value: "\(value)_\(index)").description - } - - // FIXME: Should be able to use structured initializers here instead - // of splatting out text. - let renderedElementList = renderedElements.joined(separator: ", ") - return "(\(raw: renderedElementList))" - } + cdeclToOriginal.asExprSyntax(isSelf: isSelf, placeholder: value) } } From 4c156028b1cbbc2352b02506b9604255591ff933 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Mon, 3 Feb 2025 17:23:15 +0100 Subject: [PATCH 226/426] Separate Swift-to-cdecl parameter lowering from the conversion sequences Make the operation to convert from cdecl parameter(s) into a Swift parameter a standalone operation, separate from the lowering of Swift parameters to cdecl parameters. They need to be synchronized, but they are not the same. --- .../CDeclLowering/CDeclConversions.swift | 90 ++++++ .../CRepresentation.swift} | 62 +++- ...wift2JavaTranslator+FunctionLowering.swift | 295 +++++------------- .../SwiftNominalTypeDeclaration.swift | 16 + .../SwiftStandardLibraryTypes.swift | 72 ++--- 5 files changed, 270 insertions(+), 265 deletions(-) create mode 100644 Sources/JExtractSwift/CDeclLowering/CDeclConversions.swift rename Sources/JExtractSwift/{SwiftTypes/SwiftStandardLibraryTypes+CLowering.swift => CDeclLowering/CRepresentation.swift} (63%) rename Sources/JExtractSwift/{ => CDeclLowering}/Swift2JavaTranslator+FunctionLowering.swift (55%) diff --git a/Sources/JExtractSwift/CDeclLowering/CDeclConversions.swift b/Sources/JExtractSwift/CDeclLowering/CDeclConversions.swift new file mode 100644 index 00000000..08816139 --- /dev/null +++ b/Sources/JExtractSwift/CDeclLowering/CDeclConversions.swift @@ -0,0 +1,90 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +extension ConversionStep { + /// Produce a conversion that takes in a value (or set of values) that + /// would be available in a @_cdecl function to represent the given Swift + /// type, and convert that to an instance of the Swift type. + init(cdeclToSwift swiftType: SwiftType) throws { + switch swiftType { + case .function, .optional: + throw LoweringError.unhandledType(swiftType) + + case .metatype(let instanceType): + self = .unsafeCastPointer( + .placeholder, + swiftType: instanceType + ) + + case .nominal(let nominal): + if let knownType = nominal.nominalTypeDecl.knownStandardLibraryType { + // Swift types that map to primitive types in C. These can be passed + // through directly. + if knownType.primitiveCType != nil { + self = .placeholder + return + } + + // Typed pointers + if let firstGenericArgument = nominal.genericArguments?.first { + switch knownType { + case .unsafePointer, .unsafeMutablePointer: + self = .typedPointer( + .explodedComponent(.placeholder, component: "pointer"), + swiftType: firstGenericArgument + ) + return + + case .unsafeBufferPointer, .unsafeMutableBufferPointer: + self = .initialize( + swiftType, + arguments: [ + LabeledArgument( + label: "start", + argument: .typedPointer( + .explodedComponent(.placeholder, component: "pointer"), + swiftType: firstGenericArgument) + ), + LabeledArgument( + label: "count", + argument: .explodedComponent(.placeholder, component: "count") + ) + ] + ) + return + + default: + break + } + } + } + + // Arbitrary nominal types. + switch nominal.nominalTypeDecl.kind { + case .actor, .class: + // For actor and class, we pass around the pointer directly. + self = .unsafeCastPointer(.placeholder, swiftType: swiftType) + case .enum, .struct, .protocol: + // For enums, structs, and protocol types, we pass around the + // values indirectly. + self = .passIndirectly( + .pointee(.typedPointer(.placeholder, swiftType: swiftType)) + ) + } + + case .tuple(let elements): + self = .tuplify(try elements.map { try ConversionStep(cdeclToSwift: $0) }) + } + } +} diff --git a/Sources/JExtractSwift/SwiftTypes/SwiftStandardLibraryTypes+CLowering.swift b/Sources/JExtractSwift/CDeclLowering/CRepresentation.swift similarity index 63% rename from Sources/JExtractSwift/SwiftTypes/SwiftStandardLibraryTypes+CLowering.swift rename to Sources/JExtractSwift/CDeclLowering/CRepresentation.swift index 3913f9cc..08e10de1 100644 --- a/Sources/JExtractSwift/SwiftTypes/SwiftStandardLibraryTypes+CLowering.swift +++ b/Sources/JExtractSwift/CDeclLowering/CRepresentation.swift @@ -12,17 +12,19 @@ // //===----------------------------------------------------------------------===// -extension SwiftStandardLibraryTypes { +extension CType { /// Lower the given Swift type down to a its corresponding C type. /// /// This operation only supports the subset of Swift types that are /// representable in a Swift `@_cdecl` function. If lowering an arbitrary /// Swift function, first go through Swift -> cdecl lowering. - func cdeclToCLowering(_ swiftType: SwiftType) throws -> CType { - switch swiftType { + init(cdeclType: SwiftType) throws { + switch cdeclType { case .nominal(let nominalType): - if let knownType = self[nominalType.nominalTypeDecl] { - return try knownType.loweredCType() + if let knownType = nominalType.nominalTypeDecl.knownStandardLibraryType, + let primitiveCType = knownType.primitiveCType { + self = primitiveCType + return } throw CDeclToCLoweringError.invalidNominalType(nominalType.nominalTypeDecl) @@ -33,12 +35,12 @@ extension SwiftStandardLibraryTypes { throw CDeclToCLoweringError.invalidFunctionConvention(functionType) case .c: - let resultType = try cdeclToCLowering(functionType.resultType) + let resultType = try CType(cdeclType: functionType.resultType) let parameterTypes = try functionType.parameters.map { param in - try cdeclToCLowering(param.type) + try CType(cdeclType: param.type) } - return .function( + self = .function( resultType: resultType, parameters: parameterTypes, variadic: false @@ -46,16 +48,46 @@ extension SwiftStandardLibraryTypes { } case .tuple([]): - return .void + self = .void case .metatype, .optional, .tuple: - throw CDeclToCLoweringError.invalidCDeclType(swiftType) + throw CDeclToCLoweringError.invalidCDeclType(cdeclType) } } } +extension CFunction { + /// Produce a C function that represents the given @_cdecl Swift function. + init(cdeclSignature: SwiftFunctionSignature, cName: String) throws { + assert(cdeclSignature.selfParameter == nil) + + let cResultType = try CType(cdeclType: cdeclSignature.result.type) + let cParameters = try cdeclSignature.parameters.map { parameter in + CParameter( + name: parameter.parameterName, + type: try CType(cdeclType: parameter.type).parameterDecay + ) + } + + self = CFunction( + resultType: cResultType, + name: cName, + parameters: cParameters, + isVariadic: false + ) + } +} + +enum CDeclToCLoweringError: Error { + case invalidCDeclType(SwiftType) + case invalidNominalType(SwiftNominalTypeDeclaration) + case invalidFunctionConvention(SwiftFunctionType) +} + extension KnownStandardLibraryType { - func loweredCType() throws -> CType { + /// Determine the primitive C type that corresponds to this C standard + /// library type, if there is one. + var primitiveCType: CType? { switch self { case .bool: .integral(.bool) case .int: .integral(.ptrdiff_t) @@ -74,12 +106,8 @@ extension KnownStandardLibraryType { case .unsafeRawPointer: .pointer( .qualified(const: true, volatile: false, type: .void) ) + case .unsafePointer, .unsafeMutablePointer, .unsafeBufferPointer, .unsafeMutableBufferPointer: + nil } } } -enum CDeclToCLoweringError: Error { - case invalidCDeclType(SwiftType) - case invalidNominalType(SwiftNominalTypeDeclaration) - case invalidFunctionConvention(SwiftFunctionType) -} - diff --git a/Sources/JExtractSwift/Swift2JavaTranslator+FunctionLowering.swift b/Sources/JExtractSwift/CDeclLowering/Swift2JavaTranslator+FunctionLowering.swift similarity index 55% rename from Sources/JExtractSwift/Swift2JavaTranslator+FunctionLowering.swift rename to Sources/JExtractSwift/CDeclLowering/Swift2JavaTranslator+FunctionLowering.swift index 8143e3cd..ab89c0b2 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator+FunctionLowering.swift +++ b/Sources/JExtractSwift/CDeclLowering/Swift2JavaTranslator+FunctionLowering.swift @@ -135,12 +135,8 @@ extension Swift2JavaTranslator { case .function, .optional: throw LoweringError.unhandledType(type) - case .metatype(let instanceType): + case .metatype: return LoweredParameters( - cdeclToOriginal: .unsafeCastPointer( - .placeholder, - swiftType: instanceType - ), cdeclParameters: [ SwiftParameter( convention: .byValue, @@ -156,39 +152,80 @@ extension Swift2JavaTranslator { case .nominal(let nominal): // Types from the Swift standard library that we know about. - if nominal.nominalTypeDecl.moduleName == "Swift", - nominal.nominalTypeDecl.parent == nil { - // Primitive types - if let loweredPrimitive = try lowerParameterPrimitive(nominal, convention: convention, parameterName: parameterName) { - return loweredPrimitive + if let knownType = nominal.nominalTypeDecl.knownStandardLibraryType, + convention != .inout { + // Swift types that map to primitive types in C. These can be passed + // through directly. + if knownType.primitiveCType != nil { + return LoweredParameters( + cdeclParameters: [ + SwiftParameter( + convention: convention, + parameterName: parameterName, + type: type, + isPrimitive: true + ) + ] + ) } - // Swift pointer types. - if let loweredPointers = try lowerParameterPointers(nominal, convention: convention, parameterName: parameterName) { - return loweredPointers + // Typed pointers are mapped down to their raw forms in cdecl entry + // points. These can be passed through directly. + if knownType == .unsafePointer || knownType == .unsafeMutablePointer { + let isMutable = knownType == .unsafeMutablePointer + let cdeclPointerType = isMutable + ? swiftStdlibTypes[.unsafeMutableRawPointer] + : swiftStdlibTypes[.unsafeRawPointer] + return LoweredParameters( + cdeclParameters: [ + SwiftParameter( + convention: convention, + parameterName: parameterName + "_pointer", + type: SwiftType.nominal( + SwiftNominalType(nominalTypeDecl: cdeclPointerType) + ) + ) + ] + ) } - } - let mutable = (convention == .inout) - let loweringStep: ConversionStep - switch nominal.nominalTypeDecl.kind { - case .actor, .class: - loweringStep = - .unsafeCastPointer(.placeholder, swiftType: type) - case .enum, .struct, .protocol: - loweringStep = - .passIndirectly(.pointee(.typedPointer(.placeholder, swiftType: type))) + // Typed buffer pointers are mapped down to a (pointer, count) pair + // so those parts can be passed through directly. + if knownType == .unsafeBufferPointer || knownType == .unsafeMutableBufferPointer { + let isMutable = knownType == .unsafeMutableBufferPointer + let cdeclPointerType = isMutable + ? swiftStdlibTypes[.unsafeMutableRawPointer] + : swiftStdlibTypes[.unsafeRawPointer] + return LoweredParameters( + cdeclParameters: [ + SwiftParameter( + convention: convention, + parameterName: parameterName + "_pointer", + type: SwiftType.nominal( + SwiftNominalType(nominalTypeDecl: cdeclPointerType) + ) + ), + SwiftParameter( + convention: convention, + parameterName: parameterName + "_count", + type: SwiftType.nominal( + SwiftNominalType(nominalTypeDecl: swiftStdlibTypes[.int]) + ) + ) + ] + ) + } } + let isMutable = (convention == .inout) return LoweredParameters( - cdeclToOriginal: loweringStep, cdeclParameters: [ SwiftParameter( convention: .byValue, parameterName: parameterName, type: .nominal( SwiftNominalType( - nominalTypeDecl: mutable + nominalTypeDecl: isMutable ? swiftStdlibTypes[.unsafeMutableRawPointer] : swiftStdlibTypes[.unsafeRawPointer] ) @@ -203,163 +240,11 @@ extension Swift2JavaTranslator { try lowerParameter(element, convention: convention, parameterName: name) } return LoweredParameters( - cdeclToOriginal: .tuplify(loweredElements.map { $0.cdeclToOriginal }), cdeclParameters: loweredElements.flatMap { $0.cdeclParameters } ) } } - func lowerParameterPrimitive( - _ nominal: SwiftNominalType, - convention: SwiftParameterConvention, - parameterName: String - ) throws -> LoweredParameters? { - let nominalName = nominal.nominalTypeDecl.name - let type = SwiftType.nominal(nominal) - - // Swift types that map directly to Java primitive types. - if let primitiveType = JavaType(swiftTypeName: nominalName) { - // FIXME: Should be using C types here, not Java types. - _ = primitiveType - - // We cannot handle inout on primitive types. - if convention == .inout { - throw LoweringError.inoutNotSupported(type) - } - - return LoweredParameters( - cdeclToOriginal: .placeholder, - cdeclParameters: [ - SwiftParameter( - convention: convention, - parameterName: parameterName, - type: type, - isPrimitive: true - ) - ] - ) - } - - // The Swift "Int" type, which maps to whatever the pointer-sized primitive - // integer type is in Java (int for 32-bit, long for 64-bit). - if nominalName == "Int" { - // We cannot handle inout on primitive types. - if convention == .inout { - throw LoweringError.inoutNotSupported(type) - } - - return LoweredParameters( - cdeclToOriginal: .placeholder, - cdeclParameters: [ - SwiftParameter( - convention: convention, - parameterName: parameterName, - type: type, - isPrimitive: true - ) - ] - ) - } - - return nil - } - - func lowerParameterPointers( - _ nominal: SwiftNominalType, - convention: SwiftParameterConvention, - parameterName: String - ) throws -> LoweredParameters? { - let nominalName = nominal.nominalTypeDecl.name - let type = SwiftType.nominal(nominal) - - guard let (requiresArgument, mutable, hasCount) = nominalName.isNameOfSwiftPointerType else { - return nil - } - - // At the @_cdecl level, make everything a raw pointer. - let cdeclPointerType = mutable - ? swiftStdlibTypes[.unsafeMutableRawPointer] - : swiftStdlibTypes[.unsafeRawPointer] - var cdeclToOriginal: ConversionStep - switch (requiresArgument, hasCount) { - case (false, false): - cdeclToOriginal = .placeholder - - case (true, false): - cdeclToOriginal = .typedPointer( - .explodedComponent(.placeholder, component: "pointer"), - swiftType: nominal.genericArguments![0] - ) - - case (false, true): - cdeclToOriginal = .initialize(type, arguments: [ - LabeledArgument(label: "start", argument: .explodedComponent(.placeholder, component: "pointer")), - LabeledArgument(label: "count", argument: .explodedComponent(.placeholder, component: "count")) - ]) - - case (true, true): - cdeclToOriginal = .initialize( - type, - arguments: [ - LabeledArgument( - label: "start", - argument: .typedPointer( - .explodedComponent(.placeholder, component: "pointer"), - swiftType: nominal.genericArguments![0]) - ), - LabeledArgument( - label: "count", - argument: .explodedComponent(.placeholder, component: "count") - ) - ] - ) - } - - let lowered: [(SwiftParameter, ForeignValueLayout)] - if hasCount { - lowered = [ - ( - SwiftParameter( - convention: convention, - parameterName: parameterName + "_pointer", - type: SwiftType.nominal( - SwiftNominalType(nominalTypeDecl: cdeclPointerType) - ) - ), - .SwiftPointer - ), - ( - SwiftParameter( - convention: convention, - parameterName: parameterName + "_count", - type: SwiftType.nominal( - SwiftNominalType(nominalTypeDecl: swiftStdlibTypes[.int]) - ) - ), - .SwiftInt - ) - ] - } else { - lowered = [ - ( - SwiftParameter( - convention: convention, - parameterName: parameterName + "_pointer", - type: SwiftType.nominal( - SwiftNominalType(nominalTypeDecl: cdeclPointerType) - ) - ), - .SwiftPointer - ), - ] - } - - return LoweredParameters( - cdeclToOriginal: cdeclToOriginal, - cdeclParameters: lowered.map(\.0) - ) - } - /// Given a Swift function signature that represents a @_cdecl function, /// produce the equivalent C function with the given name. /// @@ -369,22 +254,7 @@ extension Swift2JavaTranslator { _ cdeclSignature: SwiftFunctionSignature, cName: String ) -> CFunction { - assert(cdeclSignature.selfParameter == nil) - - let cResultType = try! swiftStdlibTypes.cdeclToCLowering(cdeclSignature.result.type) - let cParameters = cdeclSignature.parameters.map { parameter in - CParameter( - name: parameter.parameterName, - type: try! swiftStdlibTypes.cdeclToCLowering(parameter.type).parameterDecay - ) - } - - return CFunction( - resultType: cResultType, - name: cName, - parameters: cParameters, - isVariadic: false - ) + return try! CFunction(cdeclSignature: cdeclSignature, cName: cName) } } @@ -397,22 +267,10 @@ extension LabeledArgument: Equatable where Element: Equatable { } struct LoweredParameters: Equatable { - /// The steps needed to get from the @_cdecl parameters to the original function - /// parameter. - var cdeclToOriginal: ConversionStep - /// The lowering of the parameters at the C level in Swift. var cdeclParameters: [SwiftParameter] } -extension LoweredParameters { - /// Produce an expression that computes the argument for this parameter - /// when calling the original function from the cdecl entrypoint. - func cdeclToOriginalArgumentExpr(isSelf: Bool, value: String)-> ExprSyntax { - cdeclToOriginal.asExprSyntax(isSelf: isSelf, placeholder: value) - } -} - enum LoweringError: Error { case inoutNotSupported(SwiftType) case unhandledType(SwiftType) @@ -443,9 +301,13 @@ extension LoweredFunctionSignature { // Lower "self", if there is one. let parametersToLower: ArraySlice let cdeclToOriginalSelf: ExprSyntax? - if let originalSelfParam = original.selfParameter, - let selfParameter = parameters.last { - cdeclToOriginalSelf = selfParameter.cdeclToOriginalArgumentExpr(isSelf: true, value: originalSelfParam.parameterName ?? "self") + if let originalSelfParam = original.selfParameter { + cdeclToOriginalSelf = try! ConversionStep( + cdeclToSwift: originalSelfParam.type + ).asExprSyntax( + isSelf: true, + placeholder: originalSelfParam.parameterName ?? "self" + ) parametersToLower = parameters.dropLast() } else { cdeclToOriginalSelf = nil @@ -453,8 +315,15 @@ extension LoweredFunctionSignature { } // Lower the remaining arguments. - let cdeclToOriginalArguments = zip(parametersToLower, original.parameters).map { lowering, originalParam in - let cdeclToOriginalArg = lowering.cdeclToOriginalArgumentExpr(isSelf: false, value: originalParam.parameterName ?? "FIXME") + let cdeclToOriginalArguments = parametersToLower.indices.map { index in + let originalParam = original.parameters[index] + let cdeclToOriginalArg = try! ConversionStep( + cdeclToSwift: originalParam.type + ).asExprSyntax( + isSelf: false, + placeholder: originalParam.parameterName ?? "_\(index)" + ) + if let argumentLabel = originalParam.argumentLabel { return "\(argumentLabel): \(cdeclToOriginalArg.description)" } else { @@ -478,10 +347,12 @@ extension LoweredFunctionSignature { """ } else if cdecl.result.type.isVoid { // Indirect return. This is a regular return in Swift that turns - // into a + // into an assignment via the indirect parameters. + // FIXME: This should actually be a swiftToCDecl conversion! + let resultConversion = try! ConversionStep(cdeclToSwift: original.result.type) loweredCDecl.body = """ { - \(result.cdeclToOriginalArgumentExpr(isSelf: true, value: "_result")) = \(callExpression) + \(resultConversion.asExprSyntax(isSelf: true, placeholder: "_result")) = \(callExpression) } """ } else { diff --git a/Sources/JExtractSwift/SwiftTypes/SwiftNominalTypeDeclaration.swift b/Sources/JExtractSwift/SwiftTypes/SwiftNominalTypeDeclaration.swift index cf017f98..53e103b0 100644 --- a/Sources/JExtractSwift/SwiftTypes/SwiftNominalTypeDeclaration.swift +++ b/Sources/JExtractSwift/SwiftTypes/SwiftNominalTypeDeclaration.swift @@ -42,6 +42,12 @@ class SwiftNominalTypeDeclaration { // TODO: Generic parameters. + /// Identify this nominal declaration as one of the known standard library + /// types, like 'Swift.Int[. + lazy var knownStandardLibraryType: KnownStandardLibraryType? = { + self.computeKnownStandardLibraryType() + }() + /// Create a nominal type declaration from the syntax node for a nominal type /// declaration. init( @@ -63,6 +69,16 @@ class SwiftNominalTypeDeclaration { default: fatalError("Not a nominal type declaration") } } + + /// Determine the known standard library type for this nominal type + /// declaration. + private func computeKnownStandardLibraryType() -> KnownStandardLibraryType? { + if parent != nil || moduleName != "Swift" { + return nil + } + + return KnownStandardLibraryType(typeNameInSwiftModule: name) + } } extension SwiftNominalTypeDeclaration: Equatable { diff --git a/Sources/JExtractSwift/SwiftTypes/SwiftStandardLibraryTypes.swift b/Sources/JExtractSwift/SwiftTypes/SwiftStandardLibraryTypes.swift index b9689e9c..77ab9530 100644 --- a/Sources/JExtractSwift/SwiftTypes/SwiftStandardLibraryTypes.swift +++ b/Sources/JExtractSwift/SwiftTypes/SwiftStandardLibraryTypes.swift @@ -14,45 +14,45 @@ import SwiftSyntax -enum KnownStandardLibraryType: Int, Hashable, CaseIterable { - case bool = 0 - case int - case uint - case int8 - case uint8 - case int16 - case uint16 - case int32 - case uint32 - case int64 - case uint64 - case float - case double - case unsafeRawPointer - case unsafeMutableRawPointer - - var typeName: String { - switch self { - case .bool: return "Bool" - case .int: return "Int" - case .uint: return "UInt" - case .int8: return "Int8" - case .uint8: return "UInt8" - case .int16: return "Int16" - case .uint16: return "UInt16" - case .int32: return "Int32" - case .uint32: return "UInt32" - case .int64: return "Int64" - case .uint64: return "UInt64" - case .float: return "Float" - case .double: return "Double" - case .unsafeRawPointer: return "UnsafeRawPointer" - case .unsafeMutableRawPointer: return "UnsafeMutableRawPointer" - } +enum KnownStandardLibraryType: String, Hashable, CaseIterable { + case bool = "Bool" + case int = "Int" + case uint = "UInt" + case int8 = "Int8" + case uint8 = "UInt8" + case int16 = "Int16" + case uint16 = "UInt16" + case int32 = "Int32" + case uint32 = "UInt32" + case int64 = "Int64" + case uint64 = "UInt64" + case float = "Float" + case double = "Double" + case unsafeRawPointer = "UnsafeRawPointer" + case unsafeMutableRawPointer = "UnsafeMutableRawPointer" + case unsafePointer = "UnsafePointer" + case unsafeMutablePointer = "UnsafeMutablePointer" + case unsafeBufferPointer = "UnsafeBufferPointer" + case unsafeMutableBufferPointer = "UnsafeMutableBufferPointer" + + var typeName: String { rawValue } + + init?(typeNameInSwiftModule: String) { + self.init(rawValue: typeNameInSwiftModule) } + /// Whether this declaration is generic. var isGeneric: Bool { - false + switch self { + case .bool, .double, .float, .int, .int8, .int16, .int32, .int64, + .uint, .uint8, .uint16, .uint32, .uint64, .unsafeRawPointer, + .unsafeMutableRawPointer: + false + + case .unsafePointer, .unsafeMutablePointer, .unsafeBufferPointer, + .unsafeMutableBufferPointer: + true + } } } From a2982f953d259e1e28f405bce8cf695c391103e2 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Mon, 3 Feb 2025 19:15:26 +0100 Subject: [PATCH 227/426] Rework handling of returns in cdecl thunks to handle more types Implement a separate "swift to cdecl" conversion path that turns a Swift value into cdecl-compatible return values. This includes returning class and actor references (as unsafe raw pointers), unsafe pointers (also as unsafe raw pointers), and returned tuples (which are passed indirectly). --- .../CDeclLowering/CDeclConversions.swift | 103 +++++++++++++++++ ...wift2JavaTranslator+FunctionLowering.swift | 105 ++++++++++++++---- Sources/JExtractSwift/ConversionStep.swift | 50 +++++++++ .../JExtractSwift/Swift2JavaTranslator.swift | 2 +- .../SwiftTypes/SwiftParameter.swift | 2 +- .../SwiftStandardLibraryTypes.swift | 2 +- .../Asserts/LoweringAssertions.swift | 6 +- .../FunctionLoweringTests.swift | 85 +++++++++++++- 8 files changed, 328 insertions(+), 27 deletions(-) diff --git a/Sources/JExtractSwift/CDeclLowering/CDeclConversions.swift b/Sources/JExtractSwift/CDeclLowering/CDeclConversions.swift index 08816139..c8b7e57c 100644 --- a/Sources/JExtractSwift/CDeclLowering/CDeclConversions.swift +++ b/Sources/JExtractSwift/CDeclLowering/CDeclConversions.swift @@ -87,4 +87,107 @@ extension ConversionStep { self = .tuplify(try elements.map { try ConversionStep(cdeclToSwift: $0) }) } } + + /// Produce a conversion that takes in a value that would be available in a + /// Swift function and convert that to the corresponding cdecl values. + /// + /// This conversion goes in the opposite direction of init(cdeclToSwift:), and + /// is used for (e.g.) returning the Swift value from a cdecl function. When + /// there are multiple cdecl values that correspond to this one Swift value, + /// the result will be a tuple that can be assigned to a tuple of the cdecl + /// values, e.g., (.baseAddress, .count). + init( + swiftToCDecl swiftType: SwiftType, + stdlibTypes: SwiftStandardLibraryTypes + ) throws { + switch swiftType { + case .function, .optional: + throw LoweringError.unhandledType(swiftType) + + case .metatype: + self = .unsafeCastPointer( + .placeholder, + swiftType: .nominal( + SwiftNominalType( + nominalTypeDecl: stdlibTypes[.unsafeRawPointer] + ) + ) + ) + return + + case .nominal(let nominal): + if let knownType = nominal.nominalTypeDecl.knownStandardLibraryType { + // Swift types that map to primitive types in C. These can be passed + // through directly. + if knownType.primitiveCType != nil { + self = .placeholder + return + } + + // Typed pointers + if nominal.genericArguments?.first != nil { + switch knownType { + case .unsafePointer, .unsafeMutablePointer: + let isMutable = knownType == .unsafeMutablePointer + self = ConversionStep( + initializeRawPointerFromTyped: .placeholder, + isMutable: isMutable, + isPartOfBufferPointer: false, + stdlibTypes: stdlibTypes + ) + return + + case .unsafeBufferPointer, .unsafeMutableBufferPointer: + let isMutable = knownType == .unsafeMutableBufferPointer + self = .tuplify( + [ + ConversionStep( + initializeRawPointerFromTyped: .explodedComponent( + .placeholder, + component: "pointer" + ), + isMutable: isMutable, + isPartOfBufferPointer: true, + stdlibTypes: stdlibTypes + ), + .explodedComponent(.placeholder, component: "count") + ] + ) + return + + default: + break + } + } + } + + // Arbitrary nominal types. + switch nominal.nominalTypeDecl.kind { + case .actor, .class: + // For actor and class, we pass around the pointer directly. Case to + // the unsafe raw pointer type we use to represent it in C. + self = .unsafeCastPointer( + .placeholder, + swiftType: .nominal( + SwiftNominalType( + nominalTypeDecl: stdlibTypes[.unsafeRawPointer] + ) + ) + ) + + case .enum, .struct, .protocol: + // For enums, structs, and protocol types, we leave the value alone. + // The indirection will be handled by the caller. + self = .placeholder + } + + case .tuple(let elements): + // Convert all of the elements. + self = .tuplify( + try elements.map { element in + try ConversionStep(swiftToCDecl: element, stdlibTypes: stdlibTypes) + } + ) + } + } } diff --git a/Sources/JExtractSwift/CDeclLowering/Swift2JavaTranslator+FunctionLowering.swift b/Sources/JExtractSwift/CDeclLowering/Swift2JavaTranslator+FunctionLowering.swift index ab89c0b2..9ea8ea63 100644 --- a/Sources/JExtractSwift/CDeclLowering/Swift2JavaTranslator+FunctionLowering.swift +++ b/Sources/JExtractSwift/CDeclLowering/Swift2JavaTranslator+FunctionLowering.swift @@ -63,7 +63,7 @@ extension Swift2JavaTranslator { // void result type indirectResult = false } else if loweredResult.cdeclParameters.count == 1, - loweredResult.cdeclParameters[0].isPrimitive { + loweredResult.cdeclParameters[0].canBeDirectReturn { // Primitive result type indirectResult = false } else { @@ -145,7 +145,8 @@ extension Swift2JavaTranslator { SwiftNominalType( nominalTypeDecl: swiftStdlibTypes[.unsafeRawPointer] ) - ) + ), + canBeDirectReturn: true ) ] ) @@ -163,7 +164,7 @@ extension Swift2JavaTranslator { convention: convention, parameterName: parameterName, type: type, - isPrimitive: true + canBeDirectReturn: true ) ] ) @@ -183,7 +184,8 @@ extension Swift2JavaTranslator { parameterName: parameterName + "_pointer", type: SwiftType.nominal( SwiftNominalType(nominalTypeDecl: cdeclPointerType) - ) + ), + canBeDirectReturn: true ) ] ) @@ -217,6 +219,13 @@ extension Swift2JavaTranslator { } } + // Arbitrary types are lowered to raw pointers that either "are" the + // reference (for classes and actors) or will point to it. + let canBeDirectReturn = switch nominal.nominalTypeDecl.kind { + case .actor, .class: true + case .enum, .protocol, .struct: false + } + let isMutable = (convention == .inout) return LoweredParameters( cdeclParameters: [ @@ -229,7 +238,8 @@ extension Swift2JavaTranslator { ? swiftStdlibTypes[.unsafeMutableRawPointer] : swiftStdlibTypes[.unsafeRawPointer] ) - ) + ), + canBeDirectReturn: canBeDirectReturn ) ] ) @@ -289,7 +299,11 @@ extension LoweredFunctionSignature { /// Produce the `@_cdecl` thunk for this lowered function signature that will /// call into the original function. @_spi(Testing) - public func cdeclThunk(cName: String, inputFunction: FunctionDeclSyntax) -> FunctionDeclSyntax { + public func cdeclThunk( + cName: String, + inputFunction: FunctionDeclSyntax, + stdlibTypes: SwiftStandardLibraryTypes + ) -> FunctionDeclSyntax { var loweredCDecl = cdecl.createFunctionDecl(cName) // Add the @_cdecl attribute. @@ -345,23 +359,70 @@ extension LoweredFunctionSignature { \(callExpression) } """ - } else if cdecl.result.type.isVoid { - // Indirect return. This is a regular return in Swift that turns - // into an assignment via the indirect parameters. - // FIXME: This should actually be a swiftToCDecl conversion! - let resultConversion = try! ConversionStep(cdeclToSwift: original.result.type) - loweredCDecl.body = """ - { - \(resultConversion.asExprSyntax(isSelf: true, placeholder: "_result")) = \(callExpression) - } - """ } else { - // Direct return. - loweredCDecl.body = """ - { - return \(callExpression) - } - """ + // Determine the necessary conversion of the Swift return value to the + // cdecl return value. + let resultConversion = try! ConversionStep( + swiftToCDecl: original.result.type, + stdlibTypes: stdlibTypes + ) + + var bodyItems: [CodeBlockItemSyntax] = [] + + // If the are multiple places in the result conversion that reference + // the placeholder, capture the result of the call in a local variable. + // This prevents us from calling the function multiple times. + let originalResult: ExprSyntax + if resultConversion.placeholderCount > 1 { + bodyItems.append(""" + let __swift_result = \(callExpression) + """ + ) + originalResult = "__swift_result" + } else { + originalResult = callExpression + } + + // FIXME: Check whether there are multiple places in which we reference + // the placeholder in resultConversion. If so, we should write it into a + // local let "_resultValue" or similar so we don't call the underlying + // function multiple times. + + // Convert the result. + let convertedResult = resultConversion.asExprSyntax( + isSelf: true, + placeholder: originalResult.description + ) + + if cdecl.result.type.isVoid { + // Indirect return. This is a regular return in Swift that turns + // into an assignment via the indirect parameters. We do a cdeclToSwift + // conversion on the left-hand side of the tuple to gather all of the + // indirect output parameters we need to assign to, and the result + // conversion is the corresponding right-hand side. + let cdeclParamConversion = try! ConversionStep( + cdeclToSwift: original.result.type + ) + let indirectResults = cdeclParamConversion.asExprSyntax( + isSelf: true, + placeholder: "_result" + ) + bodyItems.append(""" + \(indirectResults) = \(convertedResult) + """ + ) + } else { + // Direct return. Just convert the expression. + bodyItems.append(""" + return \(convertedResult) + """ + ) + } + + loweredCDecl.body = CodeBlockSyntax( + leftBrace: .leftBraceToken(trailingTrivia: .newline), + statements: .init(bodyItems.map { $0.with(\.trailingTrivia, .newline) }) + ) } return loweredCDecl diff --git a/Sources/JExtractSwift/ConversionStep.swift b/Sources/JExtractSwift/ConversionStep.swift index cde2dc4f..31b33a86 100644 --- a/Sources/JExtractSwift/ConversionStep.swift +++ b/Sources/JExtractSwift/ConversionStep.swift @@ -51,6 +51,56 @@ enum ConversionStep: Equatable { /// tuples, which Swift will convert to the labeled tuple form. case tuplify([ConversionStep]) + /// Create an initialization step that produces the raw pointer type that + /// corresponds to the typed pointer. + init( + initializeRawPointerFromTyped typedStep: ConversionStep, + isMutable: Bool, + isPartOfBufferPointer: Bool, + stdlibTypes: SwiftStandardLibraryTypes + ) { + // Initialize the corresponding raw pointer type from the typed + // pointer we have on the Swift side. + let rawPointerType = isMutable + ? stdlibTypes[.unsafeMutableRawPointer] + : stdlibTypes[.unsafeRawPointer] + self = .initialize( + .nominal( + SwiftNominalType( + nominalTypeDecl: rawPointerType + ) + ), + arguments: [ + LabeledArgument( + argument: isPartOfBufferPointer + ? .explodedComponent( + typedStep, + component: "pointer" + ) + : typedStep + ), + ] + ) + } + + /// Count the number of times that the placeholder occurs within this + /// conversion step. + var placeholderCount: Int { + switch self { + case .explodedComponent(let inner, component: _), + .passIndirectly(let inner), .pointee(let inner), + .typedPointer(let inner, swiftType: _), + .unsafeCastPointer(let inner, swiftType: _): + inner.placeholderCount + case .initialize(_, arguments: let arguments): + arguments.reduce(0) { $0 + $1.argument.placeholderCount } + case .placeholder: + 1 + case .tuplify(let elements): + elements.reduce(0) { $0 + $1.placeholderCount } + } + } + /// Convert the conversion step into an expression with the given /// value as the placeholder value in the expression. func asExprSyntax(isSelf: Bool, placeholder: String) -> ExprSyntax { diff --git a/Sources/JExtractSwift/Swift2JavaTranslator.swift b/Sources/JExtractSwift/Swift2JavaTranslator.swift index ff81ef16..6577a37c 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator.swift @@ -39,7 +39,7 @@ public final class Swift2JavaTranslator { /// type representation. package var importedTypes: [String: ImportedNominalType] = [:] - var swiftStdlibTypes: SwiftStandardLibraryTypes + public var swiftStdlibTypes: SwiftStandardLibraryTypes let symbolTable: SwiftSymbolTable let nominalResolution: NominalTypeResolution = NominalTypeResolution() diff --git a/Sources/JExtractSwift/SwiftTypes/SwiftParameter.swift b/Sources/JExtractSwift/SwiftTypes/SwiftParameter.swift index 15b905a4..4cdb27e8 100644 --- a/Sources/JExtractSwift/SwiftTypes/SwiftParameter.swift +++ b/Sources/JExtractSwift/SwiftTypes/SwiftParameter.swift @@ -19,7 +19,7 @@ struct SwiftParameter: Equatable { var argumentLabel: String? var parameterName: String? var type: SwiftType - var isPrimitive = false + var canBeDirectReturn = false } extension SwiftParameter: CustomStringConvertible { diff --git a/Sources/JExtractSwift/SwiftTypes/SwiftStandardLibraryTypes.swift b/Sources/JExtractSwift/SwiftTypes/SwiftStandardLibraryTypes.swift index 77ab9530..fbd7b4f0 100644 --- a/Sources/JExtractSwift/SwiftTypes/SwiftStandardLibraryTypes.swift +++ b/Sources/JExtractSwift/SwiftTypes/SwiftStandardLibraryTypes.swift @@ -58,7 +58,7 @@ enum KnownStandardLibraryType: String, Hashable, CaseIterable { /// Captures many types from the Swift standard library in their most basic /// forms, so that the translator can reason about them in source code. -struct SwiftStandardLibraryTypes { +public struct SwiftStandardLibraryTypes { // Swift.UnsafePointer let unsafePointerDecl: SwiftNominalTypeDeclaration diff --git a/Tests/JExtractSwiftTests/Asserts/LoweringAssertions.swift b/Tests/JExtractSwiftTests/Asserts/LoweringAssertions.swift index 3be4931c..e86d09df 100644 --- a/Tests/JExtractSwiftTests/Asserts/LoweringAssertions.swift +++ b/Tests/JExtractSwiftTests/Asserts/LoweringAssertions.swift @@ -47,7 +47,11 @@ func assertLoweredFunction( inputFunction, enclosingType: enclosingType ) - let loweredCDecl = loweredFunction.cdeclThunk(cName: "c_\(inputFunction.name.text)", inputFunction: inputFunction) + let loweredCDecl = loweredFunction.cdeclThunk( + cName: "c_\(inputFunction.name.text)", + inputFunction: inputFunction, + stdlibTypes: translator.swiftStdlibTypes + ) #expect( loweredCDecl.description == expectedCDecl.description, diff --git a/Tests/JExtractSwiftTests/FunctionLoweringTests.swift b/Tests/JExtractSwiftTests/FunctionLoweringTests.swift index 0c51ccf6..f47ee3b9 100644 --- a/Tests/JExtractSwiftTests/FunctionLoweringTests.swift +++ b/Tests/JExtractSwiftTests/FunctionLoweringTests.swift @@ -136,7 +136,90 @@ final class FunctionLoweringTests { } """, expectedCFunction: "void c_f(void const* t)" - ) + ) + + try assertLoweredFunction(""" + func f() -> Int.Type { } + """, + expectedCDecl: """ + @_cdecl("c_f") + func c_f() -> UnsafeRawPointer { + return unsafeBitCast(f(), to: UnsafeRawPointer.self) + } + """, + expectedCFunction: "void const* c_f(void)" + ) + } + + @Test("Lowering class returns") + func lowerClassReturns() throws { + try assertLoweredFunction(""" + func shifted(by delta: (Double, Double)) -> Point { } + """, + sourceFile: """ + class Point { } + """, + enclosingType: "Point", + expectedCDecl: """ + @_cdecl("c_shifted") + func c_shifted(_ delta_0: Double, _ delta_1: Double, _ self: UnsafeRawPointer) -> UnsafeRawPointer { + return unsafeBitCast(unsafeBitCast(self, to: Point.self).shifted(by: (delta_0, delta_1)), to: UnsafeRawPointer.self) + } + """, + expectedCFunction: "void const* c_shifted(double delta_0, double delta_1, void const* self)" + ) + } + + @Test("Lowering pointer returns") + func lowerPointerReturns() throws { + try assertLoweredFunction(""" + func getPointer() -> UnsafePointer { } + """, + sourceFile: """ + struct Point { } + """, + expectedCDecl: """ + @_cdecl("c_getPointer") + func c_getPointer() -> UnsafeRawPointer { + return UnsafeRawPointer(getPointer()) + } + """, + expectedCFunction: "void const* c_getPointer(void)" + ) + } + + @Test("Lowering tuple returns") + func lowerTupleReturns() throws { + try assertLoweredFunction(""" + func getTuple() -> (Int, (Float, Double)) { } + """, + expectedCDecl: """ + @_cdecl("c_getTuple") + func c_getTuple(_ _result_0: UnsafeMutableRawPointer, _ _result_1_0: UnsafeMutableRawPointer, _ _result_1_1: UnsafeMutableRawPointer) { + let __swift_result = getTuple() + (_result_0, (_result_1_0, _result_1_1)) = (__swift_result_0, (__swift_result_1_0, __swift_result_1_1)) + } + """, + expectedCFunction: "void c_getTuple(void* _result_0, void* _result_1_0, void* _result_1_1)" + ) + } + + @Test("Lowering buffer pointer returns", .disabled("Doesn't turn into the indirect returns")) + func lowerBufferPointerReturns() throws { + try assertLoweredFunction(""" + func getBufferPointer() -> UnsafeMutableBufferPointer { } + """, + sourceFile: """ + struct Point { } + """, + expectedCDecl: """ + @_cdecl("c_getBufferPointer") + func c_getBufferPointer(_result_pointer: UnsafeMutableRawPointer, _result_count: UnsafeMutableRawPointer) { + return UnsafeRawPointer(getPointer()) + } + """, + expectedCFunction: "c_getBufferPointer(void* _result_pointer, void* _result_count)" + ) } } From cebc48ece7e87abd116041268901318216a18d46 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Mon, 3 Feb 2025 20:05:31 +0100 Subject: [PATCH 228/426] Lower initializers and static methods to C declarations --- ...wift2JavaTranslator+FunctionLowering.swift | 83 ++++++++++---- .../SwiftTypes/SwiftFunctionSignature.swift | 101 +++++++++++++----- .../Asserts/LoweringAssertions.swift | 29 +++-- .../FunctionLoweringTests.swift | 71 +++++++++++- 4 files changed, 230 insertions(+), 54 deletions(-) diff --git a/Sources/JExtractSwift/CDeclLowering/Swift2JavaTranslator+FunctionLowering.swift b/Sources/JExtractSwift/CDeclLowering/Swift2JavaTranslator+FunctionLowering.swift index 9ea8ea63..84218a01 100644 --- a/Sources/JExtractSwift/CDeclLowering/Swift2JavaTranslator+FunctionLowering.swift +++ b/Sources/JExtractSwift/CDeclLowering/Swift2JavaTranslator+FunctionLowering.swift @@ -33,6 +33,22 @@ extension Swift2JavaTranslator { return try lowerFunctionSignature(signature) } + /// Lower the given initializer to a C-compatible entrypoint, + /// providing all of the mappings between the parameter and result types + /// of the original function and its `@_cdecl` counterpart. + @_spi(Testing) + public func lowerFunctionSignature( + _ decl: InitializerDeclSyntax, + enclosingType: TypeSyntax? = nil + ) throws -> LoweredFunctionSignature { + let signature = try SwiftFunctionSignature( + decl, + enclosingType: try enclosingType.map { try SwiftType($0, symbolTable: symbolTable) }, + symbolTable: symbolTable + ) + + return try lowerFunctionSignature(signature) + } /// Lower the given Swift function signature to a Swift @_cdecl function signature, /// which is C compatible, and the corresponding Java method signature. /// @@ -75,12 +91,18 @@ extension Swift2JavaTranslator { indirectResult = true } - let loweredSelf = try signature.selfParameter.map { selfParameter in - try lowerParameter( - selfParameter.type, - convention: selfParameter.convention, - parameterName: selfParameter.parameterName ?? "self" - ) + // Lower the self parameter. + let loweredSelf = try signature.selfParameter.flatMap { selfParameter in + switch selfParameter { + case .instance(let selfParameter): + try lowerParameter( + selfParameter.type, + convention: selfParameter.convention, + parameterName: selfParameter.parameterName ?? "self" + ) + case .initializer, .staticMethod: + nil + } } // Collect all of the lowered parameters for the @_cdecl function. @@ -112,7 +134,6 @@ extension Swift2JavaTranslator { } let cdeclSignature = SwiftFunctionSignature( - isStaticOrClass: false, selfParameter: nil, parameters: cdeclLoweredParameters, result: cdeclResult @@ -301,7 +322,7 @@ extension LoweredFunctionSignature { @_spi(Testing) public func cdeclThunk( cName: String, - inputFunction: FunctionDeclSyntax, + swiftFunctionName: String, stdlibTypes: SwiftStandardLibraryTypes ) -> FunctionDeclSyntax { var loweredCDecl = cdecl.createFunctionDecl(cName) @@ -315,14 +336,33 @@ extension LoweredFunctionSignature { // Lower "self", if there is one. let parametersToLower: ArraySlice let cdeclToOriginalSelf: ExprSyntax? - if let originalSelfParam = original.selfParameter { - cdeclToOriginalSelf = try! ConversionStep( - cdeclToSwift: originalSelfParam.type - ).asExprSyntax( - isSelf: true, - placeholder: originalSelfParam.parameterName ?? "self" - ) - parametersToLower = parameters.dropLast() + var initializerType: SwiftType? = nil + if let originalSelf = original.selfParameter { + switch originalSelf { + case .instance(let originalSelfParam): + // The instance was provided to the cdecl thunk, so convert it to + // its Swift representation. + cdeclToOriginalSelf = try! ConversionStep( + cdeclToSwift: originalSelfParam.type + ).asExprSyntax( + isSelf: true, + placeholder: originalSelfParam.parameterName ?? "self" + ) + parametersToLower = parameters.dropLast() + + case .staticMethod(let selfType): + // Static methods use the Swift type as "self", but there is no + // corresponding cdecl parameter. + cdeclToOriginalSelf = "\(raw: selfType.description)" + parametersToLower = parameters[...] + + case .initializer(let selfType): + // Initializers use the Swift type to create the instance. Save it + // for later. There is no corresponding cdecl parameter. + initializerType = selfType + cdeclToOriginalSelf = nil + parametersToLower = parameters[...] + } } else { cdeclToOriginalSelf = nil parametersToLower = parameters[...] @@ -346,9 +386,14 @@ extension LoweredFunctionSignature { } // Form the call expression. - var callExpression: ExprSyntax = "\(inputFunction.name)(\(raw: cdeclToOriginalArguments.joined(separator: ", ")))" - if let cdeclToOriginalSelf { - callExpression = "\(cdeclToOriginalSelf).\(callExpression)" + let callArguments: ExprSyntax = "(\(raw: cdeclToOriginalArguments.joined(separator: ", ")))" + let callExpression: ExprSyntax + if let initializerType { + callExpression = "\(raw: initializerType.description)\(callArguments)" + } else if let cdeclToOriginalSelf { + callExpression = "\(cdeclToOriginalSelf).\(raw: swiftFunctionName)\(callArguments)" + } else { + callExpression = "\(raw: swiftFunctionName)\(callArguments)" } // Handle the return. diff --git a/Sources/JExtractSwift/SwiftTypes/SwiftFunctionSignature.swift b/Sources/JExtractSwift/SwiftTypes/SwiftFunctionSignature.swift index c2b626f2..dc8aadb1 100644 --- a/Sources/JExtractSwift/SwiftTypes/SwiftFunctionSignature.swift +++ b/Sources/JExtractSwift/SwiftTypes/SwiftFunctionSignature.swift @@ -19,13 +19,25 @@ import SwiftSyntaxBuilder /// parameters and return type. @_spi(Testing) public struct SwiftFunctionSignature: Equatable { - // FIXME: isStaticOrClass probably shouldn't be here? - var isStaticOrClass: Bool - var selfParameter: SwiftParameter? + var selfParameter: SwiftSelfParameter? var parameters: [SwiftParameter] var result: SwiftResult } +/// Describes the "self" parameter of a Swift function signature. +enum SwiftSelfParameter: Equatable { + /// 'self' is an instance parameter. + case instance(SwiftParameter) + + /// 'self' is a metatype for a static method. We only need the type to + /// form the call. + case staticMethod(SwiftType) + + /// 'self' is the type for a call to an initializer. We only need the type + /// to form the call. + case initializer(SwiftType) +} + extension SwiftFunctionSignature { /// Create a function declaration with the given name that has this /// signature. @@ -49,6 +61,33 @@ extension SwiftFunctionSignature { } extension SwiftFunctionSignature { + init( + _ node: InitializerDeclSyntax, + enclosingType: SwiftType?, + symbolTable: SwiftSymbolTable + ) throws { + guard let enclosingType else { + throw SwiftFunctionTranslationError.missingEnclosingType(node) + } + + // We do not yet support failable initializers. + if node.optionalMark != nil { + throw SwiftFunctionTranslationError.failableInitializer(node) + } + + // Prohibit generics for now. + if let generics = node.genericParameterClause { + throw SwiftFunctionTranslationError.generic(generics) + } + + self.selfParameter = .initializer(enclosingType) + self.result = SwiftResult(convention: .direct, type: enclosingType) + self.parameters = try Self.translateFunctionSignature( + node.signature, + symbolTable: symbolTable + ) + } + init( _ node: FunctionDeclSyntax, enclosingType: SwiftType?, @@ -59,40 +98,36 @@ extension SwiftFunctionSignature { if let enclosingType { var isMutating = false var isConsuming = false - var isStaticOrClass = false + var isStatic = false for modifier in node.modifiers { switch modifier.name.tokenKind { case .keyword(.mutating): isMutating = true - case .keyword(.static), .keyword(.class): isStaticOrClass = true + case .keyword(.static): isStatic = true case .keyword(.consuming): isConsuming = true + case .keyword(.class): throw SwiftFunctionTranslationError.classMethod(modifier.name) default: break } } - if isStaticOrClass { - self.selfParameter = SwiftParameter( - convention: .byValue, - type: .metatype( - enclosingType - ) - ) + if isStatic { + self.selfParameter = .staticMethod(enclosingType) } else { - self.selfParameter = SwiftParameter( - convention: isMutating ? .inout : isConsuming ? .consuming : .byValue, - type: enclosingType + self.selfParameter = .instance( + SwiftParameter( + convention: isMutating ? .inout : isConsuming ? .consuming : .byValue, + type: enclosingType + ) ) } - - self.isStaticOrClass = isStaticOrClass } else { self.selfParameter = nil - self.isStaticOrClass = false } // Translate the parameters. - self.parameters = try node.signature.parameterClause.parameters.map { param in - try SwiftParameter(param, symbolTable: symbolTable) - } + self.parameters = try Self.translateFunctionSignature( + node.signature, + symbolTable: symbolTable + ) // Translate the result type. if let resultType = node.signature.returnClause?.type { @@ -104,17 +139,28 @@ extension SwiftFunctionSignature { self.result = SwiftResult(convention: .direct, type: .tuple([])) } + // Prohibit generics for now. + if let generics = node.genericParameterClause { + throw SwiftFunctionTranslationError.generic(generics) + } + } + + /// Translate the function signature, returning the list of translated + /// parameters. + static func translateFunctionSignature( + _ signature: FunctionSignatureSyntax, + symbolTable: SwiftSymbolTable + ) throws -> [SwiftParameter] { // FIXME: Prohibit effects for now. - if let throwsClause = node.signature.effectSpecifiers?.throwsClause { + if let throwsClause = signature.effectSpecifiers?.throwsClause { throw SwiftFunctionTranslationError.throws(throwsClause) } - if let asyncSpecifier = node.signature.effectSpecifiers?.asyncSpecifier { + if let asyncSpecifier = signature.effectSpecifiers?.asyncSpecifier { throw SwiftFunctionTranslationError.async(asyncSpecifier) } - // Prohibit generics for now. - if let generics = node.genericParameterClause { - throw SwiftFunctionTranslationError.generic(generics) + return try signature.parameterClause.parameters.map { param in + try SwiftParameter(param, symbolTable: symbolTable) } } } @@ -123,4 +169,7 @@ enum SwiftFunctionTranslationError: Error { case `throws`(ThrowsClauseSyntax) case async(TokenSyntax) case generic(GenericParameterClauseSyntax) + case classMethod(TokenSyntax) + case missingEnclosingType(InitializerDeclSyntax) + case failableInitializer(InitializerDeclSyntax) } diff --git a/Tests/JExtractSwiftTests/Asserts/LoweringAssertions.swift b/Tests/JExtractSwiftTests/Asserts/LoweringAssertions.swift index e86d09df..6f7a5e83 100644 --- a/Tests/JExtractSwiftTests/Asserts/LoweringAssertions.swift +++ b/Tests/JExtractSwiftTests/Asserts/LoweringAssertions.swift @@ -42,14 +42,27 @@ func assertLoweredFunction( translator.prepareForTranslation() - let inputFunction = inputDecl.cast(FunctionDeclSyntax.self) - let loweredFunction = try translator.lowerFunctionSignature( - inputFunction, - enclosingType: enclosingType - ) + let swiftFunctionName: String + let loweredFunction: LoweredFunctionSignature + if let inputFunction = inputDecl.as(FunctionDeclSyntax.self) { + loweredFunction = try translator.lowerFunctionSignature( + inputFunction, + enclosingType: enclosingType + ) + swiftFunctionName = inputFunction.name.text + } else if let inputInitializer = inputDecl.as(InitializerDeclSyntax.self) { + loweredFunction = try translator.lowerFunctionSignature( + inputInitializer, + enclosingType: enclosingType + ) + swiftFunctionName = "init" + } else { + fatalError("Unhandling declaration kind for lowering") + } + let loweredCDecl = loweredFunction.cdeclThunk( - cName: "c_\(inputFunction.name.text)", - inputFunction: inputFunction, + cName: "c_\(swiftFunctionName)", + swiftFunctionName: swiftFunctionName, stdlibTypes: translator.swiftStdlibTypes ) @@ -65,7 +78,7 @@ func assertLoweredFunction( let cFunction = translator.cdeclToCFunctionLowering( loweredFunction.cdecl, - cName: "c_\(inputFunction.name.text)" + cName: "c_\(swiftFunctionName)" ) #expect( cFunction.description == expectedCFunction, diff --git a/Tests/JExtractSwiftTests/FunctionLoweringTests.swift b/Tests/JExtractSwiftTests/FunctionLoweringTests.swift index f47ee3b9..66c02632 100644 --- a/Tests/JExtractSwiftTests/FunctionLoweringTests.swift +++ b/Tests/JExtractSwiftTests/FunctionLoweringTests.swift @@ -124,6 +124,76 @@ final class FunctionLoweringTests { ) } + @Test("Lowering static methods") + func loweringStaticMethods() throws { + try assertLoweredFunction(""" + static func scaledUnit(by value: Double) -> Point { } + """, + sourceFile: """ + struct Point { } + """, + enclosingType: "Point", + expectedCDecl: """ + @_cdecl("c_scaledUnit") + func c_scaledUnit(_ value: Double, _ _result: UnsafeMutableRawPointer) { + _result.assumingMemoryBound(to: Point.self).pointee = Point.scaledUnit(by: value) + } + """, + expectedCFunction: "void c_scaledUnit(double value, void* _result)" + ) + + try assertLoweredFunction(""" + static func randomPerson(seed: Double) -> Person { } + """, + sourceFile: """ + class Person { } + """, + enclosingType: "Person", + expectedCDecl: """ + @_cdecl("c_randomPerson") + func c_randomPerson(_ seed: Double) -> UnsafeRawPointer { + return unsafeBitCast(Person.randomPerson(seed: seed), to: UnsafeRawPointer.self) + } + """, + expectedCFunction: "void const* c_randomPerson(double seed)" + ) + } + + @Test("Lowering initializers") + func loweringInitializers() throws { + try assertLoweredFunction(""" + init(scaledBy value: Double) { } + """, + sourceFile: """ + struct Point { } + """, + enclosingType: "Point", + expectedCDecl: """ + @_cdecl("c_init") + func c_init(_ value: Double, _ _result: UnsafeMutableRawPointer) { + _result.assumingMemoryBound(to: Point.self).pointee = Point(scaledBy: value) + } + """, + expectedCFunction: "void c_init(double value, void* _result)" + ) + + try assertLoweredFunction(""" + init(seed: Double) { } + """, + sourceFile: """ + class Person { } + """, + enclosingType: "Person", + expectedCDecl: """ + @_cdecl("c_init") + func c_init(_ seed: Double) -> UnsafeRawPointer { + return unsafeBitCast(Person(seed: seed), to: UnsafeRawPointer.self) + } + """, + expectedCFunction: "void const* c_init(double seed)" + ) + } + @Test("Lowering metatypes") func lowerMetatype() throws { try assertLoweredFunction(""" @@ -222,4 +292,3 @@ final class FunctionLoweringTests { ) } } - From 97299cc39e15d247493819c4a5365e7c9309c10c Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Mon, 3 Feb 2025 20:36:36 +0100 Subject: [PATCH 229/426] cdecl lowering: move indirect returns after self This is meant to match the existing thunk generation. --- .../Swift2JavaTranslator+FunctionLowering.swift | 12 +++++++----- Tests/JExtractSwiftTests/FunctionLoweringTests.swift | 4 ++-- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/Sources/JExtractSwift/CDeclLowering/Swift2JavaTranslator+FunctionLowering.swift b/Sources/JExtractSwift/CDeclLowering/Swift2JavaTranslator+FunctionLowering.swift index 84218a01..a18ddc76 100644 --- a/Sources/JExtractSwift/CDeclLowering/Swift2JavaTranslator+FunctionLowering.swift +++ b/Sources/JExtractSwift/CDeclLowering/Swift2JavaTranslator+FunctionLowering.swift @@ -113,6 +113,13 @@ extension Swift2JavaTranslator { contentsOf: loweredParameters.flatMap { $0.cdeclParameters } ) + // Lower self. + if let loweredSelf { + allLoweredParameters.append(loweredSelf) + cdeclLoweredParameters.append(contentsOf: loweredSelf.cdeclParameters) + } + + // Lower indirect results. let cdeclResult: SwiftResult if indirectResult { cdeclLoweredParameters.append( @@ -128,11 +135,6 @@ extension Swift2JavaTranslator { fatalError("Improper lowering of result for \(signature)") } - if let loweredSelf { - allLoweredParameters.append(loweredSelf) - cdeclLoweredParameters.append(contentsOf: loweredSelf.cdeclParameters) - } - let cdeclSignature = SwiftFunctionSignature( selfParameter: nil, parameters: cdeclLoweredParameters, diff --git a/Tests/JExtractSwiftTests/FunctionLoweringTests.swift b/Tests/JExtractSwiftTests/FunctionLoweringTests.swift index 66c02632..c3b3bf58 100644 --- a/Tests/JExtractSwiftTests/FunctionLoweringTests.swift +++ b/Tests/JExtractSwiftTests/FunctionLoweringTests.swift @@ -78,11 +78,11 @@ final class FunctionLoweringTests { enclosingType: "Point", expectedCDecl: """ @_cdecl("c_shifted") - func c_shifted(_ delta_0: Double, _ delta_1: Double, _ _result: UnsafeMutableRawPointer, _ self: UnsafeRawPointer) { + func c_shifted(_ delta_0: Double, _ delta_1: Double, _ self: UnsafeRawPointer, _ _result: UnsafeMutableRawPointer) { _result.assumingMemoryBound(to: Point.self).pointee = self.assumingMemoryBound(to: Point.self).pointee.shifted(by: (delta_0, delta_1)) } """, - expectedCFunction: "void c_shifted(double delta_0, double delta_1, void* _result, void const* self)" + expectedCFunction: "void c_shifted(double delta_0, double delta_1, void const* self, void* _result)" ) } From 8f00df5e124a5d929fd2d215705cdea127ab7044 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Mon, 3 Feb 2025 22:02:20 +0100 Subject: [PATCH 230/426] cdecl thunks: property initialize indirect returns via initialize(to:) This requires us to walk the parallel structure between indirect returns (where we need to introduce the initialize(to:) calls instead of pointee references) and the Swift value. --- ...wift2JavaTranslator+FunctionLowering.swift | 87 +++++++++++++++---- .../FunctionLoweringTests.swift | 15 ++-- 2 files changed, 79 insertions(+), 23 deletions(-) diff --git a/Sources/JExtractSwift/CDeclLowering/Swift2JavaTranslator+FunctionLowering.swift b/Sources/JExtractSwift/CDeclLowering/Swift2JavaTranslator+FunctionLowering.swift index a18ddc76..95bbeb0b 100644 --- a/Sources/JExtractSwift/CDeclLowering/Swift2JavaTranslator+FunctionLowering.swift +++ b/Sources/JExtractSwift/CDeclLowering/Swift2JavaTranslator+FunctionLowering.swift @@ -430,17 +430,6 @@ extension LoweredFunctionSignature { originalResult = callExpression } - // FIXME: Check whether there are multiple places in which we reference - // the placeholder in resultConversion. If so, we should write it into a - // local let "_resultValue" or similar so we don't call the underlying - // function multiple times. - - // Convert the result. - let convertedResult = resultConversion.asExprSyntax( - isSelf: true, - placeholder: originalResult.description - ) - if cdecl.result.type.isVoid { // Indirect return. This is a regular return in Swift that turns // into an assignment via the indirect parameters. We do a cdeclToSwift @@ -450,16 +439,23 @@ extension LoweredFunctionSignature { let cdeclParamConversion = try! ConversionStep( cdeclToSwift: original.result.type ) - let indirectResults = cdeclParamConversion.asExprSyntax( - isSelf: true, - placeholder: "_result" - ) - bodyItems.append(""" - \(indirectResults) = \(convertedResult) - """ + + // For each indirect result, initialize the value directly with the + // corresponding element in the converted result. + bodyItems.append( + contentsOf: cdeclParamConversion.initialize( + placeholder: "_result", + from: resultConversion, + otherPlaceholder: originalResult.description + ) ) } else { // Direct return. Just convert the expression. + let convertedResult = resultConversion.asExprSyntax( + isSelf: true, + placeholder: originalResult.description + ) + bodyItems.append(""" return \(convertedResult) """ @@ -475,3 +471,58 @@ extension LoweredFunctionSignature { return loweredCDecl } } + +extension ConversionStep { + /// Form a set of statements that initializes the placeholders within + /// the given conversion step from ones in the other step, effectively + /// exploding something like `(a, (b, c)) = (d, (e, f))` into + /// separate initializations for a, b, and c from d, e, and f, respectively. + func initialize( + placeholder: String, + from otherStep: ConversionStep, + otherPlaceholder: String + ) -> [CodeBlockItemSyntax] { + // Create separate assignments for each element in paired tuples. + if case .tuplify(let elements) = self, + case .tuplify(let otherElements) = otherStep { + assert(elements.count == otherElements.count) + + return elements.indices.flatMap { index in + elements[index].initialize( + placeholder: "\(placeholder)_\(index)", + from: otherElements[index], + otherPlaceholder: "\(otherPlaceholder)_\(index)" + ) + } + } + + // Look through "pass indirectly" steps; they do nothing here. + if case .passIndirectly(let conversionStep) = self { + return conversionStep.initialize( + placeholder: placeholder, + from: otherStep, + otherPlaceholder: otherPlaceholder + ) + } + + // The value we're initializing from. + let otherExpr = otherStep.asExprSyntax( + isSelf: false, + placeholder: otherPlaceholder + ) + + // If we have a "pointee" on where we are performing initialization, we + // need to instead produce an initialize(to:) call. + if case .pointee(let innerSelf) = self { + let selfPointerExpr = innerSelf.asExprSyntax( + isSelf: true, + placeholder: placeholder + ) + + return [ " \(selfPointerExpr).initialize(to: \(otherExpr))" ] + } + + let selfExpr = self.asExprSyntax(isSelf: true, placeholder: placeholder) + return [ " \(selfExpr) = \(otherExpr)" ] + } +} diff --git a/Tests/JExtractSwiftTests/FunctionLoweringTests.swift b/Tests/JExtractSwiftTests/FunctionLoweringTests.swift index c3b3bf58..bc08245c 100644 --- a/Tests/JExtractSwiftTests/FunctionLoweringTests.swift +++ b/Tests/JExtractSwiftTests/FunctionLoweringTests.swift @@ -79,7 +79,7 @@ final class FunctionLoweringTests { expectedCDecl: """ @_cdecl("c_shifted") func c_shifted(_ delta_0: Double, _ delta_1: Double, _ self: UnsafeRawPointer, _ _result: UnsafeMutableRawPointer) { - _result.assumingMemoryBound(to: Point.self).pointee = self.assumingMemoryBound(to: Point.self).pointee.shifted(by: (delta_0, delta_1)) + _result.assumingMemoryBound(to: Point.self).initialize(to: self.assumingMemoryBound(to: Point.self).pointee.shifted(by: (delta_0, delta_1))) } """, expectedCFunction: "void c_shifted(double delta_0, double delta_1, void const* self, void* _result)" @@ -136,7 +136,7 @@ final class FunctionLoweringTests { expectedCDecl: """ @_cdecl("c_scaledUnit") func c_scaledUnit(_ value: Double, _ _result: UnsafeMutableRawPointer) { - _result.assumingMemoryBound(to: Point.self).pointee = Point.scaledUnit(by: value) + _result.assumingMemoryBound(to: Point.self).initialize(to: Point.scaledUnit(by: value)) } """, expectedCFunction: "void c_scaledUnit(double value, void* _result)" @@ -171,7 +171,7 @@ final class FunctionLoweringTests { expectedCDecl: """ @_cdecl("c_init") func c_init(_ value: Double, _ _result: UnsafeMutableRawPointer) { - _result.assumingMemoryBound(to: Point.self).pointee = Point(scaledBy: value) + _result.assumingMemoryBound(to: Point.self).initialize(to: Point(scaledBy: value)) } """, expectedCFunction: "void c_init(double value, void* _result)" @@ -261,13 +261,18 @@ final class FunctionLoweringTests { @Test("Lowering tuple returns") func lowerTupleReturns() throws { try assertLoweredFunction(""" - func getTuple() -> (Int, (Float, Double)) { } + func getTuple() -> (Int, (Float, Point)) { } + """, + sourceFile: """ + struct Point { } """, expectedCDecl: """ @_cdecl("c_getTuple") func c_getTuple(_ _result_0: UnsafeMutableRawPointer, _ _result_1_0: UnsafeMutableRawPointer, _ _result_1_1: UnsafeMutableRawPointer) { let __swift_result = getTuple() - (_result_0, (_result_1_0, _result_1_1)) = (__swift_result_0, (__swift_result_1_0, __swift_result_1_1)) + _result_0 = __swift_result_0 + _result_1_0 = __swift_result_1_0 + _result_1_1.assumingMemoryBound(to: Point.self).initialize(to: __swift_result_1_1) } """, expectedCFunction: "void c_getTuple(void* _result_0, void* _result_1_0, void* _result_1_1)" From e11dceae04607c50b399e2d63159a48169c52fef Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Mon, 3 Feb 2025 22:13:23 +0100 Subject: [PATCH 231/426] Always mark @cdecl thunks we generate in lowering as public --- ...wift2JavaTranslator+FunctionLowering.swift | 6 ++++ .../FunctionLoweringTests.swift | 32 +++++++++---------- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/Sources/JExtractSwift/CDeclLowering/Swift2JavaTranslator+FunctionLowering.swift b/Sources/JExtractSwift/CDeclLowering/Swift2JavaTranslator+FunctionLowering.swift index 95bbeb0b..edc78fa7 100644 --- a/Sources/JExtractSwift/CDeclLowering/Swift2JavaTranslator+FunctionLowering.swift +++ b/Sources/JExtractSwift/CDeclLowering/Swift2JavaTranslator+FunctionLowering.swift @@ -49,6 +49,7 @@ extension Swift2JavaTranslator { return try lowerFunctionSignature(signature) } + /// Lower the given Swift function signature to a Swift @_cdecl function signature, /// which is C compatible, and the corresponding Java method signature. /// @@ -333,6 +334,11 @@ extension LoweredFunctionSignature { let cdeclAttribute: AttributeSyntax = "@_cdecl(\(literal: cName))\n" loweredCDecl.attributes.append(.attribute(cdeclAttribute)) + // Make it public. + loweredCDecl.modifiers.append( + DeclModifierSyntax(name: .keyword(.public), trailingTrivia: .space) + ) + // Create the body. // Lower "self", if there is one. diff --git a/Tests/JExtractSwiftTests/FunctionLoweringTests.swift b/Tests/JExtractSwiftTests/FunctionLoweringTests.swift index bc08245c..3a036594 100644 --- a/Tests/JExtractSwiftTests/FunctionLoweringTests.swift +++ b/Tests/JExtractSwiftTests/FunctionLoweringTests.swift @@ -26,7 +26,7 @@ final class FunctionLoweringTests { """, expectedCDecl: """ @_cdecl("c_f") - func c_f(_ x: Int, _ y: Float, _ z_pointer: UnsafeRawPointer, _ z_count: Int) { + public func c_f(_ x: Int, _ y: Float, _ z_pointer: UnsafeRawPointer, _ z_count: Int) { f(x: x, y: y, z: UnsafeBufferPointer(start: z_pointer.assumingMemoryBound(to: Bool.self), count: z_count)) } """, @@ -41,7 +41,7 @@ final class FunctionLoweringTests { """, expectedCDecl: """ @_cdecl("c_f") - func c_f(_ t_0: Int, _ t_1_0: Float, _ t_1_1: Double, _ z_pointer: UnsafeRawPointer) -> Int { + public func c_f(_ t_0: Int, _ t_1_0: Float, _ t_1_1: Double, _ z_pointer: UnsafeRawPointer) -> Int { return f(t: (t_0, (t_1_0, t_1_1)), z: z_pointer.assumingMemoryBound(to: Int.self)) } """, @@ -59,7 +59,7 @@ final class FunctionLoweringTests { """, expectedCDecl: """ @_cdecl("c_shift") - func c_shift(_ point: UnsafeMutableRawPointer, _ delta_0: Double, _ delta_1: Double) { + public func c_shift(_ point: UnsafeMutableRawPointer, _ delta_0: Double, _ delta_1: Double) { shift(point: &point.assumingMemoryBound(to: Point.self).pointee, by: (delta_0, delta_1)) } """, @@ -78,7 +78,7 @@ final class FunctionLoweringTests { enclosingType: "Point", expectedCDecl: """ @_cdecl("c_shifted") - func c_shifted(_ delta_0: Double, _ delta_1: Double, _ self: UnsafeRawPointer, _ _result: UnsafeMutableRawPointer) { + public func c_shifted(_ delta_0: Double, _ delta_1: Double, _ self: UnsafeRawPointer, _ _result: UnsafeMutableRawPointer) { _result.assumingMemoryBound(to: Point.self).initialize(to: self.assumingMemoryBound(to: Point.self).pointee.shifted(by: (delta_0, delta_1))) } """, @@ -97,7 +97,7 @@ final class FunctionLoweringTests { enclosingType: "Point", expectedCDecl: """ @_cdecl("c_shift") - func c_shift(_ delta_0: Double, _ delta_1: Double, _ self: UnsafeMutableRawPointer) { + public func c_shift(_ delta_0: Double, _ delta_1: Double, _ self: UnsafeMutableRawPointer) { self.assumingMemoryBound(to: Point.self).pointee.shift(by: (delta_0, delta_1)) } """, @@ -116,7 +116,7 @@ final class FunctionLoweringTests { enclosingType: "Point", expectedCDecl: """ @_cdecl("c_shift") - func c_shift(_ delta_0: Double, _ delta_1: Double, _ self: UnsafeRawPointer) { + public func c_shift(_ delta_0: Double, _ delta_1: Double, _ self: UnsafeRawPointer) { unsafeBitCast(self, to: Point.self).shift(by: (delta_0, delta_1)) } """, @@ -135,7 +135,7 @@ final class FunctionLoweringTests { enclosingType: "Point", expectedCDecl: """ @_cdecl("c_scaledUnit") - func c_scaledUnit(_ value: Double, _ _result: UnsafeMutableRawPointer) { + public func c_scaledUnit(_ value: Double, _ _result: UnsafeMutableRawPointer) { _result.assumingMemoryBound(to: Point.self).initialize(to: Point.scaledUnit(by: value)) } """, @@ -151,7 +151,7 @@ final class FunctionLoweringTests { enclosingType: "Person", expectedCDecl: """ @_cdecl("c_randomPerson") - func c_randomPerson(_ seed: Double) -> UnsafeRawPointer { + public func c_randomPerson(_ seed: Double) -> UnsafeRawPointer { return unsafeBitCast(Person.randomPerson(seed: seed), to: UnsafeRawPointer.self) } """, @@ -170,7 +170,7 @@ final class FunctionLoweringTests { enclosingType: "Point", expectedCDecl: """ @_cdecl("c_init") - func c_init(_ value: Double, _ _result: UnsafeMutableRawPointer) { + public func c_init(_ value: Double, _ _result: UnsafeMutableRawPointer) { _result.assumingMemoryBound(to: Point.self).initialize(to: Point(scaledBy: value)) } """, @@ -186,7 +186,7 @@ final class FunctionLoweringTests { enclosingType: "Person", expectedCDecl: """ @_cdecl("c_init") - func c_init(_ seed: Double) -> UnsafeRawPointer { + public func c_init(_ seed: Double) -> UnsafeRawPointer { return unsafeBitCast(Person(seed: seed), to: UnsafeRawPointer.self) } """, @@ -201,7 +201,7 @@ final class FunctionLoweringTests { """, expectedCDecl: """ @_cdecl("c_f") - func c_f(_ t: UnsafeRawPointer) { + public func c_f(_ t: UnsafeRawPointer) { f(t: unsafeBitCast(t, to: Int.self)) } """, @@ -213,7 +213,7 @@ final class FunctionLoweringTests { """, expectedCDecl: """ @_cdecl("c_f") - func c_f() -> UnsafeRawPointer { + public func c_f() -> UnsafeRawPointer { return unsafeBitCast(f(), to: UnsafeRawPointer.self) } """, @@ -232,7 +232,7 @@ final class FunctionLoweringTests { enclosingType: "Point", expectedCDecl: """ @_cdecl("c_shifted") - func c_shifted(_ delta_0: Double, _ delta_1: Double, _ self: UnsafeRawPointer) -> UnsafeRawPointer { + public func c_shifted(_ delta_0: Double, _ delta_1: Double, _ self: UnsafeRawPointer) -> UnsafeRawPointer { return unsafeBitCast(unsafeBitCast(self, to: Point.self).shifted(by: (delta_0, delta_1)), to: UnsafeRawPointer.self) } """, @@ -250,7 +250,7 @@ final class FunctionLoweringTests { """, expectedCDecl: """ @_cdecl("c_getPointer") - func c_getPointer() -> UnsafeRawPointer { + public func c_getPointer() -> UnsafeRawPointer { return UnsafeRawPointer(getPointer()) } """, @@ -268,7 +268,7 @@ final class FunctionLoweringTests { """, expectedCDecl: """ @_cdecl("c_getTuple") - func c_getTuple(_ _result_0: UnsafeMutableRawPointer, _ _result_1_0: UnsafeMutableRawPointer, _ _result_1_1: UnsafeMutableRawPointer) { + public func c_getTuple(_ _result_0: UnsafeMutableRawPointer, _ _result_1_0: UnsafeMutableRawPointer, _ _result_1_1: UnsafeMutableRawPointer) { let __swift_result = getTuple() _result_0 = __swift_result_0 _result_1_0 = __swift_result_1_0 @@ -289,7 +289,7 @@ final class FunctionLoweringTests { """, expectedCDecl: """ @_cdecl("c_getBufferPointer") - func c_getBufferPointer(_result_pointer: UnsafeMutableRawPointer, _result_count: UnsafeMutableRawPointer) { + public func c_getBufferPointer(_result_pointer: UnsafeMutableRawPointer, _result_count: UnsafeMutableRawPointer) { return UnsafeRawPointer(getPointer()) } """, From c6066af00adcd6a378f82989d34cfba7264dc5c0 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Mon, 3 Feb 2025 22:53:21 +0100 Subject: [PATCH 232/426] Leverage the direct Swift cdecl type <-> C type mapping for lowering When lowering a Swift function to a cdecl thunk, detect when a given Swift type is exactly representable in C. In such cases, just keep the type as written and pass it through without modification. Use this to allow `@convention(c)` functions to go through untouched. --- .../CDeclLowering/CDeclConversions.swift | 30 +++++++++--------- .../CDeclLowering/CRepresentation.swift | 7 +++-- ...wift2JavaTranslator+FunctionLowering.swift | 31 ++++++++++--------- .../SwiftTypes/SwiftFunctionType.swift | 7 ++++- .../SwiftTypes/SwiftParameter.swift | 8 +++-- .../JExtractSwift/SwiftTypes/SwiftType.swift | 4 +-- .../FunctionLoweringTests.swift | 17 ++++++++++ 7 files changed, 68 insertions(+), 36 deletions(-) diff --git a/Sources/JExtractSwift/CDeclLowering/CDeclConversions.swift b/Sources/JExtractSwift/CDeclLowering/CDeclConversions.swift index c8b7e57c..0099ae5c 100644 --- a/Sources/JExtractSwift/CDeclLowering/CDeclConversions.swift +++ b/Sources/JExtractSwift/CDeclLowering/CDeclConversions.swift @@ -17,6 +17,14 @@ extension ConversionStep { /// would be available in a @_cdecl function to represent the given Swift /// type, and convert that to an instance of the Swift type. init(cdeclToSwift swiftType: SwiftType) throws { + // If there is a 1:1 mapping between this Swift type and a C type, then + // there is no translation to do. + if let cType = try? CType(cdeclType: swiftType) { + _ = cType + self = .placeholder + return + } + switch swiftType { case .function, .optional: throw LoweringError.unhandledType(swiftType) @@ -29,13 +37,6 @@ extension ConversionStep { case .nominal(let nominal): if let knownType = nominal.nominalTypeDecl.knownStandardLibraryType { - // Swift types that map to primitive types in C. These can be passed - // through directly. - if knownType.primitiveCType != nil { - self = .placeholder - return - } - // Typed pointers if let firstGenericArgument = nominal.genericArguments?.first { switch knownType { @@ -100,6 +101,14 @@ extension ConversionStep { swiftToCDecl swiftType: SwiftType, stdlibTypes: SwiftStandardLibraryTypes ) throws { + // If there is a 1:1 mapping between this Swift type and a C type, then + // there is no translation to do. + if let cType = try? CType(cdeclType: swiftType) { + _ = cType + self = .placeholder + return + } + switch swiftType { case .function, .optional: throw LoweringError.unhandledType(swiftType) @@ -117,13 +126,6 @@ extension ConversionStep { case .nominal(let nominal): if let knownType = nominal.nominalTypeDecl.knownStandardLibraryType { - // Swift types that map to primitive types in C. These can be passed - // through directly. - if knownType.primitiveCType != nil { - self = .placeholder - return - } - // Typed pointers if nominal.genericArguments?.first != nil { switch knownType { diff --git a/Sources/JExtractSwift/CDeclLowering/CRepresentation.swift b/Sources/JExtractSwift/CDeclLowering/CRepresentation.swift index 08e10de1..15e4ebb8 100644 --- a/Sources/JExtractSwift/CDeclLowering/CRepresentation.swift +++ b/Sources/JExtractSwift/CDeclLowering/CRepresentation.swift @@ -16,8 +16,11 @@ extension CType { /// Lower the given Swift type down to a its corresponding C type. /// /// This operation only supports the subset of Swift types that are - /// representable in a Swift `@_cdecl` function. If lowering an arbitrary - /// Swift function, first go through Swift -> cdecl lowering. + /// representable in a Swift `@_cdecl` function, which means that they are + /// also directly representable in C. If lowering an arbitrary Swift + /// function, first go through Swift -> cdecl lowering. This function + /// will throw an error if it encounters a type that is not expressible in + /// C. init(cdeclType: SwiftType) throws { switch cdeclType { case .nominal(let nominalType): diff --git a/Sources/JExtractSwift/CDeclLowering/Swift2JavaTranslator+FunctionLowering.swift b/Sources/JExtractSwift/CDeclLowering/Swift2JavaTranslator+FunctionLowering.swift index edc78fa7..d65948ac 100644 --- a/Sources/JExtractSwift/CDeclLowering/Swift2JavaTranslator+FunctionLowering.swift +++ b/Sources/JExtractSwift/CDeclLowering/Swift2JavaTranslator+FunctionLowering.swift @@ -155,6 +155,22 @@ extension Swift2JavaTranslator { convention: SwiftParameterConvention, parameterName: String ) throws -> LoweredParameters { + // If there is a 1:1 mapping between this Swift type and a C type, we just + // need to add the corresponding C [arameter. + if let cType = try? CType(cdeclType: type), convention != .inout { + _ = cType + return LoweredParameters( + cdeclParameters: [ + SwiftParameter( + convention: convention, + parameterName: parameterName, + type: type, + canBeDirectReturn: true + ) + ] + ) + } + switch type { case .function, .optional: throw LoweringError.unhandledType(type) @@ -179,21 +195,6 @@ extension Swift2JavaTranslator { // Types from the Swift standard library that we know about. if let knownType = nominal.nominalTypeDecl.knownStandardLibraryType, convention != .inout { - // Swift types that map to primitive types in C. These can be passed - // through directly. - if knownType.primitiveCType != nil { - return LoweredParameters( - cdeclParameters: [ - SwiftParameter( - convention: convention, - parameterName: parameterName, - type: type, - canBeDirectReturn: true - ) - ] - ) - } - // Typed pointers are mapped down to their raw forms in cdecl entry // points. These can be passed through directly. if knownType == .unsafePointer || knownType == .unsafeMutablePointer { diff --git a/Sources/JExtractSwift/SwiftTypes/SwiftFunctionType.swift b/Sources/JExtractSwift/SwiftTypes/SwiftFunctionType.swift index 1e5637e3..565a24c3 100644 --- a/Sources/JExtractSwift/SwiftTypes/SwiftFunctionType.swift +++ b/Sources/JExtractSwift/SwiftTypes/SwiftFunctionType.swift @@ -27,7 +27,12 @@ struct SwiftFunctionType: Equatable { extension SwiftFunctionType: CustomStringConvertible { var description: String { - return "(\(parameters.map { $0.descriptionInType } )) -> \(resultType.description)" + let parameterString = parameters.map { $0.descriptionInType }.joined(separator: ", ") + let conventionPrefix = switch convention { + case .c: "@convention(c) " + case .swift: "" + } + return "\(conventionPrefix)(\(parameterString)) -> \(resultType.description)" } } diff --git a/Sources/JExtractSwift/SwiftTypes/SwiftParameter.swift b/Sources/JExtractSwift/SwiftTypes/SwiftParameter.swift index 4cdb27e8..24b3d8b4 100644 --- a/Sources/JExtractSwift/SwiftTypes/SwiftParameter.swift +++ b/Sources/JExtractSwift/SwiftTypes/SwiftParameter.swift @@ -64,8 +64,10 @@ extension SwiftParameter { var type = node.type var convention = SwiftParameterConvention.byValue if let attributedType = type.as(AttributedTypeSyntax.self) { + var sawUnknownSpecifier = false for specifier in attributedType.specifiers { guard case .simpleTypeSpecifier(let simple) = specifier else { + sawUnknownSpecifier = true continue } @@ -75,13 +77,15 @@ extension SwiftParameter { case .keyword(.inout): convention = .inout default: + sawUnknownSpecifier = true break } } // Ignore anything else in the attributed type. - // FIXME: We might want to check for these and ignore them. - type = attributedType.baseType + if !sawUnknownSpecifier && attributedType.attributes.isEmpty { + type = attributedType.baseType + } } self.convention = convention diff --git a/Sources/JExtractSwift/SwiftTypes/SwiftType.swift b/Sources/JExtractSwift/SwiftTypes/SwiftType.swift index d83d5e63..8ee0b767 100644 --- a/Sources/JExtractSwift/SwiftTypes/SwiftType.swift +++ b/Sources/JExtractSwift/SwiftTypes/SwiftType.swift @@ -129,12 +129,12 @@ extension SwiftType { // Only recognize the "@convention(c)" and "@convention(swift)" attributes, and // then only on function types. // FIXME: This string matching is a horrible hack. - switch attributedType.trimmedDescription { + switch attributedType.attributes.trimmedDescription { case "@convention(c)", "@convention(swift)": let innerType = try SwiftType(attributedType.baseType, symbolTable: symbolTable) switch innerType { case .function(var functionType): - let isConventionC = attributedType.trimmedDescription == "@convention(c)" + let isConventionC = attributedType.attributes.trimmedDescription == "@convention(c)" let convention: SwiftFunctionType.Convention = isConventionC ? .c : .swift functionType.convention = convention self = .function(functionType) diff --git a/Tests/JExtractSwiftTests/FunctionLoweringTests.swift b/Tests/JExtractSwiftTests/FunctionLoweringTests.swift index 3a036594..a17bfe26 100644 --- a/Tests/JExtractSwiftTests/FunctionLoweringTests.swift +++ b/Tests/JExtractSwiftTests/FunctionLoweringTests.swift @@ -296,4 +296,21 @@ final class FunctionLoweringTests { expectedCFunction: "c_getBufferPointer(void* _result_pointer, void* _result_count)" ) } + + @Test("Lowering C function types") + func lowerFunctionTypes() throws { + // FIXME: C pretty printing isn't handling parameters of function pointer + // type yet. + try assertLoweredFunction(""" + func doSomething(body: @convention(c) (Int32) -> Double) { } + """, + expectedCDecl: """ + @_cdecl("c_doSomething") + public func c_doSomething(_ body: @convention(c) (Int32) -> Double) { + doSomething(body: body) + } + """, + expectedCFunction: "void c_doSomething(double* body(int32_t))" + ) + } } From bfd791d69337b2b4b28f66dd2f624861175e00b6 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Mon, 3 Feb 2025 17:32:02 -0800 Subject: [PATCH 233/426] Improve printing of C types with better spacing and proper parentheses --- Sources/JExtractSwift/CTypes/CFunction.swift | 10 +- Sources/JExtractSwift/CTypes/CType.swift | 115 +++++++++++++++--- Tests/JExtractSwiftTests/CTypeTests.swift | 34 +++++- .../FunctionLoweringTests.swift | 32 ++--- 4 files changed, 147 insertions(+), 44 deletions(-) diff --git a/Sources/JExtractSwift/CTypes/CFunction.swift b/Sources/JExtractSwift/CTypes/CFunction.swift index 9dc69e41..0d01f383 100644 --- a/Sources/JExtractSwift/CTypes/CFunction.swift +++ b/Sources/JExtractSwift/CTypes/CFunction.swift @@ -48,10 +48,9 @@ extension CFunction: CustomStringConvertible { public var description: String { var result = "" - resultType.printBefore(result: &result) + var hasEmptyPlaceholder = false + resultType.printBefore(hasEmptyPlaceholder: &hasEmptyPlaceholder, result: &result) - // FIXME: parentheses when needed. - result += " " result += name // Function parameters. @@ -64,7 +63,10 @@ extension CFunction: CustomStringConvertible { ) result += ")" - resultType.printAfter(result: &result) + resultType.printAfter( + hasEmptyPlaceholder: &hasEmptyPlaceholder, + result: &result + ) result += "" return result diff --git a/Sources/JExtractSwift/CTypes/CType.swift b/Sources/JExtractSwift/CTypes/CType.swift index e69e89f4..699ccfaf 100644 --- a/Sources/JExtractSwift/CTypes/CType.swift +++ b/Sources/JExtractSwift/CTypes/CType.swift @@ -74,7 +74,14 @@ public enum CType { extension CType: CustomStringConvertible { /// Print the part of this type that comes before the declarator, appending /// it to the provided `result` string. - func printBefore(result: inout String) { + func printBefore(hasEmptyPlaceholder: inout Bool, result: inout String) { + // Save the value of hasEmptyPlaceholder and restore it once we're done + // here. + let previousHasEmptyPlaceholder = hasEmptyPlaceholder + defer { + hasEmptyPlaceholder = previousHasEmptyPlaceholder + } + switch self { case .floating(let floating): switch floating { @@ -82,11 +89,25 @@ extension CType: CustomStringConvertible { case .double: result += "double" } + spaceBeforePlaceHolder( + hasEmptyPlaceholder: hasEmptyPlaceholder, + result: &result + ) + case .function(resultType: let resultType, parameters: _, variadic: _): - resultType.printBefore(result: &result) + let previousHasEmptyPlaceholder = hasEmptyPlaceholder + hasEmptyPlaceholder = false + defer { + hasEmptyPlaceholder = previousHasEmptyPlaceholder + } + resultType.printBefore( + hasEmptyPlaceholder: &hasEmptyPlaceholder, + result: &result + ) - // FIXME: Clang inserts a parentheses in here if there's a non-empty - // placeholder, which is Very Stateful. How should I model that? + if !previousHasEmptyPlaceholder { + result += "(" + } case .integral(let integral): switch integral { @@ -97,21 +118,47 @@ extension CType: CustomStringConvertible { case .size_t: result += "size_t" } + spaceBeforePlaceHolder( + hasEmptyPlaceholder: hasEmptyPlaceholder, + result: &result + ) + case .pointer(let pointee): - pointee.printBefore(result: &result) + var innerHasEmptyPlaceholder = false + pointee.printBefore( + hasEmptyPlaceholder: &innerHasEmptyPlaceholder, + result: &result + ) result += "*" case .qualified(const: let isConst, volatile: let isVolatile, type: let underlying): - underlying.printBefore(result: &result) + if isConst || isVolatile { + hasEmptyPlaceholder = false + } + + underlying.printBefore(hasEmptyPlaceholder: &hasEmptyPlaceholder, result: &result) // FIXME: "east const" is easier to print correctly, so do that. We could // follow Clang and decide when it's correct to print "west const" by // splitting the qualifiers before we get here. if isConst { - result += " const" + result += "const" + hasEmptyPlaceholder = false + + spaceBeforePlaceHolder( + hasEmptyPlaceholder: hasEmptyPlaceholder, + result: &result + ) + } if isVolatile { - result += " volatile" + result += "volatile" + hasEmptyPlaceholder = false + + spaceBeforePlaceHolder( + hasEmptyPlaceholder: hasEmptyPlaceholder, + result: &result + ) } case .tag(let tag): @@ -121,7 +168,18 @@ extension CType: CustomStringConvertible { case .union(let cUnion): result += "union \(cUnion.name)" } - case .void: result += "void" + spaceBeforePlaceHolder( + hasEmptyPlaceholder: hasEmptyPlaceholder, + result: &result + ) + + case .void: + result += "void" + + spaceBeforePlaceHolder( + hasEmptyPlaceholder: hasEmptyPlaceholder, + result: &result + ) } } @@ -146,13 +204,14 @@ extension CType: CustomStringConvertible { /// Print the part of the type that comes after the declarator, appending /// it to the provided `result` string. - func printAfter(result: inout String) { + func printAfter(hasEmptyPlaceholder: inout Bool, result: inout String) { switch self { case .floating, .integral, .tag, .void: break case .function(resultType: let resultType, parameters: let parameters, variadic: let variadic): - // FIXME: Clang inserts a parentheses in here if there's a non-empty - // placeholder, which is Very Stateful. How should I model that? + if !hasEmptyPlaceholder { + result += ")" + } result += "(" @@ -167,26 +226,37 @@ extension CType: CustomStringConvertible { result += ")" - resultType.printAfter(result: &result) + var innerHasEmptyPlaceholder = false + resultType.printAfter( + hasEmptyPlaceholder: &innerHasEmptyPlaceholder, + result: &result + ) case .pointer(let pointee): - pointee.printAfter(result: &result) + var innerHasEmptyPlaceholder = false + pointee.printAfter( + hasEmptyPlaceholder: &innerHasEmptyPlaceholder, + result: &result + ) case .qualified(const: _, volatile: _, type: let underlying): - underlying.printAfter(result: &result) + underlying.printAfter( + hasEmptyPlaceholder: &hasEmptyPlaceholder, + result: &result + ) } } /// Print this type into a string, with the given placeholder as the name /// of the entity being declared. public func print(placeholder: String?) -> String { + var hasEmptyPlaceholder = (placeholder == nil) var result = "" - printBefore(result: &result) + printBefore(hasEmptyPlaceholder: &hasEmptyPlaceholder, result: &result) if let placeholder { - result += " " result += placeholder } - printAfter(result: &result) + printAfter(hasEmptyPlaceholder: &hasEmptyPlaceholder, result: &result) return result } @@ -194,6 +264,15 @@ extension CType: CustomStringConvertible { public var description: String { print(placeholder: nil) } + + private func spaceBeforePlaceHolder( + hasEmptyPlaceholder: Bool, + result: inout String + ) { + if !hasEmptyPlaceholder { + result += " " + } + } } extension CType { diff --git a/Tests/JExtractSwiftTests/CTypeTests.swift b/Tests/JExtractSwiftTests/CTypeTests.swift index c60a38b6..1599adeb 100644 --- a/Tests/JExtractSwiftTests/CTypeTests.swift +++ b/Tests/JExtractSwiftTests/CTypeTests.swift @@ -17,7 +17,7 @@ import Testing @Suite("C type system tests") struct CTypeTests { - @Test("Function declaration printing") + @Test("C function declaration printing") func testFunctionDeclarationPrint() { let malloc = CFunction( resultType: .pointer(.void), @@ -27,7 +27,7 @@ struct CTypeTests { ], isVariadic: false ) - #expect(malloc.description == "void* malloc(size_t size)") + #expect(malloc.description == "void *malloc(size_t size)") let free = CFunction( resultType: .void, @@ -37,7 +37,7 @@ struct CTypeTests { ], isVariadic: false ) - #expect(free.description == "void free(void* ptr)") + #expect(free.description == "void free(void *ptr)") let snprintf = CFunction( resultType: .integral(.signed(bits: 32)), @@ -58,8 +58,8 @@ struct CTypeTests { ], isVariadic: true ) - #expect(snprintf.description == "int32_t snprintf(int8_t* str, size_t size, int8_t const* format, ...)") - #expect(snprintf.functionType.description == "int32_t(int8_t*, size_t, int8_t const*, ...)") + #expect(snprintf.description == "int32_t snprintf(int8_t *str, size_t size, int8_t const *format, ...)") + #expect(snprintf.functionType.description == "int32_t (int8_t *, size_t, int8_t const *, ...)") let rand = CFunction( resultType: .integral(.signed(bits: 32)), @@ -68,6 +68,28 @@ struct CTypeTests { isVariadic: false ) #expect(rand.description == "int32_t rand(void)") - #expect(rand.functionType.description == "int32_t(void)") + #expect(rand.functionType.description == "int32_t (void)") + } + + @Test("C pointer declarator printing") + func testPointerDeclaratorPrinting() { + let doit = CFunction( + resultType: .void, + name: "doit", + parameters: [ + .init( + name: "body", + type: .pointer( + .function( + resultType: .void, + parameters: [.integral(.bool)], + variadic: false + ) + ) + ) + ], + isVariadic: false + ) + #expect(doit.description == "void doit(void (*body)(_Bool))") } } diff --git a/Tests/JExtractSwiftTests/FunctionLoweringTests.swift b/Tests/JExtractSwiftTests/FunctionLoweringTests.swift index a17bfe26..3104e291 100644 --- a/Tests/JExtractSwiftTests/FunctionLoweringTests.swift +++ b/Tests/JExtractSwiftTests/FunctionLoweringTests.swift @@ -30,7 +30,7 @@ final class FunctionLoweringTests { f(x: x, y: y, z: UnsafeBufferPointer(start: z_pointer.assumingMemoryBound(to: Bool.self), count: z_count)) } """, - expectedCFunction: "void c_f(ptrdiff_t x, float y, void const* z_pointer, ptrdiff_t z_count)" + expectedCFunction: "void c_f(ptrdiff_t x, float y, void const *z_pointer, ptrdiff_t z_count)" ) } @@ -45,7 +45,7 @@ final class FunctionLoweringTests { return f(t: (t_0, (t_1_0, t_1_1)), z: z_pointer.assumingMemoryBound(to: Int.self)) } """, - expectedCFunction: "ptrdiff_t c_f(ptrdiff_t t_0, float t_1_0, double t_1_1, void const* z_pointer)" + expectedCFunction: "ptrdiff_t c_f(ptrdiff_t t_0, float t_1_0, double t_1_1, void const *z_pointer)" ) } @@ -63,7 +63,7 @@ final class FunctionLoweringTests { shift(point: &point.assumingMemoryBound(to: Point.self).pointee, by: (delta_0, delta_1)) } """, - expectedCFunction: "void c_shift(void* point, double delta_0, double delta_1)" + expectedCFunction: "void c_shift(void *point, double delta_0, double delta_1)" ) } @@ -82,7 +82,7 @@ final class FunctionLoweringTests { _result.assumingMemoryBound(to: Point.self).initialize(to: self.assumingMemoryBound(to: Point.self).pointee.shifted(by: (delta_0, delta_1))) } """, - expectedCFunction: "void c_shifted(double delta_0, double delta_1, void const* self, void* _result)" + expectedCFunction: "void c_shifted(double delta_0, double delta_1, void const *self, void *_result)" ) } @@ -101,7 +101,7 @@ final class FunctionLoweringTests { self.assumingMemoryBound(to: Point.self).pointee.shift(by: (delta_0, delta_1)) } """, - expectedCFunction: "void c_shift(double delta_0, double delta_1, void* self)" + expectedCFunction: "void c_shift(double delta_0, double delta_1, void *self)" ) } @@ -120,7 +120,7 @@ final class FunctionLoweringTests { unsafeBitCast(self, to: Point.self).shift(by: (delta_0, delta_1)) } """, - expectedCFunction: "void c_shift(double delta_0, double delta_1, void const* self)" + expectedCFunction: "void c_shift(double delta_0, double delta_1, void const *self)" ) } @@ -139,7 +139,7 @@ final class FunctionLoweringTests { _result.assumingMemoryBound(to: Point.self).initialize(to: Point.scaledUnit(by: value)) } """, - expectedCFunction: "void c_scaledUnit(double value, void* _result)" + expectedCFunction: "void c_scaledUnit(double value, void *_result)" ) try assertLoweredFunction(""" @@ -155,7 +155,7 @@ final class FunctionLoweringTests { return unsafeBitCast(Person.randomPerson(seed: seed), to: UnsafeRawPointer.self) } """, - expectedCFunction: "void const* c_randomPerson(double seed)" + expectedCFunction: "void const *c_randomPerson(double seed)" ) } @@ -174,7 +174,7 @@ final class FunctionLoweringTests { _result.assumingMemoryBound(to: Point.self).initialize(to: Point(scaledBy: value)) } """, - expectedCFunction: "void c_init(double value, void* _result)" + expectedCFunction: "void c_init(double value, void *_result)" ) try assertLoweredFunction(""" @@ -190,7 +190,7 @@ final class FunctionLoweringTests { return unsafeBitCast(Person(seed: seed), to: UnsafeRawPointer.self) } """, - expectedCFunction: "void const* c_init(double seed)" + expectedCFunction: "void const *c_init(double seed)" ) } @@ -205,7 +205,7 @@ final class FunctionLoweringTests { f(t: unsafeBitCast(t, to: Int.self)) } """, - expectedCFunction: "void c_f(void const* t)" + expectedCFunction: "void c_f(void const *t)" ) try assertLoweredFunction(""" @@ -217,7 +217,7 @@ final class FunctionLoweringTests { return unsafeBitCast(f(), to: UnsafeRawPointer.self) } """, - expectedCFunction: "void const* c_f(void)" + expectedCFunction: "void const *c_f(void)" ) } @@ -236,7 +236,7 @@ final class FunctionLoweringTests { return unsafeBitCast(unsafeBitCast(self, to: Point.self).shifted(by: (delta_0, delta_1)), to: UnsafeRawPointer.self) } """, - expectedCFunction: "void const* c_shifted(double delta_0, double delta_1, void const* self)" + expectedCFunction: "void const *c_shifted(double delta_0, double delta_1, void const *self)" ) } @@ -254,7 +254,7 @@ final class FunctionLoweringTests { return UnsafeRawPointer(getPointer()) } """, - expectedCFunction: "void const* c_getPointer(void)" + expectedCFunction: "void const *c_getPointer(void)" ) } @@ -275,7 +275,7 @@ final class FunctionLoweringTests { _result_1_1.assumingMemoryBound(to: Point.self).initialize(to: __swift_result_1_1) } """, - expectedCFunction: "void c_getTuple(void* _result_0, void* _result_1_0, void* _result_1_1)" + expectedCFunction: "void c_getTuple(void *_result_0, void *_result_1_0, void *_result_1_1)" ) } @@ -310,7 +310,7 @@ final class FunctionLoweringTests { doSomething(body: body) } """, - expectedCFunction: "void c_doSomething(double* body(int32_t))" + expectedCFunction: "void c_doSomething(double (*body)(int32_t))" ) } } From e7bd5d09ad428fa931041821c86f727cd993cb1a Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Mon, 3 Feb 2025 17:53:11 -0800 Subject: [PATCH 234/426] Switch C type printing to prefer east const/volatile when possible Consistency be damned, it's what looks nice. Clang does it too. --- Sources/JExtractSwift/CTypes/CType.swift | 53 +++++++++++-------- Tests/JExtractSwiftTests/CTypeTests.swift | 15 +++++- .../FunctionLoweringTests.swift | 20 +++---- 3 files changed, 55 insertions(+), 33 deletions(-) diff --git a/Sources/JExtractSwift/CTypes/CType.swift b/Sources/JExtractSwift/CTypes/CType.swift index 699ccfaf..9b8744d0 100644 --- a/Sources/JExtractSwift/CTypes/CType.swift +++ b/Sources/JExtractSwift/CTypes/CType.swift @@ -132,33 +132,33 @@ extension CType: CustomStringConvertible { result += "*" case .qualified(const: let isConst, volatile: let isVolatile, type: let underlying): - if isConst || isVolatile { - hasEmptyPlaceholder = false + func printQualifier(_ qualifier: String, if condition: Bool) { + if condition { + result += qualifier + hasEmptyPlaceholder = false + + spaceBeforePlaceHolder( + hasEmptyPlaceholder: hasEmptyPlaceholder, + result: &result + ) + } } - underlying.printBefore(hasEmptyPlaceholder: &hasEmptyPlaceholder, result: &result) + let canPrefixQualifiers = underlying.canPrefixQualifiers + if canPrefixQualifiers { + printQualifier("const", if: isConst) + printQualifier("volatile", if: isVolatile) + } - // FIXME: "east const" is easier to print correctly, so do that. We could - // follow Clang and decide when it's correct to print "west const" by - // splitting the qualifiers before we get here. - if isConst { - result += "const" + if (isConst || isVolatile) && !canPrefixQualifiers { hasEmptyPlaceholder = false - - spaceBeforePlaceHolder( - hasEmptyPlaceholder: hasEmptyPlaceholder, - result: &result - ) - } - if isVolatile { - result += "volatile" - hasEmptyPlaceholder = false - spaceBeforePlaceHolder( - hasEmptyPlaceholder: hasEmptyPlaceholder, - result: &result - ) + underlying.printBefore(hasEmptyPlaceholder: &hasEmptyPlaceholder, result: &result) + + if !canPrefixQualifiers { + printQualifier("const", if: isConst) + printQualifier("volatile", if: isVolatile) } case .tag(let tag): @@ -265,6 +265,7 @@ extension CType: CustomStringConvertible { print(placeholder: nil) } + /// Print a space before the placeholder in a declarator. private func spaceBeforePlaceHolder( hasEmptyPlaceholder: Bool, result: inout String @@ -273,6 +274,16 @@ extension CType: CustomStringConvertible { result += " " } } + + /// Determine whether qualifiers can be printed before the given type + /// (`const int`) vs. having to be afterward to maintain semantics. + var canPrefixQualifiers: Bool { + switch self { + case .floating, .integral, .tag, .void: true + case .function, .pointer: false + case .qualified(const: _, volatile: _, type: let type): type.canPrefixQualifiers + } + } } extension CType { diff --git a/Tests/JExtractSwiftTests/CTypeTests.swift b/Tests/JExtractSwiftTests/CTypeTests.swift index 1599adeb..569296d6 100644 --- a/Tests/JExtractSwiftTests/CTypeTests.swift +++ b/Tests/JExtractSwiftTests/CTypeTests.swift @@ -58,8 +58,8 @@ struct CTypeTests { ], isVariadic: true ) - #expect(snprintf.description == "int32_t snprintf(int8_t *str, size_t size, int8_t const *format, ...)") - #expect(snprintf.functionType.description == "int32_t (int8_t *, size_t, int8_t const *, ...)") + #expect(snprintf.description == "int32_t snprintf(int8_t *str, size_t size, const int8_t *format, ...)") + #expect(snprintf.functionType.description == "int32_t (int8_t *, size_t, const int8_t *, ...)") let rand = CFunction( resultType: .integral(.signed(bits: 32)), @@ -91,5 +91,16 @@ struct CTypeTests { isVariadic: false ) #expect(doit.description == "void doit(void (*body)(_Bool))") + + let ptrptr = CType.pointer( + .qualified( + const: true, + volatile: false, + type: .pointer( + .qualified(const: false, volatile: true, type: .void) + ) + ) + ) + #expect(ptrptr.description == "volatile void *const *") } } diff --git a/Tests/JExtractSwiftTests/FunctionLoweringTests.swift b/Tests/JExtractSwiftTests/FunctionLoweringTests.swift index 3104e291..97fa95fc 100644 --- a/Tests/JExtractSwiftTests/FunctionLoweringTests.swift +++ b/Tests/JExtractSwiftTests/FunctionLoweringTests.swift @@ -30,7 +30,7 @@ final class FunctionLoweringTests { f(x: x, y: y, z: UnsafeBufferPointer(start: z_pointer.assumingMemoryBound(to: Bool.self), count: z_count)) } """, - expectedCFunction: "void c_f(ptrdiff_t x, float y, void const *z_pointer, ptrdiff_t z_count)" + expectedCFunction: "void c_f(ptrdiff_t x, float y, const void *z_pointer, ptrdiff_t z_count)" ) } @@ -45,7 +45,7 @@ final class FunctionLoweringTests { return f(t: (t_0, (t_1_0, t_1_1)), z: z_pointer.assumingMemoryBound(to: Int.self)) } """, - expectedCFunction: "ptrdiff_t c_f(ptrdiff_t t_0, float t_1_0, double t_1_1, void const *z_pointer)" + expectedCFunction: "ptrdiff_t c_f(ptrdiff_t t_0, float t_1_0, double t_1_1, const void *z_pointer)" ) } @@ -82,7 +82,7 @@ final class FunctionLoweringTests { _result.assumingMemoryBound(to: Point.self).initialize(to: self.assumingMemoryBound(to: Point.self).pointee.shifted(by: (delta_0, delta_1))) } """, - expectedCFunction: "void c_shifted(double delta_0, double delta_1, void const *self, void *_result)" + expectedCFunction: "void c_shifted(double delta_0, double delta_1, const void *self, void *_result)" ) } @@ -120,7 +120,7 @@ final class FunctionLoweringTests { unsafeBitCast(self, to: Point.self).shift(by: (delta_0, delta_1)) } """, - expectedCFunction: "void c_shift(double delta_0, double delta_1, void const *self)" + expectedCFunction: "void c_shift(double delta_0, double delta_1, const void *self)" ) } @@ -155,7 +155,7 @@ final class FunctionLoweringTests { return unsafeBitCast(Person.randomPerson(seed: seed), to: UnsafeRawPointer.self) } """, - expectedCFunction: "void const *c_randomPerson(double seed)" + expectedCFunction: "const void *c_randomPerson(double seed)" ) } @@ -190,7 +190,7 @@ final class FunctionLoweringTests { return unsafeBitCast(Person(seed: seed), to: UnsafeRawPointer.self) } """, - expectedCFunction: "void const *c_init(double seed)" + expectedCFunction: "const void *c_init(double seed)" ) } @@ -205,7 +205,7 @@ final class FunctionLoweringTests { f(t: unsafeBitCast(t, to: Int.self)) } """, - expectedCFunction: "void c_f(void const *t)" + expectedCFunction: "void c_f(const void *t)" ) try assertLoweredFunction(""" @@ -217,7 +217,7 @@ final class FunctionLoweringTests { return unsafeBitCast(f(), to: UnsafeRawPointer.self) } """, - expectedCFunction: "void const *c_f(void)" + expectedCFunction: "const void *c_f(void)" ) } @@ -236,7 +236,7 @@ final class FunctionLoweringTests { return unsafeBitCast(unsafeBitCast(self, to: Point.self).shifted(by: (delta_0, delta_1)), to: UnsafeRawPointer.self) } """, - expectedCFunction: "void const *c_shifted(double delta_0, double delta_1, void const *self)" + expectedCFunction: "const void *c_shifted(double delta_0, double delta_1, const void *self)" ) } @@ -254,7 +254,7 @@ final class FunctionLoweringTests { return UnsafeRawPointer(getPointer()) } """, - expectedCFunction: "void const *c_getPointer(void)" + expectedCFunction: "const void *c_getPointer(void)" ) } From 126661e0f559cbed2f97ff32c1fe5a8b242bd94c Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Tue, 15 Apr 2025 23:22:41 +0900 Subject: [PATCH 235/426] [jextract] CodePrinter indentation improvements Improve indentations. Introduce 'atNewline' property in the printer, to indicate if the next 'print()' should print the indentation on the first line. Stop handling single line 'print()' specially. --- Sources/JExtractSwift/CodePrinter.swift | 30 ++++++++++--------- .../ImportedDecls+Printing.swift | 6 ++-- .../Swift2JavaTranslator+Printing.swift | 13 ++++---- .../VariableImportTests.swift | 4 +-- 4 files changed, 27 insertions(+), 26 deletions(-) diff --git a/Sources/JExtractSwift/CodePrinter.swift b/Sources/JExtractSwift/CodePrinter.swift index 6e26b960..83669ebb 100644 --- a/Sources/JExtractSwift/CodePrinter.swift +++ b/Sources/JExtractSwift/CodePrinter.swift @@ -33,6 +33,8 @@ public struct CodePrinter { } } public var indentationText: String = "" + /// If true, next print() should starts with indentation. + var atNewline = true public static func toString(_ block: (inout CodePrinter) throws -> ()) rethrows -> String { var printer = CodePrinter() @@ -73,8 +75,8 @@ public struct CodePrinter { line: UInt = #line, body: (inout CodePrinter) -> () ) { - indent() print("\(text) {") + indent() body(&self) outdent() print("}", .sloc, function: function, file: file, line: line) @@ -113,27 +115,27 @@ public struct CodePrinter { file: String = #fileID, line: UInt = #line ) { - append(indentationText) - - let lines = "\(text)".split(separator: "\n") - if indentationDepth > 0 && lines.count > 1 { - for line in lines { - append(indentationText) - append(contentsOf: line) + let lines = "\(text)".split(separator: "\n", omittingEmptySubsequences: false) + var first = true + for line in lines { + if !first { append("\n") + append(indentationText) + } else { + if atNewline { + append(indentationText) + } + first = false } - } else { - append("\(text)") + append(contentsOf: line) } if terminator == .sloc { append(" // \(function) @ \(file):\(line)\n") - append(indentationText) + atNewline = true } else { append(terminator.rawValue) - if terminator == .newLine || terminator == .commaNewLine { - append(indentationText) - } + atNewline = terminator == .newLine || terminator == .commaNewLine } } diff --git a/Sources/JExtractSwift/ImportedDecls+Printing.swift b/Sources/JExtractSwift/ImportedDecls+Printing.swift index 966b5a3d..bc755015 100644 --- a/Sources/JExtractSwift/ImportedDecls+Printing.swift +++ b/Sources/JExtractSwift/ImportedDecls+Printing.swift @@ -22,9 +22,9 @@ extension ImportedFunc { var renderCommentSnippet: String? { if let syntax { """ - * {@snippet lang=swift : - * \(syntax) - * } + * {@snippet lang=swift : + * \(syntax) + * } """ } else { nil diff --git a/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift b/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift index af85a214..41c3477b 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift @@ -510,7 +510,7 @@ extension Swift2JavaTranslator { /** * Create an instance of {@code \(parentName.unqualifiedJavaTypeName)}. * - \(decl.renderCommentSnippet ?? " *") + \(decl.renderCommentSnippet ?? " *") */ public \(parentName.unqualifiedJavaTypeName)(\(renderJavaParamDecls(decl, paramPassingStyle: .wrapper))) { this(/*arena=*/null, \(renderForwardJavaParams(decl, paramPassingStyle: .wrapper))); @@ -543,7 +543,7 @@ extension Swift2JavaTranslator { * Create an instance of {@code \(parentName.unqualifiedJavaTypeName)}. * This instance is managed by the passed in {@link SwiftArena} and may not outlive the arena's lifetime. * - \(decl.renderCommentSnippet ?? " *") + \(decl.renderCommentSnippet ?? " *") */ public \(parentName.unqualifiedJavaTypeName)(SwiftArena arena, \(renderJavaParamDecls(decl, paramPassingStyle: .wrapper))) { var mh$ = \(descClassIdentifier).HANDLE; @@ -601,7 +601,7 @@ extension Swift2JavaTranslator { """ /** * Address for: - \(snippet) + \(snippet) */ public static MemorySegment \(decl.baseIdentifier)\(methodNameSegment)$address() { return \(decl.baseIdentifier).\(addrName); @@ -623,7 +623,7 @@ extension Swift2JavaTranslator { """ /** * Downcall method handle for: - \(snippet) + \(snippet) */ public static MethodHandle \(decl.baseIdentifier)\(methodNameSegment)$handle() { return \(decl.baseIdentifier).\(handleName); @@ -645,7 +645,7 @@ extension Swift2JavaTranslator { """ /** * Function descriptor for: - \(snippet) + \(snippet) */ public static FunctionDescriptor \(decl.baseIdentifier)\(methodNameSegment)$descriptor() { return \(decl.baseIdentifier).\(descName); @@ -744,7 +744,7 @@ extension Swift2JavaTranslator { """ /** * Downcall to Swift: - \(decl.renderCommentSnippet ?? "* ") + \(decl.renderCommentSnippet ?? "* ") */ """ @@ -1065,7 +1065,6 @@ extension Swift2JavaTranslator { } else { printer.print("FunctionDescriptor.of(") printer.indent() - printer.print("", .continue) // Write return type let returnTyIsLastTy = decl.parameters.isEmpty && !decl.hasParent diff --git a/Tests/JExtractSwiftTests/VariableImportTests.swift b/Tests/JExtractSwiftTests/VariableImportTests.swift index 0d45b08b..7a97e195 100644 --- a/Tests/JExtractSwiftTests/VariableImportTests.swift +++ b/Tests/JExtractSwiftTests/VariableImportTests.swift @@ -47,7 +47,7 @@ final class VariableImportTests { expectedChunks: [ """ private static class counterInt { - public static final FunctionDescriptor DESC_GET = FunctionDescriptor.of( + public static final FunctionDescriptor DESC_GET = FunctionDescriptor.of( /* -> */SWIFT_INT, /*self$*/SWIFT_POINTER ); @@ -55,7 +55,7 @@ final class VariableImportTests { FakeModule.findOrThrow("swiftjava_FakeModule_MySwiftClass_counterInt"); public static final MethodHandle HANDLE_GET = Linker.nativeLinker().downcallHandle(ADDR_GET, DESC_GET); - public static final FunctionDescriptor DESC_SET = FunctionDescriptor.ofVoid( + public static final FunctionDescriptor DESC_SET = FunctionDescriptor.ofVoid( /*newValue*/SWIFT_INT, /*self$*/SWIFT_POINTER ); From 36e74f60d8517e08269c1bf7c7e4c61a87a71f20 Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Tue, 15 Apr 2025 23:41:01 +0900 Subject: [PATCH 236/426] [jextract] Prepare all inputs before analyze() Register all the files to `Swift2JavaTranslator` (and `NominalTypeResolution`) and `analye()` all the files at once. `Swift2JavaVisitor.visit(_: ExtentionDeclSyntax)` requires all the nominal types are prepared in the `nominalResolution`. Otherwise it's just ignored. Also previously, writing files happend for each file iteration but actually, it is not a per-source file operation. Instead, it only writes the current state of the translator. --- Sources/JExtractSwift/Swift2Java.swift | 23 ++++++--- .../JExtractSwift/Swift2JavaTranslator.swift | 50 +++++++++++-------- .../Asserts/LoweringAssertions.swift | 4 +- 3 files changed, 46 insertions(+), 31 deletions(-) diff --git a/Sources/JExtractSwift/Swift2Java.swift b/Sources/JExtractSwift/Swift2Java.swift index a46d1ab4..5eaab18a 100644 --- a/Sources/JExtractSwift/Swift2Java.swift +++ b/Sources/JExtractSwift/Swift2Java.swift @@ -74,16 +74,23 @@ public struct SwiftToJava: ParsableCommand { } } - for file in allFiles where canExtract(from: file) { - translator.log.debug("Importing module '\(swiftModule)', file: \(file)") - - try translator.analyze(file: file.path) - try translator.writeExportedJavaSources(outputDirectory: outputDirectoryJava) - try translator.writeSwiftThunkSources(outputDirectory: outputDirectorySwift) - - log.debug("[swift-java] Imported interface file: \(file.path)") + // Register files to the translator. + for file in allFiles { + guard canExtract(from: file) else { + continue + } + guard let data = fileManager.contents(atPath: file.path) else { + continue + } + guard let text = String(data:data, encoding: .utf8) else { + continue + } + translator.add(filePath: file.path, text: text) } + try translator.analyze() + try translator.writeSwiftThunkSources(outputDirectory: outputDirectorySwift) + try translator.writeExportedJavaSources(outputDirectory: outputDirectoryJava) try translator.writeExportedJavaModule(outputDirectory: outputDirectoryJava) print("[swift-java] Generated Java sources (\(packageName)) in: \(outputDirectoryJava)/") print("[swift-java] Imported Swift module '\(swiftModule)': " + "done.".green) diff --git a/Sources/JExtractSwift/Swift2JavaTranslator.swift b/Sources/JExtractSwift/Swift2JavaTranslator.swift index 6577a37c..446dd4c2 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator.swift @@ -24,6 +24,15 @@ public final class Swift2JavaTranslator { package var log = Logger(label: "translator", logLevel: .info) + // ==== Input + + struct Input { + let filePath: String + let syntax: Syntax + } + + var inputs: [Input] = [] + // ==== Output configuration let javaPackage: String @@ -39,7 +48,7 @@ public final class Swift2JavaTranslator { /// type representation. package var importedTypes: [String: ImportedNominalType] = [:] - public var swiftStdlibTypes: SwiftStandardLibraryTypes + package var swiftStdlibTypes: SwiftStandardLibraryTypes let symbolTable: SwiftSymbolTable let nominalResolution: NominalTypeResolution = NominalTypeResolution() @@ -78,26 +87,24 @@ extension Swift2JavaTranslator { /// a checked truncation operation at the Java/Swift board. var javaPrimitiveForSwiftInt: JavaType { .long } - public func analyze( + package func add(filePath: String, text: String) { + log.trace("Adding: \(filePath)") + let sourceFileSyntax = Parser.parse(source: text) + self.nominalResolution.addSourceFile(sourceFileSyntax) + self.inputs.append(Input(filePath: filePath, syntax: Syntax(sourceFileSyntax))) + } + + /// Convenient method for analyzing single file. + package func analyze( file: String, - text: String? = nil + text: String ) throws { - guard text != nil || FileManager.default.fileExists(atPath: file) else { - throw Swift2JavaTranslatorError(message: "Missing input file: \(file)") - } - - log.trace("Analyze: \(file)") - let text = try text ?? String(contentsOfFile: file) - - try analyzeSwiftInterface(interfaceFilePath: file, text: text) - - log.debug("Done processing: \(file)") + self.add(filePath: file, text: text) + try self.analyze() } - package func analyzeSwiftInterface(interfaceFilePath: String, text: String) throws { - let sourceFileSyntax = Parser.parse(source: text) - - addSourceFile(sourceFileSyntax) + /// Analyze registered inputs. + func analyze() throws { prepareForTranslation() let visitor = Swift2JavaVisitor( @@ -105,16 +112,17 @@ extension Swift2JavaTranslator { targetJavaPackage: self.javaPackage, translator: self ) - visitor.walk(sourceFileSyntax) - } - package func addSourceFile(_ sourceFile: SourceFileSyntax) { - nominalResolution.addSourceFile(sourceFile) + for input in self.inputs { + log.trace("Analyzing \(input.filePath)") + visitor.walk(input.syntax) + } } package func prepareForTranslation() { nominalResolution.bindExtensions() + // Prepare symbol table for nominal type names. for (_, node) in nominalResolution.topLevelNominalTypes { symbolTable.parsedModule.addNominalTypeDeclaration(node, parent: nil) } diff --git a/Tests/JExtractSwiftTests/Asserts/LoweringAssertions.swift b/Tests/JExtractSwiftTests/Asserts/LoweringAssertions.swift index 6f7a5e83..c37325cb 100644 --- a/Tests/JExtractSwiftTests/Asserts/LoweringAssertions.swift +++ b/Tests/JExtractSwiftTests/Asserts/LoweringAssertions.swift @@ -22,7 +22,7 @@ func assertLoweredFunction( _ inputDecl: DeclSyntax, javaPackage: String = "org.swift.mypackage", swiftModuleName: String = "MyModule", - sourceFile: SourceFileSyntax? = nil, + sourceFile: String? = nil, enclosingType: TypeSyntax? = nil, expectedCDecl: DeclSyntax, expectedCFunction: String, @@ -37,7 +37,7 @@ func assertLoweredFunction( ) if let sourceFile { - translator.addSourceFile(sourceFile) + translator.add(filePath: "Fake.swift", text: sourceFile) } translator.prepareForTranslation() From 5c6d7ba6aede3284adedde1d5b483c4f982da548 Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Wed, 16 Apr 2025 00:13:26 +0900 Subject: [PATCH 237/426] [jextract] Misc improvements * Introduce `Swift2JavaVisitor.typeContext` to handle nested types * Unify `shouldImport(log:)` method using `WithModifiersSyntax & WithAttributesSyntax` * Unify `accessControlModifiers` as an extention to `WithModifiersSyntax` * Don't import `JavaKit` declarations. e.g. `@JavaClass` * Don't import non-public variable decls. * Introduce `DeclSyntaxProtocol.qualifiedNameForDebug` and use it for log messages * Introduce `DeclSyntaxProtocol.signatureString` and use it as the snippet in the exported `.java` files. --- .../Convenience/SwiftSyntax+Extensions.swift | 163 ++++++++++++++++-- Sources/JExtractSwift/ImportedDecls.swift | 2 +- .../JExtractSwift/NominalTypeResolution.swift | 2 +- .../JExtractSwift/Swift2JavaTranslator.swift | 2 +- Sources/JExtractSwift/Swift2JavaVisitor.swift | 90 +++++----- .../FunctionDescriptorImportTests.swift | 2 +- .../MethodImportTests.swift | 4 +- 7 files changed, 200 insertions(+), 65 deletions(-) diff --git a/Sources/JExtractSwift/Convenience/SwiftSyntax+Extensions.swift b/Sources/JExtractSwift/Convenience/SwiftSyntax+Extensions.swift index 6b814f8a..a7c12cc9 100644 --- a/Sources/JExtractSwift/Convenience/SwiftSyntax+Extensions.swift +++ b/Sources/JExtractSwift/Convenience/SwiftSyntax+Extensions.swift @@ -15,23 +15,7 @@ import SwiftDiagnostics import SwiftSyntax -extension DeclGroupSyntax { - internal var accessControlModifiers: DeclModifierListSyntax { - modifiers.filter { modifier in - modifier.isAccessControl - } - } -} - -extension FunctionDeclSyntax { - internal var accessControlModifiers: DeclModifierListSyntax { - modifiers.filter { modifier in - modifier.isAccessControl - } - } -} - -extension VariableDeclSyntax { +extension WithModifiersSyntax { internal var accessControlModifiers: DeclModifierListSyntax { modifiers.filter { modifier in modifier.isAccessControl @@ -89,7 +73,7 @@ extension DeclModifierSyntax { var isAccessControl: Bool { switch self.name.tokenKind { case .keyword(.private), .keyword(.fileprivate), .keyword(.internal), .keyword(.package), - .keyword(.public): + .keyword(.public), .keyword(.open): return true default: return false @@ -105,7 +89,150 @@ extension DeclModifierSyntax { case .keyword(.internal): return false case .keyword(.package): return false case .keyword(.public): return true + case .keyword(.open): return true default: return false } } } + +extension WithModifiersSyntax { + var isPublic: Bool { + self.modifiers.contains { modifier in + modifier.isPublic + } + } +} + +extension AttributeListSyntax.Element { + /// Whether this node has `JavaKit` attributes. + var isJava: Bool { + guard case let .attribute(attr) = self else { + // FIXME: Handle #if. + return false + } + let attrName = attr.attributeName.description + switch attrName { + case "JavaClass", "JavaInterface", "JavaField", "JavaStaticField", "JavaMethod", "JavaStaticMethod", "JavaImplementation": + return true + default: + return false + } + } +} + +extension DeclSyntaxProtocol { + /// Find inner most "decl" node in ancestors. + var ancestorDecl: DeclSyntax? { + var node: Syntax = Syntax(self) + while let parent = node.parent { + if let decl = parent.as(DeclSyntax.self) { + return decl + } + node = parent + } + return nil + } + + /// Declaration name primarily for debugging. + var nameForDebug: String { + return switch DeclSyntax(self).as(DeclSyntaxEnum.self) { + case .accessorDecl(let node): + node.accessorSpecifier.text + case .actorDecl(let node): + node.name.text + case .associatedTypeDecl(let node): + node.name.text + case .classDecl(let node): + node.name.text + case .deinitializerDecl(_): + "deinit" + case .editorPlaceholderDecl: + "" + case .enumCaseDecl(let node): + // FIXME: Handle multiple elements. + if let element = node.elements.first { + element.name.text + } else { + "case" + } + case .enumDecl(let node): + node.name.text + case .extensionDecl(let node): + node.extendedType.description + case .functionDecl(let node): + node.name.text + "(" + node.signature.parameterClause.parameters.map({ $0.firstName.text + ":" }).joined() + ")" + case .ifConfigDecl(_): + "#if" + case .importDecl(_): + "import" + case .initializerDecl(let node): + "init" + "(" + node.signature.parameterClause.parameters.map({ $0.firstName.text + ":" }).joined() + ")" + case .macroDecl(let node): + node.name.text + case .macroExpansionDecl(let node): + "#" + node.macroName.trimmedDescription + case .missingDecl(_): + "(missing)" + case .operatorDecl(let node): + node.name.text + case .poundSourceLocation(_): + "#sourceLocation" + case .precedenceGroupDecl(let node): + node.name.text + case .protocolDecl(let node): + node.name.text + case .structDecl(let node): + node.name.text + case .subscriptDecl(let node): + "subscript" + "(" + node.parameterClause.parameters.map({ $0.firstName.text + ":" }).joined() + ")" + case .typeAliasDecl(let node): + node.name.text + case .variableDecl(let node): + // FIXME: Handle multiple variables. + if let element = node.bindings.first { + element.pattern.trimmedDescription + } else { + "var" + } + } + } + + /// Qualified declaration name primarily for debugging. + var qualifiedNameForDebug: String { + if let parent = ancestorDecl { + parent.qualifiedNameForDebug + "." + nameForDebug + } else { + nameForDebug + } + } + + /// Signature part of the declaration. I.e. without body or member block. + var signatureString: String { + return switch DeclSyntax(self.detached).as(DeclSyntaxEnum.self) { + case .functionDecl(let node): + node.with(\.body, nil).trimmedDescription + case .initializerDecl(let node): + node.with(\.body, nil).trimmedDescription + case .classDecl(let node): + node.with(\.memberBlock, "").trimmedDescription + case .structDecl(let node): + node.with(\.memberBlock, "").trimmedDescription + case .protocolDecl(let node): + node.with(\.memberBlock, "").trimmedDescription + case .accessorDecl(let node): + node.with(\.body, nil).trimmedDescription + case .variableDecl(let node): + node + .with(\.bindings, PatternBindingListSyntax( + node.bindings.map { + $0.detached + .with(\.accessorBlock, nil) + .with(\.initializer, nil) + } + )) + .trimmedDescription + default: + fatalError("unimplemented \(self.kind)") + } + } +} diff --git a/Sources/JExtractSwift/ImportedDecls.swift b/Sources/JExtractSwift/ImportedDecls.swift index 72204e66..c246dcbc 100644 --- a/Sources/JExtractSwift/ImportedDecls.swift +++ b/Sources/JExtractSwift/ImportedDecls.swift @@ -261,7 +261,7 @@ public struct ImportedFunc: ImportedDecl, CustomStringConvertible { public var swiftDecl: any DeclSyntaxProtocol public var syntax: String? { - "\(self.swiftDecl)" + self.swiftDecl.signatureString } public var isInit: Bool = false diff --git a/Sources/JExtractSwift/NominalTypeResolution.swift b/Sources/JExtractSwift/NominalTypeResolution.swift index d2421a24..b1185cde 100644 --- a/Sources/JExtractSwift/NominalTypeResolution.swift +++ b/Sources/JExtractSwift/NominalTypeResolution.swift @@ -38,7 +38,7 @@ public class NominalTypeResolution { /// A syntax node for a nominal type declaration. @_spi(Testing) -public typealias NominalTypeDeclSyntaxNode = any DeclGroupSyntax & NamedDeclSyntax +public typealias NominalTypeDeclSyntaxNode = any DeclGroupSyntax & NamedDeclSyntax & WithAttributesSyntax & WithModifiersSyntax // MARK: Nominal type name resolution. extension NominalTypeResolution { diff --git a/Sources/JExtractSwift/Swift2JavaTranslator.swift b/Sources/JExtractSwift/Swift2JavaTranslator.swift index 6577a37c..8c0c78c6 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator.swift @@ -159,7 +159,7 @@ extension Swift2JavaTranslator { /// Try to resolve the given nominal type node into its imported /// representation. func importedNominalType( - _ nominal: some DeclGroupSyntax & NamedDeclSyntax + _ nominal: some DeclGroupSyntax & NamedDeclSyntax & WithModifiersSyntax & WithAttributesSyntax ) -> ImportedNominalType? { if !nominal.shouldImport(log: log) { return nil diff --git a/Sources/JExtractSwift/Swift2JavaVisitor.swift b/Sources/JExtractSwift/Swift2JavaVisitor.swift index 5b577589..96aab517 100644 --- a/Sources/JExtractSwift/Swift2JavaVisitor.swift +++ b/Sources/JExtractSwift/Swift2JavaVisitor.swift @@ -26,7 +26,11 @@ final class Swift2JavaVisitor: SyntaxVisitor { /// store this along with type names as we import them. let targetJavaPackage: String - var currentType: ImportedNominalType? = nil + /// Type context stack associated with the syntax. + var typeContext: [(syntaxID: Syntax.ID, type: ImportedNominalType)] = [] + + /// Innermost type context. + var currentType: ImportedNominalType? { typeContext.last?.type } /// The current type name as a nested name like A.B.C. var currentTypeName: String? { self.currentType?.swiftTypeName } @@ -41,37 +45,50 @@ final class Swift2JavaVisitor: SyntaxVisitor { super.init(viewMode: .all) } + /// Push specified type to the type context associated with the syntax. + func pushTypeContext(syntax: some SyntaxProtocol, importedNominal: ImportedNominalType) { + typeContext.append((syntax.id, importedNominal)) + } + + /// Pop type context if the current context is associated with the syntax. + func popTypeContext(syntax: some SyntaxProtocol) -> Bool { + if typeContext.last?.syntaxID == syntax.id { + typeContext.removeLast() + return true + } else { + return false + } + } + override func visit(_ node: ClassDeclSyntax) -> SyntaxVisitorContinueKind { - log.debug("Visit \(node.kind): \(node)") + log.debug("Visit \(node.kind): '\(node.qualifiedNameForDebug)'") guard let importedNominalType = translator.importedNominalType(node) else { return .skipChildren } - self.currentType = importedNominalType + self.pushTypeContext(syntax: node, importedNominal: importedNominalType) return .visitChildren } override func visitPost(_ node: ClassDeclSyntax) { - if currentType != nil { + if self.popTypeContext(syntax: node) { log.debug("Completed import: \(node.kind) \(node.name)") - self.currentType = nil } } override func visit(_ node: StructDeclSyntax) -> SyntaxVisitorContinueKind { - log.debug("Visit \(node.kind): \(node)") + log.debug("Visit \(node.kind): \(node.qualifiedNameForDebug)") guard let importedNominalType = translator.importedNominalType(node) else { return .skipChildren } - self.currentType = importedNominalType + self.pushTypeContext(syntax: node, importedNominal: importedNominalType) return .visitChildren } override func visitPost(_ node: StructDeclSyntax) { - if currentType != nil { - log.debug("Completed import: \(node.kind) \(node.name)") - self.currentType = nil + if self.popTypeContext(syntax: node) { + log.debug("Completed import: \(node.kind) \(node.qualifiedNameForDebug)") } } @@ -84,13 +101,13 @@ final class Swift2JavaVisitor: SyntaxVisitor { return .skipChildren } - self.currentType = importedNominalType + self.pushTypeContext(syntax: node, importedNominal: importedNominalType) return .visitChildren } override func visitPost(_ node: ExtensionDeclSyntax) { - if currentType != nil { - self.currentType = nil + if self.popTypeContext(syntax: node) { + log.debug("Completed import: \(node.kind) \(node.qualifiedNameForDebug)") } } @@ -148,6 +165,10 @@ final class Swift2JavaVisitor: SyntaxVisitor { } override func visit(_ node: VariableDeclSyntax) -> SyntaxVisitorContinueKind { + guard node.shouldImport(log: log) else { + return .skipChildren + } + guard let binding = node.bindings.first else { return .skipChildren } @@ -156,7 +177,7 @@ final class Swift2JavaVisitor: SyntaxVisitor { // TODO: filter out kinds of variables we cannot import - self.log.debug("Import variable: \(node.kind) \(fullName)") + self.log.debug("Import variable: \(node.kind) '\(node.qualifiedNameForDebug)'") let returnTy: TypeSyntax if let typeAnnotation = binding.typeAnnotation { @@ -169,7 +190,7 @@ final class Swift2JavaVisitor: SyntaxVisitor { do { javaResultType = try cCompatibleType(for: returnTy) } catch { - self.log.info("Unable to import variable \(node.debugDescription) - \(error)") + log.info("Unable to import variable '\(node.qualifiedNameForDebug)' - \(error)") return .skipChildren } @@ -190,7 +211,7 @@ final class Swift2JavaVisitor: SyntaxVisitor { log.debug("Record variable in \(currentTypeName)") translator.importedTypes[currentTypeName]!.variables.append(varDecl) } else { - fatalError("Global variables are not supported yet: \(node.debugDescription)") + fatalError("Global variables are not supported yet: \(node.qualifiedNameForDebug)") } return .skipChildren @@ -206,7 +227,7 @@ final class Swift2JavaVisitor: SyntaxVisitor { return .skipChildren } - self.log.debug("Import initializer: \(node.kind) \(currentType.javaType.description)") + self.log.debug("Import initializer: \(node.kind) '\(node.qualifiedNameForDebug)'") let params: [ImportedParam] do { params = try node.signature.parameterClause.parameters.map { param in @@ -247,37 +268,24 @@ final class Swift2JavaVisitor: SyntaxVisitor { } } -extension DeclGroupSyntax where Self: NamedDeclSyntax { +extension DeclSyntaxProtocol where Self: WithModifiersSyntax & WithAttributesSyntax { func shouldImport(log: Logger) -> Bool { - guard (accessControlModifiers.first { $0.isPublic }) != nil else { - log.trace("Cannot import \(self.name) because: is not public") + guard accessControlModifiers.contains(where: { $0.isPublic }) else { + log.trace("Skip import '\(self.qualifiedNameForDebug)': not public") return false } - - return true - } -} - -extension InitializerDeclSyntax { - func shouldImport(log: Logger) -> Bool { - let isFailable = self.optionalMark != nil - - if isFailable { - log.warning("Skip importing failable initializer: \(self)") + guard !attributes.contains(where: { $0.isJava }) else { + log.trace("Skip import '\(self.qualifiedNameForDebug)': is Java") return false } - // Ok, import it - log.warning("Import initializer: \(self)") - return true - } -} + if let node = self.as(InitializerDeclSyntax.self) { + let isFailable = node.optionalMark != nil -extension FunctionDeclSyntax { - func shouldImport(log: Logger) -> Bool { - guard (accessControlModifiers.first { $0.isPublic }) != nil else { - log.trace("Cannot import \(self.name) because: is not public") - return false + if isFailable { + log.warning("Skip import '\(self.qualifiedNameForDebug)': failable initializer") + return false + } } return true diff --git a/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift b/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift index 734d9eab..38d43432 100644 --- a/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift +++ b/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift @@ -49,7 +49,7 @@ final class FunctionDescriptorTests { // #MySwiftClass.counter!getter: (MySwiftClass) -> () -> Int32 : @$s14MySwiftLibrary0aB5ClassC7counters5Int32Vvg\t// MySwiftClass.counter.getter // #MySwiftClass.counter!setter: (MySwiftClass) -> (Int32) -> () : @$s14MySwiftLibrary0aB5ClassC7counters5Int32Vvs\t// MySwiftClass.counter.setter // #MySwiftClass.counter!modify: (MySwiftClass) -> () -> () : @$s14MySwiftLibrary0aB5ClassC7counters5Int32VvM\t// MySwiftClass.counter.modify - var counter: Int32 + public var counter: Int32 } """ diff --git a/Tests/JExtractSwiftTests/MethodImportTests.swift b/Tests/JExtractSwiftTests/MethodImportTests.swift index 39d72dc0..38cfd8f2 100644 --- a/Tests/JExtractSwiftTests/MethodImportTests.swift +++ b/Tests/JExtractSwiftTests/MethodImportTests.swift @@ -483,7 +483,7 @@ final class MethodImportTests { * Create an instance of {@code MySwiftStruct}. * * {@snippet lang=swift : - * public init(len: Swift.Int, cap: Swift.Int) {} + * public init(len: Swift.Int, cap: Swift.Int) * } */ public MySwiftStruct(long len, long cap) { @@ -494,7 +494,7 @@ final class MethodImportTests { * This instance is managed by the passed in {@link SwiftArena} and may not outlive the arena's lifetime. * * {@snippet lang=swift : - * public init(len: Swift.Int, cap: Swift.Int) {} + * public init(len: Swift.Int, cap: Swift.Int) * } */ From 2d48cb4f9139c0421c841254912dbf4c247b5536 Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Wed, 16 Apr 2025 00:29:47 +0900 Subject: [PATCH 238/426] [jextract/JExtractSwiftCommandPlugin] Pass extra arguments to the tool Pass `swift package jextract` arguments to `JExtractSwiftTool`. E.g. `swift package jextract --log-level debug` --- .../JExtractSwiftCommandPlugin.swift | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/Plugins/JExtractSwiftCommandPlugin/JExtractSwiftCommandPlugin.swift b/Plugins/JExtractSwiftCommandPlugin/JExtractSwiftCommandPlugin.swift index 65ce8971..d6cfb7cb 100644 --- a/Plugins/JExtractSwiftCommandPlugin/JExtractSwiftCommandPlugin.swift +++ b/Plugins/JExtractSwiftCommandPlugin/JExtractSwiftCommandPlugin.swift @@ -40,14 +40,6 @@ final class JExtractSwiftCommandPlugin: SwiftJavaPluginProtocol, BuildToolPlugin // Plugin can't have dependencies, so we have some naive argument parsing instead: self.verbose = arguments.contains("-v") || arguments.contains("--verbose") - let selectedTargets: [String] = - if let last = arguments.lastIndex(where: { $0.starts(with: "-")}), - last < arguments.endIndex { - Array(arguments[.. Date: Mon, 26 May 2025 12:13:56 +0200 Subject: [PATCH 239/426] Move layout constants from generated code to SwiftKit --- .../JavaConstants/ForeignValueLayouts.swift | 2 +- .../Swift2JavaTranslator+Printing.swift | 43 +------------------ .../org/swift/swiftkit/SwiftValueLayout.java | 20 ++++++--- .../FunctionDescriptorImportTests.swift | 18 ++++---- .../VariableImportTests.swift | 8 ++-- 5 files changed, 28 insertions(+), 63 deletions(-) diff --git a/Sources/JExtractSwift/JavaConstants/ForeignValueLayouts.swift b/Sources/JExtractSwift/JavaConstants/ForeignValueLayouts.swift index 190f9993..9b9d4ece 100644 --- a/Sources/JExtractSwift/JavaConstants/ForeignValueLayouts.swift +++ b/Sources/JExtractSwift/JavaConstants/ForeignValueLayouts.swift @@ -57,7 +57,7 @@ public struct ForeignValueLayout: CustomStringConvertible, Equatable { result.append("/*\(inlineComment)*/") } - result.append("\(value)") + result.append("SwiftValueLayout.\(value)") // When the type is some custom type, e.g. another Swift struct that we imported, // we need to import its layout. We do this by calling $layout() on it. diff --git a/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift b/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift index 41c3477b..c8a26382 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift @@ -298,7 +298,6 @@ extension Swift2JavaTranslator { // Constants printClassConstants(printer: &printer) - printTypeMappingDecls(&printer) body(&printer) } @@ -310,7 +309,6 @@ extension Swift2JavaTranslator { // Constants printClassConstants(printer: &printer) - printTypeMappingDecls(&printer) printer.print( """ @@ -443,45 +441,6 @@ extension Swift2JavaTranslator { ) } - public func printTypeMappingDecls(_ printer: inout CodePrinter) { - // TODO: use some dictionary for those - printer.print( - """ - // TODO: rather than the C ones offer the Swift mappings - public static final ValueLayout.OfBoolean C_BOOL = ValueLayout.JAVA_BOOLEAN; - public static final ValueLayout.OfByte C_CHAR = ValueLayout.JAVA_BYTE; - public static final ValueLayout.OfShort C_SHORT = ValueLayout.JAVA_SHORT; - public static final ValueLayout.OfInt C_INT = ValueLayout.JAVA_INT; - public static final ValueLayout.OfLong C_LONG_LONG = ValueLayout.JAVA_LONG; - public static final ValueLayout.OfFloat C_FLOAT = ValueLayout.JAVA_FLOAT; - public static final ValueLayout.OfDouble C_DOUBLE = ValueLayout.JAVA_DOUBLE; - public static final AddressLayout C_POINTER = ValueLayout.ADDRESS - .withTargetLayout(MemoryLayout.sequenceLayout(java.lang.Long.MAX_VALUE, ValueLayout.JAVA_BYTE)); - public static final ValueLayout.OfLong C_LONG = ValueLayout.JAVA_LONG; - """ - ) - printer.print("") - printer.print( - """ - public static final ValueLayout.OfBoolean SWIFT_BOOL = ValueLayout.JAVA_BOOLEAN; - public static final ValueLayout.OfByte SWIFT_INT8 = ValueLayout.JAVA_BYTE; - public static final ValueLayout.OfChar SWIFT_UINT16 = ValueLayout.JAVA_CHAR; - public static final ValueLayout.OfShort SWIFT_INT16 = ValueLayout.JAVA_SHORT; - public static final ValueLayout.OfInt SWIFT_INT32 = ValueLayout.JAVA_INT; - public static final ValueLayout.OfLong SWIFT_INT64 = ValueLayout.JAVA_LONG; - public static final ValueLayout.OfFloat SWIFT_FLOAT = ValueLayout.JAVA_FLOAT; - public static final ValueLayout.OfDouble SWIFT_DOUBLE = ValueLayout.JAVA_DOUBLE; - public static final AddressLayout SWIFT_POINTER = ValueLayout.ADDRESS; - // On the platform this was generated on, Int was Int64 - public static final SequenceLayout SWIFT_BYTE_ARRAY = MemoryLayout.sequenceLayout(8, ValueLayout.JAVA_BYTE); - public static final ValueLayout.OfLong SWIFT_INT = SWIFT_INT64; - public static final ValueLayout.OfLong SWIFT_UINT = SWIFT_INT64; - - public static final AddressLayout SWIFT_SELF = SWIFT_POINTER; - """ - ) - } - public func printClassConstructors(_ printer: inout CodePrinter, _ decl: ImportedFunc) { guard let parentName = decl.parent else { fatalError("init must be inside a parent type! Was: \(decl)") @@ -1054,7 +1013,7 @@ extension Swift2JavaTranslator { let isIndirectReturn = decl.isIndirectReturn - var parameterLayoutDescriptors: [ForeignValueLayout] = javaMemoryLayoutDescriptors( + let parameterLayoutDescriptors: [ForeignValueLayout] = javaMemoryLayoutDescriptors( forParametersOf: decl, paramPassingStyle: .pointer ) diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValueLayout.java b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValueLayout.java index 565b6da5..65949cb3 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValueLayout.java +++ b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValueLayout.java @@ -32,13 +32,24 @@ public static long addressByteSize() { return ValueLayout.ADDRESS.byteSize(); } + public static final ValueLayout.OfBoolean SWIFT_BOOL = ValueLayout.JAVA_BOOLEAN; + public static final ValueLayout.OfByte SWIFT_INT8 = ValueLayout.JAVA_BYTE; + public static final ValueLayout.OfChar SWIFT_UINT16 = ValueLayout.JAVA_CHAR; + public static final ValueLayout.OfShort SWIFT_INT16 = ValueLayout.JAVA_SHORT; + public static final ValueLayout.OfInt SWIFT_INT32 = ValueLayout.JAVA_INT; + public static final ValueLayout.OfLong SWIFT_INT64 = ValueLayout.JAVA_LONG; + public static final ValueLayout.OfFloat SWIFT_FLOAT = ValueLayout.JAVA_FLOAT; + public static final ValueLayout.OfDouble SWIFT_DOUBLE = ValueLayout.JAVA_DOUBLE; + public static final AddressLayout SWIFT_POINTER = ValueLayout.ADDRESS + .withTargetLayout(MemoryLayout.sequenceLayout(Long.MAX_VALUE, JAVA_BYTE)); + public static final SequenceLayout SWIFT_BYTE_ARRAY = MemoryLayout.sequenceLayout(8, ValueLayout.JAVA_BYTE); + /** * The value layout for Swift's {@code Int} type, which is a signed type that follows * the size of a pointer (aka C's {@code ptrdiff_t}). */ public static ValueLayout SWIFT_INT = (ValueLayout.ADDRESS.byteSize() == 4) ? - ValueLayout.JAVA_INT : ValueLayout.JAVA_LONG; - + SWIFT_INT32 : SWIFT_INT64; /** * The value layout for Swift's {@code UInt} type, which is an unsigned type that follows @@ -47,9 +58,4 @@ public static long addressByteSize() { * Java does not have unsigned integer types, so we use the layout for Swift's {@code Int}. */ public static ValueLayout SWIFT_UINT = SWIFT_INT; - - - public static final AddressLayout SWIFT_POINTER = ValueLayout.ADDRESS - .withTargetLayout(MemoryLayout.sequenceLayout(Long.MAX_VALUE, JAVA_BYTE)); - } diff --git a/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift b/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift index 38d43432..5c190388 100644 --- a/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift +++ b/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift @@ -61,7 +61,7 @@ final class FunctionDescriptorTests { expected: """ public static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( - /*i*/SWIFT_INT + /*i*/SwiftValueLayout.SWIFT_INT ); """ ) @@ -76,8 +76,8 @@ final class FunctionDescriptorTests { expected: """ public static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( - /*l*/SWIFT_INT64, - /*i32*/SWIFT_INT32 + /*l*/SwiftValueLayout.SWIFT_INT64, + /*i32*/SwiftValueLayout.SWIFT_INT32 ); """ ) @@ -92,8 +92,8 @@ final class FunctionDescriptorTests { expected: """ public static final FunctionDescriptor DESC = FunctionDescriptor.of( - /* -> */SWIFT_INT, - /*i*/SWIFT_INT + /* -> */SwiftValueLayout.SWIFT_INT, + /*i*/SwiftValueLayout.SWIFT_INT ); """ ) @@ -108,8 +108,8 @@ final class FunctionDescriptorTests { expected: """ public static final FunctionDescriptor DESC_GET = FunctionDescriptor.of( - /* -> */SWIFT_INT32, - /*self$*/SWIFT_POINTER + /* -> */SwiftValueLayout.SWIFT_INT32, + /*self$*/SwiftValueLayout.SWIFT_POINTER ); """ ) @@ -123,8 +123,8 @@ final class FunctionDescriptorTests { expected: """ public static final FunctionDescriptor DESC_SET = FunctionDescriptor.ofVoid( - /*newValue*/SWIFT_INT32, - /*self$*/SWIFT_POINTER + /*newValue*/SwiftValueLayout.SWIFT_INT32, + /*self$*/SwiftValueLayout.SWIFT_POINTER ); """ ) diff --git a/Tests/JExtractSwiftTests/VariableImportTests.swift b/Tests/JExtractSwiftTests/VariableImportTests.swift index 7a97e195..527eda50 100644 --- a/Tests/JExtractSwiftTests/VariableImportTests.swift +++ b/Tests/JExtractSwiftTests/VariableImportTests.swift @@ -48,16 +48,16 @@ final class VariableImportTests { """ private static class counterInt { public static final FunctionDescriptor DESC_GET = FunctionDescriptor.of( - /* -> */SWIFT_INT, - /*self$*/SWIFT_POINTER + /* -> */SwiftValueLayout.SWIFT_INT, + /*self$*/SwiftValueLayout.SWIFT_POINTER ); public static final MemorySegment ADDR_GET = FakeModule.findOrThrow("swiftjava_FakeModule_MySwiftClass_counterInt"); public static final MethodHandle HANDLE_GET = Linker.nativeLinker().downcallHandle(ADDR_GET, DESC_GET); public static final FunctionDescriptor DESC_SET = FunctionDescriptor.ofVoid( - /*newValue*/SWIFT_INT, - /*self$*/SWIFT_POINTER + /*newValue*/SwiftValueLayout.SWIFT_INT, + /*self$*/SwiftValueLayout.SWIFT_POINTER ); public static final MemorySegment ADDR_SET = FakeModule.findOrThrow("swiftjava_FakeModule_MySwiftClass_counterInt"); From 008d9d1c82e623946e4e9818199904e139502b37 Mon Sep 17 00:00:00 2001 From: Mads Odgaard Date: Mon, 26 May 2025 12:14:13 +0200 Subject: [PATCH 240/426] add missing import --- SwiftKit/src/main/java/org/swift/swiftkit/SwiftValueLayout.java | 1 + 1 file changed, 1 insertion(+) diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValueLayout.java b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValueLayout.java index 65949cb3..dea52154 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValueLayout.java +++ b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValueLayout.java @@ -16,6 +16,7 @@ import java.lang.foreign.AddressLayout; import java.lang.foreign.MemoryLayout; +import java.lang.foreign.SequenceLayout; import java.lang.foreign.ValueLayout; import static java.lang.foreign.ValueLayout.*; From 7a9ecb82f6d7dba216e9e89f34b946afb4ad2b10 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Wed, 28 May 2025 17:07:49 +0900 Subject: [PATCH 241/426] Add JavaIO and CSV example (#234) * [javakit] Generate some java.io types * [javakit] exception description should include type, otherwise hard to act on * [sample] extend dependency example to consume commons csv as an example * add missing license in empty file * [javakit] correct the description/toString of Throwable * Discard changes to Samples/JavaKitSampleApp/Sources/JavaKitExample/com/example/swift/HelloSwift.java * Discard changes to Samples/JavaKitSampleApp/Sources/JavaKitExample/JavaKitExample.swift --- Package.swift | 16 +- Samples/JavaDependencySampleApp/Package.swift | 4 + .../Sources/JavaCommonsCSV/swift-java.config | 5 +- .../Sources/JavaDependencySample/main.swift | 10 ++ .../Sources/JavaExample/JavaExample.swift | 13 ++ .../JavaToSwift+FetchDependencies.swift | 6 + .../JavaKit/Exceptions/Throwable+Error.swift | 2 +- Sources/JavaKit/generated/Appendable.swift | 14 ++ Sources/JavaKit/generated/CharSequence.swift | 24 +++ Sources/JavaKit/generated/JavaInteger.swift | 1 + Sources/JavaKit/generated/JavaLong.swift | 6 + Sources/JavaKit/generated/JavaString.swift | 61 ++++--- Sources/JavaKit/swift-java.config | 2 + .../JavaKitCollection/generated/BitSet.swift | 56 +++--- .../JavaKitCollection/generated/HashMap.swift | 50 ------ .../JavaKitCollection/generated/TreeMap.swift | 50 ++++++ .../generated/BufferedInputStream.swift | 39 ++++ Sources/JavaKitIO/generated/Charset.swift | 49 ++++++ Sources/JavaKitIO/generated/Closeable.swift | 9 + Sources/JavaKitIO/generated/File.swift | 166 ++++++++++++++++++ .../JavaKitIO/generated/FileDescriptor.swift | 25 +++ Sources/JavaKitIO/generated/FileReader.swift | 21 +++ Sources/JavaKitIO/generated/Flushable.swift | 9 + Sources/JavaKitIO/generated/InputStream.swift | 55 ++++++ .../generated/InputStreamReader.swift | 30 ++++ .../JavaKitIO/generated/OutputStream.swift | 28 +++ Sources/JavaKitIO/generated/Path.swift | 88 ++++++++++ Sources/JavaKitIO/generated/Readable.swift | 8 + Sources/JavaKitIO/generated/Reader.swift | 40 +++++ .../JavaKitIO/generated/StringReader.swift | 33 ++++ .../JavaKitIO/generated/WatchService.swift | 9 + Sources/JavaKitIO/generated/Writer.swift | 49 ++++++ Sources/JavaKitIO/swift-java.config | 21 +++ Tests/JavaKitTests/BasicRuntimeTests.swift | 4 +- 34 files changed, 897 insertions(+), 106 deletions(-) create mode 100644 Samples/JavaDependencySampleApp/Sources/JavaExample/JavaExample.swift create mode 100644 Sources/JavaKit/generated/Appendable.swift create mode 100644 Sources/JavaKit/generated/CharSequence.swift create mode 100644 Sources/JavaKitIO/generated/BufferedInputStream.swift create mode 100644 Sources/JavaKitIO/generated/Charset.swift create mode 100644 Sources/JavaKitIO/generated/Closeable.swift create mode 100644 Sources/JavaKitIO/generated/File.swift create mode 100644 Sources/JavaKitIO/generated/FileDescriptor.swift create mode 100644 Sources/JavaKitIO/generated/FileReader.swift create mode 100644 Sources/JavaKitIO/generated/Flushable.swift create mode 100644 Sources/JavaKitIO/generated/InputStream.swift create mode 100644 Sources/JavaKitIO/generated/InputStreamReader.swift create mode 100644 Sources/JavaKitIO/generated/OutputStream.swift create mode 100644 Sources/JavaKitIO/generated/Path.swift create mode 100644 Sources/JavaKitIO/generated/Readable.swift create mode 100644 Sources/JavaKitIO/generated/Reader.swift create mode 100644 Sources/JavaKitIO/generated/StringReader.swift create mode 100644 Sources/JavaKitIO/generated/WatchService.swift create mode 100644 Sources/JavaKitIO/generated/Writer.swift create mode 100644 Sources/JavaKitIO/swift-java.config diff --git a/Package.swift b/Package.swift index 72a95155..42b74041 100644 --- a/Package.swift +++ b/Package.swift @@ -76,6 +76,11 @@ let package = Package( targets: ["JavaKitNetwork"] ), + .library( + name: "JavaKitIO", + targets: ["JavaKitIO"] + ), + .library( name: "JavaKitReflection", targets: ["JavaKitReflection"] @@ -241,6 +246,15 @@ let package = Package( .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) ] ), + .target( + name: "JavaKitIO", + dependencies: ["JavaKit", "JavaKitCollection"], + exclude: ["swift-java.config"], + swiftSettings: [ + .swiftLanguageMode(.v5), + .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) + ] + ), .target( name: "JavaKitReflection", dependencies: ["JavaKit", "JavaKitCollection"], @@ -448,6 +462,6 @@ let package = Package( swiftSettings: [ .swiftLanguageMode(.v5) ] - ) + ), ] ) diff --git a/Samples/JavaDependencySampleApp/Package.swift b/Samples/JavaDependencySampleApp/Package.swift index a90cd255..2b5ae361 100644 --- a/Samples/JavaDependencySampleApp/Package.swift +++ b/Samples/JavaDependencySampleApp/Package.swift @@ -86,6 +86,8 @@ let package = Package( .product(name: "JavaKit", package: "swift-java"), .product(name: "JavaKitFunction", package: "swift-java"), .product(name: "JavaKitCollection", package: "swift-java"), + .product(name: "JavaKitIO", package: "swift-java"), + .product(name: "JavaKitNetwork", package: "swift-java"), ], exclude: ["swift-java.config"], swiftSettings: [ @@ -98,5 +100,7 @@ let package = Package( ] ), + .target(name: "JavaExample"), + ] ) diff --git a/Samples/JavaDependencySampleApp/Sources/JavaCommonsCSV/swift-java.config b/Samples/JavaDependencySampleApp/Sources/JavaCommonsCSV/swift-java.config index 3ab83f79..3b685159 100644 --- a/Samples/JavaDependencySampleApp/Sources/JavaCommonsCSV/swift-java.config +++ b/Samples/JavaDependencySampleApp/Sources/JavaCommonsCSV/swift-java.config @@ -1,7 +1,10 @@ { "classes" : { "org.apache.commons.io.FilenameUtils" : "FilenameUtils", - "org.apache.commons.io.IOCase" : "IOCase" + "org.apache.commons.io.IOCase" : "IOCase", + "org.apache.commons.csv.CSVFormat" : "CSVFormat", + "org.apache.commons.csv.CSVParser" : "CSVParser", + "org.apache.commons.csv.CSVRecord" : "CSVRecord" }, "dependencies" : [ "org.apache.commons:commons-csv:1.12.0" diff --git a/Samples/JavaDependencySampleApp/Sources/JavaDependencySample/main.swift b/Samples/JavaDependencySampleApp/Sources/JavaDependencySample/main.swift index 16c2f4a9..c75cf553 100644 --- a/Samples/JavaDependencySampleApp/Sources/JavaDependencySample/main.swift +++ b/Samples/JavaDependencySampleApp/Sources/JavaDependencySample/main.swift @@ -14,6 +14,7 @@ import JavaKit import JavaKitFunction +import JavaKitIO import JavaKitConfigurationShared import Foundation @@ -42,4 +43,13 @@ let ext = try! FilenameUtilsClass.getExtension(path) print("org.apache.commons.io.FilenameUtils.getExtension = \(ext)") precondition(ext == "exe") +let CSVFormatClass = try JavaClass() + +let reader = StringReader("hello,example") +for record in try CSVFormatClass.RFC4180.parse(reader)!.getRecords()! { + for field in record.toList()! { + print("Field: \(field)") + } +} + print("Done.") diff --git a/Samples/JavaDependencySampleApp/Sources/JavaExample/JavaExample.swift b/Samples/JavaDependencySampleApp/Sources/JavaExample/JavaExample.swift new file mode 100644 index 00000000..4724da99 --- /dev/null +++ b/Samples/JavaDependencySampleApp/Sources/JavaExample/JavaExample.swift @@ -0,0 +1,13 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) YEARS Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// diff --git a/Sources/Java2Swift/JavaToSwift+FetchDependencies.swift b/Sources/Java2Swift/JavaToSwift+FetchDependencies.swift index 9656c310..2a9694c0 100644 --- a/Sources/Java2Swift/JavaToSwift+FetchDependencies.swift +++ b/Sources/Java2Swift/JavaToSwift+FetchDependencies.swift @@ -40,6 +40,10 @@ extension JavaToSwift { print("[info][swift-java] Resolved classpath for \(deps.count) dependencies of '\(moduleName)', classpath entries: \(classpathEntries.count), ", terminator: "") print("done.".green) + for entry in classpathEntries { + print("[info][swift-java] Classpath entry: \(entry)") + } + return ResolvedDependencyClasspath(for: dependencies, classpath: dependenciesClasspath) } @@ -133,6 +137,8 @@ extension JavaToSwift { // The file contents are just plain let contents = resolvedClasspath.classpath + print("[debug][swift-java] Resolved dependency: \(classpath)") + // Write the file try writeContents( contents, diff --git a/Sources/JavaKit/Exceptions/Throwable+Error.swift b/Sources/JavaKit/Exceptions/Throwable+Error.swift index bae53123..fbf8393d 100644 --- a/Sources/JavaKit/Exceptions/Throwable+Error.swift +++ b/Sources/JavaKit/Exceptions/Throwable+Error.swift @@ -15,7 +15,7 @@ // Translate all Java Throwable instances in a Swift error. extension Throwable: Error, CustomStringConvertible { public var description: String { - return getMessage() + return toString() } } diff --git a/Sources/JavaKit/generated/Appendable.swift b/Sources/JavaKit/generated/Appendable.swift new file mode 100644 index 00000000..5c6663f2 --- /dev/null +++ b/Sources/JavaKit/generated/Appendable.swift @@ -0,0 +1,14 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaRuntime + +@JavaInterface("java.lang.Appendable") +public struct Appendable { + @JavaMethod + public func append(_ arg0: CharSequence?) throws -> Appendable! + + @JavaMethod + public func append(_ arg0: CharSequence?, _ arg1: Int32, _ arg2: Int32) throws -> Appendable! + + @JavaMethod + public func append(_ arg0: UInt16) throws -> Appendable! +} diff --git a/Sources/JavaKit/generated/CharSequence.swift b/Sources/JavaKit/generated/CharSequence.swift new file mode 100644 index 00000000..cab17273 --- /dev/null +++ b/Sources/JavaKit/generated/CharSequence.swift @@ -0,0 +1,24 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaRuntime + +@JavaInterface("java.lang.CharSequence") +public struct CharSequence { + @JavaMethod + public func length() -> Int32 + + @JavaMethod + public func toString() -> String + + @JavaMethod + public func charAt(_ arg0: Int32) -> UInt16 + + @JavaMethod + public func isEmpty() -> Bool + + @JavaMethod + public func subSequence(_ arg0: Int32, _ arg1: Int32) -> CharSequence! +} +extension JavaClass { + @JavaStaticMethod + public func compare(_ arg0: CharSequence?, _ arg1: CharSequence?) -> Int32 +} diff --git a/Sources/JavaKit/generated/JavaInteger.swift b/Sources/JavaKit/generated/JavaInteger.swift index e5cd5fc1..646aac9e 100644 --- a/Sources/JavaKit/generated/JavaInteger.swift +++ b/Sources/JavaKit/generated/JavaInteger.swift @@ -3,6 +3,7 @@ import JavaRuntime @JavaClass("java.lang.Integer") open class JavaInteger: JavaNumber { + @JavaMethod @_nonoverride public convenience init(_ arg0: Int32, environment: JNIEnvironment? = nil) diff --git a/Sources/JavaKit/generated/JavaLong.swift b/Sources/JavaKit/generated/JavaLong.swift index 491ef1dd..7ff70efa 100644 --- a/Sources/JavaKit/generated/JavaLong.swift +++ b/Sources/JavaKit/generated/JavaLong.swift @@ -167,12 +167,18 @@ extension JavaClass { @JavaStaticMethod public func rotateRight(_ arg0: Int64, _ arg1: Int32) -> Int64 + @JavaStaticMethod + public func parseLong(_ arg0: CharSequence?, _ arg1: Int32, _ arg2: Int32, _ arg3: Int32) throws -> Int64 + @JavaStaticMethod public func parseLong(_ arg0: String, _ arg1: Int32) throws -> Int64 @JavaStaticMethod public func parseLong(_ arg0: String) throws -> Int64 + @JavaStaticMethod + public func parseUnsignedLong(_ arg0: CharSequence?, _ arg1: Int32, _ arg2: Int32, _ arg3: Int32) throws -> Int64 + @JavaStaticMethod public func parseUnsignedLong(_ arg0: String, _ arg1: Int32) throws -> Int64 diff --git a/Sources/JavaKit/generated/JavaString.swift b/Sources/JavaKit/generated/JavaString.swift index 34d0080c..c5f627f2 100644 --- a/Sources/JavaKit/generated/JavaString.swift +++ b/Sources/JavaKit/generated/JavaString.swift @@ -1,7 +1,7 @@ // Auto-generated by Java-to-Swift wrapper generator. import JavaRuntime -@JavaClass("java.lang.String") +@JavaClass("java.lang.String", implements: CharSequence.self) open class JavaString: JavaObject { @JavaMethod @_nonoverride public convenience init(_ arg0: [Int8], _ arg1: String, environment: JNIEnvironment? = nil) throws @@ -52,16 +52,16 @@ open class JavaString: JavaObject { open func getChars(_ arg0: Int32, _ arg1: Int32, _ arg2: [UInt16], _ arg3: Int32) @JavaMethod - open func compareTo(_ arg0: JavaObject?) -> Int32 + open func compareTo(_ arg0: String) -> Int32 @JavaMethod - open func compareTo(_ arg0: String) -> Int32 + open func compareTo(_ arg0: JavaObject?) -> Int32 @JavaMethod - open func indexOf(_ arg0: String, _ arg1: Int32, _ arg2: Int32) -> Int32 + open func indexOf(_ arg0: String, _ arg1: Int32) -> Int32 @JavaMethod - open func indexOf(_ arg0: String) -> Int32 + open func indexOf(_ arg0: String, _ arg1: Int32, _ arg2: Int32) -> Int32 @JavaMethod open func indexOf(_ arg0: Int32) -> Int32 @@ -73,7 +73,7 @@ open class JavaString: JavaObject { open func indexOf(_ arg0: Int32, _ arg1: Int32, _ arg2: Int32) -> Int32 @JavaMethod - open func indexOf(_ arg0: String, _ arg1: Int32) -> Int32 + open func indexOf(_ arg0: String) -> Int32 @JavaMethod open func charAt(_ arg0: Int32) -> UInt16 @@ -90,9 +90,6 @@ open class JavaString: JavaObject { @JavaMethod open func offsetByCodePoints(_ arg0: Int32, _ arg1: Int32) -> Int32 - @JavaMethod - open func getBytes() -> [Int8] - @JavaMethod open func getBytes(_ arg0: String) throws -> [Int8] @@ -100,11 +97,17 @@ open class JavaString: JavaObject { open func getBytes(_ arg0: Int32, _ arg1: Int32, _ arg2: [Int8], _ arg3: Int32) @JavaMethod - open func regionMatches(_ arg0: Bool, _ arg1: Int32, _ arg2: String, _ arg3: Int32, _ arg4: Int32) -> Bool + open func getBytes() -> [Int8] + + @JavaMethod + open func contentEquals(_ arg0: CharSequence?) -> Bool @JavaMethod open func regionMatches(_ arg0: Int32, _ arg1: String, _ arg2: Int32, _ arg3: Int32) -> Bool + @JavaMethod + open func regionMatches(_ arg0: Bool, _ arg1: Int32, _ arg2: String, _ arg3: Int32, _ arg4: Int32) -> Bool + @JavaMethod open func startsWith(_ arg0: String) -> Bool @@ -112,26 +115,29 @@ open class JavaString: JavaObject { open func startsWith(_ arg0: String, _ arg1: Int32) -> Bool @JavaMethod - open func lastIndexOf(_ arg0: String) -> Int32 + open func lastIndexOf(_ arg0: Int32) -> Int32 @JavaMethod - open func lastIndexOf(_ arg0: Int32, _ arg1: Int32) -> Int32 + open func lastIndexOf(_ arg0: String) -> Int32 @JavaMethod open func lastIndexOf(_ arg0: String, _ arg1: Int32) -> Int32 @JavaMethod - open func lastIndexOf(_ arg0: Int32) -> Int32 + open func lastIndexOf(_ arg0: Int32, _ arg1: Int32) -> Int32 @JavaMethod - open func substring(_ arg0: Int32) -> String + open func substring(_ arg0: Int32, _ arg1: Int32) -> String @JavaMethod - open func substring(_ arg0: Int32, _ arg1: Int32) -> String + open func substring(_ arg0: Int32) -> String @JavaMethod open func isEmpty() -> Bool + @JavaMethod + open func replace(_ arg0: CharSequence?, _ arg1: CharSequence?) -> String + @JavaMethod open func replace(_ arg0: UInt16, _ arg1: UInt16) -> String @@ -189,9 +195,15 @@ open class JavaString: JavaObject { @JavaMethod open func endsWith(_ arg0: String) -> Bool + @JavaMethod + open func subSequence(_ arg0: Int32, _ arg1: Int32) -> CharSequence! + @JavaMethod open func concat(_ arg0: String) -> String + @JavaMethod + open func contains(_ arg0: CharSequence?) -> Bool + @JavaMethod open func indent(_ arg0: Int32) -> String @@ -215,39 +227,42 @@ open class JavaString: JavaObject { } } extension JavaClass { + @JavaStaticMethod + public func valueOf(_ arg0: JavaObject?) -> String + @JavaStaticMethod public func valueOf(_ arg0: Int64) -> String @JavaStaticMethod - public func valueOf(_ arg0: [UInt16]) -> String + public func valueOf(_ arg0: Int32) -> String @JavaStaticMethod - public func valueOf(_ arg0: JavaObject?) -> String + public func valueOf(_ arg0: UInt16) -> String @JavaStaticMethod public func valueOf(_ arg0: [UInt16], _ arg1: Int32, _ arg2: Int32) -> String @JavaStaticMethod - public func valueOf(_ arg0: Float) -> String + public func valueOf(_ arg0: Bool) -> String @JavaStaticMethod public func valueOf(_ arg0: Double) -> String @JavaStaticMethod - public func valueOf(_ arg0: UInt16) -> String + public func valueOf(_ arg0: [UInt16]) -> String @JavaStaticMethod - public func valueOf(_ arg0: Bool) -> String + public func valueOf(_ arg0: Float) -> String @JavaStaticMethod - public func valueOf(_ arg0: Int32) -> String + public func join(_ arg0: CharSequence?, _ arg1: [CharSequence?]) -> String @JavaStaticMethod public func format(_ arg0: String, _ arg1: [JavaObject?]) -> String @JavaStaticMethod - public func copyValueOf(_ arg0: [UInt16]) -> String + public func copyValueOf(_ arg0: [UInt16], _ arg1: Int32, _ arg2: Int32) -> String @JavaStaticMethod - public func copyValueOf(_ arg0: [UInt16], _ arg1: Int32, _ arg2: Int32) -> String + public func copyValueOf(_ arg0: [UInt16]) -> String } diff --git a/Sources/JavaKit/swift-java.config b/Sources/JavaKit/swift-java.config index 34751edd..b45671a7 100644 --- a/Sources/JavaKit/swift-java.config +++ b/Sources/JavaKit/swift-java.config @@ -19,6 +19,8 @@ "java.lang.String" : "JavaString", "java.lang.Throwable" : "Throwable", "java.lang.Void" : "JavaVoid", + "java.lang.CharSequence": "CharSequence", + "java.lang.Appendable": "Appendable", "java.util.Optional": "JavaOptional", "java.util.OptionalDouble": "JavaOptionalDouble", "java.util.OptionalInt": "JavaOptionalInt", diff --git a/Sources/JavaKitCollection/generated/BitSet.swift b/Sources/JavaKitCollection/generated/BitSet.swift index c7e54b95..d5211c28 100644 --- a/Sources/JavaKitCollection/generated/BitSet.swift +++ b/Sources/JavaKitCollection/generated/BitSet.swift @@ -4,38 +4,20 @@ import JavaRuntime @JavaClass("java.util.BitSet") open class BitSet: JavaObject { - @JavaMethod - @_nonoverride public convenience init(environment: JNIEnvironment? = nil) - @JavaMethod @_nonoverride public convenience init(_ arg0: Int32, environment: JNIEnvironment? = nil) @JavaMethod - open func cardinality() -> Int32 - - @JavaMethod - open func nextSetBit(_ arg0: Int32) -> Int32 - - @JavaMethod - open func toLongArray() -> [Int64] - - @JavaMethod - open func previousSetBit(_ arg0: Int32) -> Int32 - - @JavaMethod - open func previousClearBit(_ arg0: Int32) -> Int32 - - @JavaMethod - open func intersects(_ arg0: BitSet?) -> Bool + @_nonoverride public convenience init(environment: JNIEnvironment? = nil) @JavaMethod open func size() -> Int32 @JavaMethod - open func get(_ arg0: Int32, _ arg1: Int32) -> BitSet! + open func get(_ arg0: Int32) -> Bool @JavaMethod - open func get(_ arg0: Int32) -> Bool + open func get(_ arg0: Int32, _ arg1: Int32) -> BitSet! @JavaMethod open override func equals(_ arg0: JavaObject?) -> Bool @@ -52,9 +34,6 @@ open class BitSet: JavaObject { @JavaMethod open override func clone() -> JavaObject! - @JavaMethod - open func clear(_ arg0: Int32) - @JavaMethod open func clear(_ arg0: Int32, _ arg1: Int32) @@ -62,19 +41,22 @@ open class BitSet: JavaObject { open func clear() @JavaMethod - open func isEmpty() -> Bool + open func clear(_ arg0: Int32) @JavaMethod - open func set(_ arg0: Int32, _ arg1: Int32, _ arg2: Bool) + open func isEmpty() -> Bool @JavaMethod - open func set(_ arg0: Int32, _ arg1: Int32) + open func set(_ arg0: Int32, _ arg1: Bool) @JavaMethod open func set(_ arg0: Int32) @JavaMethod - open func set(_ arg0: Int32, _ arg1: Bool) + open func set(_ arg0: Int32, _ arg1: Int32) + + @JavaMethod + open func set(_ arg0: Int32, _ arg1: Int32, _ arg2: Bool) @JavaMethod open func flip(_ arg0: Int32, _ arg1: Int32) @@ -99,6 +81,24 @@ open class BitSet: JavaObject { @JavaMethod open func andNot(_ arg0: BitSet?) + + @JavaMethod + open func cardinality() -> Int32 + + @JavaMethod + open func nextSetBit(_ arg0: Int32) -> Int32 + + @JavaMethod + open func toLongArray() -> [Int64] + + @JavaMethod + open func previousSetBit(_ arg0: Int32) -> Int32 + + @JavaMethod + open func previousClearBit(_ arg0: Int32) -> Int32 + + @JavaMethod + open func intersects(_ arg0: BitSet?) -> Bool } extension JavaClass { @JavaStaticMethod diff --git a/Sources/JavaKitCollection/generated/HashMap.swift b/Sources/JavaKitCollection/generated/HashMap.swift index e8cfa118..424dfbb9 100644 --- a/Sources/JavaKitCollection/generated/HashMap.swift +++ b/Sources/JavaKitCollection/generated/HashMap.swift @@ -61,56 +61,6 @@ open class HashMap: JavaObject { @JavaMethod open func getOrDefault(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject! } -extension HashMap { - @JavaClass("java.util.AbstractMap$SimpleEntry") - open class SimpleEntry: JavaObject { - @JavaMethod - @_nonoverride public convenience init(_ arg0: JavaObject?, _ arg1: JavaObject?, environment: JNIEnvironment? = nil) - - @JavaMethod - open override func equals(_ arg0: JavaObject?) -> Bool - - @JavaMethod - open override func toString() -> String - - @JavaMethod - open override func hashCode() -> Int32 - - @JavaMethod - open func getValue() -> JavaObject! - - @JavaMethod - open func getKey() -> JavaObject! - - @JavaMethod - open func setValue(_ arg0: JavaObject?) -> JavaObject! - } -} -extension HashMap { - @JavaClass("java.util.AbstractMap$SimpleImmutableEntry") - open class SimpleImmutableEntry: JavaObject { - @JavaMethod - @_nonoverride public convenience init(_ arg0: JavaObject?, _ arg1: JavaObject?, environment: JNIEnvironment? = nil) - - @JavaMethod - open override func equals(_ arg0: JavaObject?) -> Bool - - @JavaMethod - open override func toString() -> String - - @JavaMethod - open override func hashCode() -> Int32 - - @JavaMethod - open func getValue() -> JavaObject! - - @JavaMethod - open func getKey() -> JavaObject! - - @JavaMethod - open func setValue(_ arg0: JavaObject?) -> JavaObject! - } -} extension JavaClass { @JavaStaticMethod public func newHashMap(_ arg0: Int32) -> HashMap! where ObjectType == HashMap diff --git a/Sources/JavaKitCollection/generated/TreeMap.swift b/Sources/JavaKitCollection/generated/TreeMap.swift index 79560905..7796d555 100644 --- a/Sources/JavaKitCollection/generated/TreeMap.swift +++ b/Sources/JavaKitCollection/generated/TreeMap.swift @@ -70,3 +70,53 @@ open class TreeMap: JavaObject { @JavaMethod open func lastKey() -> JavaObject! } +extension TreeMap { + @JavaClass("java.util.AbstractMap$SimpleEntry") + open class SimpleEntry: JavaObject { + @JavaMethod + @_nonoverride public convenience init(_ arg0: JavaObject?, _ arg1: JavaObject?, environment: JNIEnvironment? = nil) + + @JavaMethod + open override func equals(_ arg0: JavaObject?) -> Bool + + @JavaMethod + open override func toString() -> String + + @JavaMethod + open override func hashCode() -> Int32 + + @JavaMethod + open func getValue() -> JavaObject! + + @JavaMethod + open func getKey() -> JavaObject! + + @JavaMethod + open func setValue(_ arg0: JavaObject?) -> JavaObject! + } +} +extension TreeMap { + @JavaClass("java.util.AbstractMap$SimpleImmutableEntry") + open class SimpleImmutableEntry: JavaObject { + @JavaMethod + @_nonoverride public convenience init(_ arg0: JavaObject?, _ arg1: JavaObject?, environment: JNIEnvironment? = nil) + + @JavaMethod + open override func equals(_ arg0: JavaObject?) -> Bool + + @JavaMethod + open override func toString() -> String + + @JavaMethod + open override func hashCode() -> Int32 + + @JavaMethod + open func getValue() -> JavaObject! + + @JavaMethod + open func getKey() -> JavaObject! + + @JavaMethod + open func setValue(_ arg0: JavaObject?) -> JavaObject! + } +} diff --git a/Sources/JavaKitIO/generated/BufferedInputStream.swift b/Sources/JavaKitIO/generated/BufferedInputStream.swift new file mode 100644 index 00000000..8ea95eeb --- /dev/null +++ b/Sources/JavaKitIO/generated/BufferedInputStream.swift @@ -0,0 +1,39 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaClass("java.io.BufferedInputStream") +open class BufferedInputStream: InputStream { + @JavaMethod + @_nonoverride public convenience init(_ arg0: InputStream?, environment: JNIEnvironment? = nil) + + @JavaMethod + @_nonoverride public convenience init(_ arg0: InputStream?, _ arg1: Int32, environment: JNIEnvironment? = nil) + + @JavaMethod + open override func reset() throws + + @JavaMethod + open override func read(_ arg0: [Int8], _ arg1: Int32, _ arg2: Int32) throws -> Int32 + + @JavaMethod + open override func read() throws -> Int32 + + @JavaMethod + open override func close() throws + + @JavaMethod + open override func mark(_ arg0: Int32) + + @JavaMethod + open override func transferTo(_ arg0: OutputStream?) throws -> Int64 + + @JavaMethod + open override func skip(_ arg0: Int64) throws -> Int64 + + @JavaMethod + open override func available() throws -> Int32 + + @JavaMethod + open override func markSupported() -> Bool +} diff --git a/Sources/JavaKitIO/generated/Charset.swift b/Sources/JavaKitIO/generated/Charset.swift new file mode 100644 index 00000000..fda054ef --- /dev/null +++ b/Sources/JavaKitIO/generated/Charset.swift @@ -0,0 +1,49 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaClass("java.nio.charset.Charset") +open class Charset: JavaObject { + @JavaMethod + open func name() -> String + + @JavaMethod + open override func equals(_ arg0: JavaObject?) -> Bool + + @JavaMethod + open override func toString() -> String + + @JavaMethod + open override func hashCode() -> Int32 + + @JavaMethod + open func compareTo(_ arg0: JavaObject?) -> Int32 + + @JavaMethod + open func compareTo(_ arg0: Charset?) -> Int32 + + @JavaMethod + open func canEncode() -> Bool + + @JavaMethod + open func contains(_ arg0: Charset?) -> Bool + + @JavaMethod + open func isRegistered() -> Bool + + @JavaMethod + open func displayName() -> String +} +extension JavaClass { + @JavaStaticMethod + public func forName(_ arg0: String, _ arg1: Charset?) -> Charset! + + @JavaStaticMethod + public func forName(_ arg0: String) -> Charset! + + @JavaStaticMethod + public func defaultCharset() -> Charset! + + @JavaStaticMethod + public func isSupported(_ arg0: String) -> Bool +} diff --git a/Sources/JavaKitIO/generated/Closeable.swift b/Sources/JavaKitIO/generated/Closeable.swift new file mode 100644 index 00000000..6da8e2a9 --- /dev/null +++ b/Sources/JavaKitIO/generated/Closeable.swift @@ -0,0 +1,9 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaInterface("java.io.Closeable") +public struct Closeable { + @JavaMethod + public func close() throws +} diff --git a/Sources/JavaKitIO/generated/File.swift b/Sources/JavaKitIO/generated/File.swift new file mode 100644 index 00000000..5cbdb70e --- /dev/null +++ b/Sources/JavaKitIO/generated/File.swift @@ -0,0 +1,166 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaClass("java.io.File") +open class File: JavaObject { + @JavaMethod + @_nonoverride public convenience init(_ arg0: String, environment: JNIEnvironment? = nil) + + @JavaMethod + @_nonoverride public convenience init(_ arg0: String, _ arg1: String, environment: JNIEnvironment? = nil) + + @JavaMethod + @_nonoverride public convenience init(_ arg0: File?, _ arg1: String, environment: JNIEnvironment? = nil) + + @JavaMethod + open func getName() -> String + + @JavaMethod + open override func equals(_ arg0: JavaObject?) -> Bool + + @JavaMethod + open func length() -> Int64 + + @JavaMethod + open override func toString() -> String + + @JavaMethod + open override func hashCode() -> Int32 + + @JavaMethod + open func isHidden() -> Bool + + @JavaMethod + open func compareTo(_ arg0: File?) -> Int32 + + @JavaMethod + open func compareTo(_ arg0: JavaObject?) -> Int32 + + @JavaMethod + open func list() -> [String] + + @JavaMethod + open func isAbsolute() -> Bool + + @JavaMethod + open func getParent() -> String + + @JavaMethod + open func delete() -> Bool + + @JavaMethod + open func setReadOnly() -> Bool + + @JavaMethod + open func canRead() -> Bool + + @JavaMethod + open func getPath() -> String + + @JavaMethod + open func getAbsolutePath() -> String + + @JavaMethod + open func exists() -> Bool + + @JavaMethod + open func createNewFile() throws -> Bool + + @JavaMethod + open func renameTo(_ arg0: File?) -> Bool + + @JavaMethod + open func isDirectory() -> Bool + + @JavaMethod + open func getCanonicalPath() throws -> String + + @JavaMethod + open func getAbsoluteFile() -> File! + + @JavaMethod + open func mkdir() -> Bool + + @JavaMethod + open func getCanonicalFile() throws -> File! + + @JavaMethod + open func getParentFile() -> File! + + @JavaMethod + open func mkdirs() -> Bool + + @JavaMethod + open func setWritable(_ arg0: Bool) -> Bool + + @JavaMethod + open func setWritable(_ arg0: Bool, _ arg1: Bool) -> Bool + + @JavaMethod + open func setReadable(_ arg0: Bool, _ arg1: Bool) -> Bool + + @JavaMethod + open func setReadable(_ arg0: Bool) -> Bool + + @JavaMethod + open func setExecutable(_ arg0: Bool, _ arg1: Bool) -> Bool + + @JavaMethod + open func setExecutable(_ arg0: Bool) -> Bool + + @JavaMethod + open func canWrite() -> Bool + + @JavaMethod + open func isFile() -> Bool + + @JavaMethod + open func lastModified() -> Int64 + + @JavaMethod + open func deleteOnExit() + + @JavaMethod + open func listFiles() -> [File?] + + @JavaMethod + open func setLastModified(_ arg0: Int64) -> Bool + + @JavaMethod + open func canExecute() -> Bool + + @JavaMethod + open func getTotalSpace() -> Int64 + + @JavaMethod + open func getFreeSpace() -> Int64 + + @JavaMethod + open func getUsableSpace() -> Int64 + + @JavaMethod + open func toPath() -> Path! +} +extension JavaClass { + @JavaStaticField(isFinal: true) + public var separatorChar: UInt16 + + @JavaStaticField(isFinal: true) + public var separator: String + + @JavaStaticField(isFinal: true) + public var pathSeparatorChar: UInt16 + + @JavaStaticField(isFinal: true) + public var pathSeparator: String + + @JavaStaticMethod + public func listRoots() -> [File?] + + @JavaStaticMethod + public func createTempFile(_ arg0: String, _ arg1: String) throws -> File! + + @JavaStaticMethod + public func createTempFile(_ arg0: String, _ arg1: String, _ arg2: File?) throws -> File! +} diff --git a/Sources/JavaKitIO/generated/FileDescriptor.swift b/Sources/JavaKitIO/generated/FileDescriptor.swift new file mode 100644 index 00000000..81490e46 --- /dev/null +++ b/Sources/JavaKitIO/generated/FileDescriptor.swift @@ -0,0 +1,25 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaClass("java.io.FileDescriptor") +open class FileDescriptor: JavaObject { + @JavaMethod + @_nonoverride public convenience init(environment: JNIEnvironment? = nil) + + @JavaMethod + open func sync() throws + + @JavaMethod + open func valid() -> Bool +} +extension JavaClass { + @JavaStaticField(isFinal: true) + public var `in`: FileDescriptor! + + @JavaStaticField(isFinal: true) + public var out: FileDescriptor! + + @JavaStaticField(isFinal: true) + public var err: FileDescriptor! +} diff --git a/Sources/JavaKitIO/generated/FileReader.swift b/Sources/JavaKitIO/generated/FileReader.swift new file mode 100644 index 00000000..5254bdd0 --- /dev/null +++ b/Sources/JavaKitIO/generated/FileReader.swift @@ -0,0 +1,21 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaClass("java.io.FileReader") +open class FileReader: InputStreamReader { + @JavaMethod + @_nonoverride public convenience init(_ arg0: File?, _ arg1: Charset?, environment: JNIEnvironment? = nil) throws + + @JavaMethod + @_nonoverride public convenience init(_ arg0: String, _ arg1: Charset?, environment: JNIEnvironment? = nil) throws + + @JavaMethod + @_nonoverride public convenience init(_ arg0: FileDescriptor?, environment: JNIEnvironment? = nil) + + @JavaMethod + @_nonoverride public convenience init(_ arg0: File?, environment: JNIEnvironment? = nil) throws + + @JavaMethod + @_nonoverride public convenience init(_ arg0: String, environment: JNIEnvironment? = nil) throws +} diff --git a/Sources/JavaKitIO/generated/Flushable.swift b/Sources/JavaKitIO/generated/Flushable.swift new file mode 100644 index 00000000..daf621f6 --- /dev/null +++ b/Sources/JavaKitIO/generated/Flushable.swift @@ -0,0 +1,9 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaInterface("java.io.Flushable") +public struct Flushable { + @JavaMethod + public func flush() throws +} diff --git a/Sources/JavaKitIO/generated/InputStream.swift b/Sources/JavaKitIO/generated/InputStream.swift new file mode 100644 index 00000000..971a610b --- /dev/null +++ b/Sources/JavaKitIO/generated/InputStream.swift @@ -0,0 +1,55 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaClass("java.io.InputStream", implements: Closeable.self) +open class InputStream: JavaObject { + @JavaMethod + @_nonoverride public convenience init(environment: JNIEnvironment? = nil) + + @JavaMethod + open func reset() throws + + @JavaMethod + open func read(_ arg0: [Int8]) throws -> Int32 + + @JavaMethod + open func read(_ arg0: [Int8], _ arg1: Int32, _ arg2: Int32) throws -> Int32 + + @JavaMethod + open func read() throws -> Int32 + + @JavaMethod + open func close() throws + + @JavaMethod + open func readAllBytes() throws -> [Int8] + + @JavaMethod + open func mark(_ arg0: Int32) + + @JavaMethod + open func readNBytes(_ arg0: [Int8], _ arg1: Int32, _ arg2: Int32) throws -> Int32 + + @JavaMethod + open func readNBytes(_ arg0: Int32) throws -> [Int8] + + @JavaMethod + open func transferTo(_ arg0: OutputStream?) throws -> Int64 + + @JavaMethod + open func skip(_ arg0: Int64) throws -> Int64 + + @JavaMethod + open func available() throws -> Int32 + + @JavaMethod + open func markSupported() -> Bool + + @JavaMethod + open func skipNBytes(_ arg0: Int64) throws +} +extension JavaClass { + @JavaStaticMethod + public func nullInputStream() -> InputStream! +} diff --git a/Sources/JavaKitIO/generated/InputStreamReader.swift b/Sources/JavaKitIO/generated/InputStreamReader.swift new file mode 100644 index 00000000..2766aeba --- /dev/null +++ b/Sources/JavaKitIO/generated/InputStreamReader.swift @@ -0,0 +1,30 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaClass("java.io.InputStreamReader") +open class InputStreamReader: Reader { + @JavaMethod + @_nonoverride public convenience init(_ arg0: InputStream?, _ arg1: Charset?, environment: JNIEnvironment? = nil) + + @JavaMethod + @_nonoverride public convenience init(_ arg0: InputStream?, _ arg1: String, environment: JNIEnvironment? = nil) throws + + @JavaMethod + @_nonoverride public convenience init(_ arg0: InputStream?, environment: JNIEnvironment? = nil) + + @JavaMethod + open override func ready() throws -> Bool + + @JavaMethod + open override func read() throws -> Int32 + + @JavaMethod + open override func read(_ arg0: [UInt16], _ arg1: Int32, _ arg2: Int32) throws -> Int32 + + @JavaMethod + open override func close() throws + + @JavaMethod + open func getEncoding() -> String +} diff --git a/Sources/JavaKitIO/generated/OutputStream.swift b/Sources/JavaKitIO/generated/OutputStream.swift new file mode 100644 index 00000000..e169bfd0 --- /dev/null +++ b/Sources/JavaKitIO/generated/OutputStream.swift @@ -0,0 +1,28 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaClass("java.io.OutputStream", implements: Closeable.self, Flushable.self) +open class OutputStream: JavaObject { + @JavaMethod + @_nonoverride public convenience init(environment: JNIEnvironment? = nil) + + @JavaMethod + open func flush() throws + + @JavaMethod + open func write(_ arg0: [Int8]) throws + + @JavaMethod + open func write(_ arg0: [Int8], _ arg1: Int32, _ arg2: Int32) throws + + @JavaMethod + open func write(_ arg0: Int32) throws + + @JavaMethod + open func close() throws +} +extension JavaClass { + @JavaStaticMethod + public func nullOutputStream() -> OutputStream! +} diff --git a/Sources/JavaKitIO/generated/Path.swift b/Sources/JavaKitIO/generated/Path.swift new file mode 100644 index 00000000..e93d0381 --- /dev/null +++ b/Sources/JavaKitIO/generated/Path.swift @@ -0,0 +1,88 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaInterface("java.nio.file.Path") +public struct Path { + @JavaMethod + public func getName(_ arg0: Int32) -> Path! + + @JavaMethod + public func equals(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func toString() -> String + + @JavaMethod + public func hashCode() -> Int32 + + @JavaMethod + public func compareTo(_ arg0: Path?) -> Int32 + + @JavaMethod + public func compareTo(_ arg0: JavaObject?) -> Int32 + + @JavaMethod + public func startsWith(_ arg0: String) -> Bool + + @JavaMethod + public func startsWith(_ arg0: Path?) -> Bool + + @JavaMethod + public func endsWith(_ arg0: String) -> Bool + + @JavaMethod + public func endsWith(_ arg0: Path?) -> Bool + + @JavaMethod + public func isAbsolute() -> Bool + + @JavaMethod + public func resolve(_ arg0: String, _ arg1: [String]) -> Path! + + @JavaMethod + public func resolve(_ arg0: Path?, _ arg1: [Path?]) -> Path! + + @JavaMethod + public func resolve(_ arg0: String) -> Path! + + @JavaMethod + public func resolve(_ arg0: Path?) -> Path! + + @JavaMethod + public func getParent() -> Path! + + @JavaMethod + public func getRoot() -> Path! + + @JavaMethod + public func toFile() -> File! + + @JavaMethod + public func getFileName() -> Path! + + @JavaMethod + public func normalize() -> Path! + + @JavaMethod + public func relativize(_ arg0: Path?) -> Path! + + @JavaMethod + public func getNameCount() -> Int32 + + @JavaMethod + public func toAbsolutePath() -> Path! + + @JavaMethod + public func resolveSibling(_ arg0: String) -> Path! + + @JavaMethod + public func resolveSibling(_ arg0: Path?) -> Path! + + @JavaMethod + public func subpath(_ arg0: Int32, _ arg1: Int32) -> Path! +} +extension JavaClass { + @JavaStaticMethod + public func of(_ arg0: String, _ arg1: [String]) -> Path! +} diff --git a/Sources/JavaKitIO/generated/Readable.swift b/Sources/JavaKitIO/generated/Readable.swift new file mode 100644 index 00000000..16825989 --- /dev/null +++ b/Sources/JavaKitIO/generated/Readable.swift @@ -0,0 +1,8 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaInterface("java.lang.Readable") +public struct Readable { + +} diff --git a/Sources/JavaKitIO/generated/Reader.swift b/Sources/JavaKitIO/generated/Reader.swift new file mode 100644 index 00000000..2f6cdfe2 --- /dev/null +++ b/Sources/JavaKitIO/generated/Reader.swift @@ -0,0 +1,40 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaClass("java.io.Reader", implements: Readable.self, Closeable.self) +open class Reader: JavaObject { + @JavaMethod + open func ready() throws -> Bool + + @JavaMethod + open func reset() throws + + @JavaMethod + open func read(_ arg0: [UInt16], _ arg1: Int32, _ arg2: Int32) throws -> Int32 + + @JavaMethod + open func read() throws -> Int32 + + @JavaMethod + open func read(_ arg0: [UInt16]) throws -> Int32 + + @JavaMethod + open func close() throws + + @JavaMethod + open func mark(_ arg0: Int32) throws + + @JavaMethod + open func transferTo(_ arg0: Writer?) throws -> Int64 + + @JavaMethod + open func skip(_ arg0: Int64) throws -> Int64 + + @JavaMethod + open func markSupported() -> Bool +} +extension JavaClass { + @JavaStaticMethod + public func nullReader() -> Reader! +} diff --git a/Sources/JavaKitIO/generated/StringReader.swift b/Sources/JavaKitIO/generated/StringReader.swift new file mode 100644 index 00000000..e2af1166 --- /dev/null +++ b/Sources/JavaKitIO/generated/StringReader.swift @@ -0,0 +1,33 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaClass("java.io.StringReader") +open class StringReader: Reader { + @JavaMethod + @_nonoverride public convenience init(_ arg0: String, environment: JNIEnvironment? = nil) + + @JavaMethod + open override func ready() throws -> Bool + + @JavaMethod + open override func reset() throws + + @JavaMethod + open override func read() throws -> Int32 + + @JavaMethod + open override func read(_ arg0: [UInt16], _ arg1: Int32, _ arg2: Int32) throws -> Int32 + + @JavaMethod + open override func close() + + @JavaMethod + open override func mark(_ arg0: Int32) throws + + @JavaMethod + open override func skip(_ arg0: Int64) throws -> Int64 + + @JavaMethod + open override func markSupported() -> Bool +} diff --git a/Sources/JavaKitIO/generated/WatchService.swift b/Sources/JavaKitIO/generated/WatchService.swift new file mode 100644 index 00000000..20bca06f --- /dev/null +++ b/Sources/JavaKitIO/generated/WatchService.swift @@ -0,0 +1,9 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaInterface("java.nio.file.WatchService", extends: Closeable.self) +public struct WatchService { + @JavaMethod + public func close() throws +} diff --git a/Sources/JavaKitIO/generated/Writer.swift b/Sources/JavaKitIO/generated/Writer.swift new file mode 100644 index 00000000..5e3fdff2 --- /dev/null +++ b/Sources/JavaKitIO/generated/Writer.swift @@ -0,0 +1,49 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaKit +import JavaRuntime + +@JavaClass("java.io.Writer", implements: Appendable.self, Closeable.self, Flushable.self) +open class Writer: JavaObject { + @JavaMethod + open func append(_ arg0: UInt16) throws -> Writer! + + @JavaMethod + open func append(_ arg0: CharSequence?, _ arg1: Int32, _ arg2: Int32) throws -> Writer! + + @JavaMethod + open func append(_ arg0: CharSequence?) throws -> Writer! + + @JavaMethod + open func append(_ arg0: CharSequence?) throws -> Appendable! + + @JavaMethod + open func append(_ arg0: UInt16) throws -> Appendable! + + @JavaMethod + open func append(_ arg0: CharSequence?, _ arg1: Int32, _ arg2: Int32) throws -> Appendable! + + @JavaMethod + open func flush() throws + + @JavaMethod + open func write(_ arg0: Int32) throws + + @JavaMethod + open func write(_ arg0: [UInt16], _ arg1: Int32, _ arg2: Int32) throws + + @JavaMethod + open func write(_ arg0: String) throws + + @JavaMethod + open func write(_ arg0: String, _ arg1: Int32, _ arg2: Int32) throws + + @JavaMethod + open func write(_ arg0: [UInt16]) throws + + @JavaMethod + open func close() throws +} +extension JavaClass { + @JavaStaticMethod + public func nullWriter() -> Writer! +} diff --git a/Sources/JavaKitIO/swift-java.config b/Sources/JavaKitIO/swift-java.config new file mode 100644 index 00000000..7b40b2da --- /dev/null +++ b/Sources/JavaKitIO/swift-java.config @@ -0,0 +1,21 @@ +{ + "classes" : { + "java.io.FileReader" : "FileReader", + "java.io.StringReader" : "StringReader", + "java.io.InputStreamReader" : "InputStreamReader", + "java.io.BufferedInputStream" : "BufferedInputStream", + "java.io.InputStream" : "InputStream", + "java.io.OutputStream" : "OutputStream", + "java.io.Reader" : "Reader", + "java.lang.Readable" : "Readable", + "java.io.Writer" : "Writer", + "java.io.File" : "File", + "java.nio.file.Path" : "Path", + "java.io.FileDescriptor" : "FileDescriptor", + "java.nio.charset.Charset" : "Charset", + "java.io.Closeable" : "Closeable", + "java.io.Flushable" : "Flushable", + "java.io.Flushable" : "ByteBuffer", + "java.nio.file.WatchService" : "WatchService", + } +} diff --git a/Tests/JavaKitTests/BasicRuntimeTests.swift b/Tests/JavaKitTests/BasicRuntimeTests.swift index 1cb0e787..d42fa4b1 100644 --- a/Tests/JavaKitTests/BasicRuntimeTests.swift +++ b/Tests/JavaKitTests/BasicRuntimeTests.swift @@ -56,7 +56,7 @@ class BasicRuntimeTests: XCTestCase { do { _ = try URL("bad url", environment: environment) } catch { - XCTAssert(String(describing: error) == "no protocol: bad url") + XCTAssertEqual(String(describing: error), "java.net.MalformedURLException: no protocol: bad url") } } @@ -73,7 +73,7 @@ class BasicRuntimeTests: XCTestCase { do { _ = try JavaClass(environment: environment) } catch { - XCTAssertEqual(String(describing: error), "org/swift/javakit/Nonexistent") + XCTAssertEqual(String(describing: error), "java.lang.NoClassDefFoundError: org/swift/javakit/Nonexistent") } } From 1e458ca9d2166ac9036b2b8b8275a7f09cabf2f2 Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Wed, 30 Apr 2025 16:31:43 -0700 Subject: [PATCH 242/426] [jextract] Remove NominalTypeResolution Instead, use SwiftSymbolTable mechanism. --- Sources/JExtractSwift/ImportedDecls.swift | 20 +- .../JExtractSwift/NominalTypeResolution.swift | 354 ------------------ .../Swift2JavaTranslator+Printing.swift | 10 +- .../JExtractSwift/Swift2JavaTranslator.swift | 70 ++-- Sources/JExtractSwift/Swift2JavaVisitor.swift | 10 +- Sources/JExtractSwift/SwiftKit+Printing.swift | 4 +- .../JExtractSwift/SwiftThunkTranslator.swift | 2 +- .../SwiftNominalTypeDeclaration.swift | 18 +- .../SwiftTypes/SwiftSymbolTable.swift | 89 +++-- Sources/JExtractSwift/TranslatedType.swift | 7 +- .../NominalTypeResolutionTests.swift | 64 ---- .../SwiftSymbolTableTests.swift | 47 +++ 12 files changed, 192 insertions(+), 503 deletions(-) delete mode 100644 Sources/JExtractSwift/NominalTypeResolution.swift delete mode 100644 Tests/JExtractSwiftTests/NominalTypeResolutionTests.swift create mode 100644 Tests/JExtractSwiftTests/SwiftSymbolTableTests.swift diff --git a/Sources/JExtractSwift/ImportedDecls.swift b/Sources/JExtractSwift/ImportedDecls.swift index c246dcbc..64693967 100644 --- a/Sources/JExtractSwift/ImportedDecls.swift +++ b/Sources/JExtractSwift/ImportedDecls.swift @@ -25,17 +25,17 @@ public typealias JavaPackage = String /// Describes a Swift nominal type (e.g., a class, struct, enum) that has been /// imported and is being translated into Java. -public struct ImportedNominalType: ImportedDecl { - public let swiftTypeName: String - public let javaType: JavaType - public var kind: NominalTypeKind +package struct ImportedNominalType: ImportedDecl { + let swiftNominal: SwiftNominalTypeDeclaration + let javaType: JavaType + var kind: NominalTypeKind - public var initializers: [ImportedFunc] = [] - public var methods: [ImportedFunc] = [] - public var variables: [ImportedVariable] = [] + package var initializers: [ImportedFunc] = [] + package var methods: [ImportedFunc] = [] + package var variables: [ImportedVariable] = [] - public init(swiftTypeName: String, javaType: JavaType, kind: NominalTypeKind) { - self.swiftTypeName = swiftTypeName + init(swiftNominal: SwiftNominalTypeDeclaration, javaType: JavaType, kind: NominalTypeKind) { + self.swiftNominal = swiftNominal self.javaType = javaType self.kind = kind } @@ -43,7 +43,7 @@ public struct ImportedNominalType: ImportedDecl { var translatedType: TranslatedType { TranslatedType( cCompatibleConvention: .direct, - originalSwiftType: "\(raw: swiftTypeName)", + originalSwiftType: "\(raw: swiftNominal.qualifiedName)", originalSwiftTypeKind: self.kind, cCompatibleSwiftType: "UnsafeRawPointer", cCompatibleJavaMemoryLayout: .heapObject, diff --git a/Sources/JExtractSwift/NominalTypeResolution.swift b/Sources/JExtractSwift/NominalTypeResolution.swift deleted file mode 100644 index b1185cde..00000000 --- a/Sources/JExtractSwift/NominalTypeResolution.swift +++ /dev/null @@ -1,354 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of Swift.org project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -import SwiftSyntax - -/// Perform nominal type resolution, including the binding of extensions to -/// their extended nominal types and mapping type names to their full names. -@_spi(Testing) -public class NominalTypeResolution { - /// Mapping from the syntax identifier for a given type declaration node, - /// such as StructDeclSyntax, to the set of extensions of this particular - /// type. - private var extensionsByType: [SyntaxIdentifier: [ExtensionDeclSyntax]] = [:] - - /// Mapping from extension declarations to the type declaration that they - /// extend. - var resolvedExtensions: [ExtensionDeclSyntax: NominalTypeDeclSyntaxNode] = [:] - - /// Extensions that have been encountered but not yet resolved to - private var unresolvedExtensions: [ExtensionDeclSyntax] = [] - - /// Mapping from qualified nominal type names to their syntax nodes. - var topLevelNominalTypes: [String: NominalTypeDeclSyntaxNode] = [:] - - @_spi(Testing) public init() { } -} - -/// A syntax node for a nominal type declaration. -@_spi(Testing) -public typealias NominalTypeDeclSyntaxNode = any DeclGroupSyntax & NamedDeclSyntax & WithAttributesSyntax & WithModifiersSyntax - -// MARK: Nominal type name resolution. -extension NominalTypeResolution { - /// Compute the fully-qualified name of the given nominal type node. - /// - /// This produces the name that can be resolved back to the nominal type - /// via resolveNominalType(_:). - @_spi(Testing) - public func fullyQualifiedName(of node: NominalTypeDeclSyntaxNode) -> String? { - let nameComponents = fullyQualifiedNameComponents(of: node) - return nameComponents.isEmpty ? nil : nameComponents.joined(separator: ".") - } - - private func fullyQualifiedNameComponents(of node: NominalTypeDeclSyntaxNode) -> [String] { - var nameComponents: [String] = [] - - var currentNode = Syntax(node) - while true { - // If it's a nominal type, add its name. - if let nominal = currentNode.asProtocol(SyntaxProtocol.self) as? NominalTypeDeclSyntaxNode, - let nominalName = nominal.name.identifier?.name { - nameComponents.append(nominalName) - } - - // If it's an extension, add the full name of the extended type. - if let extensionDecl = currentNode.as(ExtensionDeclSyntax.self), - let extendedNominal = extendedType(of: extensionDecl) { - let extendedNominalNameComponents = fullyQualifiedNameComponents(of: extendedNominal) - return extendedNominalNameComponents + nameComponents.reversed() - } - - guard let parent = currentNode.parent else { - break - - } - currentNode = parent - } - - return nameComponents.reversed() - } - - /// Resolve a nominal type name to its syntax node, or nil if it cannot be - /// resolved for any reason. - @_spi(Testing) - public func resolveNominalType(_ name: String) -> NominalTypeDeclSyntaxNode? { - let components = name.split(separator: ".") - return resolveNominalType(components) - } - - /// Resolve a nominal type name to its syntax node, or nil if it cannot be - /// resolved for any reason. - private func resolveNominalType(_ nameComponents: some Sequence) -> NominalTypeDeclSyntaxNode? { - // Resolve the name components in order. - var currentNode: NominalTypeDeclSyntaxNode? = nil - for nameComponentStr in nameComponents { - let nameComponent = String(nameComponentStr) - - var nextNode: NominalTypeDeclSyntaxNode? = nil - if let currentNode { - nextNode = lookupNominalType(nameComponent, in: currentNode) - } else { - nextNode = topLevelNominalTypes[nameComponent] - } - - // If we couldn't resolve the next name, we're done. - guard let nextNode else { - return nil - } - - currentNode = nextNode - } - - return currentNode - } - - /// Look for a nominal type with the given name within this declaration group, - /// which could be a nominal type declaration or extension thereof. - private func lookupNominalType( - _ name: String, - inDeclGroup parentNode: some DeclGroupSyntax - ) -> NominalTypeDeclSyntaxNode? { - for member in parentNode.memberBlock.members { - let memberDecl = member.decl.asProtocol(DeclSyntaxProtocol.self) - - // If we have a member with the given name that is a nominal type - // declaration, we found what we're looking for. - if let namedMemberDecl = memberDecl.asProtocol(NamedDeclSyntax.self), - namedMemberDecl.name.identifier?.name == name, - let nominalTypeDecl = memberDecl as? NominalTypeDeclSyntaxNode - { - return nominalTypeDecl - } - } - - return nil - } - - /// Lookup nominal type name within a given nominal type. - private func lookupNominalType( - _ name: String, - in parentNode: NominalTypeDeclSyntaxNode - ) -> NominalTypeDeclSyntaxNode? { - // Look in the parent node itself. - if let found = lookupNominalType(name, inDeclGroup: parentNode) { - return found - } - - // Look in known extensions of the parent node. - if let extensions = extensionsByType[parentNode.id] { - for extensionDecl in extensions { - if let found = lookupNominalType(name, inDeclGroup: extensionDecl) { - return found - } - } - } - - return nil - } -} - -// MARK: Binding extensions -extension NominalTypeResolution { - /// Look up the nominal type declaration to which this extension is bound. - @_spi(Testing) - public func extendedType(of extensionDecl: ExtensionDeclSyntax) -> NominalTypeDeclSyntaxNode? { - return resolvedExtensions[extensionDecl] - } - - /// Bind all of the unresolved extensions to their nominal types. - /// - /// Returns the list of extensions that could not be resolved. - @_spi(Testing) - @discardableResult - public func bindExtensions() -> [ExtensionDeclSyntax] { - while !unresolvedExtensions.isEmpty { - // Try to resolve all of the unresolved extensions. - let numExtensionsBefore = unresolvedExtensions.count - unresolvedExtensions.removeAll { extensionDecl in - // Try to resolve the type referenced by this extension declaration. If - // it fails, we'll try again later. - let nestedTypeNameComponents = extensionDecl.nestedTypeName - guard let resolvedType = resolveNominalType(nestedTypeNameComponents) else { - return false - } - - // We have successfully resolved the extended type. Record it and - // remove the extension from the list of unresolved extensions. - extensionsByType[resolvedType.id, default: []].append(extensionDecl) - resolvedExtensions[extensionDecl] = resolvedType - - return true - } - - // If we didn't resolve anything, we're done. - if numExtensionsBefore == unresolvedExtensions.count { - break - } - - assert(numExtensionsBefore > unresolvedExtensions.count) - } - - // Any unresolved extensions at this point are fundamentally unresolvable. - return unresolvedExtensions - } -} - -extension ExtensionDeclSyntax { - /// Produce the nested type name for the given decl - fileprivate var nestedTypeName: [String] { - var nameComponents: [String] = [] - var extendedType = extendedType - while true { - switch extendedType.as(TypeSyntaxEnum.self) { - case .attributedType(let attributedType): - extendedType = attributedType.baseType - continue - - case .identifierType(let identifierType): - guard let identifier = identifierType.name.identifier else { - return [] - } - - nameComponents.append(identifier.name) - return nameComponents.reversed() - - case .memberType(let memberType): - guard let identifier = memberType.name.identifier else { - return [] - } - - nameComponents.append(identifier.name) - extendedType = memberType.baseType - continue - - // Structural types implemented as nominal types. - case .arrayType: - return ["Array"] - - case .dictionaryType: - return ["Dictionary"] - - case .implicitlyUnwrappedOptionalType, .optionalType: - return [ "Optional" ] - - // Types that never involve nominals. - - case .classRestrictionType, .compositionType, .functionType, .metatypeType, - .missingType, .namedOpaqueReturnType, .packElementType, - .packExpansionType, .someOrAnyType, .suppressedType, .tupleType: - return [] - } - } - } -} - -// MARK: Adding source files to the resolution. -extension NominalTypeResolution { - /// Add the given source file. - @_spi(Testing) - public func addSourceFile(_ sourceFile: SourceFileSyntax) { - let visitor = NominalAndExtensionFinder(typeResolution: self) - visitor.walk(sourceFile) - } - - private class NominalAndExtensionFinder: SyntaxVisitor { - var typeResolution: NominalTypeResolution - var nestingDepth = 0 - - init(typeResolution: NominalTypeResolution) { - self.typeResolution = typeResolution - super.init(viewMode: .sourceAccurate) - } - - // Entering nominal type declarations. - - func visitNominal(_ node: NominalTypeDeclSyntaxNode) { - if nestingDepth == 0 { - typeResolution.topLevelNominalTypes[node.name.text] = node - } - - nestingDepth += 1 - } - - override func visit(_ node: ActorDeclSyntax) -> SyntaxVisitorContinueKind { - visitNominal(node) - return .visitChildren - } - - override func visit(_ node: ClassDeclSyntax) -> SyntaxVisitorContinueKind { - visitNominal(node) - return .visitChildren - } - - override func visit(_ node: EnumDeclSyntax) -> SyntaxVisitorContinueKind { - visitNominal(node) - return .visitChildren - } - - override func visit(_ node: ProtocolDeclSyntax) -> SyntaxVisitorContinueKind { - visitNominal(node) - return .visitChildren - } - - override func visit(_ node: StructDeclSyntax) -> SyntaxVisitorContinueKind { - visitNominal(node) - return .visitChildren - } - - // Exiting nominal type declarations. - func visitPostNominal(_ node: NominalTypeDeclSyntaxNode) { - assert(nestingDepth > 0) - nestingDepth -= 1 - } - - override func visitPost(_ node: ActorDeclSyntax) { - visitPostNominal(node) - } - - override func visitPost(_ node: ClassDeclSyntax) { - visitPostNominal(node) - } - - override func visitPost(_ node: EnumDeclSyntax) { - visitPostNominal(node) - } - - override func visitPost(_ node: ProtocolDeclSyntax) { - visitPostNominal(node) - } - - override func visitPost(_ node: StructDeclSyntax) { - visitPostNominal(node) - } - - // Extension handling - override func visit(_ node: ExtensionDeclSyntax) -> SyntaxVisitorContinueKind { - // Note that the extension is unresolved. We'll bind it later. - typeResolution.unresolvedExtensions.append(node) - nestingDepth += 1 - return .visitChildren - } - - override func visitPost(_ node: ExtensionDeclSyntax) { - nestingDepth -= 1 - } - - // Avoid stepping into functions. - - override func visit(_ node: CodeBlockSyntax) -> SyntaxVisitorContinueKind { - return .skipChildren - } - } -} diff --git a/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift b/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift index c8a26382..19c8fe57 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift @@ -87,7 +87,7 @@ extension Swift2JavaTranslator { // === All types for (_, ty) in importedTypes.sorted(by: { (lhs, rhs) in lhs.key < rhs.key }) { - let fileNameBase = "\(ty.swiftTypeName)+SwiftJava" + let fileNameBase = "\(ty.swiftNominal.qualifiedName)+SwiftJava" let filename = "\(fileNameBase).swift" log.info("Printing contents: \(filename)") @@ -132,7 +132,7 @@ extension Swift2JavaTranslator { } } - public func printSwiftThunkSources(_ printer: inout CodePrinter, ty: ImportedNominalType) throws { + package func printSwiftThunkSources(_ printer: inout CodePrinter, ty: ImportedNominalType) throws { let stt = SwiftThunkTranslator(self) printer.print( @@ -192,7 +192,7 @@ extension Swift2JavaTranslator { } } - public func printImportedClass(_ printer: inout CodePrinter, _ decl: ImportedNominalType) { + package func printImportedClass(_ printer: inout CodePrinter, _ decl: ImportedNominalType) { printHeader(&printer) printPackage(&printer) printImports(&printer) @@ -280,7 +280,7 @@ extension Swift2JavaTranslator { printer.print("") } - public func printNominal( + package func printNominal( _ printer: inout CodePrinter, _ decl: ImportedNominalType, body: (inout CodePrinter) -> Void ) { let parentProtocol: String @@ -1048,7 +1048,7 @@ extension Swift2JavaTranslator { printer.print(");") } - public func printHeapObjectToStringMethod( + package func printHeapObjectToStringMethod( _ printer: inout CodePrinter, _ decl: ImportedNominalType ) { printer.print( diff --git a/Sources/JExtractSwift/Swift2JavaTranslator.swift b/Sources/JExtractSwift/Swift2JavaTranslator.swift index 098333e7..25fd3e44 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator.swift @@ -28,7 +28,7 @@ public final class Swift2JavaTranslator { struct Input { let filePath: String - let syntax: Syntax + let syntax: SourceFileSyntax } var inputs: [Input] = [] @@ -51,7 +51,6 @@ public final class Swift2JavaTranslator { package var swiftStdlibTypes: SwiftStandardLibraryTypes let symbolTable: SwiftSymbolTable - let nominalResolution: NominalTypeResolution = NominalTypeResolution() var thunkNameRegistry: ThunkNameRegistry = ThunkNameRegistry() @@ -90,8 +89,7 @@ extension Swift2JavaTranslator { package func add(filePath: String, text: String) { log.trace("Adding: \(filePath)") let sourceFileSyntax = Parser.parse(source: text) - self.nominalResolution.addSourceFile(sourceFileSyntax) - self.inputs.append(Input(filePath: filePath, syntax: Syntax(sourceFileSyntax))) + self.inputs.append(Input(filePath: filePath, syntax: sourceFileSyntax)) } /// Convenient method for analyzing single file. @@ -120,20 +118,8 @@ extension Swift2JavaTranslator { } package func prepareForTranslation() { - nominalResolution.bindExtensions() - - // Prepare symbol table for nominal type names. - for (_, node) in nominalResolution.topLevelNominalTypes { - symbolTable.parsedModule.addNominalTypeDeclaration(node, parent: nil) - } - - for (ext, nominalNode) in nominalResolution.resolvedExtensions { - guard let nominalDecl = symbolTable.parsedModule.lookup(nominalNode) else { - continue - } - - symbolTable.parsedModule.addExtension(ext, extending: nominalDecl) - } + /// Setup the symbol table. + symbolTable.setup(inputs.map({ $0.syntax })) } } @@ -164,18 +150,42 @@ extension Swift2JavaTranslator { // ==== ---------------------------------------------------------------------------------------------------------------- // MARK: Type translation extension Swift2JavaTranslator { - /// Try to resolve the given nominal type node into its imported - /// representation. + /// Try to resolve the given nominal declaration node into its imported representation. func importedNominalType( - _ nominal: some DeclGroupSyntax & NamedDeclSyntax & WithModifiersSyntax & WithAttributesSyntax + _ nominalNode: some DeclGroupSyntax & NamedDeclSyntax & WithModifiersSyntax & WithAttributesSyntax, + parent: ImportedNominalType? ) -> ImportedNominalType? { - if !nominal.shouldImport(log: log) { + if !nominalNode.shouldImport(log: log) { return nil } - guard let fullName = nominalResolution.fullyQualifiedName(of: nominal) else { + guard let nominal = symbolTable.lookupType(nominalNode.name.text, parent: parent?.swiftNominal) else { return nil } + return self.importedNominalType(nominal) + } + + /// Try to resolve the given nominal type node into its imported representation. + func importedNominalType( + _ typeNode: TypeSyntax + ) -> ImportedNominalType? { + guard let swiftType = try? SwiftType(typeNode, symbolTable: self.symbolTable) else { + return nil + } + guard let swiftNominalDecl = swiftType.asNominalTypeDeclaration else { + return nil + } + guard let nominalNode = symbolTable.parsedModule.nominalTypeSyntaxNodes[swiftNominalDecl] else { + return nil + } + guard nominalNode.shouldImport(log: log) else { + return nil + } + return importedNominalType(swiftNominalDecl) + } + + func importedNominalType(_ nominal: SwiftNominalTypeDeclaration) -> ImportedNominalType? { + let fullName = nominal.qualifiedName if let alreadyImported = importedTypes[fullName] { return alreadyImported @@ -183,19 +193,19 @@ extension Swift2JavaTranslator { // Determine the nominal type kind. let kind: NominalTypeKind - switch Syntax(nominal).as(SyntaxEnum.self) { - case .actorDecl: kind = .actor - case .classDecl: kind = .class - case .enumDecl: kind = .enum - case .structDecl: kind = .struct + switch nominal.kind { + case .actor: kind = .actor + case .class: kind = .class + case .enum: kind = .enum + case .struct: kind = .struct default: return nil } let importedNominal = ImportedNominalType( - swiftTypeName: fullName, + swiftNominal: nominal, javaType: .class( package: javaPackage, - name: fullName + name: nominal.qualifiedName ), kind: kind ) diff --git a/Sources/JExtractSwift/Swift2JavaVisitor.swift b/Sources/JExtractSwift/Swift2JavaVisitor.swift index 96aab517..3df49782 100644 --- a/Sources/JExtractSwift/Swift2JavaVisitor.swift +++ b/Sources/JExtractSwift/Swift2JavaVisitor.swift @@ -33,7 +33,7 @@ final class Swift2JavaVisitor: SyntaxVisitor { var currentType: ImportedNominalType? { typeContext.last?.type } /// The current type name as a nested name like A.B.C. - var currentTypeName: String? { self.currentType?.swiftTypeName } + var currentTypeName: String? { self.currentType?.swiftNominal.qualifiedName } var log: Logger { translator.log } @@ -62,7 +62,7 @@ final class Swift2JavaVisitor: SyntaxVisitor { override func visit(_ node: ClassDeclSyntax) -> SyntaxVisitorContinueKind { log.debug("Visit \(node.kind): '\(node.qualifiedNameForDebug)'") - guard let importedNominalType = translator.importedNominalType(node) else { + guard let importedNominalType = translator.importedNominalType(node, parent: self.currentType) else { return .skipChildren } @@ -78,7 +78,7 @@ final class Swift2JavaVisitor: SyntaxVisitor { override func visit(_ node: StructDeclSyntax) -> SyntaxVisitorContinueKind { log.debug("Visit \(node.kind): \(node.qualifiedNameForDebug)") - guard let importedNominalType = translator.importedNominalType(node) else { + guard let importedNominalType = translator.importedNominalType(node, parent: self.currentType) else { return .skipChildren } @@ -95,9 +95,7 @@ final class Swift2JavaVisitor: SyntaxVisitor { override func visit(_ node: ExtensionDeclSyntax) -> SyntaxVisitorContinueKind { // Resolve the extended type of the extension as an imported nominal, and // recurse if we found it. - guard let nominal = translator.nominalResolution.extendedType(of: node), - let importedNominalType = translator.importedNominalType(nominal) - else { + guard let importedNominalType = translator.importedNominalType(node.extendedType) else { return .skipChildren } diff --git a/Sources/JExtractSwift/SwiftKit+Printing.swift b/Sources/JExtractSwift/SwiftKit+Printing.swift index ed7d05d6..aa01502d 100644 --- a/Sources/JExtractSwift/SwiftKit+Printing.swift +++ b/Sources/JExtractSwift/SwiftKit+Printing.swift @@ -23,7 +23,7 @@ package struct SwiftKitPrinting { /// Forms syntax for a Java call to a swiftkit exposed function. static func renderCallGetSwiftType(module: String, nominal: ImportedNominalType) -> String { """ - SwiftKit.swiftjava.getType("\(module)", "\(nominal.swiftTypeName)") + SwiftKit.swiftjava.getType("\(module)", "\(nominal.swiftNominal.qualifiedName)") """ } } @@ -38,7 +38,7 @@ extension SwiftKitPrinting { extension SwiftKitPrinting.Names { static func getType(module: String, nominal: ImportedNominalType) -> String { - "swiftjava_getType_\(module)_\(nominal.swiftTypeName)" + "swiftjava_getType_\(module)_\(nominal.swiftNominal.qualifiedName)" } } diff --git a/Sources/JExtractSwift/SwiftThunkTranslator.swift b/Sources/JExtractSwift/SwiftThunkTranslator.swift index 2676ef2e..6a423a78 100644 --- a/Sources/JExtractSwift/SwiftThunkTranslator.swift +++ b/Sources/JExtractSwift/SwiftThunkTranslator.swift @@ -73,7 +73,7 @@ struct SwiftThunkTranslator { """ @_cdecl("\(raw: funcName)") public func \(raw: funcName)() -> UnsafeMutableRawPointer /* Any.Type */ { - return unsafeBitCast(\(raw: nominal.swiftTypeName).self, to: UnsafeMutableRawPointer.self) + return unsafeBitCast(\(raw: nominal.swiftNominal.qualifiedName).self, to: UnsafeMutableRawPointer.self) } """ } diff --git a/Sources/JExtractSwift/SwiftTypes/SwiftNominalTypeDeclaration.swift b/Sources/JExtractSwift/SwiftTypes/SwiftNominalTypeDeclaration.swift index 53e103b0..5e1c0b18 100644 --- a/Sources/JExtractSwift/SwiftTypes/SwiftNominalTypeDeclaration.swift +++ b/Sources/JExtractSwift/SwiftTypes/SwiftNominalTypeDeclaration.swift @@ -14,9 +14,13 @@ import SwiftSyntax +///// A syntax node for a nominal type declaration. +@_spi(Testing) +public typealias NominalTypeDeclSyntaxNode = any DeclGroupSyntax & NamedDeclSyntax & WithAttributesSyntax & WithModifiersSyntax + /// Describes a nominal type declaration, which can be of any kind (class, struct, etc.) /// and has a name, parent type (if nested), and owning module. -class SwiftNominalTypeDeclaration { +package class SwiftNominalTypeDeclaration { enum Kind { case actor case `class` @@ -79,16 +83,24 @@ class SwiftNominalTypeDeclaration { return KnownStandardLibraryType(typeNameInSwiftModule: name) } + + package var qualifiedName: String { + if let parent = self.parent { + return parent.qualifiedName + "." + name + } else { + return name + } + } } extension SwiftNominalTypeDeclaration: Equatable { - static func ==(lhs: SwiftNominalTypeDeclaration, rhs: SwiftNominalTypeDeclaration) -> Bool { + package static func ==(lhs: SwiftNominalTypeDeclaration, rhs: SwiftNominalTypeDeclaration) -> Bool { lhs === rhs } } extension SwiftNominalTypeDeclaration: Hashable { - func hash(into hasher: inout Hasher) { + package func hash(into hasher: inout Hasher) { hasher.combine(ObjectIdentifier(self)) } } diff --git a/Sources/JExtractSwift/SwiftTypes/SwiftSymbolTable.swift b/Sources/JExtractSwift/SwiftTypes/SwiftSymbolTable.swift index bb3c2f5f..87c2c80f 100644 --- a/Sources/JExtractSwift/SwiftTypes/SwiftSymbolTable.swift +++ b/Sources/JExtractSwift/SwiftTypes/SwiftSymbolTable.swift @@ -14,7 +14,7 @@ import SwiftSyntax -protocol SwiftSymbolTableProtocol { +package protocol SwiftSymbolTableProtocol { /// The module name that this symbol table describes. var moduleName: String { get } @@ -28,7 +28,7 @@ protocol SwiftSymbolTableProtocol { extension SwiftSymbolTableProtocol { /// Look for a type - func lookupType(_ name: String, parent: SwiftNominalTypeDeclaration?) -> SwiftNominalTypeDeclaration? { + package func lookupType(_ name: String, parent: SwiftNominalTypeDeclaration?) -> SwiftNominalTypeDeclaration? { if let parent { return lookupNestedType(name, parent: parent) } @@ -37,19 +37,62 @@ extension SwiftSymbolTableProtocol { } } -class SwiftSymbolTable { +package class SwiftSymbolTable { var importedModules: [SwiftModuleSymbolTable] = [] var parsedModule: SwiftParsedModuleSymbolTable - init(parsedModuleName: String) { + package init(parsedModuleName: String) { self.parsedModule = SwiftParsedModuleSymbolTable(moduleName: parsedModuleName) } func addImportedModule(symbolTable: SwiftModuleSymbolTable) { importedModules.append(symbolTable) } +} + +extension SwiftSymbolTable { + package func setup(_ sourceFiles: some Collection) { + // First, register top-level and nested nominal types to the symbol table. + for sourceFile in sourceFiles { + self.addNominalTypeDeclarations(sourceFile) + } + + // Next bind the extensions. + + // The work queue is required because, the extending type might be declared + // in another extension that hasn't been processed. E.g.: + // + // extension Outer.Inner { struct Deeper {} } + // extension Outer { struct Inner {} } + // struct Outer {} + // + var unresolvedExtensions: [ExtensionDeclSyntax] = [] + for sourceFile in sourceFiles { + // Find extensions. + for statement in sourceFile.statements { + // We only care about extensions at top-level. + if case .decl(let decl) = statement.item, let extNode = decl.as(ExtensionDeclSyntax.self) { + let resolved = handleExtension(extNode) + if !resolved { + unresolvedExtensions.append(extNode) + } + } + } + } + + while !unresolvedExtensions.isEmpty { + let numExtensionsBefore = unresolvedExtensions.count + unresolvedExtensions.removeAll(where: handleExtension(_:)) + + // If we didn't resolve anything, we're done. + if numExtensionsBefore == unresolvedExtensions.count { + break + } + assert(numExtensionsBefore > unresolvedExtensions.count) + } + } - func addTopLevelNominalTypeDeclarations(_ sourceFile: SourceFileSyntax) { + private func addNominalTypeDeclarations(_ sourceFile: SourceFileSyntax) { // Find top-level nominal type declarations. for statement in sourceFile.statements { // We only care about declarations. @@ -62,31 +105,31 @@ class SwiftSymbolTable { } } - func addExtensions( - _ sourceFile: SourceFileSyntax, - nominalResolution: NominalTypeResolution - ) { - // Find extensions. - for statement in sourceFile.statements { - // We only care about declarations. - guard case .decl(let decl) = statement.item, - let extNode = decl.as(ExtensionDeclSyntax.self), - let extendedTypeNode = nominalResolution.extendedType(of: extNode), - let extendedTypeDecl = parsedModule.nominalTypeDeclarations[extendedTypeNode.id] else { - continue - } - - parsedModule.addExtension(extNode, extending: extendedTypeDecl) + private func handleExtension(_ extensionDecl: ExtensionDeclSyntax) -> Bool { + // Try to resolve the type referenced by this extension declaration. + // If it fails, we'll try again later. + guard let extendedType = try? SwiftType(extensionDecl.extendedType, symbolTable: self) else { + return false + } + guard let extendedNominal = extendedType.asNominalTypeDeclaration else { + // Extending type was not a nominal type. Ignore it. + return true } + + // Register nested nominals in extensions to the symbol table. + parsedModule.addExtension(extensionDecl, extending: extendedNominal) + + // We have successfully resolved the extended type. Record it. + return true } } extension SwiftSymbolTable: SwiftSymbolTableProtocol { - var moduleName: String { parsedModule.moduleName } + package var moduleName: String { parsedModule.moduleName } /// Look for a top-level nominal type with the given name. This should only /// return nominal types within this module. - func lookupTopLevelNominalType(_ name: String) -> SwiftNominalTypeDeclaration? { + package func lookupTopLevelNominalType(_ name: String) -> SwiftNominalTypeDeclaration? { if let parsedResult = parsedModule.lookupTopLevelNominalType(name) { return parsedResult } @@ -101,7 +144,7 @@ extension SwiftSymbolTable: SwiftSymbolTableProtocol { } // Look for a nested type with the given name. - func lookupNestedType(_ name: String, parent: SwiftNominalTypeDeclaration) -> SwiftNominalTypeDeclaration? { + package func lookupNestedType(_ name: String, parent: SwiftNominalTypeDeclaration) -> SwiftNominalTypeDeclaration? { if let parsedResult = parsedModule.lookupNestedType(name, parent: parent) { return parsedResult } diff --git a/Sources/JExtractSwift/TranslatedType.swift b/Sources/JExtractSwift/TranslatedType.swift index b36d7e77..19c38ce6 100644 --- a/Sources/JExtractSwift/TranslatedType.swift +++ b/Sources/JExtractSwift/TranslatedType.swift @@ -158,16 +158,13 @@ extension Swift2JavaVisitor { ) } - // Generic types aren't mapped into Java. + // FIXME: Generic types aren't mapped into Java. if let genericArguments { throw TypeTranslationError.unexpectedGenericArguments(type, genericArguments) } // Look up the imported types by name to resolve it to a nominal type. - let swiftTypeName = type.trimmedDescription // FIXME: This is a hack. - guard let resolvedNominal = translator.nominalResolution.resolveNominalType(swiftTypeName), - let importedNominal = translator.importedNominalType(resolvedNominal) - else { + guard let importedNominal = translator.importedNominalType(type) else { throw TypeTranslationError.unknown(type) } diff --git a/Tests/JExtractSwiftTests/NominalTypeResolutionTests.swift b/Tests/JExtractSwiftTests/NominalTypeResolutionTests.swift deleted file mode 100644 index 01b507df..00000000 --- a/Tests/JExtractSwiftTests/NominalTypeResolutionTests.swift +++ /dev/null @@ -1,64 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of Swift.org project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -@_spi(Testing) import JExtractSwift -import SwiftSyntax -import SwiftParser -import Testing - -@Suite("Nominal type lookup") -struct NominalTypeLookupSuite { - func checkNominalRoundTrip( - _ resolution: NominalTypeResolution, - name: String, - fileID: String = #fileID, - filePath: String = #filePath, - line: Int = #line, - column: Int = #column - ) { - let sourceLocation = SourceLocation(fileID: fileID, filePath: filePath, line: line, column: column) - let nominal = resolution.resolveNominalType(name) - #expect(nominal != nil, sourceLocation: sourceLocation) - if let nominal { - #expect(resolution.fullyQualifiedName(of: nominal) == name, sourceLocation: sourceLocation) - } - } - - @Test func lookupBindingTests() { - let resolution = NominalTypeResolution() - resolution.addSourceFile(""" - extension X { - struct Y { - } - } - - struct X { - } - - extension X.Y { - struct Z { } - } - """) - - // Bind all extensions and verify that all were bound. - #expect(resolution.bindExtensions().isEmpty) - - checkNominalRoundTrip(resolution, name: "X") - checkNominalRoundTrip(resolution, name: "X.Y") - checkNominalRoundTrip(resolution, name: "X.Y.Z") - #expect(resolution.resolveNominalType("Y") == nil) - #expect(resolution.resolveNominalType("X.Z") == nil) - } -} - diff --git a/Tests/JExtractSwiftTests/SwiftSymbolTableTests.swift b/Tests/JExtractSwiftTests/SwiftSymbolTableTests.swift new file mode 100644 index 00000000..5d1e5e2b --- /dev/null +++ b/Tests/JExtractSwiftTests/SwiftSymbolTableTests.swift @@ -0,0 +1,47 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024-2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +@_spi(Testing) import JExtractSwift +import SwiftSyntax +import SwiftParser +import Testing + +@Suite("Swift symbol table") +struct SwiftSymbolTableSuite { + + @Test func lookupBindingTests() throws { + let symbolTable = SwiftSymbolTable(parsedModuleName: "MyModule") + let sourceFile1: SourceFileSyntax = """ + extension X.Y { + struct Z { } + } + extension X { + struct Y {} + } + """ + let sourceFile2: SourceFileSyntax = """ + struct X {} + """ + + symbolTable.setup([sourceFile1, sourceFile2]) + + let x = try #require(symbolTable.lookupType("X", parent: nil)) + let xy = try #require(symbolTable.lookupType("Y", parent: x)) + let xyz = try #require(symbolTable.lookupType("Z", parent: xy)) + #expect(xyz.qualifiedName == "X.Y.Z") + + #expect(symbolTable.lookupType("Y", parent: nil) == nil) + #expect(symbolTable.lookupType("Z", parent: nil) == nil) + } +} From bcd5e0e85c5b9cfe0693f7260fd74cc843647cbc Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Fri, 30 May 2025 13:47:03 -0700 Subject: [PATCH 243/426] [jextract] Improve CDecl lowering * Newly introduce `lowerResult()` (splitted from `lowerParameter()` because result lowering can be differnt from parameter lowering. * Remove `ConversionStep.init(cdeclToSwift:)/.init(swiftToCdecl:)`. Instead embed the logic in `lowerParameter()`/`lowerResult()` so that we can implement type lowering and the actual conversion at the same place. * Support 'String', 'Void' and '() -> Void) types * Implement getter / setter lowering * Fix conversion for tuple returns (see: `lowerTupleReturns()` test) * Reference types are now returned indirectly, as the logic are being unifed. Thanks to this we don't need manual `retain()` before returning instances, which wasn't implemented correctly. --- .../CDeclLowering/CDeclConversions.swift | 195 ----- .../CDeclLowering/CRepresentation.swift | 23 +- ...wift2JavaTranslator+FunctionLowering.swift | 809 ++++++++++-------- Sources/JExtractSwift/ConversionStep.swift | 102 ++- .../SwiftTypes/SwiftFunctionSignature.swift | 168 +++- .../SwiftNominalTypeDeclaration.swift | 13 + .../SwiftTypes/SwiftResult.swift | 8 +- .../SwiftStandardLibraryTypes.swift | 4 +- .../JExtractSwift/SwiftTypes/SwiftType.swift | 51 +- .../Asserts/LoweringAssertions.swift | 67 +- .../FunctionLoweringTests.swift | 163 +++- 11 files changed, 927 insertions(+), 676 deletions(-) delete mode 100644 Sources/JExtractSwift/CDeclLowering/CDeclConversions.swift diff --git a/Sources/JExtractSwift/CDeclLowering/CDeclConversions.swift b/Sources/JExtractSwift/CDeclLowering/CDeclConversions.swift deleted file mode 100644 index 0099ae5c..00000000 --- a/Sources/JExtractSwift/CDeclLowering/CDeclConversions.swift +++ /dev/null @@ -1,195 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2025 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of Swift.org project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -extension ConversionStep { - /// Produce a conversion that takes in a value (or set of values) that - /// would be available in a @_cdecl function to represent the given Swift - /// type, and convert that to an instance of the Swift type. - init(cdeclToSwift swiftType: SwiftType) throws { - // If there is a 1:1 mapping between this Swift type and a C type, then - // there is no translation to do. - if let cType = try? CType(cdeclType: swiftType) { - _ = cType - self = .placeholder - return - } - - switch swiftType { - case .function, .optional: - throw LoweringError.unhandledType(swiftType) - - case .metatype(let instanceType): - self = .unsafeCastPointer( - .placeholder, - swiftType: instanceType - ) - - case .nominal(let nominal): - if let knownType = nominal.nominalTypeDecl.knownStandardLibraryType { - // Typed pointers - if let firstGenericArgument = nominal.genericArguments?.first { - switch knownType { - case .unsafePointer, .unsafeMutablePointer: - self = .typedPointer( - .explodedComponent(.placeholder, component: "pointer"), - swiftType: firstGenericArgument - ) - return - - case .unsafeBufferPointer, .unsafeMutableBufferPointer: - self = .initialize( - swiftType, - arguments: [ - LabeledArgument( - label: "start", - argument: .typedPointer( - .explodedComponent(.placeholder, component: "pointer"), - swiftType: firstGenericArgument) - ), - LabeledArgument( - label: "count", - argument: .explodedComponent(.placeholder, component: "count") - ) - ] - ) - return - - default: - break - } - } - } - - // Arbitrary nominal types. - switch nominal.nominalTypeDecl.kind { - case .actor, .class: - // For actor and class, we pass around the pointer directly. - self = .unsafeCastPointer(.placeholder, swiftType: swiftType) - case .enum, .struct, .protocol: - // For enums, structs, and protocol types, we pass around the - // values indirectly. - self = .passIndirectly( - .pointee(.typedPointer(.placeholder, swiftType: swiftType)) - ) - } - - case .tuple(let elements): - self = .tuplify(try elements.map { try ConversionStep(cdeclToSwift: $0) }) - } - } - - /// Produce a conversion that takes in a value that would be available in a - /// Swift function and convert that to the corresponding cdecl values. - /// - /// This conversion goes in the opposite direction of init(cdeclToSwift:), and - /// is used for (e.g.) returning the Swift value from a cdecl function. When - /// there are multiple cdecl values that correspond to this one Swift value, - /// the result will be a tuple that can be assigned to a tuple of the cdecl - /// values, e.g., (.baseAddress, .count). - init( - swiftToCDecl swiftType: SwiftType, - stdlibTypes: SwiftStandardLibraryTypes - ) throws { - // If there is a 1:1 mapping between this Swift type and a C type, then - // there is no translation to do. - if let cType = try? CType(cdeclType: swiftType) { - _ = cType - self = .placeholder - return - } - - switch swiftType { - case .function, .optional: - throw LoweringError.unhandledType(swiftType) - - case .metatype: - self = .unsafeCastPointer( - .placeholder, - swiftType: .nominal( - SwiftNominalType( - nominalTypeDecl: stdlibTypes[.unsafeRawPointer] - ) - ) - ) - return - - case .nominal(let nominal): - if let knownType = nominal.nominalTypeDecl.knownStandardLibraryType { - // Typed pointers - if nominal.genericArguments?.first != nil { - switch knownType { - case .unsafePointer, .unsafeMutablePointer: - let isMutable = knownType == .unsafeMutablePointer - self = ConversionStep( - initializeRawPointerFromTyped: .placeholder, - isMutable: isMutable, - isPartOfBufferPointer: false, - stdlibTypes: stdlibTypes - ) - return - - case .unsafeBufferPointer, .unsafeMutableBufferPointer: - let isMutable = knownType == .unsafeMutableBufferPointer - self = .tuplify( - [ - ConversionStep( - initializeRawPointerFromTyped: .explodedComponent( - .placeholder, - component: "pointer" - ), - isMutable: isMutable, - isPartOfBufferPointer: true, - stdlibTypes: stdlibTypes - ), - .explodedComponent(.placeholder, component: "count") - ] - ) - return - - default: - break - } - } - } - - // Arbitrary nominal types. - switch nominal.nominalTypeDecl.kind { - case .actor, .class: - // For actor and class, we pass around the pointer directly. Case to - // the unsafe raw pointer type we use to represent it in C. - self = .unsafeCastPointer( - .placeholder, - swiftType: .nominal( - SwiftNominalType( - nominalTypeDecl: stdlibTypes[.unsafeRawPointer] - ) - ) - ) - - case .enum, .struct, .protocol: - // For enums, structs, and protocol types, we leave the value alone. - // The indirection will be handled by the caller. - self = .placeholder - } - - case .tuple(let elements): - // Convert all of the elements. - self = .tuplify( - try elements.map { element in - try ConversionStep(swiftToCDecl: element, stdlibTypes: stdlibTypes) - } - ) - } - } -} diff --git a/Sources/JExtractSwift/CDeclLowering/CRepresentation.swift b/Sources/JExtractSwift/CDeclLowering/CRepresentation.swift index 15e4ebb8..e1a69d12 100644 --- a/Sources/JExtractSwift/CDeclLowering/CRepresentation.swift +++ b/Sources/JExtractSwift/CDeclLowering/CRepresentation.swift @@ -24,10 +24,22 @@ extension CType { init(cdeclType: SwiftType) throws { switch cdeclType { case .nominal(let nominalType): - if let knownType = nominalType.nominalTypeDecl.knownStandardLibraryType, - let primitiveCType = knownType.primitiveCType { - self = primitiveCType - return + if let knownType = nominalType.nominalTypeDecl.knownStandardLibraryType { + if let primitiveCType = knownType.primitiveCType { + self = primitiveCType + return + } + + switch knownType { + case .unsafePointer where nominalType.genericArguments?.count == 1: + self = .pointer(.qualified(const: true, volatile: false, type: try CType(cdeclType: nominalType.genericArguments![0]))) + return + case .unsafeMutablePointer where nominalType.genericArguments?.count == 1: + self = .pointer(try CType(cdeclType: nominalType.genericArguments![0])) + return + default: + break + } } throw CDeclToCLoweringError.invalidNominalType(nominalType.nominalTypeDecl) @@ -109,7 +121,8 @@ extension KnownStandardLibraryType { case .unsafeRawPointer: .pointer( .qualified(const: true, volatile: false, type: .void) ) - case .unsafePointer, .unsafeMutablePointer, .unsafeBufferPointer, .unsafeMutableBufferPointer: + case .void: .void + case .unsafePointer, .unsafeMutablePointer, .unsafeBufferPointer, .unsafeMutableBufferPointer, .string: nil } } diff --git a/Sources/JExtractSwift/CDeclLowering/Swift2JavaTranslator+FunctionLowering.swift b/Sources/JExtractSwift/CDeclLowering/Swift2JavaTranslator+FunctionLowering.swift index d65948ac..9dbcb510 100644 --- a/Sources/JExtractSwift/CDeclLowering/Swift2JavaTranslator+FunctionLowering.swift +++ b/Sources/JExtractSwift/CDeclLowering/Swift2JavaTranslator+FunctionLowering.swift @@ -29,8 +29,7 @@ extension Swift2JavaTranslator { enclosingType: try enclosingType.map { try SwiftType($0, symbolTable: symbolTable) }, symbolTable: symbolTable ) - - return try lowerFunctionSignature(signature) + return try CdeclLowering(swiftStdlibTypes: swiftStdlibTypes).lowerFunctionSignature(signature, apiKind: .function) } /// Lower the given initializer to a C-compatible entrypoint, @@ -47,16 +46,57 @@ extension Swift2JavaTranslator { symbolTable: symbolTable ) - return try lowerFunctionSignature(signature) + return try CdeclLowering(swiftStdlibTypes: swiftStdlibTypes).lowerFunctionSignature(signature, apiKind: .initializer) + } + + /// Lower the given variable decl to a C-compatible entrypoint, + /// providing all of the mappings between the parameter and result types + /// of the original function and its `@_cdecl` counterpart. + @_spi(Testing) + public func lowerFunctionSignature( + _ decl: VariableDeclSyntax, + isSet: Bool, + enclosingType: TypeSyntax? = nil + ) throws -> LoweredFunctionSignature? { + let supportedAccessors = decl.supportedAccessorKinds(binding: decl.bindings.first!) + guard supportedAccessors.contains(isSet ? .set : .get) else { + return nil + } + + let signature = try SwiftFunctionSignature( + decl, + isSet: isSet, + enclosingType: try enclosingType.map { try SwiftType($0, symbolTable: symbolTable) }, + symbolTable: symbolTable + ) + return try CdeclLowering(swiftStdlibTypes: swiftStdlibTypes).lowerFunctionSignature(signature, apiKind: isSet ? .setter : .getter) } +} + +/// Responsible for lowering Swift API to C API. +struct CdeclLowering { + var swiftStdlibTypes: SwiftStandardLibraryTypes /// Lower the given Swift function signature to a Swift @_cdecl function signature, /// which is C compatible, and the corresponding Java method signature. /// /// Throws an error if this function cannot be lowered for any reason. func lowerFunctionSignature( - _ signature: SwiftFunctionSignature + _ signature: SwiftFunctionSignature, + apiKind: SwiftAPIKind ) throws -> LoweredFunctionSignature { + // Lower the self parameter. + let loweredSelf: LoweredParameter? = switch signature.selfParameter { + case .instance(let selfParameter): + try lowerParameter( + selfParameter.type, + convention: selfParameter.convention, + parameterName: selfParameter.parameterName ?? "self" + ) + case nil, .initializer(_), .staticMethod(_): + nil + } + // Lower all of the parameters. let loweredParameters = try signature.parameters.enumerated().map { (index, param) in try lowerParameter( @@ -67,116 +107,46 @@ extension Swift2JavaTranslator { } // Lower the result. - var loweredResult = try lowerParameter( - signature.result.type, - convention: .byValue, - parameterName: "_result" - ) - - // If the result type doesn't lower to either empty (void) or a single - // result, make it indirect. - let indirectResult: Bool - if loweredResult.cdeclParameters.count == 0 { - // void result type - indirectResult = false - } else if loweredResult.cdeclParameters.count == 1, - loweredResult.cdeclParameters[0].canBeDirectReturn { - // Primitive result type - indirectResult = false - } else { - loweredResult = try lowerParameter( - signature.result.type, - convention: .inout, - parameterName: "_result" - ) - indirectResult = true - } - - // Lower the self parameter. - let loweredSelf = try signature.selfParameter.flatMap { selfParameter in - switch selfParameter { - case .instance(let selfParameter): - try lowerParameter( - selfParameter.type, - convention: selfParameter.convention, - parameterName: selfParameter.parameterName ?? "self" - ) - case .initializer, .staticMethod: - nil - } - } - - // Collect all of the lowered parameters for the @_cdecl function. - var allLoweredParameters: [LoweredParameters] = [] - var cdeclLoweredParameters: [SwiftParameter] = [] - allLoweredParameters.append(contentsOf: loweredParameters) - cdeclLoweredParameters.append( - contentsOf: loweredParameters.flatMap { $0.cdeclParameters } - ) - - // Lower self. - if let loweredSelf { - allLoweredParameters.append(loweredSelf) - cdeclLoweredParameters.append(contentsOf: loweredSelf.cdeclParameters) - } - - // Lower indirect results. - let cdeclResult: SwiftResult - if indirectResult { - cdeclLoweredParameters.append( - contentsOf: loweredResult.cdeclParameters - ) - cdeclResult = .init(convention: .direct, type: .tuple([])) - } else if loweredResult.cdeclParameters.count == 1, - let primitiveResult = loweredResult.cdeclParameters.first { - cdeclResult = .init(convention: .direct, type: primitiveResult.type) - } else if loweredResult.cdeclParameters.count == 0 { - cdeclResult = .init(convention: .direct, type: .tuple([])) - } else { - fatalError("Improper lowering of result for \(signature)") - } - - let cdeclSignature = SwiftFunctionSignature( - selfParameter: nil, - parameters: cdeclLoweredParameters, - result: cdeclResult - ) + let loweredResult = try lowerResult(signature.result.type) return LoweredFunctionSignature( original: signature, - cdecl: cdeclSignature, - parameters: allLoweredParameters, + apiKind: apiKind, + selfParameter: loweredSelf, + parameters: loweredParameters, result: loweredResult ) } + /// Lower a Swift function parameter type to cdecl parameters. + /// + /// For example, Swift parameter `arg value: inout Int` can be lowered with + /// `lowerParameter(intTy, .inout, "value")`. + /// + /// - Parameters: + /// - type: The parameter type. + /// - convention: the parameter convention, e.g. `inout`. + /// - parameterName: The name of the parameter. + /// func lowerParameter( _ type: SwiftType, convention: SwiftParameterConvention, parameterName: String - ) throws -> LoweredParameters { + ) throws -> LoweredParameter { // If there is a 1:1 mapping between this Swift type and a C type, we just - // need to add the corresponding C [arameter. - if let cType = try? CType(cdeclType: type), convention != .inout { - _ = cType - return LoweredParameters( - cdeclParameters: [ - SwiftParameter( - convention: convention, - parameterName: parameterName, - type: type, - canBeDirectReturn: true - ) - ] - ) + // return it. + if let _ = try? CType(cdeclType: type) { + if convention != .inout { + return LoweredParameter( + cdeclParameters: [SwiftParameter(convention: .byValue, parameterName: parameterName, type: type)], + conversion: .placeholder + ) + } } switch type { - case .function, .optional: - throw LoweringError.unhandledType(type) - - case .metatype: - return LoweredParameters( + case .metatype(let instanceType): + return LoweredParameter( cdeclParameters: [ SwiftParameter( convention: .byValue, @@ -185,98 +155,271 @@ extension Swift2JavaTranslator { SwiftNominalType( nominalTypeDecl: swiftStdlibTypes[.unsafeRawPointer] ) - ), - canBeDirectReturn: true + ) ) - ] + ], + conversion: .unsafeCastPointer(.placeholder, swiftType: instanceType) ) case .nominal(let nominal): - // Types from the Swift standard library that we know about. - if let knownType = nominal.nominalTypeDecl.knownStandardLibraryType, - convention != .inout { - // Typed pointers are mapped down to their raw forms in cdecl entry - // points. These can be passed through directly. - if knownType == .unsafePointer || knownType == .unsafeMutablePointer { + if let knownType = nominal.nominalTypeDecl.knownStandardLibraryType { + if convention == .inout { + // FIXME: Support non-trivial 'inout' for builtin types. + throw LoweringError.inoutNotSupported(type) + } + switch knownType { + case .unsafePointer, .unsafeMutablePointer: + guard let genericArgs = type.asNominalType?.genericArguments, genericArgs.count == 1 else { + throw LoweringError.unhandledType(type) + } + // Typed pointers are mapped down to their raw forms in cdecl entry + // points. These can be passed through directly. let isMutable = knownType == .unsafeMutablePointer - let cdeclPointerType = isMutable - ? swiftStdlibTypes[.unsafeMutableRawPointer] - : swiftStdlibTypes[.unsafeRawPointer] - return LoweredParameters( - cdeclParameters: [ - SwiftParameter( - convention: convention, - parameterName: parameterName + "_pointer", - type: SwiftType.nominal( - SwiftNominalType(nominalTypeDecl: cdeclPointerType) - ), - canBeDirectReturn: true - ) - ] + let rawPointerNominal = swiftStdlibTypes[isMutable ? .unsafeMutableRawPointer : .unsafeRawPointer] + let paramType: SwiftType = .nominal(SwiftNominalType(nominalTypeDecl: rawPointerNominal)) + return LoweredParameter( + cdeclParameters: [SwiftParameter(convention: .byValue, parameterName: parameterName, type: paramType)], + conversion: .typedPointer(.placeholder, swiftType: genericArgs[0]) ) - } - // Typed buffer pointers are mapped down to a (pointer, count) pair - // so those parts can be passed through directly. - if knownType == .unsafeBufferPointer || knownType == .unsafeMutableBufferPointer { + case .unsafeBufferPointer, .unsafeMutableBufferPointer: + guard let genericArgs = type.asNominalType?.genericArguments, genericArgs.count == 1 else { + throw LoweringError.unhandledType(type) + } + // Typed pointers are lowered to (raw-pointer, count) pair. let isMutable = knownType == .unsafeMutableBufferPointer - let cdeclPointerType = isMutable - ? swiftStdlibTypes[.unsafeMutableRawPointer] - : swiftStdlibTypes[.unsafeRawPointer] - return LoweredParameters( + let rawPointerNominal = swiftStdlibTypes[isMutable ? .unsafeMutableRawPointer : .unsafeRawPointer] + + return LoweredParameter( cdeclParameters: [ SwiftParameter( - convention: convention, - parameterName: parameterName + "_pointer", - type: SwiftType.nominal( - SwiftNominalType(nominalTypeDecl: cdeclPointerType) - ) + convention: .byValue, parameterName: "\(parameterName)_pointer", + type: .nominal(SwiftNominalType(nominalTypeDecl: rawPointerNominal)) ), SwiftParameter( - convention: convention, - parameterName: parameterName + "_count", - type: SwiftType.nominal( - SwiftNominalType(nominalTypeDecl: swiftStdlibTypes[.int]) + convention: .byValue, parameterName: "\(parameterName)_count", + type: .nominal(SwiftNominalType(nominalTypeDecl: swiftStdlibTypes[.int])) + ), + ], conversion: .initialize( + type, + arguments: [ + LabeledArgument( + label: "start", + argument: .typedPointer(.explodedComponent(.placeholder, component: "pointer"), swiftType: genericArgs[0]) + ), + LabeledArgument( + label: "count", + argument: .explodedComponent(.placeholder, component: "count") ) - ) - ] + ] + ) ) + + case .string: + // 'String' is passed in by C string. i.e. 'UnsafePointer' ('const uint8_t *') + if knownType == .string { + return LoweredParameter( + cdeclParameters: [ + SwiftParameter( + convention: .byValue, + parameterName: parameterName, + type: .nominal(SwiftNominalType( + nominalTypeDecl: swiftStdlibTypes.unsafePointerDecl, + genericArguments: [ + .nominal(SwiftNominalType(nominalTypeDecl: swiftStdlibTypes[.int8])) + ] + )) + ) + ], + conversion: .initialize(type, arguments: [ + LabeledArgument(label: "cString", argument: .placeholder) + ]) + ) + } + + default: + // Unreachable? Should be handled by `CType(cdeclType:)` lowering above. + throw LoweringError.unhandledType(type) } } - // Arbitrary types are lowered to raw pointers that either "are" the - // reference (for classes and actors) or will point to it. - let canBeDirectReturn = switch nominal.nominalTypeDecl.kind { - case .actor, .class: true - case .enum, .protocol, .struct: false + // Arbitrary nominal types are passed-in as an pointer. + let isMutable = (convention == .inout) + let rawPointerNominal = swiftStdlibTypes[isMutable ? .unsafeMutableRawPointer : .unsafeRawPointer] + let parameterType: SwiftType = .nominal(SwiftNominalType(nominalTypeDecl: rawPointerNominal)) + + return LoweredParameter( + cdeclParameters: [ + SwiftParameter( + convention: .byValue, + parameterName: parameterName, + type: parameterType + ), + ], + conversion: .pointee(.typedPointer(.placeholder, swiftType: type)) + ) + + case .tuple(let tuple): + if tuple.count == 1 { + return try lowerParameter(tuple[0], convention: convention, parameterName: parameterName) + } + if convention == .inout { + throw LoweringError.inoutNotSupported(type) + } + var parameters: [SwiftParameter] = [] + var conversions: [ConversionStep] = [] + for (idx, element) in tuple.enumerated() { + // FIXME: Use tuple element label. + let cdeclName = "\(parameterName)_\(idx)" + let lowered = try lowerParameter(element, convention: convention, parameterName: cdeclName) + + parameters.append(contentsOf: lowered.cdeclParameters) + conversions.append(lowered.conversion) } + return LoweredParameter(cdeclParameters: parameters, conversion: .tuplify(conversions)) - let isMutable = (convention == .inout) - return LoweredParameters( + case .function(let fn) where fn.parameters.isEmpty && fn.resultType.isVoid: + return LoweredParameter( cdeclParameters: [ SwiftParameter( convention: .byValue, parameterName: parameterName, - type: .nominal( - SwiftNominalType( - nominalTypeDecl: isMutable - ? swiftStdlibTypes[.unsafeMutableRawPointer] - : swiftStdlibTypes[.unsafeRawPointer] - ) - ), - canBeDirectReturn: canBeDirectReturn + type: .function(SwiftFunctionType(convention: .c, parameters: [], resultType: fn.resultType)) ) - ] + ], + // '@convention(c) () -> ()' is compatible with '() -> Void'. + conversion: .placeholder + ) + + case .function, .optional: + // FIXME: Support other function types than '() -> Void'. + throw LoweringError.unhandledType(type) + } + } + + /// Lower a Swift result type to cdecl parameters and return type. + /// + /// - Parameters: + /// - type: The return type. + /// - outParameterName: If the type is lowered to a indirect return, this parameter name should be used. + func lowerResult( + _ type: SwiftType, + outParameterName: String = "_result" + ) throws -> LoweredResult { + // If there is a 1:1 mapping between this Swift type and a C type, we just + // return it. + if let cType = try? CType(cdeclType: type) { + _ = cType + return LoweredResult(cdeclResultType: type, cdeclOutParameters: [], conversion: .placeholder); + } + + switch type { + case .metatype: + // 'unsafeBitcast(, to: UnsafeRawPointer.self)' as 'UnsafeRawPointer' + + let resultType: SwiftType = .nominal(SwiftNominalType(nominalTypeDecl: swiftStdlibTypes[.unsafeRawPointer])) + return LoweredResult( + cdeclResultType: resultType, + cdeclOutParameters: [], + conversion: .unsafeCastPointer(.placeholder, swiftType: resultType) + ) + + case .nominal(let nominal): + // Types from the Swift standard library that we know about. + if let knownType = nominal.nominalTypeDecl.knownStandardLibraryType { + switch knownType { + case .unsafePointer, .unsafeMutablePointer: + // Typed pointers are lowered to corresponding raw forms. + let isMutable = knownType == .unsafeMutablePointer + let rawPointerNominal = swiftStdlibTypes[isMutable ? .unsafeMutableRawPointer : .unsafeRawPointer] + let resultType: SwiftType = .nominal(SwiftNominalType(nominalTypeDecl: rawPointerNominal)) + return LoweredResult( + cdeclResultType: resultType, + cdeclOutParameters: [], + conversion: .initialize(resultType, arguments: [LabeledArgument(argument: .placeholder)]) + ) + + case .unsafeBufferPointer, .unsafeMutableBufferPointer: + // Typed pointers are lowered to (raw-pointer, count) pair. + let isMutable = knownType == .unsafeMutableBufferPointer + let rawPointerType = swiftStdlibTypes[isMutable ? .unsafeMutableRawPointer : .unsafeRawPointer] + return try lowerResult( + .tuple([ + .nominal(SwiftNominalType(nominalTypeDecl: rawPointerType)), + .nominal(SwiftNominalType(nominalTypeDecl: swiftStdlibTypes[.int])) + ]), + outParameterName: outParameterName + ) + + case .void: + return LoweredResult(cdeclResultType: .void, cdeclOutParameters: [], conversion: .placeholder) + + case .string: + // Returning string is not supported at this point. + throw LoweringError.unhandledType(type) + + default: + // Unreachable? Should be handled by `CType(cdeclType:)` lowering above. + throw LoweringError.unhandledType(type) + } + } + + // Arbitrary nominal types are indirectly returned. + return LoweredResult( + cdeclResultType: .void, + cdeclOutParameters: [ + SwiftParameter( + convention: .byValue, + parameterName: outParameterName, + type: .nominal(SwiftNominalType(nominalTypeDecl: swiftStdlibTypes[.unsafeMutableRawPointer])) + ) + ], + conversion: .populatePointer(name: outParameterName, assumingType: type, to: .placeholder) ) case .tuple(let tuple): - let parameterNames = tuple.indices.map { "\(parameterName)_\($0)" } - let loweredElements: [LoweredParameters] = try zip(tuple, parameterNames).map { element, name in - try lowerParameter(element, convention: convention, parameterName: name) + if tuple.count == 1 { + return try lowerResult(tuple[0], outParameterName: outParameterName) + } + + var parameters: [SwiftParameter] = [] + var conversions: [ConversionStep] = [] + for (idx, element) in tuple.enumerated() { + let outName = "\(outParameterName)_\(idx)" + let lowered = try lowerResult(element, outParameterName: outName) + + // Convert direct return values to typed mutable pointers. + // E.g. (Int8, Int8) is lowered to '_ result_0: UnsafePointer, _ result_1: UnsafePointer' + if !lowered.cdeclResultType.isVoid { + let parameterName = lowered.cdeclOutParameters.isEmpty ? outName : "\(outName)_return" + let parameter = SwiftParameter( + convention: .byValue, + parameterName: parameterName, + type: .nominal(SwiftNominalType( + nominalTypeDecl: swiftStdlibTypes.unsafeMutablePointerDecl, + genericArguments: [lowered.cdeclResultType] + )) + ) + parameters.append(parameter) + conversions.append(.populatePointer( + name: parameterName, + to: lowered.conversion + )) + } else { + // If the element returns void, it should already be a no-result conversion. + parameters.append(contentsOf: lowered.cdeclOutParameters) + conversions.append(lowered.conversion) + } } - return LoweredParameters( - cdeclParameters: loweredElements.flatMap { $0.cdeclParameters } + + return LoweredResult( + cdeclResultType: .void, + cdeclOutParameters: parameters, + conversion: .tupleExplode(conversions, name: outParameterName) ) + + case .function(_), .optional(_): + throw LoweringError.unhandledType(type) } } @@ -293,243 +436,201 @@ extension Swift2JavaTranslator { } } -struct LabeledArgument { - var label: String? - var argument: Element +package enum SwiftAPIKind { + case function + case initializer + case getter + case setter } -extension LabeledArgument: Equatable where Element: Equatable { } +/// Represent a Swift parameter in the cdecl thunk. +struct LoweredParameter: Equatable { + /// Lowered parameters in cdecl thunk. + /// One Swift parameter can be lowered to multiple parameters. + /// E.g. 'Data' as (baseAddress, length) pair. + var cdeclParameters: [SwiftParameter] + /// Conversion to convert the cdecl thunk parameters to the original Swift argument. + var conversion: ConversionStep -struct LoweredParameters: Equatable { - /// The lowering of the parameters at the C level in Swift. - var cdeclParameters: [SwiftParameter] + init(cdeclParameters: [SwiftParameter], conversion: ConversionStep) { + self.cdeclParameters = cdeclParameters + self.conversion = conversion + + assert(cdeclParameters.count == conversion.placeholderCount) + } } -enum LoweringError: Error { - case inoutNotSupported(SwiftType) - case unhandledType(SwiftType) +struct LoweredResult: Equatable { + /// The return type of the cdecl thunk. + var cdeclResultType: SwiftType + + /// Out parameters for populating the returning values. + /// + /// Currently, if this is not empty, `cdeclResultType` is `Void`. But the thunk + /// may utilize both in the future, for example returning the status while + /// populating the out parameter. + var cdeclOutParameters: [SwiftParameter] + + /// The conversion from the Swift result to cdecl result. + var conversion: ConversionStep +} + +extension LoweredResult { + /// Whether the result is returned by populating the passed-in pointer parameters. + var hasIndirectResult: Bool { + !cdeclOutParameters.isEmpty + } } @_spi(Testing) public struct LoweredFunctionSignature: Equatable { var original: SwiftFunctionSignature - public var cdecl: SwiftFunctionSignature - var parameters: [LoweredParameters] - var result: LoweredParameters + var apiKind: SwiftAPIKind + + var selfParameter: LoweredParameter? + var parameters: [LoweredParameter] + var result: LoweredResult + + var allLoweredParameters: [SwiftParameter] { + var all: [SwiftParameter] = [] + // Original parameters. + for loweredParam in parameters { + all += loweredParam.cdeclParameters + } + // Self. + if let selfParameter = self.selfParameter { + all += selfParameter.cdeclParameters + } + // Out parameters. + all += result.cdeclOutParameters + return all + } + + var cdeclSignature: SwiftFunctionSignature { + SwiftFunctionSignature( + selfParameter: nil, + parameters: allLoweredParameters, + result: SwiftResult(convention: .direct, type: result.cdeclResultType) + ) + } } extension LoweredFunctionSignature { /// Produce the `@_cdecl` thunk for this lowered function signature that will /// call into the original function. - @_spi(Testing) public func cdeclThunk( cName: String, - swiftFunctionName: String, + swiftAPIName: String, stdlibTypes: SwiftStandardLibraryTypes ) -> FunctionDeclSyntax { - var loweredCDecl = cdecl.createFunctionDecl(cName) - // Add the @_cdecl attribute. - let cdeclAttribute: AttributeSyntax = "@_cdecl(\(literal: cName))\n" - loweredCDecl.attributes.append(.attribute(cdeclAttribute)) + let cdeclParams = allLoweredParameters.map(\.description).joined(separator: ", ") + let returnClause = !result.cdeclResultType.isVoid ? " -> \(result.cdeclResultType.description)" : "" - // Make it public. - loweredCDecl.modifiers.append( - DeclModifierSyntax(name: .keyword(.public), trailingTrivia: .space) + var loweredCDecl = try! FunctionDeclSyntax( + """ + @_cdecl(\(literal: cName)) + public func \(raw: cName)(\(raw: cdeclParams))\(raw: returnClause) { + } + """ ) - // Create the body. - - // Lower "self", if there is one. - let parametersToLower: ArraySlice - let cdeclToOriginalSelf: ExprSyntax? - var initializerType: SwiftType? = nil - if let originalSelf = original.selfParameter { - switch originalSelf { - case .instance(let originalSelfParam): - // The instance was provided to the cdecl thunk, so convert it to - // its Swift representation. - cdeclToOriginalSelf = try! ConversionStep( - cdeclToSwift: originalSelfParam.type - ).asExprSyntax( - isSelf: true, - placeholder: originalSelfParam.parameterName ?? "self" - ) - parametersToLower = parameters.dropLast() - - case .staticMethod(let selfType): - // Static methods use the Swift type as "self", but there is no - // corresponding cdecl parameter. - cdeclToOriginalSelf = "\(raw: selfType.description)" - parametersToLower = parameters[...] - - case .initializer(let selfType): - // Initializers use the Swift type to create the instance. Save it - // for later. There is no corresponding cdecl parameter. - initializerType = selfType - cdeclToOriginalSelf = nil - parametersToLower = parameters[...] - } - } else { - cdeclToOriginalSelf = nil - parametersToLower = parameters[...] - } + var bodyItems: [CodeBlockItemSyntax] = [] - // Lower the remaining arguments. - let cdeclToOriginalArguments = parametersToLower.indices.map { index in - let originalParam = original.parameters[index] - let cdeclToOriginalArg = try! ConversionStep( - cdeclToSwift: originalParam.type - ).asExprSyntax( - isSelf: false, - placeholder: originalParam.parameterName ?? "_\(index)" + let selfExpr: ExprSyntax? + switch original.selfParameter { + case .instance(let swiftSelf): + // Raise the 'self' from cdecl parameters. + selfExpr = self.selfParameter!.conversion.asExprSyntax( + placeholder: swiftSelf.parameterName ?? "self", + bodyItems: &bodyItems ) + case .staticMethod(let selfType), .initializer(let selfType): + selfExpr = "\(raw: selfType.description)" + case .none: + selfExpr = nil + } - if let argumentLabel = originalParam.argumentLabel { - return "\(argumentLabel): \(cdeclToOriginalArg.description)" - } else { - return cdeclToOriginalArg.description - } + /// Raise the other parameters. + let paramExprs = parameters.enumerated().map { idx, param in + param.conversion.asExprSyntax( + placeholder: original.parameters[idx].parameterName ?? "_\(idx)", + bodyItems: &bodyItems + )! } - // Form the call expression. - let callArguments: ExprSyntax = "(\(raw: cdeclToOriginalArguments.joined(separator: ", ")))" - let callExpression: ExprSyntax - if let initializerType { - callExpression = "\(raw: initializerType.description)\(callArguments)" - } else if let cdeclToOriginalSelf { - callExpression = "\(cdeclToOriginalSelf).\(raw: swiftFunctionName)\(callArguments)" + // Build callee expression. + let callee: ExprSyntax = if let selfExpr { + if case .initializer = self.apiKind { + // Don't bother to create explicit ${Self}.init expression. + selfExpr + } else { + ExprSyntax(MemberAccessExprSyntax(base: selfExpr, name: .identifier(swiftAPIName))) + } } else { - callExpression = "\(raw: swiftFunctionName)\(callArguments)" + ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(swiftAPIName))) } - // Handle the return. - if cdecl.result.type.isVoid && original.result.type.isVoid { - // Nothing to return. - loweredCDecl.body = """ - { - \(callExpression) + // Build the result. + let resultExpr: ExprSyntax + switch apiKind { + case .function, .initializer: + let arguments = paramExprs.enumerated() + .map { (i, argument) -> String in + let argExpr = original.parameters[i].convention == .inout ? "&\(argument)" : argument + return LabeledExprSyntax(label: original.parameters[i].argumentLabel, expression: argExpr).description } - """ - } else { - // Determine the necessary conversion of the Swift return value to the - // cdecl return value. - let resultConversion = try! ConversionStep( - swiftToCDecl: original.result.type, - stdlibTypes: stdlibTypes - ) - - var bodyItems: [CodeBlockItemSyntax] = [] + .joined(separator: ", ") + resultExpr = "\(callee)(\(raw: arguments))" - // If the are multiple places in the result conversion that reference - // the placeholder, capture the result of the call in a local variable. - // This prevents us from calling the function multiple times. - let originalResult: ExprSyntax - if resultConversion.placeholderCount > 1 { - bodyItems.append(""" - let __swift_result = \(callExpression) - """ - ) - originalResult = "__swift_result" - } else { - originalResult = callExpression - } + case .getter: + assert(paramExprs.isEmpty) + resultExpr = callee - if cdecl.result.type.isVoid { - // Indirect return. This is a regular return in Swift that turns - // into an assignment via the indirect parameters. We do a cdeclToSwift - // conversion on the left-hand side of the tuple to gather all of the - // indirect output parameters we need to assign to, and the result - // conversion is the corresponding right-hand side. - let cdeclParamConversion = try! ConversionStep( - cdeclToSwift: original.result.type - ) + case .setter: + assert(paramExprs.count == 1) + resultExpr = "\(callee) = \(paramExprs[0])" + } - // For each indirect result, initialize the value directly with the - // corresponding element in the converted result. - bodyItems.append( - contentsOf: cdeclParamConversion.initialize( - placeholder: "_result", - from: resultConversion, - otherPlaceholder: originalResult.description - ) - ) - } else { - // Direct return. Just convert the expression. - let convertedResult = resultConversion.asExprSyntax( - isSelf: true, - placeholder: originalResult.description - ) + // Lower the result. + if !original.result.type.isVoid { + let loweredResult: ExprSyntax? = result.conversion.asExprSyntax( + placeholder: resultExpr.description, + bodyItems: &bodyItems + ) - bodyItems.append(""" - return \(convertedResult) - """ - ) + if let loweredResult { + bodyItems.append(!result.cdeclResultType.isVoid ? "return \(loweredResult)" : "\(loweredResult)") } - - loweredCDecl.body = CodeBlockSyntax( - leftBrace: .leftBraceToken(trailingTrivia: .newline), - statements: .init(bodyItems.map { $0.with(\.trailingTrivia, .newline) }) - ) + } else { + bodyItems.append("\(resultExpr)") } - return loweredCDecl - } -} - -extension ConversionStep { - /// Form a set of statements that initializes the placeholders within - /// the given conversion step from ones in the other step, effectively - /// exploding something like `(a, (b, c)) = (d, (e, f))` into - /// separate initializations for a, b, and c from d, e, and f, respectively. - func initialize( - placeholder: String, - from otherStep: ConversionStep, - otherPlaceholder: String - ) -> [CodeBlockItemSyntax] { - // Create separate assignments for each element in paired tuples. - if case .tuplify(let elements) = self, - case .tuplify(let otherElements) = otherStep { - assert(elements.count == otherElements.count) - - return elements.indices.flatMap { index in - elements[index].initialize( - placeholder: "\(placeholder)_\(index)", - from: otherElements[index], - otherPlaceholder: "\(otherPlaceholder)_\(index)" - ) + loweredCDecl.body!.statements = CodeBlockItemListSyntax { + bodyItems.map { + $0.with(\.leadingTrivia, [.newlines(1), .spaces(2)]) } } - // Look through "pass indirectly" steps; they do nothing here. - if case .passIndirectly(let conversionStep) = self { - return conversionStep.initialize( - placeholder: placeholder, - from: otherStep, - otherPlaceholder: otherPlaceholder - ) - } + return loweredCDecl + } - // The value we're initializing from. - let otherExpr = otherStep.asExprSyntax( - isSelf: false, - placeholder: otherPlaceholder + @_spi(Testing) + public func cFunctionDecl(cName: String) throws -> CFunction { + return CFunction( + resultType: try CType(cdeclType: self.result.cdeclResultType), + name: cName, + parameters: try self.allLoweredParameters.map { + try CParameter(name: $0.parameterName, type: CType(cdeclType: $0.type).parameterDecay) + }, + isVariadic: false ) - - // If we have a "pointee" on where we are performing initialization, we - // need to instead produce an initialize(to:) call. - if case .pointee(let innerSelf) = self { - let selfPointerExpr = innerSelf.asExprSyntax( - isSelf: true, - placeholder: placeholder - ) - - return [ " \(selfPointerExpr).initialize(to: \(otherExpr))" ] - } - - let selfExpr = self.asExprSyntax(isSelf: true, placeholder: placeholder) - return [ " \(selfExpr) = \(otherExpr)" ] } } + +enum LoweringError: Error { + case inoutNotSupported(SwiftType) + case unhandledType(SwiftType) +} diff --git a/Sources/JExtractSwift/ConversionStep.swift b/Sources/JExtractSwift/ConversionStep.swift index 31b33a86..31d731bc 100644 --- a/Sources/JExtractSwift/ConversionStep.swift +++ b/Sources/JExtractSwift/ConversionStep.swift @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// import SwiftSyntax +import SwiftSyntaxBuilder /// Describes the transformation needed to take the parameters of a thunk /// and map them to the corresponding parameter (or result value) of the @@ -37,9 +38,6 @@ enum ConversionStep: Equatable { /// of the `Unsafe(Mutable)Pointer` types in Swift. indirect case pointee(ConversionStep) - /// Pass this value indirectly, via & for explicit `inout` parameters. - indirect case passIndirectly(ConversionStep) - /// Initialize a value of the given Swift type with the set of labeled /// arguments. case initialize(SwiftType, arguments: [LabeledArgument]) @@ -51,50 +49,25 @@ enum ConversionStep: Equatable { /// tuples, which Swift will convert to the labeled tuple form. case tuplify([ConversionStep]) - /// Create an initialization step that produces the raw pointer type that - /// corresponds to the typed pointer. - init( - initializeRawPointerFromTyped typedStep: ConversionStep, - isMutable: Bool, - isPartOfBufferPointer: Bool, - stdlibTypes: SwiftStandardLibraryTypes - ) { - // Initialize the corresponding raw pointer type from the typed - // pointer we have on the Swift side. - let rawPointerType = isMutable - ? stdlibTypes[.unsafeMutableRawPointer] - : stdlibTypes[.unsafeRawPointer] - self = .initialize( - .nominal( - SwiftNominalType( - nominalTypeDecl: rawPointerType - ) - ), - arguments: [ - LabeledArgument( - argument: isPartOfBufferPointer - ? .explodedComponent( - typedStep, - component: "pointer" - ) - : typedStep - ), - ] - ) - } + /// Initialize mutable raw pointer with a typed value. + indirect case populatePointer(name: String, assumingType: SwiftType? = nil, to: ConversionStep) + + /// Perform multiple conversions, but discard the result. + case tupleExplode([ConversionStep], name: String?) /// Count the number of times that the placeholder occurs within this /// conversion step. var placeholderCount: Int { switch self { case .explodedComponent(let inner, component: _), - .passIndirectly(let inner), .pointee(let inner), + .pointee(let inner), .typedPointer(let inner, swiftType: _), - .unsafeCastPointer(let inner, swiftType: _): + .unsafeCastPointer(let inner, swiftType: _), + .populatePointer(name: _, assumingType: _, to: let inner): inner.placeholderCount case .initialize(_, arguments: let arguments): arguments.reduce(0) { $0 + $1.argument.placeholderCount } - case .placeholder: + case .placeholder, .tupleExplode: 1 case .tuplify(let elements): elements.reduce(0) { $0 + $1.placeholderCount } @@ -103,38 +76,30 @@ enum ConversionStep: Equatable { /// Convert the conversion step into an expression with the given /// value as the placeholder value in the expression. - func asExprSyntax(isSelf: Bool, placeholder: String) -> ExprSyntax { + func asExprSyntax(placeholder: String, bodyItems: inout [CodeBlockItemSyntax]) -> ExprSyntax? { switch self { case .placeholder: return "\(raw: placeholder)" case .explodedComponent(let step, component: let component): - return step.asExprSyntax(isSelf: false, placeholder: "\(placeholder)_\(component)") + return step.asExprSyntax(placeholder: "\(placeholder)_\(component)", bodyItems: &bodyItems) case .unsafeCastPointer(let step, swiftType: let swiftType): - let untypedExpr = step.asExprSyntax(isSelf: false, placeholder: placeholder) + let untypedExpr = step.asExprSyntax(placeholder: placeholder, bodyItems: &bodyItems) return "unsafeBitCast(\(untypedExpr), to: \(swiftType.metatypeReferenceExprSyntax))" case .typedPointer(let step, swiftType: let type): - let untypedExpr = step.asExprSyntax(isSelf: isSelf, placeholder: placeholder) + let untypedExpr = step.asExprSyntax(placeholder: placeholder, bodyItems: &bodyItems) return "\(untypedExpr).assumingMemoryBound(to: \(type.metatypeReferenceExprSyntax))" case .pointee(let step): - let untypedExpr = step.asExprSyntax(isSelf: isSelf, placeholder: placeholder) + let untypedExpr = step.asExprSyntax(placeholder: placeholder, bodyItems: &bodyItems) return "\(untypedExpr).pointee" - case .passIndirectly(let step): - let innerExpr = step.asExprSyntax(isSelf: false, placeholder: placeholder) - return isSelf ? innerExpr : "&\(innerExpr)" - case .initialize(let type, arguments: let arguments): let renderedArguments: [String] = arguments.map { labeledArgument in - let renderedArg = labeledArgument.argument.asExprSyntax(isSelf: false, placeholder: placeholder) - if let argmentLabel = labeledArgument.label { - return "\(argmentLabel): \(renderedArg.description)" - } else { - return renderedArg.description - } + let argExpr = labeledArgument.argument.asExprSyntax(placeholder: placeholder, bodyItems: &bodyItems) + return LabeledExprSyntax(label: labeledArgument.label, expression: argExpr!).description } // FIXME: Should be able to use structured initializers here instead @@ -144,13 +109,44 @@ enum ConversionStep: Equatable { case .tuplify(let elements): let renderedElements: [String] = elements.enumerated().map { (index, element) in - element.asExprSyntax(isSelf: false, placeholder: "\(placeholder)_\(index)").description + element.asExprSyntax(placeholder: "\(placeholder)_\(index)", bodyItems: &bodyItems)!.description } // FIXME: Should be able to use structured initializers here instead // of splatting out text. let renderedElementList = renderedElements.joined(separator: ", ") return "(\(raw: renderedElementList))" + + case .populatePointer(name: let pointer, assumingType: let type, to: let step): + let inner = step.asExprSyntax(placeholder: placeholder, bodyItems: &bodyItems) + let casting = if let type { + ".assumingMemoryBound(to: \(type.metatypeReferenceExprSyntax))" + } else { + "" + } + return "\(raw: pointer)\(raw: casting).initialize(to: \(inner))" + + case .tupleExplode(let steps, let name): + let toExplode: String + if let name { + bodyItems.append("let \(raw: name) = \(raw: placeholder)") + toExplode = name + } else { + toExplode = placeholder + } + for (i, step) in steps.enumerated() { + if let result = step.asExprSyntax(placeholder: "\(toExplode).\(i)", bodyItems: &bodyItems) { + bodyItems.append(CodeBlockItemSyntax(item: .expr(result))) + } + } + return nil } } } + +struct LabeledArgument { + var label: String? + var argument: Element +} + +extension LabeledArgument: Equatable where Element: Equatable { } diff --git a/Sources/JExtractSwift/SwiftTypes/SwiftFunctionSignature.swift b/Sources/JExtractSwift/SwiftTypes/SwiftFunctionSignature.swift index dc8aadb1..db427767 100644 --- a/Sources/JExtractSwift/SwiftTypes/SwiftFunctionSignature.swift +++ b/Sources/JExtractSwift/SwiftTypes/SwiftFunctionSignature.swift @@ -17,11 +17,16 @@ import SwiftSyntaxBuilder /// Provides a complete signature for a Swift function, which includes its /// parameters and return type. -@_spi(Testing) public struct SwiftFunctionSignature: Equatable { var selfParameter: SwiftSelfParameter? var parameters: [SwiftParameter] var result: SwiftResult + + init(selfParameter: SwiftSelfParameter? = nil, parameters: [SwiftParameter], result: SwiftResult) { + self.selfParameter = selfParameter + self.parameters = parameters + self.result = result + } } /// Describes the "self" parameter of a Swift function signature. @@ -38,34 +43,17 @@ enum SwiftSelfParameter: Equatable { case initializer(SwiftType) } -extension SwiftFunctionSignature { - /// Create a function declaration with the given name that has this - /// signature. - package func createFunctionDecl(_ name: String) -> FunctionDeclSyntax { - let parametersStr = parameters.map(\.description).joined(separator: ", ") - - let resultWithArrow: String - if result.type.isVoid { - resultWithArrow = "" - } else { - resultWithArrow = " -> \(result.type.description)" - } - - let decl: DeclSyntax = """ - func \(raw: name)(\(raw: parametersStr))\(raw: resultWithArrow) { - // implementation - } - """ - return decl.cast(FunctionDeclSyntax.self) - } -} - extension SwiftFunctionSignature { init( _ node: InitializerDeclSyntax, enclosingType: SwiftType?, symbolTable: SwiftSymbolTable ) throws { + // Prohibit generics for now. + if let generics = node.genericParameterClause { + throw SwiftFunctionTranslationError.generic(generics) + } + guard let enclosingType else { throw SwiftFunctionTranslationError.missingEnclosingType(node) } @@ -80,11 +68,13 @@ extension SwiftFunctionSignature { throw SwiftFunctionTranslationError.generic(generics) } - self.selfParameter = .initializer(enclosingType) - self.result = SwiftResult(convention: .direct, type: enclosingType) - self.parameters = try Self.translateFunctionSignature( - node.signature, - symbolTable: symbolTable + self.init( + selfParameter: .initializer(enclosingType), + parameters: try Self.translateFunctionSignature( + node.signature, + symbolTable: symbolTable + ), + result: SwiftResult(convention: .direct, type: enclosingType) ) } @@ -93,8 +83,14 @@ extension SwiftFunctionSignature { enclosingType: SwiftType?, symbolTable: SwiftSymbolTable ) throws { + // Prohibit generics for now. + if let generics = node.genericParameterClause { + throw SwiftFunctionTranslationError.generic(generics) + } + // If this is a member of a type, so we will have a self parameter. Figure out the // type and convention for the self parameter. + let selfParameter: SwiftSelfParameter? if let enclosingType { var isMutating = false var isConsuming = false @@ -110,9 +106,9 @@ extension SwiftFunctionSignature { } if isStatic { - self.selfParameter = .staticMethod(enclosingType) + selfParameter = .staticMethod(enclosingType) } else { - self.selfParameter = .instance( + selfParameter = .instance( SwiftParameter( convention: isMutating ? .inout : isConsuming ? .consuming : .byValue, type: enclosingType @@ -120,29 +116,27 @@ extension SwiftFunctionSignature { ) } } else { - self.selfParameter = nil + selfParameter = nil } // Translate the parameters. - self.parameters = try Self.translateFunctionSignature( + let parameters = try Self.translateFunctionSignature( node.signature, symbolTable: symbolTable ) // Translate the result type. + let result: SwiftResult if let resultType = node.signature.returnClause?.type { - self.result = try SwiftResult( + result = try SwiftResult( convention: .direct, type: SwiftType(resultType, symbolTable: symbolTable) ) } else { - self.result = SwiftResult(convention: .direct, type: .tuple([])) + result = .void } - // Prohibit generics for now. - if let generics = node.genericParameterClause { - throw SwiftFunctionTranslationError.generic(generics) - } + self.init(selfParameter: selfParameter, parameters: parameters, result: result) } /// Translate the function signature, returning the list of translated @@ -163,6 +157,101 @@ extension SwiftFunctionSignature { try SwiftParameter(param, symbolTable: symbolTable) } } + + init(_ varNode: VariableDeclSyntax, isSet: Bool, enclosingType: SwiftType?, symbolTable: SwiftSymbolTable) throws { + + // If this is a member of a type, so we will have a self parameter. Figure out the + // type and convention for the self parameter. + if let enclosingType { + var isStatic = false + for modifier in varNode.modifiers { + switch modifier.name.tokenKind { + case .keyword(.static): isStatic = true + case .keyword(.class): throw SwiftFunctionTranslationError.classMethod(modifier.name) + default: break + } + } + + if isStatic { + self.selfParameter = .staticMethod(enclosingType) + } else { + self.selfParameter = .instance( + SwiftParameter( + convention: isSet && !enclosingType.isReferenceType ? .inout : .byValue, + type: enclosingType + ) + ) + } + } else { + self.selfParameter = nil + } + + guard let binding = varNode.bindings.first, varNode.bindings.count == 1 else { + throw SwiftFunctionTranslationError.multipleBindings(varNode) + } + + guard let varTypeNode = binding.typeAnnotation?.type else { + throw SwiftFunctionTranslationError.missingTypeAnnotation(varNode) + } + let valueType = try SwiftType(varTypeNode, symbolTable: symbolTable) + + if isSet { + self.parameters = [SwiftParameter(convention: .byValue, parameterName: "newValue", type: valueType)] + self.result = .void + } else { + self.parameters = [] + self.result = .init(convention: .direct, type: valueType) + } + } +} + +extension VariableDeclSyntax { + struct SupportedAccessorKinds: OptionSet { + var rawValue: UInt8 + + static var get: Self = .init(rawValue: 1 << 0) + static var set: Self = .init(rawValue: 1 << 1) + } + + /// Determine what operations (i.e. get and/or set) supported in this `VariableDeclSyntax` + /// + /// - Parameters: + /// - binding the pattern binding in this declaration. + func supportedAccessorKinds(binding: PatternBindingSyntax) -> SupportedAccessorKinds { + if self.bindingSpecifier == .keyword(.let) { + return [.get] + } + + if let accessorBlock = binding.accessorBlock { + switch accessorBlock.accessors { + case .getter: + return [.get] + case .accessors(let accessors): + var hasGetter = false + var hasSetter = false + + for accessor in accessors { + switch accessor.accessorSpecifier { + case .keyword(.get), .keyword(._read), .keyword(.unsafeAddress): + hasGetter = true + case .keyword(.set), .keyword(._modify), .keyword(.unsafeMutableAddress): + hasSetter = true + default: // Ignore willSet/didSet and unknown accessors. + break + } + } + + switch (hasGetter, hasSetter) { + case (true, true): return [.get, .set] + case (true, false): return [.get] + case (false, true): return [.set] + case (false, false): break + } + } + } + + return [.get, .set] + } } enum SwiftFunctionTranslationError: Error { @@ -172,4 +261,7 @@ enum SwiftFunctionTranslationError: Error { case classMethod(TokenSyntax) case missingEnclosingType(InitializerDeclSyntax) case failableInitializer(InitializerDeclSyntax) + case multipleBindings(VariableDeclSyntax) + case missingTypeAnnotation(VariableDeclSyntax) + case unsupportedAccessor(AccessorDeclSyntax) } diff --git a/Sources/JExtractSwift/SwiftTypes/SwiftNominalTypeDeclaration.swift b/Sources/JExtractSwift/SwiftTypes/SwiftNominalTypeDeclaration.swift index 5e1c0b18..c8330126 100644 --- a/Sources/JExtractSwift/SwiftTypes/SwiftNominalTypeDeclaration.swift +++ b/Sources/JExtractSwift/SwiftTypes/SwiftNominalTypeDeclaration.swift @@ -29,6 +29,10 @@ package class SwiftNominalTypeDeclaration { case `struct` } + /// The syntax node this declaration is derived from. + /// Can be `nil` if this is loaded from a .swiftmodule. + var syntax: NominalTypeDeclSyntaxNode? + /// The kind of nominal type. var kind: Kind @@ -91,6 +95,15 @@ package class SwiftNominalTypeDeclaration { return name } } + + var isReferenceType: Bool { + switch kind { + case .actor, .class: + return true + case .enum, .struct, .protocol: + return false + } + } } extension SwiftNominalTypeDeclaration: Equatable { diff --git a/Sources/JExtractSwift/SwiftTypes/SwiftResult.swift b/Sources/JExtractSwift/SwiftTypes/SwiftResult.swift index 4ca14815..d4a19f6e 100644 --- a/Sources/JExtractSwift/SwiftTypes/SwiftResult.swift +++ b/Sources/JExtractSwift/SwiftTypes/SwiftResult.swift @@ -15,7 +15,7 @@ import SwiftSyntax struct SwiftResult: Equatable { - var convention: SwiftResultConvention + var convention: SwiftResultConvention // currently not used. var type: SwiftType } @@ -23,3 +23,9 @@ enum SwiftResultConvention: Equatable { case direct case indirect } + +extension SwiftResult { + static var void: Self { + return Self(convention: .direct, type: .void) + } +} diff --git a/Sources/JExtractSwift/SwiftTypes/SwiftStandardLibraryTypes.swift b/Sources/JExtractSwift/SwiftTypes/SwiftStandardLibraryTypes.swift index fbd7b4f0..4b07c575 100644 --- a/Sources/JExtractSwift/SwiftTypes/SwiftStandardLibraryTypes.swift +++ b/Sources/JExtractSwift/SwiftTypes/SwiftStandardLibraryTypes.swift @@ -34,6 +34,8 @@ enum KnownStandardLibraryType: String, Hashable, CaseIterable { case unsafeMutablePointer = "UnsafeMutablePointer" case unsafeBufferPointer = "UnsafeBufferPointer" case unsafeMutableBufferPointer = "UnsafeMutableBufferPointer" + case string = "String" + case void = "Void" var typeName: String { rawValue } @@ -46,7 +48,7 @@ enum KnownStandardLibraryType: String, Hashable, CaseIterable { switch self { case .bool, .double, .float, .int, .int8, .int16, .int32, .int64, .uint, .uint8, .uint16, .uint32, .uint64, .unsafeRawPointer, - .unsafeMutableRawPointer: + .unsafeMutableRawPointer, .string, .void: false case .unsafePointer, .unsafeMutablePointer, .unsafeBufferPointer, diff --git a/Sources/JExtractSwift/SwiftTypes/SwiftType.swift b/Sources/JExtractSwift/SwiftTypes/SwiftType.swift index 8ee0b767..4e17e32d 100644 --- a/Sources/JExtractSwift/SwiftTypes/SwiftType.swift +++ b/Sources/JExtractSwift/SwiftTypes/SwiftType.swift @@ -22,6 +22,10 @@ enum SwiftType: Equatable { indirect case optional(SwiftType) case tuple([SwiftType]) + static var void: Self { + return .tuple([]) + } + var asNominalType: SwiftNominalType? { switch self { case .nominal(let nominal): nominal @@ -37,7 +41,29 @@ enum SwiftType: Equatable { /// Whether this is the "Void" type, which is actually an empty /// tuple. var isVoid: Bool { - return self == .tuple([]) + switch self { + case .tuple([]): + return true + case .nominal(let nominal): + return nominal.parent == nil && nominal.nominalTypeDecl.moduleName == "Swift" && nominal.nominalTypeDecl.name == "Void" + default: + return false + } + } + + /// Reference type + /// + /// * Mutations don't require 'inout' convention. + /// * The value is a pointer of the instance data, + var isReferenceType: Bool { + switch self { + case .nominal(let nominal): + return nominal.nominalTypeDecl.isReferenceType + case .metatype, .function: + return true + case .optional, .tuple: + return false + } } } @@ -83,7 +109,7 @@ struct SwiftNominalType: Equatable { nominalTypeDecl: SwiftNominalTypeDeclaration, genericArguments: [SwiftType]? = nil ) { - self.storedParent = parent.map { .nominal($0) } + self.storedParent = parent.map { .nominal($0) } ?? nominalTypeDecl.parent.map { .nominal(SwiftNominalType(nominalTypeDecl: $0)) } self.nominalTypeDecl = nominalTypeDecl self.genericArguments = genericArguments } @@ -233,6 +259,27 @@ extension SwiftType { ) } + init?( + nominalDecl: NamedDeclSyntax & DeclGroupSyntax, + parent: SwiftType?, + symbolTable: SwiftSymbolTable + ) { + guard let nominalTypeDecl = symbolTable.lookupType( + nominalDecl.name.text, + parent: parent?.asNominalTypeDeclaration + ) else { + return nil + } + + self = .nominal( + SwiftNominalType( + parent: parent?.asNominalType, + nominalTypeDecl: nominalTypeDecl, + genericArguments: nil + ) + ) + } + /// Produce an expression that creates the metatype for this type in /// Swift source code. var metatypeReferenceExprSyntax: ExprSyntax { diff --git a/Tests/JExtractSwiftTests/Asserts/LoweringAssertions.swift b/Tests/JExtractSwiftTests/Asserts/LoweringAssertions.swift index c37325cb..f0d3ce2d 100644 --- a/Tests/JExtractSwiftTests/Asserts/LoweringAssertions.swift +++ b/Tests/JExtractSwiftTests/Asserts/LoweringAssertions.swift @@ -62,7 +62,7 @@ func assertLoweredFunction( let loweredCDecl = loweredFunction.cdeclThunk( cName: "c_\(swiftFunctionName)", - swiftFunctionName: swiftFunctionName, + swiftAPIName: swiftFunctionName, stdlibTypes: translator.swiftStdlibTypes ) @@ -76,10 +76,10 @@ func assertLoweredFunction( ) ) - let cFunction = translator.cdeclToCFunctionLowering( - loweredFunction.cdecl, + let cFunction = try loweredFunction.cFunctionDecl( cName: "c_\(swiftFunctionName)" ) + #expect( cFunction.description == expectedCFunction, sourceLocation: Testing.SourceLocation( @@ -90,3 +90,64 @@ func assertLoweredFunction( ) ) } + +/// Assert that the lowering of the function function declaration to a @_cdecl +/// entrypoint matches the expected form. +func assertLoweredVariableAccessor( + _ inputDecl: VariableDeclSyntax, + isSet: Bool, + javaPackage: String = "org.swift.mypackage", + swiftModuleName: String = "MyModule", + sourceFile: String? = nil, + enclosingType: TypeSyntax? = nil, + expectedCDecl: DeclSyntax?, + expectedCFunction: String?, + fileID: String = #fileID, + filePath: String = #filePath, + line: Int = #line, + column: Int = #column +) throws { + let translator = Swift2JavaTranslator( + javaPackage: javaPackage, + swiftModuleName: swiftModuleName + ) + + if let sourceFile { + translator.add(filePath: "Fake.swift", text: sourceFile) + } + + translator.prepareForTranslation() + + let swiftVariableName = inputDecl.bindings.first!.pattern.description + let loweredFunction = try translator.lowerFunctionSignature(inputDecl, isSet: isSet, enclosingType: enclosingType) + + let loweredCDecl = loweredFunction?.cdeclThunk( + cName: "c_\(swiftVariableName)", + swiftAPIName: swiftVariableName, + stdlibTypes: translator.swiftStdlibTypes + ) + + #expect( + loweredCDecl?.description == expectedCDecl?.description, + sourceLocation: Testing.SourceLocation( + fileID: fileID, + filePath: filePath, + line: line, + column: column + ) + ) + + let cFunction = try loweredFunction?.cFunctionDecl( + cName: "c_\(swiftVariableName)" + ) + + #expect( + cFunction?.description == expectedCFunction, + sourceLocation: Testing.SourceLocation( + fileID: fileID, + filePath: filePath, + line: line, + column: column + ) + ) +} diff --git a/Tests/JExtractSwiftTests/FunctionLoweringTests.swift b/Tests/JExtractSwiftTests/FunctionLoweringTests.swift index 97fa95fc..dce594ae 100644 --- a/Tests/JExtractSwiftTests/FunctionLoweringTests.swift +++ b/Tests/JExtractSwiftTests/FunctionLoweringTests.swift @@ -14,7 +14,6 @@ import JExtractSwift import SwiftSyntax -import SwiftSyntaxBuilder import Testing @Suite("Swift function lowering tests") @@ -41,14 +40,30 @@ final class FunctionLoweringTests { """, expectedCDecl: """ @_cdecl("c_f") - public func c_f(_ t_0: Int, _ t_1_0: Float, _ t_1_1: Double, _ z_pointer: UnsafeRawPointer) -> Int { - return f(t: (t_0, (t_1_0, t_1_1)), z: z_pointer.assumingMemoryBound(to: Int.self)) + public func c_f(_ t_0: Int, _ t_1_0: Float, _ t_1_1: Double, _ z: UnsafePointer) -> Int { + return f(t: (t_0, (t_1_0, t_1_1)), z: z) } """, - expectedCFunction: "ptrdiff_t c_f(ptrdiff_t t_0, float t_1_0, double t_1_1, const void *z_pointer)" + expectedCFunction: "ptrdiff_t c_f(ptrdiff_t t_0, float t_1_0, double t_1_1, const ptrdiff_t *z)" ) } + @Test("Lowering String") func loweringString() throws { + try assertLoweredFunction( + """ + func takeString(str: String) {} + """, + expectedCDecl: """ + @_cdecl("c_takeString") + public func c_takeString(_ str: UnsafePointer) { + takeString(str: String(cString: str)) + } + """, + expectedCFunction: """ + void c_takeString(const int8_t *str) + """) + } + @Test("Lowering functions involving inout") func loweringInoutParameters() throws { try assertLoweredFunction(""" @@ -117,7 +132,7 @@ final class FunctionLoweringTests { expectedCDecl: """ @_cdecl("c_shift") public func c_shift(_ delta_0: Double, _ delta_1: Double, _ self: UnsafeRawPointer) { - unsafeBitCast(self, to: Point.self).shift(by: (delta_0, delta_1)) + self.assumingMemoryBound(to: Point.self).pointee.shift(by: (delta_0, delta_1)) } """, expectedCFunction: "void c_shift(double delta_0, double delta_1, const void *self)" @@ -151,11 +166,11 @@ final class FunctionLoweringTests { enclosingType: "Person", expectedCDecl: """ @_cdecl("c_randomPerson") - public func c_randomPerson(_ seed: Double) -> UnsafeRawPointer { - return unsafeBitCast(Person.randomPerson(seed: seed), to: UnsafeRawPointer.self) + public func c_randomPerson(_ seed: Double, _ _result: UnsafeMutableRawPointer) { + _result.assumingMemoryBound(to: Person.self).initialize(to: Person.randomPerson(seed: seed)) } """, - expectedCFunction: "const void *c_randomPerson(double seed)" + expectedCFunction: "void c_randomPerson(double seed, void *_result)" ) } @@ -186,11 +201,11 @@ final class FunctionLoweringTests { enclosingType: "Person", expectedCDecl: """ @_cdecl("c_init") - public func c_init(_ seed: Double) -> UnsafeRawPointer { - return unsafeBitCast(Person(seed: seed), to: UnsafeRawPointer.self) + public func c_init(_ seed: Double, _ _result: UnsafeMutableRawPointer) { + _result.assumingMemoryBound(to: Person.self).initialize(to: Person(seed: seed)) } """, - expectedCFunction: "const void *c_init(double seed)" + expectedCFunction: "void c_init(double seed, void *_result)" ) } @@ -232,11 +247,11 @@ final class FunctionLoweringTests { enclosingType: "Point", expectedCDecl: """ @_cdecl("c_shifted") - public func c_shifted(_ delta_0: Double, _ delta_1: Double, _ self: UnsafeRawPointer) -> UnsafeRawPointer { - return unsafeBitCast(unsafeBitCast(self, to: Point.self).shifted(by: (delta_0, delta_1)), to: UnsafeRawPointer.self) + public func c_shifted(_ delta_0: Double, _ delta_1: Double, _ self: UnsafeRawPointer, _ _result: UnsafeMutableRawPointer) { + _result.assumingMemoryBound(to: Point.self).initialize(to: self.assumingMemoryBound(to: Point.self).pointee.shifted(by: (delta_0, delta_1))) } """, - expectedCFunction: "const void *c_shifted(double delta_0, double delta_1, const void *self)" + expectedCFunction: "void c_shifted(double delta_0, double delta_1, const void *self, void *_result)" ) } @@ -268,18 +283,19 @@ final class FunctionLoweringTests { """, expectedCDecl: """ @_cdecl("c_getTuple") - public func c_getTuple(_ _result_0: UnsafeMutableRawPointer, _ _result_1_0: UnsafeMutableRawPointer, _ _result_1_1: UnsafeMutableRawPointer) { - let __swift_result = getTuple() - _result_0 = __swift_result_0 - _result_1_0 = __swift_result_1_0 - _result_1_1.assumingMemoryBound(to: Point.self).initialize(to: __swift_result_1_1) + public func c_getTuple(_ _result_0: UnsafeMutablePointer, _ _result_1_0: UnsafeMutablePointer, _ _result_1_1: UnsafeMutableRawPointer) { + let _result = getTuple() + _result_0.initialize(to: _result.0) + let _result_1 = _result.1 + _result_1_0.initialize(to: _result_1.0) + _result_1_1.assumingMemoryBound(to: Point.self).initialize(to: _result_1.1) } """, - expectedCFunction: "void c_getTuple(void *_result_0, void *_result_1_0, void *_result_1_1)" + expectedCFunction: "void c_getTuple(ptrdiff_t *_result_0, float *_result_1_0, void *_result_1_1)" ) } - @Test("Lowering buffer pointer returns", .disabled("Doesn't turn into the indirect returns")) + @Test("Lowering buffer pointer returns") func lowerBufferPointerReturns() throws { try assertLoweredFunction(""" func getBufferPointer() -> UnsafeMutableBufferPointer { } @@ -289,11 +305,28 @@ final class FunctionLoweringTests { """, expectedCDecl: """ @_cdecl("c_getBufferPointer") - public func c_getBufferPointer(_result_pointer: UnsafeMutableRawPointer, _result_count: UnsafeMutableRawPointer) { - return UnsafeRawPointer(getPointer()) + public func c_getBufferPointer(_ _result_0: UnsafeMutablePointer, _ _result_1: UnsafeMutablePointer) { + let _result = getBufferPointer() + _result_0.initialize(to: _result.0) + _result_1.initialize(to: _result.1) + } + """, + expectedCFunction: "void c_getBufferPointer(void **_result_0, ptrdiff_t *_result_1)" + ) + } + + @Test("Lowering () -> Void type") + func lowerSimpleClosureTypes() throws { + try assertLoweredFunction(""" + func doSomething(body: () -> Void) { } + """, + expectedCDecl: """ + @_cdecl("c_doSomething") + public func c_doSomething(_ body: @convention(c) () -> Void) { + doSomething(body: body) } """, - expectedCFunction: "c_getBufferPointer(void* _result_pointer, void* _result_count)" + expectedCFunction: "void c_doSomething(void (*body)(void))" ) } @@ -313,4 +346,86 @@ final class FunctionLoweringTests { expectedCFunction: "void c_doSomething(double (*body)(int32_t))" ) } + + @Test("Lowering read accessor") + func lowerGlobalReadAccessor() throws { + try assertLoweredVariableAccessor( + DeclSyntax(""" + var value: Point = Point() + """).cast(VariableDeclSyntax.self), + isSet: false, + sourceFile: """ + struct Point { } + """, + expectedCDecl: """ + @_cdecl("c_value") + public func c_value(_ _result: UnsafeMutableRawPointer) { + _result.assumingMemoryBound(to: Point.self).initialize(to: value) + } + """, + expectedCFunction: "void c_value(void *_result)" + ) + } + + @Test("Lowering set accessor") + func lowerGlobalSetAccessor() throws { + try assertLoweredVariableAccessor( + DeclSyntax(""" + var value: Point { get { Point() } set {} } + """).cast(VariableDeclSyntax.self), + isSet: true, + sourceFile: """ + struct Point { } + """, + expectedCDecl: """ + @_cdecl("c_value") + public func c_value(_ newValue: UnsafeRawPointer) { + value = newValue.assumingMemoryBound(to: Point.self).pointee + } + """, + expectedCFunction: "void c_value(const void *newValue)" + ) + } + + @Test("Lowering member read accessor") + func lowerMemberReadAccessor() throws { + try assertLoweredVariableAccessor( + DeclSyntax(""" + var value: Int + """).cast(VariableDeclSyntax.self), + isSet: false, + sourceFile: """ + struct Point { } + """, + enclosingType: "Point", + expectedCDecl: """ + @_cdecl("c_value") + public func c_value(_ self: UnsafeRawPointer) -> Int { + return self.assumingMemoryBound(to: Point.self).pointee.value + } + """, + expectedCFunction: "ptrdiff_t c_value(const void *self)" + ) + } + + @Test("Lowering member set accessor") + func lowerMemberSetAccessor() throws { + try assertLoweredVariableAccessor( + DeclSyntax(""" + var value: Point + """).cast(VariableDeclSyntax.self), + isSet: true, + sourceFile: """ + class Point { } + """, + enclosingType: "Point", + expectedCDecl: """ + @_cdecl("c_value") + public func c_value(_ newValue: UnsafeRawPointer, _ self: UnsafeRawPointer) { + self.assumingMemoryBound(to: Point.self).pointee.value = newValue.assumingMemoryBound(to: Point.self).pointee + } + """, + expectedCFunction: "void c_value(const void *newValue, const void *self)" + ) + } } From 9f4a19237b2dc17688041906852367f87110ee15 Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Sat, 31 May 2025 09:26:00 -0700 Subject: [PATCH 244/426] [jextract] Update for review feedback --- ...wift2JavaTranslator+FunctionLowering.swift | 6 +++--- .../SwiftTypes/SwiftFunctionSignature.swift | 21 ++++++------------- 2 files changed, 9 insertions(+), 18 deletions(-) diff --git a/Sources/JExtractSwift/CDeclLowering/Swift2JavaTranslator+FunctionLowering.swift b/Sources/JExtractSwift/CDeclLowering/Swift2JavaTranslator+FunctionLowering.swift index 9dbcb510..4ab28e2c 100644 --- a/Sources/JExtractSwift/CDeclLowering/Swift2JavaTranslator+FunctionLowering.swift +++ b/Sources/JExtractSwift/CDeclLowering/Swift2JavaTranslator+FunctionLowering.swift @@ -50,8 +50,8 @@ extension Swift2JavaTranslator { } /// Lower the given variable decl to a C-compatible entrypoint, - /// providing all of the mappings between the parameter and result types - /// of the original function and its `@_cdecl` counterpart. + /// providing the mappings between the `self` and value type of the variable + /// and its `@_cdecl` counterpart. @_spi(Testing) public func lowerFunctionSignature( _ decl: VariableDeclSyntax, @@ -297,7 +297,7 @@ struct CdeclLowering { } } - /// Lower a Swift result type to cdecl parameters and return type. + /// Lower a Swift result type to cdecl out parameters and return type. /// /// - Parameters: /// - type: The return type. diff --git a/Sources/JExtractSwift/SwiftTypes/SwiftFunctionSignature.swift b/Sources/JExtractSwift/SwiftTypes/SwiftFunctionSignature.swift index db427767..cd4dbf7a 100644 --- a/Sources/JExtractSwift/SwiftTypes/SwiftFunctionSignature.swift +++ b/Sources/JExtractSwift/SwiftTypes/SwiftFunctionSignature.swift @@ -227,26 +227,17 @@ extension VariableDeclSyntax { case .getter: return [.get] case .accessors(let accessors): - var hasGetter = false - var hasSetter = false - for accessor in accessors { - switch accessor.accessorSpecifier { - case .keyword(.get), .keyword(._read), .keyword(.unsafeAddress): - hasGetter = true - case .keyword(.set), .keyword(._modify), .keyword(.unsafeMutableAddress): - hasSetter = true + switch accessor.accessorSpecifier.tokenKind { + // Existence of any write accessor or observer implies this supports read/write. + case .keyword(.set), .keyword(._modify), .keyword(.unsafeMutableAddress), + .keyword(.willSet), .keyword(.didSet): + return [.get, .set] default: // Ignore willSet/didSet and unknown accessors. break } } - - switch (hasGetter, hasSetter) { - case (true, true): return [.get, .set] - case (true, false): return [.get] - case (false, true): return [.set] - case (false, false): break - } + return [.get] } } From 77001818cfd9a9dd7ad0571d0da5f5daa4784f8f Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Sat, 31 May 2025 21:01:12 -0700 Subject: [PATCH 245/426] [JExtract] Unify mechanisms between value types and reference types Unify memory and instance management mechanism between value types (e.g. `string` or `enum`) and reference types (e.g. `class` and `actor`). Now all imported nominal types are allocated using the value witness table, are returned indirectly, and are destroyed in the same manner. `SwiftInstance` is now the abstract base class for all the imported types including reference types. Concrete types can simply construct it by calling `super(memorySegment, arena)`. --- .../org/swift/swiftkit/SwiftArenaTest.java | 22 ----- .../org/swift/swiftkit/SwiftArenaTest.java | 21 ----- Sources/JExtractSwift/ImportedDecls.swift | 8 +- .../Swift2JavaTranslator+Printing.swift | 84 ++++--------------- .../JExtractSwift/SwiftThunkTranslator.swift | 44 +++------- .../swiftkit/AutoSwiftMemorySession.java | 34 ++------ .../swiftkit/ConfinedSwiftMemorySession.java | 23 ++--- .../java/org/swift/swiftkit/SwiftAnyType.java | 24 +++--- .../java/org/swift/swiftkit/SwiftArena.java | 10 +-- .../org/swift/swiftkit/SwiftHeapObject.java | 13 ++- .../org/swift/swiftkit/SwiftInstance.java | 77 ++++++++++++++--- .../swift/swiftkit/SwiftInstanceCleanup.java | 61 ++------------ .../java/org/swift/swiftkit/SwiftKit.java | 29 ++++++- .../java/org/swift/swiftkit/SwiftValue.java | 6 +- .../swiftkit/SwiftValueWitnessTable.java | 19 +---- .../org/swift/swiftkit/AutoArenaTest.java | 37 ++------ .../MethodImportTests.swift | 57 ++++++------- .../VariableImportTests.swift | 8 +- 18 files changed, 214 insertions(+), 363 deletions(-) diff --git a/Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/SwiftArenaTest.java b/Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/SwiftArenaTest.java index ad514e1b..a621b39b 100644 --- a/Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/SwiftArenaTest.java +++ b/Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/SwiftArenaTest.java @@ -50,26 +50,4 @@ public void arena_releaseClassOnClose_class_ok() { // TODO: should we zero out the $memorySegment perhaps? } - - @Test - public void arena_releaseClassOnClose_class_leaked() { - String memorySegmentDescription = ""; - - try { - try (var arena = SwiftArena.ofConfined()) { - var obj = new MySwiftClass(arena,1, 2); - memorySegmentDescription = obj.$memorySegment().toString(); - - // Pretend that we "leaked" the class, something still holds a reference to it while we try to destroy it - retain(obj.$memorySegment()); - assertEquals(2, retainCount(obj.$memorySegment())); - } - - fail("Expected exception to be thrown while the arena is closed!"); - } catch (Exception ex) { - // The message should point out which objects "leaked": - assertTrue(ex.getMessage().contains(memorySegmentDescription)); - } - - } } diff --git a/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/SwiftArenaTest.java b/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/SwiftArenaTest.java index d9b7bebd..b5012527 100644 --- a/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/SwiftArenaTest.java +++ b/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/SwiftArenaTest.java @@ -88,27 +88,6 @@ public void arena_markAsDestroyed_preventUseAfterFree_struct() { } } - @Test - public void arena_releaseClassOnClose_class_leaked() { - String memorySegmentDescription = ""; - - try { - try (var arena = SwiftArena.ofConfined()) { - var obj = new MySwiftClass(arena,1, 2); - memorySegmentDescription = obj.$memorySegment().toString(); - - // Pretend that we "leaked" the class, something still holds a reference to it while we try to destroy it - retain(obj.$memorySegment()); - assertEquals(2, retainCount(obj.$memorySegment())); - } - - fail("Expected exception to be thrown while the arena is closed!"); - } catch (Exception ex) { - // The message should point out which objects "leaked": - assertTrue(ex.getMessage().contains(memorySegmentDescription)); - } - } - @Test public void arena_initializeWithCopy_struct() { diff --git a/Sources/JExtractSwift/ImportedDecls.swift b/Sources/JExtractSwift/ImportedDecls.swift index 64693967..f893cbb1 100644 --- a/Sources/JExtractSwift/ImportedDecls.swift +++ b/Sources/JExtractSwift/ImportedDecls.swift @@ -267,8 +267,12 @@ public struct ImportedFunc: ImportedDecl, CustomStringConvertible { public var isInit: Bool = false public var isIndirectReturn: Bool { - returnType.isValueType || - (isInit && (parent?.isValueType ?? false)) + switch returnType.originalSwiftTypeKind { + case .actor, .class, .struct, .enum: + return true + default: + return false + } } public init( diff --git a/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift b/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift index 19c8fe57..8f5062a6 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift @@ -290,11 +290,8 @@ extension Swift2JavaTranslator { parentProtocol = "SwiftValue" } - printer.printTypeDecl("public final class \(decl.javaClassName) implements \(parentProtocol)") { + printer.printTypeDecl("public final class \(decl.javaClassName) extends SwiftInstance implements \(parentProtocol)") { printer in - // ==== Storage of the class - printClassSelfProperty(&printer, decl) - printStatusFlagsField(&printer, decl) // Constants printClassConstants(printer: &printer) @@ -400,35 +397,6 @@ extension Swift2JavaTranslator { ) } - /// Print a property where we can store the "self" pointer of a class. - private func printClassSelfProperty(_ printer: inout CodePrinter, _ decl: ImportedNominalType) { - printer.print( - """ - // Pointer to the referred to class instance's "self". - private final MemorySegment selfMemorySegment; - - public final MemorySegment $memorySegment() { - return this.selfMemorySegment; - } - """ - ) - } - - private func printStatusFlagsField(_ printer: inout CodePrinter, _ decl: ImportedNominalType) { - printer.print( - """ - // TODO: make this a flagset integer and/or use a field updater - /** Used to track additional state of the underlying object, e.g. if it was explicitly destroyed. */ - private final AtomicBoolean $state$destroyed = new AtomicBoolean(false); - - @Override - public final AtomicBoolean $statusDestroyedFlag() { - return this.$state$destroyed; - } - """ - ) - } - private func printClassMemoryLayout(_ printer: inout CodePrinter, _ decl: ImportedNominalType) { printer.print( """ @@ -472,30 +440,11 @@ extension Swift2JavaTranslator { \(decl.renderCommentSnippet ?? " *") */ public \(parentName.unqualifiedJavaTypeName)(\(renderJavaParamDecls(decl, paramPassingStyle: .wrapper))) { - this(/*arena=*/null, \(renderForwardJavaParams(decl, paramPassingStyle: .wrapper))); + this(SwiftArena.ofAuto(), \(renderForwardJavaParams(decl, paramPassingStyle: .wrapper))); } """ ) - let initializeMemorySegment = - if let parent = decl.parent, - parent.isReferenceType - { - """ - this.selfMemorySegment = (MemorySegment) mh$.invokeExact( - \(renderForwardJavaParams(decl, paramPassingStyle: nil)) - ); - """ - } else { - """ - this.selfMemorySegment = arena.allocate($layout()); - mh$.invokeExact( - \(renderForwardJavaParams(decl, paramPassingStyle: nil)), - /* indirect return buffer */this.selfMemorySegment - ); - """ - } - printer.print( """ /** @@ -505,20 +454,23 @@ extension Swift2JavaTranslator { \(decl.renderCommentSnippet ?? " *") */ public \(parentName.unqualifiedJavaTypeName)(SwiftArena arena, \(renderJavaParamDecls(decl, paramPassingStyle: .wrapper))) { - var mh$ = \(descClassIdentifier).HANDLE; - try { + super(() -> { + var mh$ = \(descClassIdentifier).HANDLE; + try { + MemorySegment _result = arena.allocate($LAYOUT); + if (SwiftKit.TRACE_DOWNCALLS) { SwiftKit.traceDowncall(\(renderForwardJavaParams(decl, paramPassingStyle: nil))); } - - \(initializeMemorySegment) - - if (arena != null) { - arena.register(this); - } - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } + mh$.invokeExact( + \(renderForwardJavaParams(decl, paramPassingStyle: nil)), + /* indirect return buffer */_result + ); + return _result; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + }, arena); } """ ) @@ -714,9 +666,7 @@ extension Swift2JavaTranslator { let guardFromDestroyedObjectCalls: String = if decl.hasParent { """ - if (this.$state$destroyed.get()) { - throw new IllegalStateException("Attempted to call method on already destroyed instance of " + getClass().getSimpleName() + "!"); - } + $ensureAlive(); """ } else { "" } diff --git a/Sources/JExtractSwift/SwiftThunkTranslator.swift b/Sources/JExtractSwift/SwiftThunkTranslator.swift index 6a423a78..f72f0c58 100644 --- a/Sources/JExtractSwift/SwiftThunkTranslator.swift +++ b/Sources/JExtractSwift/SwiftThunkTranslator.swift @@ -93,32 +93,18 @@ struct SwiftThunkTranslator { """ let typeName = "\(parent.swiftTypeName)" - if parent.isReferenceType { - return [ - """ - \(raw: cDecl) - public func \(raw: thunkName)(\(raw: st.renderSwiftParamDecls(function, paramPassingStyle: nil))) -> UnsafeMutableRawPointer /* \(raw: typeName) */ { - var _self = \(raw: typeName)(\(raw: st.renderForwardSwiftParams(function, paramPassingStyle: nil))) - let self$ = unsafeBitCast(_self, to: UnsafeMutableRawPointer.self) - _swiftjava_swift_retain(object: self$) - return self$ - } - """ - ] - } else { - return [ - """ - \(raw: cDecl) - public func \(raw: thunkName)( - \(raw: st.renderSwiftParamDecls(function, paramPassingStyle: nil)), - resultBuffer: /* \(raw: typeName) */ UnsafeMutableRawPointer - ) { - var _self = \(raw: typeName)(\(raw: st.renderForwardSwiftParams(function, paramPassingStyle: nil))) - resultBuffer.assumingMemoryBound(to: \(raw: typeName).self).initialize(to: _self) - } - """ - ] - } + return [ + """ + \(raw: cDecl) + public func \(raw: thunkName)( + \(raw: st.renderSwiftParamDecls(function, paramPassingStyle: nil)), + resultBuffer: /* \(raw: typeName) */ UnsafeMutableRawPointer + ) { + var _self = \(raw: typeName)(\(raw: st.renderForwardSwiftParams(function, paramPassingStyle: nil))) + resultBuffer.assumingMemoryBound(to: \(raw: typeName).self).initialize(to: _self) + } + """ + ] } func render(forFunc decl: ImportedFunc) -> [DeclSyntax] { @@ -136,11 +122,7 @@ struct SwiftThunkTranslator { let paramPassingStyle: SelfParameterVariant? let callBase: String let callBaseDot: String - if let parent = decl.parent, parent.isReferenceType { - paramPassingStyle = .swiftThunkSelf - callBase = "let self$ = unsafeBitCast(_self, to: \(parent.originalSwiftType).self)" - callBaseDot = "self$." - } else if let parent = decl.parent, !parent.isReferenceType { + if let parent = decl.parent { paramPassingStyle = .swiftThunkSelf callBase = "var self$ = _self.assumingMemoryBound(to: \(parent.originalSwiftType).self).pointee" diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/AutoSwiftMemorySession.java b/SwiftKit/src/main/java/org/swift/swiftkit/AutoSwiftMemorySession.java index 2de79393..ecbe836e 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/AutoSwiftMemorySession.java +++ b/SwiftKit/src/main/java/org/swift/swiftkit/AutoSwiftMemorySession.java @@ -48,38 +48,16 @@ public AutoSwiftMemorySession(ThreadFactory cleanerThreadFactory) { } @Override - public void register(SwiftHeapObject object) { - var statusDestroyedFlag = object.$statusDestroyedFlag(); - Runnable markAsDestroyed = () -> statusDestroyedFlag.set(true); - - SwiftHeapObjectCleanup cleanupAction = new SwiftHeapObjectCleanup( - object.$memorySegment(), - object.$swiftType(), - markAsDestroyed - ); - register(object, cleanupAction); - } - - // visible for testing - void register(SwiftHeapObject object, SwiftHeapObjectCleanup cleanupAction) { - Objects.requireNonNull(object, "obj"); - Objects.requireNonNull(cleanupAction, "cleanupAction"); - - - cleaner.register(object, cleanupAction); - } - - @Override - public void register(SwiftValue value) { - Objects.requireNonNull(value, "value"); + public void register(SwiftInstance instance) { + Objects.requireNonNull(instance, "value"); // We're doing this dance to avoid keeping a strong reference to the value itself - var statusDestroyedFlag = value.$statusDestroyedFlag(); + var statusDestroyedFlag = instance.$statusDestroyedFlag(); Runnable markAsDestroyed = () -> statusDestroyedFlag.set(true); - MemorySegment resource = value.$memorySegment(); - var cleanupAction = new SwiftValueCleanup(resource, value.$swiftType(), markAsDestroyed); - cleaner.register(value, cleanupAction); + MemorySegment resource = instance.$memorySegment(); + var cleanupAction = new SwiftInstanceCleanup(resource, instance.$swiftType(), markAsDestroyed); + cleaner.register(instance, cleanupAction); } @Override diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/ConfinedSwiftMemorySession.java b/SwiftKit/src/main/java/org/swift/swiftkit/ConfinedSwiftMemorySession.java index 317ebcd4..86725ae8 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/ConfinedSwiftMemorySession.java +++ b/SwiftKit/src/main/java/org/swift/swiftkit/ConfinedSwiftMemorySession.java @@ -61,28 +61,15 @@ public void close() { } @Override - public void register(SwiftHeapObject object) { + public void register(SwiftInstance instance) { checkValid(); - var statusDestroyedFlag = object.$statusDestroyedFlag(); + var statusDestroyedFlag = instance.$statusDestroyedFlag(); Runnable markAsDestroyed = () -> statusDestroyedFlag.set(true); - var cleanup = new SwiftHeapObjectCleanup( - object.$memorySegment(), object.$swiftType(), - markAsDestroyed); - this.resources.add(cleanup); - } - - @Override - public void register(SwiftValue value) { - checkValid(); - - var statusDestroyedFlag = value.$statusDestroyedFlag(); - Runnable markAsDestroyed = () -> statusDestroyedFlag.set(true); - - var cleanup = new SwiftValueCleanup( - value.$memorySegment(), - value.$swiftType(), + var cleanup = new SwiftInstanceCleanup( + instance.$memorySegment(), + instance.$swiftType(), markAsDestroyed); this.resources.add(cleanup); } diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftAnyType.java b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftAnyType.java index 8b2d94de..0ca2dd23 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftAnyType.java +++ b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftAnyType.java @@ -34,18 +34,18 @@ public SwiftAnyType(MemorySegment memorySegment) { this.memorySegment = memorySegment.asReadOnly(); } - public SwiftAnyType(SwiftHeapObject object) { - if (object.$layout().name().isEmpty()) { - throw new IllegalArgumentException("SwiftHeapObject must have a mangled name in order to obtain its SwiftType."); - } - - String mangledName = object.$layout().name().get(); - var type = SwiftKit.getTypeByMangledNameInEnvironment(mangledName); - if (type.isEmpty()) { - throw new IllegalArgumentException("A Swift Any.Type cannot be null!"); - } - this.memorySegment = type.get().memorySegment; - } +// public SwiftAnyType(SwiftHeapObject object) { +// if (object.$layout().name().isEmpty()) { +// throw new IllegalArgumentException("SwiftHeapObject must have a mangled name in order to obtain its SwiftType."); +// } +// +// String mangledName = object.$layout().name().get(); +// var type = SwiftKit.getTypeByMangledNameInEnvironment(mangledName); +// if (type.isEmpty()) { +// throw new IllegalArgumentException("A Swift Any.Type cannot be null!"); +// } +// this.memorySegment = type.get().memorySegment; +// } public MemorySegment $memorySegment() { diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftArena.java b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftArena.java index fa89fd1b..f50025cc 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftArena.java +++ b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftArena.java @@ -36,16 +36,10 @@ static SwiftArena ofAuto() { } /** - * Register a Swift reference counted heap object with this arena (such as a {@code class} or {@code actor}). + * Register a Swift object. * Its memory should be considered managed by this arena, and be destroyed when the arena is closed. */ - void register(SwiftHeapObject object); - - /** - * Register a struct, enum or other non-reference counted Swift object. - * Its memory should be considered managed by this arena, and be destroyed when the arena is closed. - */ - void register(SwiftValue value); + void register(SwiftInstance instance); } diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftHeapObject.java b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftHeapObject.java index a7add138..89050fb5 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftHeapObject.java +++ b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftHeapObject.java @@ -14,9 +14,18 @@ package org.swift.swiftkit; +import java.lang.foreign.MemorySegment; + /** * Represents a wrapper around a Swift heap object, e.g. a {@code class} or an {@code actor}. */ -public interface SwiftHeapObject extends SwiftInstance { - SwiftAnyType $swiftType(); +public interface SwiftHeapObject { + MemorySegment $memorySegment(); + + /** + * Pointer to the instance. + */ + public default MemorySegment $instance() { + return this.$memorySegment().get(SwiftValueLayout.SWIFT_POINTER, 0); + } } diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftInstance.java b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftInstance.java index de642a78..2725966d 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftInstance.java +++ b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftInstance.java @@ -17,36 +17,87 @@ import java.lang.foreign.GroupLayout; import java.lang.foreign.MemorySegment; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Supplier; -public interface SwiftInstance { +public abstract class SwiftInstance { + /// Pointer to the "self". + private final MemorySegment selfMemorySegment; /** * The pointer to the instance in memory. I.e. the {@code self} of the Swift object or value. */ - MemorySegment $memorySegment(); + public final MemorySegment $memorySegment() { + return this.selfMemorySegment; + } + + // TODO: make this a flagset integer and/or use a field updater + /** Used to track additional state of the underlying object, e.g. if it was explicitly destroyed. */ + private final AtomicBoolean $state$destroyed = new AtomicBoolean(false); + + /** + * Exposes a boolean value which can be used to indicate if the object was destroyed. + *

+ * This is exposing the object, rather than performing the action because we don't want to accidentally + * form a strong reference to the {@code SwiftInstance} which could prevent the cleanup from running, + * if using an GC managed instance (e.g. using an {@link AutoSwiftMemorySession}. + */ + public final AtomicBoolean $statusDestroyedFlag() { + return this.$state$destroyed; + } /** * The in memory layout of an instance of this Swift type. */ - GroupLayout $layout(); + public abstract GroupLayout $layout(); - SwiftAnyType $swiftType(); + /** + * The Swift type metadata of this type. + */ + public abstract SwiftAnyType $swiftType(); /** - * Returns `true` if this swift instance is a reference type, i.e. a `class` or (`distributed`) `actor`. + * The designated constructor of any imported Swift types. * - * @return `true` if this instance is a reference type, `false` otherwise. + * @param segment the memory segment. + * @param arena the arena this object belongs to. When the arena goes out of scope, this value is destroyed. */ - default boolean isReferenceType() { - return this instanceof SwiftHeapObject; + protected SwiftInstance(MemorySegment segment, SwiftArena arena) { + this.selfMemorySegment = segment; + arena.register(this); } /** - * Exposes a boolean value which can be used to indicate if the object was destroyed. + * Convenience constructor subclasses can call like: + * {@snippet : + * super(() -> { ...; return segment; }, swiftArena$) + * } + * + * @param segmentSupplier Should return the memory segment of the value + * @param arena the arena where the supplied segment belongs to. When the arena goes out of scope, this value is destroyed. + */ + protected SwiftInstance(Supplier segmentSupplier, SwiftArena arena) { + this(segmentSupplier.get(), arena); + } + + /** + * Ensures that this instance has not been destroyed. *

- * This is exposing the object, rather than performing the action because we don't want to accidentally - * form a strong reference to the {@code SwiftInstance} which could prevent the cleanup from running, - * if using an GC managed instance (e.g. using an {@link AutoSwiftMemorySession}. + * If this object has been destroyed, calling this method will cause an {@link IllegalStateException} + * to be thrown. This check should be performed before accessing {@code $memorySegment} to prevent + * use-after-free errors. */ - AtomicBoolean $statusDestroyedFlag(); + protected final void $ensureAlive() { + if (this.$state$destroyed.get()) { + throw new IllegalStateException("Attempted to call method on already destroyed instance of " + getClass().getSimpleName() + "!"); + } + } + + /** + * Returns `true` if this swift instance is a reference type, i.e. a `class` or (`distributed`) `actor`. + * + * @return `true` if this instance is a reference type, `false` otherwise. + */ + public boolean isReferenceType() { + return this instanceof SwiftHeapObject; + } } diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftInstanceCleanup.java b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftInstanceCleanup.java index 4dc22127..a9fdd9c8 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftInstanceCleanup.java +++ b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftInstanceCleanup.java @@ -19,65 +19,20 @@ /** * A Swift memory instance cleanup, e.g. count-down a reference count and destroy a class, or destroy struct/enum etc. */ -interface SwiftInstanceCleanup extends Runnable { -} - -/** - * Implements cleaning up a Swift {@link SwiftHeapObject}. - *

- * This class does not store references to the Java wrapper class, and therefore the wrapper may be subject to GC, - * which may trigger a cleanup (using this class), which will clean up its underlying native memory resource. - */ -// non-final for testing -class SwiftHeapObjectCleanup implements SwiftInstanceCleanup { - - private final MemorySegment selfPointer; - private final SwiftAnyType selfType; - private final Runnable markAsDestroyed; - - /** - * This constructor on purpose does not just take a {@link SwiftHeapObject} in order to make it very - * clear that it does not take ownership of it, but we ONLY manage the native resource here. - *

- * This is important for {@link AutoSwiftMemorySession} which relies on the wrapper type to be GC-able, - * when no longer "in use" on the Java side. - */ - SwiftHeapObjectCleanup(MemorySegment selfPointer, - SwiftAnyType selfType, Runnable markAsDestroyed) { - this.selfPointer = selfPointer; - this.markAsDestroyed = markAsDestroyed; - this.selfType = selfType; - } - - @Override - public void run() throws UnexpectedRetainCountException { - // Verify we're only destroying an object that's indeed not retained by anyone else: - long retainedCount = SwiftKit.retainCount(selfPointer); - if (retainedCount > 1) { - throw new UnexpectedRetainCountException(selfPointer, retainedCount, 1); - } - - this.markAsDestroyed.run(); - - // Destroy (and deinit) the object: - SwiftValueWitnessTable.destroy(selfType, selfPointer); - - // Invalidate the Java wrapper class, in order to prevent effectively use-after-free issues. - // FIXME: some trouble with setting the pointer to null, need to figure out an appropriate way to do this - } -} - -record SwiftValueCleanup( +record SwiftInstanceCleanup( MemorySegment selfPointer, SwiftAnyType selfType, Runnable markAsDestroyed -) implements SwiftInstanceCleanup { +) implements Runnable { @Override public void run() { - System.out.println("[debug] Destroy swift value [" + selfType.getSwiftName() + "]: " + selfPointer); - markAsDestroyed.run(); - SwiftValueWitnessTable.destroy(selfType, selfPointer); + + // Allow null pointers just for AutoArena tests. + if (selfType != null && selfPointer != null) { + System.out.println("[debug] Destroy swift value [" + selfType.getSwiftName() + "]: " + selfPointer); + SwiftValueWitnessTable.destroy(selfType, selfPointer); + } } } diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftKit.java b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftKit.java index dadb87ff..82ed80b2 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftKit.java +++ b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftKit.java @@ -20,6 +20,7 @@ import java.io.IOException; import java.lang.foreign.*; import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; import java.lang.invoke.VarHandle; import java.nio.file.CopyOption; import java.nio.file.FileSystems; @@ -206,7 +207,7 @@ public static long retainCount(MemorySegment object) { } public static long retainCount(SwiftHeapObject object) { - return retainCount(object.$memorySegment()); + return retainCount(object.$instance()); } // ==== ------------------------------------------------------------------------------------------------------------ @@ -236,7 +237,7 @@ public static void retain(MemorySegment object) { } public static void retain(SwiftHeapObject object) { - retain(object.$memorySegment()); + retain(object.$instance()); } // ==== ------------------------------------------------------------------------------------------------------------ @@ -266,7 +267,7 @@ public static void release(MemorySegment object) { } public static long release(SwiftHeapObject object) { - return retainCount(object.$memorySegment()); + return retainCount(object.$instance()); } // ==== ------------------------------------------------------------------------------------------------------------ @@ -446,6 +447,28 @@ public static long getSwiftInt(MemorySegment memorySegment, VarHandle handle) { } } + /** + * Convert String to a MemorySegment filled with the C string. + */ + public static MemorySegment toCString(String str, Arena arena) { + return arena.allocateFrom(str); + } + + /** + * Convert Runnable to a MemorySegment which is an upcall stub for it. + */ + public static MemorySegment toUpcallStub(Runnable callback, Arena arena) { + try { + FunctionDescriptor descriptor = FunctionDescriptor.ofVoid(); + MethodHandle handle = MethodHandles.lookup() + .findVirtual(Runnable.class, "run", descriptor.toMethodType()) + .bindTo(callback); + return Linker.nativeLinker() + .upcallStub(handle, descriptor, arena); + } catch (Exception e) { + throw new AssertionError("should be unreachable"); + } + } private static class swift_getTypeName { diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValue.java b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValue.java index 9387fa85..a364c012 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValue.java +++ b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValue.java @@ -14,6 +14,8 @@ package org.swift.swiftkit; -public interface SwiftValue extends SwiftInstance { - SwiftAnyType $swiftType(); +/** + * Represent a wrapper around a Swift value object. e.g. {@code struct} or {@code enum}. + */ +public interface SwiftValue { } diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValueWitnessTable.java b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValueWitnessTable.java index 4bc86786..53680f5f 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValueWitnessTable.java +++ b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValueWitnessTable.java @@ -220,12 +220,8 @@ public static void destroy(SwiftAnyType type, MemorySegment object) { var mh = destroy.handle(type); - try (var arena = Arena.ofConfined()) { - // we need to make a pointer to the self pointer when calling witness table functions: - MemorySegment indirect = arena.allocate(SwiftValueLayout.SWIFT_POINTER); // TODO: remove this and just have classes have this always anyway - MemorySegmentUtils.setSwiftPointerAddress(indirect, object); - - mh.invokeExact(indirect, wtable); + try { + mh.invokeExact(object, wtable); } catch (Throwable th) { throw new AssertionError("Failed to destroy '" + type + "' at " + object, th); } @@ -285,15 +281,8 @@ public static MemorySegment initializeWithCopy(SwiftAnyType type, MemorySegment var mh = initializeWithCopy.handle(type); - try (var arena = Arena.ofConfined()) { - // we need to make a pointer to the self pointer when calling witness table functions: - MemorySegment indirectDest = arena.allocate(SwiftValueLayout.SWIFT_POINTER); - MemorySegmentUtils.setSwiftPointerAddress(indirectDest, dest); - MemorySegment indirectSrc = arena.allocate(SwiftValueLayout.SWIFT_POINTER); - MemorySegmentUtils.setSwiftPointerAddress(indirectSrc, src); - - var returnedDest = (MemorySegment) mh.invokeExact(indirectDest, indirectSrc, wtable); - return returnedDest; + try { + return (MemorySegment) mh.invokeExact(dest, src, wtable); } catch (Throwable th) { throw new AssertionError("Failed to initializeWithCopy '" + type + "' (" + dest + ", " + src + ")", th); } diff --git a/SwiftKit/src/test/java/org/swift/swiftkit/AutoArenaTest.java b/SwiftKit/src/test/java/org/swift/swiftkit/AutoArenaTest.java index c57daf16..23365de9 100644 --- a/SwiftKit/src/test/java/org/swift/swiftkit/AutoArenaTest.java +++ b/SwiftKit/src/test/java/org/swift/swiftkit/AutoArenaTest.java @@ -26,24 +26,11 @@ public class AutoArenaTest { @Test @SuppressWarnings("removal") // System.runFinalization() will be removed public void cleaner_releases_native_resource() { - SwiftHeapObject object = new FakeSwiftHeapObject(); - - // Latch waiting for the cleanup of the object - var cleanupLatch = new CountDownLatch(1); - - // we're retaining the `object`, register it with the arena: - AutoSwiftMemorySession arena = (AutoSwiftMemorySession) SwiftArena.ofAuto(); + SwiftArena arena = SwiftArena.ofAuto(); + // This object is registered to the arena. + var object = new FakeSwiftInstance(arena); var statusDestroyedFlag = object.$statusDestroyedFlag(); - Runnable markAsDestroyed = () -> statusDestroyedFlag.set(true); - - arena.register(object, - new SwiftHeapObjectCleanup(object.$memorySegment(), object.$swiftType(), markAsDestroyed) { - @Override - public void run() throws UnexpectedRetainCountException { - cleanupLatch.countDown(); - } - }); // Release the object and hope it gets GC-ed soon @@ -51,7 +38,7 @@ public void run() throws UnexpectedRetainCountException { object = null; var i = 1_000; - while (cleanupLatch.getCount() != 0) { + while (!statusDestroyedFlag.get()) { System.runFinalization(); System.gc(); @@ -59,16 +46,11 @@ public void run() throws UnexpectedRetainCountException { throw new RuntimeException("Reference was not cleaned up! Did Cleaner not pick up the release?"); } } - } - private static class FakeSwiftHeapObject implements SwiftHeapObject { - public FakeSwiftHeapObject() { - } - - @Override - public MemorySegment $memorySegment() { - return MemorySegment.NULL; + private static class FakeSwiftInstance extends SwiftInstance implements SwiftHeapObject { + public FakeSwiftInstance(SwiftArena arena) { + super(MemorySegment.NULL, arena); } @Override @@ -80,10 +62,5 @@ public FakeSwiftHeapObject() { public SwiftAnyType $swiftType() { return null; } - - @Override - public AtomicBoolean $statusDestroyedFlag() { - return new AtomicBoolean(); - } } } diff --git a/Tests/JExtractSwiftTests/MethodImportTests.swift b/Tests/JExtractSwiftTests/MethodImportTests.swift index 38cfd8f2..a7dc61d1 100644 --- a/Tests/JExtractSwiftTests/MethodImportTests.swift +++ b/Tests/JExtractSwiftTests/MethodImportTests.swift @@ -349,9 +349,7 @@ final class MethodImportTests { * } */ public void helloMemberFunction() { - if (this.$state$destroyed.get()) { - throw new IllegalStateException("Attempted to call method on already destroyed instance of " + getClass().getSimpleName() + "!") - } + $ensureAlive(); helloMemberFunction($memorySegment()); } """ @@ -387,9 +385,7 @@ final class MethodImportTests { * } */ public long makeInt() { - if (this.$state$destroyed.get()) { - throw new IllegalStateException("Attempted to call method on already destroyed instance of " + getClass().getSimpleName() + "!") - } + $ensureAlive(); return (long) makeInt($memorySegment()); } @@ -427,7 +423,7 @@ final class MethodImportTests { * } */ public MySwiftClass(long len, long cap) { - this(/*arena=*/null, len, cap); + this(SwiftArena.ofAuto(), len, cap); } /** * Create an instance of {@code MySwiftClass}. @@ -438,20 +434,22 @@ final class MethodImportTests { * } */ public MySwiftClass(SwiftArena arena, long len, long cap) { - var mh$ = init_len_cap.HANDLE; - try { + super(() -> { + var mh$ = init_len_cap.HANDLE; + try { + MemorySegment _result = arena.allocate($LAYOUT); if (SwiftKit.TRACE_DOWNCALLS) { SwiftKit.traceDowncall(len, cap); } - this.selfMemorySegment = (MemorySegment) mh$.invokeExact( - len, cap + mh$.invokeExact( + len, cap, + /* indirect return buffer */_result ); - if (arena != null) { - arena.register(this); - } - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } + return _result; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + }, arena); } """ ) @@ -487,7 +485,7 @@ final class MethodImportTests { * } */ public MySwiftStruct(long len, long cap) { - this(/*arena=*/null, len, cap); + this(SwiftArena.ofAuto(), len, cap); } /** * Create an instance of {@code MySwiftStruct}. @@ -497,24 +495,23 @@ final class MethodImportTests { * public init(len: Swift.Int, cap: Swift.Int) * } */ - public MySwiftStruct(SwiftArena arena, long len, long cap) { - var mh$ = init_len_cap.HANDLE; - try { + super(() -> { + var mh$ = init_len_cap.HANDLE; + try { + MemorySegment _result = arena.allocate($LAYOUT); if (SwiftKit.TRACE_DOWNCALLS) { SwiftKit.traceDowncall(len, cap); } - this.selfMemorySegment = arena.allocate($layout()); mh$.invokeExact( - len, cap, - /* indirect return buffer */this.selfMemorySegment + len, cap, + /* indirect return buffer */_result ); - if (arena != null) { - arena.register(this); - } - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } + return _result; + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + }, arena); } """ ) diff --git a/Tests/JExtractSwiftTests/VariableImportTests.swift b/Tests/JExtractSwiftTests/VariableImportTests.swift index 527eda50..3665d277 100644 --- a/Tests/JExtractSwiftTests/VariableImportTests.swift +++ b/Tests/JExtractSwiftTests/VariableImportTests.swift @@ -158,9 +158,7 @@ final class VariableImportTests { * } */ public long getCounterInt() { - if (this.$state$destroyed.get()) { - throw new IllegalStateException("Attempted to call method on already destroyed instance of " + getClass(). - } + $ensureAlive(); return (long) getCounterInt($memorySegment()); } """, @@ -191,9 +189,7 @@ final class VariableImportTests { * } */ public void setCounterInt(long newValue) { - if (this.$state$destroyed.get()) { - throw new IllegalStateException("Attempted to call method on already destroyed instance of " + getClass().getSimpleName() + "!"); - } + $ensureAlive(); setCounterInt(newValue, $memorySegment()); } """, From 971bb9241f7daf7357104a504edd013f855d02f8 Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Sun, 1 Jun 2025 06:19:22 -0700 Subject: [PATCH 246/426] [JExtract] Don't emit constructor without SwiftArena Users should consitently use the same arena. Also since nothing was retaining the '.ofAuto()' arena was evil. --- .../swift/swiftkit/JavaToSwiftBenchmark.java | 9 +++++++- .../com/example/swift/HelloJava2Swift.java | 4 ++-- .../com/example/swift/MySwiftClassTest.java | 21 ++++++++++++------- .../org/swift/swiftkit/MySwiftClassTest.java | 10 ++++----- .../org/swift/swiftkit/SwiftArenaTest.java | 8 +++---- .../com/example/swift/HelloJava2Swift.java | 7 +++++-- .../com/example/swift/MySwiftClassTest.java | 21 ++++++++++++------- .../org/swift/swiftkit/MySwiftClassTest.java | 10 ++++----- .../org/swift/swiftkit/SwiftArenaTest.java | 8 +++---- .../Swift2JavaTranslator+Printing.swift | 13 ------------ .../java/org/swift/swiftkit/SwiftAnyType.java | 14 ------------- .../java/org/swift/swiftkit/SwiftKit.java | 4 ++-- .../MethodImportTests.swift | 20 ------------------ 13 files changed, 61 insertions(+), 88 deletions(-) diff --git a/Samples/SwiftAndJavaJarSampleLib/src/jmh/java/org/swift/swiftkit/JavaToSwiftBenchmark.java b/Samples/SwiftAndJavaJarSampleLib/src/jmh/java/org/swift/swiftkit/JavaToSwiftBenchmark.java index 614697a3..b354c66c 100644 --- a/Samples/SwiftAndJavaJarSampleLib/src/jmh/java/org/swift/swiftkit/JavaToSwiftBenchmark.java +++ b/Samples/SwiftAndJavaJarSampleLib/src/jmh/java/org/swift/swiftkit/JavaToSwiftBenchmark.java @@ -33,6 +33,7 @@ public class JavaToSwiftBenchmark { @State(Scope.Benchmark) public static class BenchmarkState { + ClosableSwiftArena arena; MySwiftClass obj; @Setup(Level.Trial) @@ -43,7 +44,13 @@ public void beforeALl() { // Tune down debug statements so they don't fill up stdout System.setProperty("jextract.trace.downcalls", "false"); - obj = new MySwiftClass(1, 2); + arena = SwiftArena.ofConfined(); + obj = new MySwiftClass(arena, 1, 2); + } + + @TearDown(Level.Trial) + public void afterAll() { + arena.close(); } } diff --git a/Samples/SwiftAndJavaJarSampleLib/src/main/java/com/example/swift/HelloJava2Swift.java b/Samples/SwiftAndJavaJarSampleLib/src/main/java/com/example/swift/HelloJava2Swift.java index 2a86e403..6ebc4107 100644 --- a/Samples/SwiftAndJavaJarSampleLib/src/main/java/com/example/swift/HelloJava2Swift.java +++ b/Samples/SwiftAndJavaJarSampleLib/src/main/java/com/example/swift/HelloJava2Swift.java @@ -47,8 +47,8 @@ static void examples() { MySwiftClass obj = new MySwiftClass(arena, 2222, 7777); // just checking retains/releases work - SwiftKit.retain(obj.$memorySegment()); - SwiftKit.release(obj.$memorySegment()); + SwiftKit.retain(obj); + SwiftKit.release(obj); obj.voidMethod(); obj.takeIntMethod(42); diff --git a/Samples/SwiftAndJavaJarSampleLib/src/test/java/com/example/swift/MySwiftClassTest.java b/Samples/SwiftAndJavaJarSampleLib/src/test/java/com/example/swift/MySwiftClassTest.java index fa17ef1a..05627c7a 100644 --- a/Samples/SwiftAndJavaJarSampleLib/src/test/java/com/example/swift/MySwiftClassTest.java +++ b/Samples/SwiftAndJavaJarSampleLib/src/test/java/com/example/swift/MySwiftClassTest.java @@ -16,6 +16,7 @@ import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; +import org.swift.swiftkit.SwiftArena; import org.swift.swiftkit.SwiftKit; import java.io.File; @@ -41,8 +42,8 @@ void checkPaths(Throwable throwable) { @Test void test_MySwiftClass_voidMethod() { - try { - MySwiftClass o = new MySwiftClass(12, 42); + try(var arena = SwiftArena.ofConfined()) { + MySwiftClass o = new MySwiftClass(arena, 12, 42); o.voidMethod(); } catch (Throwable throwable) { checkPaths(throwable); @@ -51,17 +52,21 @@ void test_MySwiftClass_voidMethod() { @Test void test_MySwiftClass_makeIntMethod() { - MySwiftClass o = new MySwiftClass(12, 42); - var got = o.makeIntMethod(); - assertEquals(12, got); + try(var arena = SwiftArena.ofConfined()) { + MySwiftClass o = new MySwiftClass(arena, 12, 42); + var got = o.makeIntMethod(); + assertEquals(12, got); + } } @Test @Disabled // TODO: Need var mangled names in interfaces void test_MySwiftClass_property_len() { - MySwiftClass o = new MySwiftClass(12, 42); - var got = o.getLen(); - assertEquals(12, got); + try(var arena = SwiftArena.ofConfined()) { + MySwiftClass o = new MySwiftClass(arena, 12, 42); + var got = o.getLen(); + assertEquals(12, got); + } } } diff --git a/Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/MySwiftClassTest.java b/Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/MySwiftClassTest.java index 633d5f1c..c27a02bb 100644 --- a/Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/MySwiftClassTest.java +++ b/Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/MySwiftClassTest.java @@ -27,13 +27,13 @@ void call_retain_retainCount_release() { var arena = SwiftArena.ofConfined(); var obj = new MySwiftClass(arena, 1, 2); - assertEquals(1, SwiftKit.retainCount(obj.$memorySegment())); + assertEquals(1, SwiftKit.retainCount(obj)); // TODO: test directly on SwiftHeapObject inheriting obj - SwiftKit.retain(obj.$memorySegment()); - assertEquals(2, SwiftKit.retainCount(obj.$memorySegment())); + SwiftKit.retain(obj); + assertEquals(2, SwiftKit.retainCount(obj)); - SwiftKit.release(obj.$memorySegment()); - assertEquals(1, SwiftKit.retainCount(obj.$memorySegment())); + SwiftKit.release(obj); + assertEquals(1, SwiftKit.retainCount(obj)); } } diff --git a/Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/SwiftArenaTest.java b/Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/SwiftArenaTest.java index a621b39b..9e6b83e2 100644 --- a/Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/SwiftArenaTest.java +++ b/Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/SwiftArenaTest.java @@ -41,11 +41,11 @@ public void arena_releaseClassOnClose_class_ok() { try (var arena = SwiftArena.ofConfined()) { var obj = new MySwiftClass(arena,1, 2); - retain(obj.$memorySegment()); - assertEquals(2, retainCount(obj.$memorySegment())); + retain(obj); + assertEquals(2, retainCount(obj)); - release(obj.$memorySegment()); - assertEquals(1, retainCount(obj.$memorySegment())); + release(obj); + assertEquals(1, retainCount(obj)); } // TODO: should we zero out the $memorySegment perhaps? diff --git a/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java b/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java index 81c6dd0f..f66f6c2d 100644 --- a/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java +++ b/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java @@ -45,8 +45,11 @@ static void examples() { MySwiftClass obj = new MySwiftClass(arena, 2222, 7777); // just checking retains/releases work - SwiftKit.retain(obj.$memorySegment()); - SwiftKit.release(obj.$memorySegment()); + SwiftKit.trace("retainCount = " + SwiftKit.retainCount(obj)); + SwiftKit.retain(obj); + SwiftKit.trace("retainCount = " + SwiftKit.retainCount(obj)); + SwiftKit.release(obj); + SwiftKit.trace("retainCount = " + SwiftKit.retainCount(obj)); obj.voidMethod(); obj.takeIntMethod(42); diff --git a/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/MySwiftClassTest.java b/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/MySwiftClassTest.java index f0a45c62..09cc3589 100644 --- a/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/MySwiftClassTest.java +++ b/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/MySwiftClassTest.java @@ -16,6 +16,7 @@ import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; +import org.swift.swiftkit.SwiftArena; import org.swift.swiftkit.SwiftKit; import java.io.File; @@ -40,8 +41,8 @@ void checkPaths(Throwable throwable) { @Test void test_MySwiftClass_voidMethod() { - try { - MySwiftClass o = new MySwiftClass(12, 42); + try(var arena = SwiftArena.ofConfined()) { + MySwiftClass o = new MySwiftClass(arena, 12, 42); o.voidMethod(); } catch (Throwable throwable) { checkPaths(throwable); @@ -50,17 +51,21 @@ void test_MySwiftClass_voidMethod() { @Test void test_MySwiftClass_makeIntMethod() { - MySwiftClass o = new MySwiftClass(12, 42); - var got = o.makeIntMethod(); - assertEquals(12, got); + try(var arena = SwiftArena.ofConfined()) { + MySwiftClass o = new MySwiftClass(arena, 12, 42); + var got = o.makeIntMethod(); + assertEquals(12, got); + } } @Test @Disabled // TODO: Need var mangled names in interfaces void test_MySwiftClass_property_len() { - MySwiftClass o = new MySwiftClass(12, 42); - var got = o.getLen(); - assertEquals(12, got); + try(var arena = SwiftArena.ofConfined()) { + MySwiftClass o = new MySwiftClass(arena, 12, 42); + var got = o.getLen(); + assertEquals(12, got); + } } } diff --git a/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/MySwiftClassTest.java b/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/MySwiftClassTest.java index 633d5f1c..c27a02bb 100644 --- a/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/MySwiftClassTest.java +++ b/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/MySwiftClassTest.java @@ -27,13 +27,13 @@ void call_retain_retainCount_release() { var arena = SwiftArena.ofConfined(); var obj = new MySwiftClass(arena, 1, 2); - assertEquals(1, SwiftKit.retainCount(obj.$memorySegment())); + assertEquals(1, SwiftKit.retainCount(obj)); // TODO: test directly on SwiftHeapObject inheriting obj - SwiftKit.retain(obj.$memorySegment()); - assertEquals(2, SwiftKit.retainCount(obj.$memorySegment())); + SwiftKit.retain(obj); + assertEquals(2, SwiftKit.retainCount(obj)); - SwiftKit.release(obj.$memorySegment()); - assertEquals(1, SwiftKit.retainCount(obj.$memorySegment())); + SwiftKit.release(obj); + assertEquals(1, SwiftKit.retainCount(obj)); } } diff --git a/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/SwiftArenaTest.java b/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/SwiftArenaTest.java index b5012527..7c8826fa 100644 --- a/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/SwiftArenaTest.java +++ b/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/SwiftArenaTest.java @@ -42,11 +42,11 @@ public void arena_releaseClassOnClose_class_ok() { try (var arena = SwiftArena.ofConfined()) { var obj = new MySwiftClass(arena,1, 2); - retain(obj.$memorySegment()); - assertEquals(2, retainCount(obj.$memorySegment())); + retain(obj); + assertEquals(2, retainCount(obj)); - release(obj.$memorySegment()); - assertEquals(1, retainCount(obj.$memorySegment())); + release(obj); + assertEquals(1, retainCount(obj)); } } diff --git a/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift b/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift index 8f5062a6..90c05dae 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift @@ -432,19 +432,6 @@ extension Swift2JavaTranslator { ) { let descClassIdentifier = renderDescClassName(decl) - printer.print( - """ - /** - * Create an instance of {@code \(parentName.unqualifiedJavaTypeName)}. - * - \(decl.renderCommentSnippet ?? " *") - */ - public \(parentName.unqualifiedJavaTypeName)(\(renderJavaParamDecls(decl, paramPassingStyle: .wrapper))) { - this(SwiftArena.ofAuto(), \(renderForwardJavaParams(decl, paramPassingStyle: .wrapper))); - } - """ - ) - printer.print( """ /** diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftAnyType.java b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftAnyType.java index 0ca2dd23..4d13ecb7 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftAnyType.java +++ b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftAnyType.java @@ -34,20 +34,6 @@ public SwiftAnyType(MemorySegment memorySegment) { this.memorySegment = memorySegment.asReadOnly(); } -// public SwiftAnyType(SwiftHeapObject object) { -// if (object.$layout().name().isEmpty()) { -// throw new IllegalArgumentException("SwiftHeapObject must have a mangled name in order to obtain its SwiftType."); -// } -// -// String mangledName = object.$layout().name().get(); -// var type = SwiftKit.getTypeByMangledNameInEnvironment(mangledName); -// if (type.isEmpty()) { -// throw new IllegalArgumentException("A Swift Any.Type cannot be null!"); -// } -// this.memorySegment = type.get().memorySegment; -// } - - public MemorySegment $memorySegment() { return memorySegment; } diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftKit.java b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftKit.java index 82ed80b2..85c491e4 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftKit.java +++ b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftKit.java @@ -266,8 +266,8 @@ public static void release(MemorySegment object) { } } - public static long release(SwiftHeapObject object) { - return retainCount(object.$instance()); + public static void release(SwiftHeapObject object) { + release(object.$instance()); } // ==== ------------------------------------------------------------------------------------------------------------ diff --git a/Tests/JExtractSwiftTests/MethodImportTests.swift b/Tests/JExtractSwiftTests/MethodImportTests.swift index a7dc61d1..20026c76 100644 --- a/Tests/JExtractSwiftTests/MethodImportTests.swift +++ b/Tests/JExtractSwiftTests/MethodImportTests.swift @@ -415,16 +415,6 @@ final class MethodImportTests { output, expected: """ - /** - * Create an instance of {@code MySwiftClass}. - * - * {@snippet lang=swift : - * public init(len: Swift.Int, cap: Swift.Int) - * } - */ - public MySwiftClass(long len, long cap) { - this(SwiftArena.ofAuto(), len, cap); - } /** * Create an instance of {@code MySwiftClass}. * This instance is managed by the passed in {@link SwiftArena} and may not outlive the arena's lifetime. @@ -477,16 +467,6 @@ final class MethodImportTests { output, expected: """ - /** - * Create an instance of {@code MySwiftStruct}. - * - * {@snippet lang=swift : - * public init(len: Swift.Int, cap: Swift.Int) - * } - */ - public MySwiftStruct(long len, long cap) { - this(SwiftArena.ofAuto(), len, cap); - } /** * Create an instance of {@code MySwiftStruct}. * This instance is managed by the passed in {@link SwiftArena} and may not outlive the arena's lifetime. From 68f8049990702234f480ade7154374219fea3b23 Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Sun, 1 Jun 2025 06:56:26 -0700 Subject: [PATCH 247/426] [JExtract] Move the 'arena' parameter to the end Because that seems to be more common --- .../jmh/java/org/swift/swiftkit/JavaToSwiftBenchmark.java | 2 +- .../src/main/java/com/example/swift/HelloJava2Swift.java | 2 +- .../src/test/java/com/example/swift/MySwiftClassTest.java | 6 +++--- .../src/test/java/org/swift/swiftkit/MySwiftClassTest.java | 2 +- .../src/test/java/org/swift/swiftkit/SwiftArenaTest.java | 2 +- .../jmh/java/org/swift/swiftkit/JavaToSwiftBenchmark.java | 2 +- .../jmh/java/org/swift/swiftkit/StringPassingBenchmark.java | 2 +- .../src/main/java/com/example/swift/HelloJava2Swift.java | 4 ++-- .../src/test/java/com/example/swift/MySwiftClassTest.java | 6 +++--- .../src/test/java/org/swift/swiftkit/MySwiftClassTest.java | 2 +- .../src/test/java/org/swift/swiftkit/MySwiftStructTest.java | 2 +- .../src/test/java/org/swift/swiftkit/SwiftArenaTest.java | 6 +++--- Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift | 2 +- Tests/JExtractSwiftTests/MethodImportTests.swift | 4 ++-- 14 files changed, 22 insertions(+), 22 deletions(-) diff --git a/Samples/SwiftAndJavaJarSampleLib/src/jmh/java/org/swift/swiftkit/JavaToSwiftBenchmark.java b/Samples/SwiftAndJavaJarSampleLib/src/jmh/java/org/swift/swiftkit/JavaToSwiftBenchmark.java index b354c66c..aba652cb 100644 --- a/Samples/SwiftAndJavaJarSampleLib/src/jmh/java/org/swift/swiftkit/JavaToSwiftBenchmark.java +++ b/Samples/SwiftAndJavaJarSampleLib/src/jmh/java/org/swift/swiftkit/JavaToSwiftBenchmark.java @@ -45,7 +45,7 @@ public void beforeALl() { System.setProperty("jextract.trace.downcalls", "false"); arena = SwiftArena.ofConfined(); - obj = new MySwiftClass(arena, 1, 2); + obj = new MySwiftClass(1, 2, arena); } @TearDown(Level.Trial) diff --git a/Samples/SwiftAndJavaJarSampleLib/src/main/java/com/example/swift/HelloJava2Swift.java b/Samples/SwiftAndJavaJarSampleLib/src/main/java/com/example/swift/HelloJava2Swift.java index 6ebc4107..42aa1d0c 100644 --- a/Samples/SwiftAndJavaJarSampleLib/src/main/java/com/example/swift/HelloJava2Swift.java +++ b/Samples/SwiftAndJavaJarSampleLib/src/main/java/com/example/swift/HelloJava2Swift.java @@ -44,7 +44,7 @@ static void examples() { // Example of using an arena; MyClass.deinit is run at end of scope try (var arena = SwiftArena.ofConfined()) { - MySwiftClass obj = new MySwiftClass(arena, 2222, 7777); + MySwiftClass obj = new MySwiftClass(2222, 7777, arena); // just checking retains/releases work SwiftKit.retain(obj); diff --git a/Samples/SwiftAndJavaJarSampleLib/src/test/java/com/example/swift/MySwiftClassTest.java b/Samples/SwiftAndJavaJarSampleLib/src/test/java/com/example/swift/MySwiftClassTest.java index 05627c7a..47416f06 100644 --- a/Samples/SwiftAndJavaJarSampleLib/src/test/java/com/example/swift/MySwiftClassTest.java +++ b/Samples/SwiftAndJavaJarSampleLib/src/test/java/com/example/swift/MySwiftClassTest.java @@ -43,7 +43,7 @@ void checkPaths(Throwable throwable) { @Test void test_MySwiftClass_voidMethod() { try(var arena = SwiftArena.ofConfined()) { - MySwiftClass o = new MySwiftClass(arena, 12, 42); + MySwiftClass o = new MySwiftClass(12, 42, arena); o.voidMethod(); } catch (Throwable throwable) { checkPaths(throwable); @@ -53,7 +53,7 @@ void test_MySwiftClass_voidMethod() { @Test void test_MySwiftClass_makeIntMethod() { try(var arena = SwiftArena.ofConfined()) { - MySwiftClass o = new MySwiftClass(arena, 12, 42); + MySwiftClass o = new MySwiftClass(12, 42, arena); var got = o.makeIntMethod(); assertEquals(12, got); } @@ -63,7 +63,7 @@ void test_MySwiftClass_makeIntMethod() { @Disabled // TODO: Need var mangled names in interfaces void test_MySwiftClass_property_len() { try(var arena = SwiftArena.ofConfined()) { - MySwiftClass o = new MySwiftClass(arena, 12, 42); + MySwiftClass o = new MySwiftClass(12, 42, arena); var got = o.getLen(); assertEquals(12, got); } diff --git a/Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/MySwiftClassTest.java b/Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/MySwiftClassTest.java index c27a02bb..3d9a360b 100644 --- a/Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/MySwiftClassTest.java +++ b/Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/MySwiftClassTest.java @@ -25,7 +25,7 @@ public class MySwiftClassTest { @Test void call_retain_retainCount_release() { var arena = SwiftArena.ofConfined(); - var obj = new MySwiftClass(arena, 1, 2); + var obj = new MySwiftClass(1, 2, arena); assertEquals(1, SwiftKit.retainCount(obj)); // TODO: test directly on SwiftHeapObject inheriting obj diff --git a/Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/SwiftArenaTest.java b/Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/SwiftArenaTest.java index 9e6b83e2..43c03808 100644 --- a/Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/SwiftArenaTest.java +++ b/Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/SwiftArenaTest.java @@ -39,7 +39,7 @@ static boolean isAmd64() { @DisabledIf("isAmd64") public void arena_releaseClassOnClose_class_ok() { try (var arena = SwiftArena.ofConfined()) { - var obj = new MySwiftClass(arena,1, 2); + var obj = new MySwiftClass(1, 2, arena); retain(obj); assertEquals(2, retainCount(obj)); diff --git a/Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/JavaToSwiftBenchmark.java b/Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/JavaToSwiftBenchmark.java index 18ced030..70f8102c 100644 --- a/Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/JavaToSwiftBenchmark.java +++ b/Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/JavaToSwiftBenchmark.java @@ -37,7 +37,7 @@ public static class BenchmarkState { @Setup(Level.Trial) public void beforeAll() { arena = SwiftArena.ofConfined(); - obj = new MySwiftClass(arena, 1, 2); + obj = new MySwiftClass(1, 2, arena); } @TearDown(Level.Trial) diff --git a/Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/StringPassingBenchmark.java b/Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/StringPassingBenchmark.java index 1cc55e69..b7cb45ff 100644 --- a/Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/StringPassingBenchmark.java +++ b/Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/StringPassingBenchmark.java @@ -46,7 +46,7 @@ public class StringPassingBenchmark { @Setup(Level.Trial) public void beforeAll() { arena = SwiftArena.ofConfined(); - obj = new MySwiftClass(arena, 1, 2); + obj = new MySwiftClass(1, 2, arena); string = makeString(stringLen); } diff --git a/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java b/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java index f66f6c2d..82e62d6d 100644 --- a/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java +++ b/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java @@ -42,7 +42,7 @@ static void examples() { // Example of using an arena; MyClass.deinit is run at end of scope try (var arena = SwiftArena.ofConfined()) { - MySwiftClass obj = new MySwiftClass(arena, 2222, 7777); + MySwiftClass obj = new MySwiftClass(2222, 7777, arena); // just checking retains/releases work SwiftKit.trace("retainCount = " + SwiftKit.retainCount(obj)); @@ -54,7 +54,7 @@ static void examples() { obj.voidMethod(); obj.takeIntMethod(42); - MySwiftStruct swiftValue = new MySwiftStruct(arena, 2222, 1111); + MySwiftStruct swiftValue = new MySwiftStruct(2222, 1111, arena); } System.out.println("DONE."); diff --git a/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/MySwiftClassTest.java b/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/MySwiftClassTest.java index 09cc3589..71598eed 100644 --- a/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/MySwiftClassTest.java +++ b/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/MySwiftClassTest.java @@ -42,7 +42,7 @@ void checkPaths(Throwable throwable) { @Test void test_MySwiftClass_voidMethod() { try(var arena = SwiftArena.ofConfined()) { - MySwiftClass o = new MySwiftClass(arena, 12, 42); + MySwiftClass o = new MySwiftClass(12, 42, arena); o.voidMethod(); } catch (Throwable throwable) { checkPaths(throwable); @@ -52,7 +52,7 @@ void test_MySwiftClass_voidMethod() { @Test void test_MySwiftClass_makeIntMethod() { try(var arena = SwiftArena.ofConfined()) { - MySwiftClass o = new MySwiftClass(arena, 12, 42); + MySwiftClass o = new MySwiftClass(12, 42, arena); var got = o.makeIntMethod(); assertEquals(12, got); } @@ -62,7 +62,7 @@ void test_MySwiftClass_makeIntMethod() { @Disabled // TODO: Need var mangled names in interfaces void test_MySwiftClass_property_len() { try(var arena = SwiftArena.ofConfined()) { - MySwiftClass o = new MySwiftClass(arena, 12, 42); + MySwiftClass o = new MySwiftClass(12, 42, arena); var got = o.getLen(); assertEquals(12, got); } diff --git a/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/MySwiftClassTest.java b/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/MySwiftClassTest.java index c27a02bb..3d9a360b 100644 --- a/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/MySwiftClassTest.java +++ b/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/MySwiftClassTest.java @@ -25,7 +25,7 @@ public class MySwiftClassTest { @Test void call_retain_retainCount_release() { var arena = SwiftArena.ofConfined(); - var obj = new MySwiftClass(arena, 1, 2); + var obj = new MySwiftClass(1, 2, arena); assertEquals(1, SwiftKit.retainCount(obj)); // TODO: test directly on SwiftHeapObject inheriting obj diff --git a/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/MySwiftStructTest.java b/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/MySwiftStructTest.java index b48e28d3..53390da7 100644 --- a/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/MySwiftStructTest.java +++ b/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/MySwiftStructTest.java @@ -26,7 +26,7 @@ void create_struct() { try (var arena = SwiftArena.ofConfined()) { long cap = 12; long len = 34; - var struct = new MySwiftStruct(arena, cap, len); + var struct = new MySwiftStruct(cap, len, arena); assertEquals(cap, struct.getCapacity()); assertEquals(len, struct.getLength()); diff --git a/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/SwiftArenaTest.java b/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/SwiftArenaTest.java index 7c8826fa..f7832b48 100644 --- a/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/SwiftArenaTest.java +++ b/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/SwiftArenaTest.java @@ -40,7 +40,7 @@ static boolean isAmd64() { @DisabledIf("isAmd64") public void arena_releaseClassOnClose_class_ok() { try (var arena = SwiftArena.ofConfined()) { - var obj = new MySwiftClass(arena,1, 2); + var obj = new MySwiftClass(1, 2, arena); retain(obj); assertEquals(2, retainCount(obj)); @@ -57,7 +57,7 @@ public void arena_markAsDestroyed_preventUseAfterFree_class() { MySwiftClass unsafelyEscapedOutsideArenaScope = null; try (var arena = SwiftArena.ofConfined()) { - var obj = new MySwiftClass(arena,1, 2); + var obj = new MySwiftClass(1, 2, arena); unsafelyEscapedOutsideArenaScope = obj; } @@ -76,7 +76,7 @@ public void arena_markAsDestroyed_preventUseAfterFree_struct() { MySwiftStruct unsafelyEscapedOutsideArenaScope = null; try (var arena = SwiftArena.ofConfined()) { - var s = new MySwiftStruct(arena,1, 2); + var s = new MySwiftStruct(1, 2, arena); unsafelyEscapedOutsideArenaScope = s; } diff --git a/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift b/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift index 90c05dae..30dc3fb7 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift @@ -440,7 +440,7 @@ extension Swift2JavaTranslator { * \(decl.renderCommentSnippet ?? " *") */ - public \(parentName.unqualifiedJavaTypeName)(SwiftArena arena, \(renderJavaParamDecls(decl, paramPassingStyle: .wrapper))) { + public \(parentName.unqualifiedJavaTypeName)(\(renderJavaParamDecls(decl, paramPassingStyle: .wrapper)), SwiftArena arena) { super(() -> { var mh$ = \(descClassIdentifier).HANDLE; try { diff --git a/Tests/JExtractSwiftTests/MethodImportTests.swift b/Tests/JExtractSwiftTests/MethodImportTests.swift index 20026c76..b7d00e89 100644 --- a/Tests/JExtractSwiftTests/MethodImportTests.swift +++ b/Tests/JExtractSwiftTests/MethodImportTests.swift @@ -423,7 +423,7 @@ final class MethodImportTests { * public init(len: Swift.Int, cap: Swift.Int) * } */ - public MySwiftClass(SwiftArena arena, long len, long cap) { + public MySwiftClass(long len, long cap, SwiftArena arena) { super(() -> { var mh$ = init_len_cap.HANDLE; try { @@ -475,7 +475,7 @@ final class MethodImportTests { * public init(len: Swift.Int, cap: Swift.Int) * } */ - public MySwiftStruct(SwiftArena arena, long len, long cap) { + public MySwiftStruct(long len, long cap, SwiftArena arena) { super(() -> { var mh$ = init_len_cap.HANDLE; try { From 592fca1d1c511bab3dda673902cf93124c9aa09d Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Sun, 1 Jun 2025 19:24:40 -0700 Subject: [PATCH 248/426] Only enable terminal colors when supported (#241) --- Sources/JavaKitShared/TerminalColors.swift | 29 +++++++++++++++++++--- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/Sources/JavaKitShared/TerminalColors.swift b/Sources/JavaKitShared/TerminalColors.swift index 6170e2bc..a856301f 100644 --- a/Sources/JavaKitShared/TerminalColors.swift +++ b/Sources/JavaKitShared/TerminalColors.swift @@ -12,6 +12,19 @@ // //===----------------------------------------------------------------------===// +import Foundation + +private var isColorSupported: Bool { + let env = ProcessInfo.processInfo.environment + if env["NO_COLOR"] != nil { + return false + } + if let term = env["TERM"], term.contains("color") || env["COLORTERM"] != nil { + return true + } + return false +} + package enum Rainbow: String { case black = "\u{001B}[0;30m" case red = "\u{001B}[0;31m" @@ -139,13 +152,17 @@ package extension String { self } } - + var `default`: String { self.colored(as: .default) } func colored(as color: Rainbow) -> String { - "\(color.rawValue)\(self)\(Rainbow.default.rawValue)" + return if isColorSupported { + "\(color.rawValue)\(self)\(Rainbow.default.rawValue)" + } else { + self + } } } @@ -185,12 +202,16 @@ package extension Substring { var bold: String { self.colored(as: .bold) } - + var `default`: String { self.colored(as: .default) } func colored(as color: Rainbow) -> String { - "\(color.rawValue)\(self)\(Rainbow.default.rawValue)" + return if isColorSupported { + "\(color.rawValue)\(self)\(Rainbow.default.rawValue)" + } else { + String(self) + } } } From 7505e36f0c6f36d07f1cb31f93141cfc02332867 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Tue, 3 Jun 2025 08:12:25 +0900 Subject: [PATCH 249/426] update readme to not suggest using make anymore (#242) --- README.md | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index aae218ba..668c7772 100644 --- a/README.md +++ b/README.md @@ -62,30 +62,23 @@ The extract tool may become able to generate legacy compatible sources, which wo ## Development and Testing -This project contains quite a few builds, Swift, Java, and depends on some custom steps. +This project contains multiple builds, living sid3e by side together. -Easiest way to get going is to: +Depending on which part you are developing, you may want to run just the swift tests: ```bash -make javakit-run # Run the JavaKit example of Swift code using Java libraries -make jextract-run # Run the jextract-swift example of Java code using Swift libraries -swift test # test all Swift code, e.g. jextract-swift -./gradlew test # test all Java code, including integration tests that actually use jextract-ed sources +> swift test ``` -To test on Linux using Docker you can: +or the Java tests through the Gradle build. The Gradle build may also trigger some Swift compilation because of +interlinked dependencies of the two parts of Swift-Java. To run the Java build and tests use the Gradle wrapper script: -```bash -# run only Swift tests (i.e. swift test) -docker-compose -f docker/docker-compose.yaml -f docker/docker-compose.2204.main.yaml run test-swift - -# run only Java tests (i.e. gradle test) -docker-compose -f docker/docker-compose.yaml -f docker/docker-compose.2204.main.yaml run test-java - -# run all tests -docker-compose -f docker/docker-compose.yaml -f docker/docker-compose.2204.main.yaml run test +```bash +> ./gradlew test ``` +Currently it is suggested to use Swift 6.0 and a Java 24+. + ### Sample Apps Sample apps are located in the `Samples/` directory, and they showcase full "roundtrip" usage of the library and/or tools. From bcac7d8fc467551529fe41f4f687b34cd6efc11b Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Wed, 4 Jun 2025 12:56:39 +0900 Subject: [PATCH 250/426] typo in readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 668c7772..bbe3c964 100644 --- a/README.md +++ b/README.md @@ -62,7 +62,7 @@ The extract tool may become able to generate legacy compatible sources, which wo ## Development and Testing -This project contains multiple builds, living sid3e by side together. +This project contains multiple builds, living side by side together. Depending on which part you are developing, you may want to run just the swift tests: From 637d800f2f9334b634097057d1624fb7242cf35f Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Sun, 1 Jun 2025 19:52:35 -0700 Subject: [PATCH 251/426] [JExtract] Adopt SwiftFunctionSignature and the lowering mechanisms * Utilize `SwiftFunctionSignature` and the cdecl-lowering facilities throughout the code base. * `SwiftFunctionSignature` is created from the `DeclSyntax` in `Swift2JavaVisitor`. * `LoweredFunctionSignature` describing `@cdecl` thunk, is created from `SwiftFunctionSignature`. * `TranslatedFunctionSignature` describing generated Java API, is created from `LoweredFunctionSignature`. (Swift2JavaTranslator+JavaTranslation.swift) * `ImportedFunc` is now basically just a wrapper of `TranslatedFunctionSignature` with the `name`. * Remove `ImportedVariable`, instead variables are described as `ImportedFunc` as accessors. * Support APIs returning imported type values. E.g. `func factory(arg: Int) -> MyClass` such methods require `SwiftArena` parameter passed-in. * Built-in lowerings (e.g. `toCString(String)` for `String` -> C string conversion) are now implemented in JavaKit. * Stop emitting `MyClass::apiName$descriptor()` method etc. as they were not used. * Use the `@cdecl` thunk name as the function descriptor class name, for simplicity. * Getter and setter accessors are now completely separate API. No more `HANDLE_GET` and `HANDLE_SET` etc. Instead descriptor class is split to `$get` or `$set` suffixed name. --- .../com/example/swift/MySwiftLibraryTest.java | 4 - .../Sources/MySwiftLibrary/MySwiftClass.swift | 4 + Samples/SwiftKitSampleApp/build.gradle | 2 +- .../com/example/swift/HelloJava2Swift.java | 35 +- .../com/example/swift/MySwiftLibraryTest.java | 4 - ...wift2JavaTranslator+FunctionLowering.swift | 9 +- Sources/JExtractSwift/CTypes/CType.swift | 9 + Sources/JExtractSwift/CodePrinter.swift | 15 +- .../Convenience/SwiftSyntax+Extensions.swift | 33 - .../ImportedDecls+Printing.swift | 101 --- Sources/JExtractSwift/ImportedDecls.swift | 456 ++--------- .../JavaConstants/ForeignValueLayouts.swift | 24 +- .../{ => JavaConstants}/JavaTypes.swift | 0 Sources/JExtractSwift/JavaType+Printing.swift | 47 -- Sources/JExtractSwift/Swift2Java.swift | 1 - ...2JavaTranslator+JavaBindingsPrinting.swift | 356 +++++++++ ...Swift2JavaTranslator+JavaTranslation.swift | 437 ++++++++++ .../Swift2JavaTranslator+MemoryLayouts.swift | 48 -- .../Swift2JavaTranslator+Printing.swift | 746 +----------------- .../JExtractSwift/Swift2JavaTranslator.swift | 28 +- Sources/JExtractSwift/Swift2JavaVisitor.swift | 189 ++--- .../JExtractSwift/SwiftThunkTranslator.swift | 231 +++--- .../JExtractSwift/SwiftTypes/SwiftType.swift | 11 + Sources/JExtractSwift/ThunkNameRegistry.swift | 36 +- Sources/JExtractSwift/TranslatedType.swift | 332 -------- .../ClassPrintingTests.swift | 2 +- .../FuncCallbackImportTests.swift | 30 +- .../FunctionDescriptorImportTests.swift | 51 +- .../MethodImportTests.swift | 218 ++--- .../JExtractSwiftTests/MethodThunkTests.swift | 52 +- .../StringPassingTests.swift | 12 +- .../VariableImportTests.swift | 146 +--- 32 files changed, 1325 insertions(+), 2344 deletions(-) delete mode 100644 Sources/JExtractSwift/ImportedDecls+Printing.swift rename Sources/JExtractSwift/{ => JavaConstants}/JavaTypes.swift (100%) delete mode 100644 Sources/JExtractSwift/JavaType+Printing.swift create mode 100644 Sources/JExtractSwift/Swift2JavaTranslator+JavaBindingsPrinting.swift create mode 100644 Sources/JExtractSwift/Swift2JavaTranslator+JavaTranslation.swift delete mode 100644 Sources/JExtractSwift/Swift2JavaTranslator+MemoryLayouts.swift delete mode 100644 Sources/JExtractSwift/TranslatedType.swift diff --git a/Samples/SwiftAndJavaJarSampleLib/src/test/java/com/example/swift/MySwiftLibraryTest.java b/Samples/SwiftAndJavaJarSampleLib/src/test/java/com/example/swift/MySwiftLibraryTest.java index ffa90359..82472418 100644 --- a/Samples/SwiftAndJavaJarSampleLib/src/test/java/com/example/swift/MySwiftLibraryTest.java +++ b/Samples/SwiftAndJavaJarSampleLib/src/test/java/com/example/swift/MySwiftLibraryTest.java @@ -30,15 +30,11 @@ public class MySwiftLibraryTest { @Test void call_helloWorld() { MySwiftLibrary.helloWorld(); - - assertNotNull(MySwiftLibrary.helloWorld$address()); } @Test void call_globalTakeInt() { MySwiftLibrary.globalTakeInt(12); - - assertNotNull(MySwiftLibrary.globalTakeInt$address()); } @Test diff --git a/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftClass.swift b/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftClass.swift index 1ae962a3..97f5149e 100644 --- a/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftClass.swift +++ b/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftClass.swift @@ -34,6 +34,10 @@ public class MySwiftClass { public var counter: Int32 = 0 + public static func factory(len: Int, cap: Int) -> MySwiftClass { + return MySwiftClass(len: len, cap: cap) + } + public func voidMethod() { p("") } diff --git a/Samples/SwiftKitSampleApp/build.gradle b/Samples/SwiftKitSampleApp/build.gradle index fdd38a11..18a55f44 100644 --- a/Samples/SwiftKitSampleApp/build.gradle +++ b/Samples/SwiftKitSampleApp/build.gradle @@ -81,7 +81,7 @@ def jextract = tasks.register("jextract", Exec) { workingDir = layout.projectDirectory commandLine "swift" - args("package", "jextract", "-v", "--log-level", "info") // TODO: pass log level from Gradle build + args("package", "jextract", "-v", "--log-level", "debug") // TODO: pass log level from Gradle build } // Add the java-swift generated Java sources diff --git a/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java b/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java index 82e62d6d..f94a2abb 100644 --- a/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java +++ b/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java @@ -16,13 +16,10 @@ // Import swift-extract generated sources -import com.example.swift.MySwiftLibrary; -import com.example.swift.MySwiftClass; - // Import javakit/swiftkit support libraries + import org.swift.swiftkit.SwiftArena; import org.swift.swiftkit.SwiftKit; -import org.swift.swiftkit.SwiftValueWitnessTable; public class HelloJava2Swift { @@ -40,21 +37,33 @@ static void examples() { MySwiftLibrary.globalTakeInt(1337); + long cnt = MySwiftLibrary.globalWriteString("String from Java"); + + SwiftKit.trace("count = " + cnt); + + MySwiftLibrary.globalCallMeRunnable(() -> { + SwiftKit.trace("running runnable"); + }); + // Example of using an arena; MyClass.deinit is run at end of scope try (var arena = SwiftArena.ofConfined()) { - MySwiftClass obj = new MySwiftClass(2222, 7777, arena); + MySwiftClass obj = new MySwiftClass(2222, 7777, arena); + + // just checking retains/releases work + SwiftKit.trace("retainCount = " + SwiftKit.retainCount(obj)); + SwiftKit.retain(obj); + SwiftKit.trace("retainCount = " + SwiftKit.retainCount(obj)); + SwiftKit.release(obj); + SwiftKit.trace("retainCount = " + SwiftKit.retainCount(obj)); - // just checking retains/releases work - SwiftKit.trace("retainCount = " + SwiftKit.retainCount(obj)); - SwiftKit.retain(obj); - SwiftKit.trace("retainCount = " + SwiftKit.retainCount(obj)); - SwiftKit.release(obj); - SwiftKit.trace("retainCount = " + SwiftKit.retainCount(obj)); + obj.setCounter(12); + SwiftKit.trace("obj.counter = " + obj.getCounter()); - obj.voidMethod(); - obj.takeIntMethod(42); + obj.voidMethod(); + obj.takeIntMethod(42); MySwiftStruct swiftValue = new MySwiftStruct(2222, 1111, arena); + SwiftKit.trace("swiftValue.capacity = " + swiftValue.getCapacity()); } System.out.println("DONE."); diff --git a/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/MySwiftLibraryTest.java b/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/MySwiftLibraryTest.java index 007b06bd..41d83305 100644 --- a/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/MySwiftLibraryTest.java +++ b/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/MySwiftLibraryTest.java @@ -35,15 +35,11 @@ public class MySwiftLibraryTest { @Test void call_helloWorld() { MySwiftLibrary.helloWorld(); - - assertNotNull(MySwiftLibrary.helloWorld$address()); } @Test void call_globalTakeInt() { MySwiftLibrary.globalTakeInt(12); - - assertNotNull(MySwiftLibrary.globalTakeInt$address()); } @Test diff --git a/Sources/JExtractSwift/CDeclLowering/Swift2JavaTranslator+FunctionLowering.swift b/Sources/JExtractSwift/CDeclLowering/Swift2JavaTranslator+FunctionLowering.swift index 4ab28e2c..17e461aa 100644 --- a/Sources/JExtractSwift/CDeclLowering/Swift2JavaTranslator+FunctionLowering.swift +++ b/Sources/JExtractSwift/CDeclLowering/Swift2JavaTranslator+FunctionLowering.swift @@ -619,14 +619,7 @@ extension LoweredFunctionSignature { @_spi(Testing) public func cFunctionDecl(cName: String) throws -> CFunction { - return CFunction( - resultType: try CType(cdeclType: self.result.cdeclResultType), - name: cName, - parameters: try self.allLoweredParameters.map { - try CParameter(name: $0.parameterName, type: CType(cdeclType: $0.type).parameterDecay) - }, - isVariadic: false - ) + try CFunction(cdeclSignature: self.cdeclSignature, cName: cName) } } diff --git a/Sources/JExtractSwift/CTypes/CType.swift b/Sources/JExtractSwift/CTypes/CType.swift index 9b8744d0..4cd683a6 100644 --- a/Sources/JExtractSwift/CTypes/CType.swift +++ b/Sources/JExtractSwift/CTypes/CType.swift @@ -298,3 +298,12 @@ extension CType { } } } + +extension CType { + var isVoid: Bool { + return switch self { + case .void: true + default: false + } + } +} diff --git a/Sources/JExtractSwift/CodePrinter.swift b/Sources/JExtractSwift/CodePrinter.swift index 83669ebb..db823aa2 100644 --- a/Sources/JExtractSwift/CodePrinter.swift +++ b/Sources/JExtractSwift/CodePrinter.swift @@ -68,16 +68,16 @@ public struct CodePrinter { } } - public mutating func printTypeDecl( - _ text: Any, + public mutating func printBraceBlock( + _ header: Any, function: String = #function, file: String = #fileID, line: UInt = #line, - body: (inout CodePrinter) -> () - ) { - print("\(text) {") + body: (inout CodePrinter) throws -> () + ) rethrows { + print("\(header) {") indent() - body(&self) + try body(&self) outdent() print("}", .sloc, function: function, file: file, line: line) } @@ -145,9 +145,10 @@ public struct CodePrinter { // TODO: remove this in real mode, this just helps visually while working on it public mutating func printSeparator(_ text: String) { - // TODO: actually use the indentationDepth + assert(!text.contains(where: \.isNewline)) print( """ + // ==== -------------------------------------------------- // \(text) diff --git a/Sources/JExtractSwift/Convenience/SwiftSyntax+Extensions.swift b/Sources/JExtractSwift/Convenience/SwiftSyntax+Extensions.swift index a7c12cc9..848797a4 100644 --- a/Sources/JExtractSwift/Convenience/SwiftSyntax+Extensions.swift +++ b/Sources/JExtractSwift/Convenience/SwiftSyntax+Extensions.swift @@ -36,39 +36,6 @@ extension ImplicitlyUnwrappedOptionalTypeSyntax { } } -extension SyntaxProtocol { - - var asNominalTypeKind: NominalTypeKind { - if isClass { - .class - } else if isActor { - .actor - } else if isStruct { - .struct - } else if isEnum { - .enum - } else { - fatalError("Unknown nominal kind: \(self)") - } - } - - var isClass: Bool { - return self.is(ClassDeclSyntax.self) - } - - var isActor: Bool { - return self.is(ActorDeclSyntax.self) - } - - var isEnum: Bool { - return self.is(EnumDeclSyntax.self) - } - - var isStruct: Bool { - return self.is(StructDeclSyntax.self) - } -} - extension DeclModifierSyntax { var isAccessControl: Bool { switch self.name.tokenKind { diff --git a/Sources/JExtractSwift/ImportedDecls+Printing.swift b/Sources/JExtractSwift/ImportedDecls+Printing.swift deleted file mode 100644 index bc755015..00000000 --- a/Sources/JExtractSwift/ImportedDecls+Printing.swift +++ /dev/null @@ -1,101 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of Swift.org project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -import Foundation -import JavaTypes -import SwiftSyntax - -extension ImportedFunc { - /// Render a `@{@snippet ... }` comment section that can be put inside a JavaDoc comment - /// when referring to the original declaration a printed method refers to. - var renderCommentSnippet: String? { - if let syntax { - """ - * {@snippet lang=swift : - * \(syntax) - * } - """ - } else { - nil - } - } -} - -extension VariableAccessorKind { - - public var fieldSuffix: String { - switch self { - case .get: "_GET" - case .set: "_SET" - } - } - - public var renderDescFieldName: String { - switch self { - case .get: "DESC_GET" - case .set: "DESC_SET" - } - } - - public var renderAddrFieldName: String { - switch self { - case .get: "ADDR_GET" - case .set: "ADDR_SET" - } - } - - public var renderHandleFieldName: String { - switch self { - case .get: "HANDLE_GET" - case .set: "HANDLE_SET" - } - } - - /// Renders a "$get" part that can be used in a method signature representing this accessor. - public var renderMethodNameSegment: String { - switch self { - case .get: "$get" - case .set: "$set" - } - } - - func renderMethodName(_ decl: ImportedFunc) -> String? { - switch self { - case .get: "get\(decl.identifier.toCamelCase)" - case .set: "set\(decl.identifier.toCamelCase)" - } - } -} - -extension Optional where Wrapped == VariableAccessorKind { - public var renderDescFieldName: String { - self?.renderDescFieldName ?? "DESC" - } - - public var renderAddrFieldName: String { - self?.renderAddrFieldName ?? "ADDR" - } - - public var renderHandleFieldName: String { - self?.renderHandleFieldName ?? "HANDLE" - } - - public var renderMethodNameSegment: String { - self?.renderMethodNameSegment ?? "" - } - - func renderMethodName(_ decl: ImportedFunc) -> String { - self?.renderMethodName(decl) ?? decl.baseIdentifier - } -} diff --git a/Sources/JExtractSwift/ImportedDecls.swift b/Sources/JExtractSwift/ImportedDecls.swift index f893cbb1..c29e3d5a 100644 --- a/Sources/JExtractSwift/ImportedDecls.swift +++ b/Sources/JExtractSwift/ImportedDecls.swift @@ -12,466 +12,132 @@ // //===----------------------------------------------------------------------===// -import Foundation -import JavaTypes import SwiftSyntax /// Any imported (Swift) declaration -protocol ImportedDecl { - -} +protocol ImportedDecl: AnyObject {} public typealias JavaPackage = String /// Describes a Swift nominal type (e.g., a class, struct, enum) that has been /// imported and is being translated into Java. -package struct ImportedNominalType: ImportedDecl { +package class ImportedNominalType: ImportedDecl { let swiftNominal: SwiftNominalTypeDeclaration - let javaType: JavaType - var kind: NominalTypeKind package var initializers: [ImportedFunc] = [] package var methods: [ImportedFunc] = [] - package var variables: [ImportedVariable] = [] + package var variables: [ImportedFunc] = [] - init(swiftNominal: SwiftNominalTypeDeclaration, javaType: JavaType, kind: NominalTypeKind) { + init(swiftNominal: SwiftNominalTypeDeclaration) { self.swiftNominal = swiftNominal - self.javaType = javaType - self.kind = kind - } - - var translatedType: TranslatedType { - TranslatedType( - cCompatibleConvention: .direct, - originalSwiftType: "\(raw: swiftNominal.qualifiedName)", - originalSwiftTypeKind: self.kind, - cCompatibleSwiftType: "UnsafeRawPointer", - cCompatibleJavaMemoryLayout: .heapObject, - javaType: javaType - ) } - public var isReferenceType: Bool { - switch self.kind { - case .class, .actor: - true - default: - false - } - } - - /// The Java class name without the package. - public var javaClassName: String { - switch javaType { - case .class(package: _, let name): name - default: javaType.description - } + var javaClassName: String { + swiftNominal.name } } -// TODO: replace this with `SwiftNominalTypeDeclaration.Kind` -public enum NominalTypeKind { - case `actor` - case `class` - case `enum` - case `struct` - case `void` // TODO: NOT NOMINAL, BUT... - case function // TODO: NOT NOMINAL, BUT... - case primitive // TODO: NOT NOMINAL, BUT... - - var isReferenceType: Bool { - switch self { - case .actor, .class: true - case .enum, .struct: false - case .void, .function, .primitive: false - } - } +public final class ImportedFunc: ImportedDecl, CustomStringConvertible { + /// Swift module name (e.g. the target name where a type or function was declared) + public var module: String - var isValueType: Bool { - switch self { - case .actor, .class: false - case .enum, .struct: true - case .void, .function, .primitive: false - } - } + /// The function name. + /// e.g., "init" for an initializer or "foo" for "foo(a:b:)". + public var name: String - var isVoid: Bool { - switch self { - case .actor, .class: false - case .enum, .struct: false - case .void: true - case .function, .primitive: false - } - } -} - -public struct ImportedParam { - let syntax: FunctionParameterSyntax + public var swiftDecl: any DeclSyntaxProtocol - var firstName: String? { - let text = syntax.firstName.trimmed.text - guard text != "_" else { - return nil - } + var translatedSignature: TranslatedFunctionSignature - return text + public var signatureString: String { + // FIXME: Remove comments and normalize trivia. + self.swiftDecl.signatureString } - var secondName: String? { - let text = syntax.secondName?.trimmed.text - guard text != "_" else { - return nil - } - - return text + var loweredSignature: LoweredFunctionSignature { + translatedSignature.loweredSignature } - var effectiveName: String? { - firstName ?? secondName + var swiftSignature: SwiftFunctionSignature { + loweredSignature.original } - var effectiveValueName: String { - secondName ?? firstName ?? "_" + package func cFunctionDecl(cName: String) -> CFunction { + // 'try!' because we know 'loweredSignature' can be described with C. + try! loweredSignature.cFunctionDecl(cName: cName) } - // The Swift type as-is from the swift interface - var swiftType: String { - syntax.type.trimmed.description + package var kind: SwiftAPIKind { + loweredSignature.apiKind } - // The mapped-to Java type of the above Java type, collections and optionals may be replaced with Java ones etc. - var type: TranslatedType -} - -extension ImportedParam { - func renderParameterForwarding() -> String? { - if type.javaType.isPrimitive { - effectiveName - } else if type.javaType.isSwiftClosure { - // use the name of the upcall handle we'll have emitted by now - "\(effectiveName!)$" - } else { - "\(effectiveName!).$memorySegment()" + var parentType: SwiftType? { + guard let selfParameter = swiftSignature.selfParameter else { + return nil + } + switch selfParameter { + case .instance(let parameter): + return parameter.type + case .staticMethod(let type): + return type + case .initializer(let type): + return type } } -} - -public enum ParameterVariant { - /// Used when declaring the "Swift thunks" we call through into Swift. - /// - /// Some types need to be represented as raw pointers and recovered into - /// Swift types inside the thunks when we do this. - case cDeclThunk -} - -// TODO: this is used in different contexts and needs a cleanup -// Perhaps this is "which parameter passing style"? -public enum SelfParameterVariant { - // ==== Java forwarding patterns - - /// Make a method that accepts the raw memory pointer as a MemorySegment - case memorySegment - /// Make a method that accepts the the Java wrapper class of the type - case wrapper - /// Raw SWIFT_POINTER - case pointer - - // ==== Swift forwarding patterns - - case swiftThunkSelf -} - -public struct ImportedFunc: ImportedDecl, CustomStringConvertible { - - /// Swift module name (e.g. the target name where a type or function was declared) - public var module: String /// If this function/method is member of a class/struct/protocol, /// this will contain that declaration's imported name. /// /// This is necessary when rendering accessor Java code we need the type that "self" is expecting to have. - public var parent: TranslatedType? - public var hasParent: Bool { parent != nil } - - /// This is a full name such as init(cap:name:). - public var identifier: String - - /// This is the base identifier for the function, e.g., "init" for an - /// initializer or "f" for "f(a:b:)". - public var baseIdentifier: String { - guard let idx = identifier.firstIndex(of: "(") else { - return identifier - } - return String(identifier[.. [ImportedParam] { - if let parent { - var params = parameters - - // Add `self: Self` for method calls on a member - // - // allocating initializer takes a Self.Type instead, but it's also a pointer - switch paramPassingStyle { - case nil, .wrapper: - break - - case .pointer where !isInit: - let selfParam: FunctionParameterSyntax = "self$: $swift_pointer" - params.append( - ImportedParam(syntax: selfParam, type: parent) - ) - - case .memorySegment where !isInit: - let selfParam: FunctionParameterSyntax = "self$: $java_lang_foreign_MemorySegment" - var parentForSelf = parent - parentForSelf.javaType = .javaForeignMemorySegment - params.append( - ImportedParam(syntax: selfParam, type: parentForSelf) - ) - - case .swiftThunkSelf: - break - - default: - break - } - - // TODO: add any metadata for generics and other things we may need to add here - - return params + let context = if let parentType { + "\(parentType)." } else { - return self.parameters + "" } - } - - public var swiftDecl: any DeclSyntaxProtocol - - public var syntax: String? { - self.swiftDecl.signatureString - } - public var isInit: Bool = false - - public var isIndirectReturn: Bool { - switch returnType.originalSwiftTypeKind { - case .actor, .class, .struct, .enum: - return true - default: - return false - } + return prefix + context + self.name } - public init( + init( module: String, - decl: any DeclSyntaxProtocol, - parent: TranslatedType?, - identifier: String, - returnType: TranslatedType, - parameters: [ImportedParam] + swiftDecl: any DeclSyntaxProtocol, + name: String, + translatedSignature: TranslatedFunctionSignature ) { - self.swiftDecl = decl self.module = module - self.parent = parent - self.identifier = identifier - self.returnType = returnType - self.parameters = parameters + self.name = name + self.swiftDecl = swiftDecl + self.translatedSignature = translatedSignature } public var description: String { """ ImportedFunc { - identifier: \(identifier) - returnType: \(returnType) - parameters: \(parameters) - - Swift mangled name: - Imported from: - \(syntax?.description ?? "") + kind: \(kind) + module: \(module) + name: \(name) + signature: \(self.swiftDecl.signatureString) } """ } } extension ImportedFunc: Hashable { - public func hash(into hasher: inout Swift.Hasher) { - self.swiftDecl.id.hash(into: &hasher) - } - - public static func == (lhs: ImportedFunc, rhs: ImportedFunc) -> Swift.Bool { - lhs.parent?.originalSwiftType.id == rhs.parent?.originalSwiftType.id - && lhs.swiftDecl.id == rhs.swiftDecl.id - } -} - -public enum VariableAccessorKind { - case get - case set -} - -public struct ImportedVariable: ImportedDecl, CustomStringConvertible { - - public var module: String - - /// If this function/method is member of a class/struct/protocol, - /// this will contain that declaration's imported name. - /// - /// This is necessary when rendering accessor Java code we need the type that "self" is expecting to have. - public var parentName: TranslatedType? - public var hasParent: Bool { parentName != nil } - - /// This is a full name such as "counter". - public var identifier: String - - /// Which accessors are we able to expose. - /// - /// Usually this will be all the accessors the variable declares, - /// however if the getter is async or throwing we may not be able to import it - /// (yet), and therefore would skip it from the supported set. - public var supportedAccessorKinds: [VariableAccessorKind] = [.get, .set] - - /// This is the base identifier for the function, e.g., "init" for an - /// initializer or "f" for "f(a:b:)". - public var baseIdentifier: String { - guard let idx = identifier.firstIndex(of: "(") else { - return identifier - } - return String(identifier[.. ImportedFunc? { - guard self.supportedAccessorKinds.contains(kind) else { - return nil - } - - switch kind { - case .set: - let newValueParam: FunctionParameterSyntax = - "_ newValue: \(self.returnType.cCompatibleSwiftType)" - let funcDecl = ImportedFunc( - module: self.module, - decl: self.syntax!, - parent: self.parentName, - identifier: self.identifier, - returnType: TranslatedType.void, - parameters: [.init(syntax: newValueParam, type: self.returnType)]) - return funcDecl - - case .get: - let funcDecl = ImportedFunc( - module: self.module, - decl: self.syntax!, - parent: self.parentName, - identifier: self.identifier, - returnType: self.returnType, - parameters: []) - return funcDecl - } - } - - public func effectiveAccessorParameters( - _ kind: VariableAccessorKind, paramPassingStyle: SelfParameterVariant? - ) -> [ImportedParam] { - var params: [ImportedParam] = [] - - if kind == .set { - let newValueParam: FunctionParameterSyntax = - "_ newValue: \(raw: self.returnType.swiftTypeName)" - params.append( - ImportedParam( - syntax: newValueParam, - type: self.returnType) - ) - } - - if let parentName { - // Add `self: Self` for method calls on a member - // - // allocating initializer takes a Self.Type instead, but it's also a pointer - switch paramPassingStyle { - case .pointer: - let selfParam: FunctionParameterSyntax = "self$: $swift_pointer" - params.append( - ImportedParam( - syntax: selfParam, - type: parentName - ) - ) - - case .memorySegment: - let selfParam: FunctionParameterSyntax = "self$: $java_lang_foreign_MemorySegment" - var parentForSelf = parentName - parentForSelf.javaType = .javaForeignMemorySegment - params.append( - ImportedParam( - syntax: selfParam, - type: parentForSelf - ) - ) - - case nil, - .wrapper, - .swiftThunkSelf: - break - } - } - - return params - } - - public var swiftMangledName: String = "" - - public var syntax: VariableDeclSyntax? = nil - - public init( - module: String, - parentName: TranslatedType?, - identifier: String, - returnType: TranslatedType - ) { - self.module = module - self.parentName = parentName - self.identifier = identifier - self.returnType = returnType - } - - public var description: String { - """ - ImportedFunc { - mangledName: \(swiftMangledName) - identifier: \(identifier) - returnType: \(returnType) - - Swift mangled name: - Imported from: - \(syntax?.description ?? "") - } - """ + public static func == (lhs: ImportedFunc, rhs: ImportedFunc) -> Bool { + return lhs === rhs } } diff --git a/Sources/JExtractSwift/JavaConstants/ForeignValueLayouts.swift b/Sources/JExtractSwift/JavaConstants/ForeignValueLayouts.swift index 9b9d4ece..7cf1d4df 100644 --- a/Sources/JExtractSwift/JavaConstants/ForeignValueLayouts.swift +++ b/Sources/JExtractSwift/JavaConstants/ForeignValueLayouts.swift @@ -12,7 +12,6 @@ // //===----------------------------------------------------------------------===// -import Foundation import JavaTypes /// Represents a value of a `java.lang.foreign.Self` that we want to render in generated Java code. @@ -22,18 +21,16 @@ public struct ForeignValueLayout: CustomStringConvertible, Equatable { var inlineComment: String? var value: String - var needsMemoryLayoutCall: Bool = false - public init(inlineComment: String? = nil, javaConstant: String) { self.inlineComment = inlineComment - self.value = javaConstant - self.needsMemoryLayoutCall = false + self.value = "SwiftValueLayout.\(javaConstant)" } public init(inlineComment: String? = nil, customType: String) { self.inlineComment = inlineComment - self.value = customType - self.needsMemoryLayoutCall = true + // When the type is some custom type, e.g. another Swift struct that we imported, + // we need to import its layout. We do this by referring $LAYOUT on it. + self.value = "\(customType).$LAYOUT" } public init?(javaType: JavaType) { @@ -57,13 +54,7 @@ public struct ForeignValueLayout: CustomStringConvertible, Equatable { result.append("/*\(inlineComment)*/") } - result.append("SwiftValueLayout.\(value)") - - // When the type is some custom type, e.g. another Swift struct that we imported, - // we need to import its layout. We do this by calling $layout() on it. - if needsMemoryLayoutCall { - result.append(".$layout()") - } + result.append(value) return result } @@ -83,9 +74,4 @@ extension ForeignValueLayout { public static let SwiftFloat = Self(javaConstant: "SWIFT_FLOAT") public static let SwiftDouble = Self(javaConstant: "SWIFT_DOUBLE") - - var isPrimitive: Bool { - // FIXME: This is a hack, we need an enum to better describe this! - value != "SWIFT_POINTER" - } } diff --git a/Sources/JExtractSwift/JavaTypes.swift b/Sources/JExtractSwift/JavaConstants/JavaTypes.swift similarity index 100% rename from Sources/JExtractSwift/JavaTypes.swift rename to Sources/JExtractSwift/JavaConstants/JavaTypes.swift diff --git a/Sources/JExtractSwift/JavaType+Printing.swift b/Sources/JExtractSwift/JavaType+Printing.swift deleted file mode 100644 index 39a348d9..00000000 --- a/Sources/JExtractSwift/JavaType+Printing.swift +++ /dev/null @@ -1,47 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of Swift.org project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -import Foundation -import SwiftBasicFormat -import SwiftParser -import SwiftSyntax -import JavaTypes - -extension JavaType { - /// Returns a 'handle' name to pass to the `invoke` call as well as the - /// `FunctionDescription` and `MethodHandle` of the downcall handle for this parameter. - /// - /// Pass the prior to `invoke`, and directly render the latter in the Java wrapper downcall function body. - func prepareClosureDowncallHandle(decl: ImportedFunc, parameter: String) -> String { - let varNameBase = "\(decl.baseIdentifier)_\(parameter)" - let handle = "\(varNameBase)_handle$" - let desc = "\(varNameBase)_desc$" - - if self == .javaLangRunnable { - return - """ - FunctionDescriptor \(desc) = FunctionDescriptor.ofVoid(); - MethodHandle \(handle) = MethodHandles.lookup() - .findVirtual(Runnable.class, "run", - \(desc).toMethodType()); - \(handle) = \(handle).bindTo(\(parameter)); - - Linker linker = Linker.nativeLinker(); - MemorySegment \(parameter)$ = linker.upcallStub(\(handle), \(desc), arena); - """ - } - - fatalError("Cannot render closure downcall handle for: \(self), in: \(decl), parameter: \(parameter)") - } -} diff --git a/Sources/JExtractSwift/Swift2Java.swift b/Sources/JExtractSwift/Swift2Java.swift index 5eaab18a..6525fc0a 100644 --- a/Sources/JExtractSwift/Swift2Java.swift +++ b/Sources/JExtractSwift/Swift2Java.swift @@ -91,7 +91,6 @@ public struct SwiftToJava: ParsableCommand { try translator.analyze() try translator.writeSwiftThunkSources(outputDirectory: outputDirectorySwift) try translator.writeExportedJavaSources(outputDirectory: outputDirectoryJava) - try translator.writeExportedJavaModule(outputDirectory: outputDirectoryJava) print("[swift-java] Generated Java sources (\(packageName)) in: \(outputDirectoryJava)/") print("[swift-java] Imported Swift module '\(swiftModule)': " + "done.".green) } diff --git a/Sources/JExtractSwift/Swift2JavaTranslator+JavaBindingsPrinting.swift b/Sources/JExtractSwift/Swift2JavaTranslator+JavaBindingsPrinting.swift new file mode 100644 index 00000000..15fd56e3 --- /dev/null +++ b/Sources/JExtractSwift/Swift2JavaTranslator+JavaBindingsPrinting.swift @@ -0,0 +1,356 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024-2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import JavaTypes + +extension Swift2JavaTranslator { + public func printInitializerDowncallConstructors( + _ printer: inout CodePrinter, + _ decl: ImportedFunc + ) { + printer.printSeparator(decl.displayName) + + printJavaBindingDescriptorClass(&printer, decl) + + // Render the "make the downcall" functions. + printInitializerDowncallConstructor(&printer, decl) + } + + public func printFunctionDowncallMethods( + _ printer: inout CodePrinter, + _ decl: ImportedFunc + ) { + printer.printSeparator(decl.displayName) + + printJavaBindingDescriptorClass(&printer, decl) + + // Render the "make the downcall" functions. + printFuncDowncallMethod(&printer, decl) + } + + /// Print FFM Java binding descriptors for the imported Swift API. + func printJavaBindingDescriptorClass( + _ printer: inout CodePrinter, + _ decl: ImportedFunc + ) { + let thunkName = thunkNameRegistry.functionThunkName(decl: decl) + let cFunc = decl.cFunctionDecl(cName: thunkName) + + printer.printBraceBlock("private static class \(cFunc.name)") { printer in + printFunctionDescriptorValue(&printer, cFunc) + printer.print( + """ + public static final MemorySegment ADDR = + \(self.swiftModuleName).findOrThrow("\(cFunc.name)"); + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + """ + ) + } + } + + /// Print the 'FunctionDescriptor' of the lowered cdecl thunk. + public func printFunctionDescriptorValue( + _ printer: inout CodePrinter, + _ cFunc: CFunction + ) { + printer.start("public static final FunctionDescriptor DESC = ") + + let isEmptyParam = cFunc.parameters.isEmpty + if cFunc.resultType.isVoid { + printer.print("FunctionDescriptor.ofVoid(", isEmptyParam ? .continue : .newLine) + printer.indent() + } else { + printer.print("FunctionDescriptor.of(") + printer.indent() + printer.print("/* -> */", .continue) + printer.print(cFunc.resultType.foreignValueLayout, .parameterNewlineSeparator(isEmptyParam)) + } + + for (param, isLast) in cFunc.parameters.withIsLast { + printer.print("/* \(param.name ?? "_"): */", .continue) + printer.print(param.type.foreignValueLayout, .parameterNewlineSeparator(isLast)) + } + + printer.outdent() + printer.print(");") + } + + public func printInitializerDowncallConstructor( + _ printer: inout CodePrinter, + _ decl: ImportedFunc + ) { + guard let className = decl.parentType?.asNominalTypeDeclaration?.name else { + return + } + let modifiers = "public" + + var paramDecls = decl.translatedSignature.parameters + .flatMap(\.javaParameters) + .map { "\($0.type) \($0.name)" } + + assert(decl.translatedSignature.requiresSwiftArena, "constructor always require the SwiftArena") + paramDecls.append("SwiftArena swiftArena$") + + printer.printBraceBlock( + """ + /** + * Create an instance of {@code \(className)}. + * + * {@snippet lang=swift : + * \(decl.signatureString) + * } + */ + \(modifiers) \(className)(\(paramDecls.joined(separator: ", "))) + """ + ) { printer in + // Call super constructor `SwiftValue(Supplier , SwiftArena)`. + printer.print("super(() -> {") + printer.indent() + printDowncall(&printer, decl, isConstructor: true) + printer.outdent() + printer.print("}, swiftArena$);") + } + } + + /// Print the calling body that forwards all the parameters to the `methodName`, + /// with adding `SwiftArena.ofAuto()` at the end. + public func printFuncDowncallMethod( + _ printer: inout CodePrinter, + _ decl: ImportedFunc) { + let methodName: String = switch decl.kind { + case .getter: "get\(decl.name.toCamelCase)" + case .setter: "set\(decl.name.toCamelCase)" + case .function: decl.name + case .initializer: fatalError("initializers must use printInitializerDowncallConstructor()") + } + + var modifiers = "public" + switch decl.swiftSignature.selfParameter { + case .staticMethod(_), nil: + modifiers.append(" static") + default: + break + } + + let returnTy = decl.translatedSignature.result.javaResultType + + var paramDecls = decl.translatedSignature.parameters + .flatMap(\.javaParameters) + .map { "\($0.type) \($0.name)" } + if decl.translatedSignature.requiresSwiftArena { + paramDecls.append("SwiftArena swiftArena$") + } + + // TODO: we could copy the Swift method's documentation over here, that'd be great UX + printer.printBraceBlock( + """ + /** + * Downcall to Swift: + * {@snippet lang=swift : + * \(decl.signatureString) + * } + */ + \(modifiers) \(returnTy) \(methodName)(\(paramDecls.joined(separator: ", "))) + """ + ) { printer in + if case .instance(_) = decl.swiftSignature.selfParameter { + // Make sure the object has not been destroyed. + printer.print("$ensureAlive();") + } + + printDowncall(&printer, decl) + } + } + + /// Print the actual downcall to the Swift API. + /// + /// This assumes that all the parameters are passed-in with appropriate names. + package func printDowncall( + _ printer: inout CodePrinter, + _ decl: ImportedFunc, + isConstructor: Bool = false + ) { + //=== Part 1: MethodHandle + let descriptorClassIdentifier = thunkNameRegistry.functionThunkName(decl: decl) + printer.print( + "var mh$ = \(descriptorClassIdentifier).HANDLE;" + ) + + let tryHead = if decl.translatedSignature.requiresTemporaryArena { + "try(var arena$ = Arena.ofConfined()) {" + } else { + "try {" + } + printer.print(tryHead); + printer.indent(); + + //=== Part 2: prepare all arguments. + var downCallArguments: [String] = [] + + // Regular parameters. + for (i, parameter) in decl.translatedSignature.parameters.enumerated() { + let original = decl.swiftSignature.parameters[i] + let parameterName = original.parameterName ?? "_\(i)" + let converted = parameter.conversion.render(&printer, parameterName) + let lowered: String + if parameter.conversion.isTrivial { + lowered = converted + } else { + // Store the conversion to a temporary variable. + lowered = "\(parameterName)$" + printer.print("var \(lowered) = \(converted);") + } + downCallArguments.append(lowered) + } + + // 'self' parameter. + if let selfParameter = decl.translatedSignature.selfParameter { + let lowered = selfParameter.conversion.render(&printer, "this") + downCallArguments.append(lowered) + } + + // Indirect return receivers. + for outParameter in decl.translatedSignature.result.outParameters { + let memoryLayout = renderMemoryLayoutValue(for: outParameter.type) + + let arena = if let className = outParameter.type.className, + self.importedTypes[className] != nil { + // Use passed-in 'SwiftArena' for 'SwiftValue'. + "swiftArena$" + } else { + // Otherwise use the temporary 'Arena'. + "arena$" + } + + let varName = "_result" + outParameter.name + + printer.print( + "MemorySegment \(varName) = \(arena).allocate(\(memoryLayout));" + ) + downCallArguments.append(varName) + } + + //=== Part 3: Downcall. + printer.print( + """ + if (SwiftKit.TRACE_DOWNCALLS) { + SwiftKit.traceDowncall(\(downCallArguments.joined(separator: ", "))); + } + """ + ) + let downCall = "mh$.invokeExact(\(downCallArguments.joined(separator: ", ")))" + + //=== Part 4: Convert the return value. + if isConstructor { + // For constructors, the caller expects the "self" memory segment. + printer.print("\(downCall);") + printer.print("return _result;") + } else if decl.translatedSignature.result.javaResultType == .void { + printer.print("\(downCall);") + } else { + let placeholder = if decl.translatedSignature.result.outParameters.isEmpty { + downCall + } else { + // FIXME: Support cdecl thunk returning a value while populating the out parameters. + "_result" + } + let result = decl.translatedSignature.result.conversion.render(&printer, placeholder) + + if decl.translatedSignature.result.javaResultType != .void { + printer.print("return \(result);") + } else { + printer.print("\(result);") + } + } + + printer.outdent() + printer.print( + """ + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + """ + ) + } + + func renderMemoryLayoutValue(for javaType: JavaType) -> String { + if let layout = ForeignValueLayout(javaType: javaType) { + return layout.description + } else if case .class(package: _, name: let customClass) = javaType { + return ForeignValueLayout(customType: customClass).description + } else { + fatalError("renderMemoryLayoutValue not supported for \(javaType)") + } + } +} + +extension JavaConversionStep { + /// Whether the conversion uses SwiftArena. + var requiresSwiftArena: Bool { + switch self { + case .pass, .swiftValueSelfSegment, .construct, .cast, .call: + return false + case .constructSwiftValue: + return true + } + } + + /// Whether the conversion uses temporary Arena. + var requiresTemporaryArena: Bool { + switch self { + case .pass, .swiftValueSelfSegment, .construct, .constructSwiftValue, .cast: + return false + case .call(_, let withArena): + return withArena + } + } + + /// Whether if the result evaluation is trivial. + /// + /// If this is false, it's advised to store it to a variable if it's used multiple times + var isTrivial: Bool { + switch self { + case .pass, .swiftValueSelfSegment: + return true + case .cast, .construct, .constructSwiftValue, .call: + return false + } + } + + /// Returns the conversion string applied to the placeholder. + func render(_ printer: inout CodePrinter, _ placeholder: String) -> String { + // NOTE: 'printer' is used if the conversion wants to cause side-effects. + // E.g. storing a temporary values into a variable. + switch self { + case .pass: + return placeholder + + case .swiftValueSelfSegment: + return "\(placeholder).$memorySegment()" + + case .call(let function, let withArena): + let arenaArg = withArena ? ", arena$" : "" + return "\(function)(\(placeholder)\(arenaArg))" + + case .constructSwiftValue(let javaType): + return "new \(javaType.className!)(\(placeholder), swiftArena$)" + + case .construct(let javaType): + return "new \(javaType)(\(placeholder))" + + case .cast(let javaType): + return "(\(javaType)) \(placeholder)" + } + } +} diff --git a/Sources/JExtractSwift/Swift2JavaTranslator+JavaTranslation.swift b/Sources/JExtractSwift/Swift2JavaTranslator+JavaTranslation.swift new file mode 100644 index 00000000..4d5fc80a --- /dev/null +++ b/Sources/JExtractSwift/Swift2JavaTranslator+JavaTranslation.swift @@ -0,0 +1,437 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024-2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import JavaTypes + +extension Swift2JavaTranslator { + func translate( + swiftSignature: SwiftFunctionSignature, + as apiKind: SwiftAPIKind + ) throws -> TranslatedFunctionSignature { + let lowering = CdeclLowering(swiftStdlibTypes: self.swiftStdlibTypes) + let loweredSignature = try lowering.lowerFunctionSignature(swiftSignature, apiKind: apiKind) + + let translation = JavaTranslation(swiftStdlibTypes: self.swiftStdlibTypes) + let translated = try translation.translate(loweredFunctionSignature: loweredSignature) + + return translated + } +} + +/// Represent a parameter in Java code. +struct JavaParameter { + /// The type. + var type: JavaType + + /// The name. + var name: String +} + +/// Represent a Swift API parameter translated to Java. +struct TranslatedParameter { + /// Java parameter(s) mapped to the Swift parameter. + /// + /// Array because one Swift parameter can be mapped to multiple parameters. + var javaParameters: [JavaParameter] + + /// Describes how to convert the Java parameter to the lowered arguments for + /// the foreign function. + var conversion: JavaConversionStep +} + +/// Represent a Swift API result translated to Java. +struct TranslatedResult { + /// Java type that represents the Swift result type. + var javaResultType: JavaType + + /// Required indirect return receivers for receiving the result. + /// + /// 'JavaParameter.name' is the suffix for the receiver variable names. For example + /// + /// var _result_pointer = MemorySegment.allocate(...) + /// var _result_count = MemroySegment.allocate(...) + /// downCall(_result_pointer, _result_count) + /// return constructResult(_result_pointer, _result_count) + /// + /// This case, there're two out parameter, named '_pointer' and '_count'. + var outParameters: [JavaParameter] + + /// Describes how to construct the Java result from the foreign function return + /// value and/or the out parameters. + var conversion: JavaConversionStep +} + +/// Translated function signature representing a Swift API. +/// +/// Since this holds the lowered signature, and the original `SwiftFunctionSignature` +/// in it, this contains all the API information (except the name) to generate the +/// cdecl thunk, Java binding, and the Java wrapper function. +struct TranslatedFunctionSignature { + var loweredSignature: LoweredFunctionSignature + + var selfParameter: TranslatedParameter? + var parameters: [TranslatedParameter] + var result: TranslatedResult +} + +extension TranslatedFunctionSignature { + /// Whether or not if the down-calling requires temporary "Arena" which is + /// only used during the down-calling. + var requiresTemporaryArena: Bool { + if self.parameters.contains(where: { $0.conversion.requiresTemporaryArena }) { + return true + } + if self.selfParameter?.conversion.requiresTemporaryArena ?? false { + return true + } + if self.result.conversion.requiresTemporaryArena { + return true + } + return false + } + + /// Whether if the down-calling requires "SwiftArena" or not, which should be + /// passed-in by the API caller. This is needed if the API returns a `SwiftValue` + var requiresSwiftArena: Bool { + return self.result.conversion.requiresSwiftArena + } +} + +struct JavaTranslation { + var swiftStdlibTypes: SwiftStandardLibraryTypes + + /// Translate Swift API to user-facing Java API. + /// + /// Note that the result signature is for the high-level Java API, not the + /// low-level FFM down-calling interface. + func translate( + loweredFunctionSignature: LoweredFunctionSignature + ) throws -> TranslatedFunctionSignature { + let swiftSignature = loweredFunctionSignature.original + + // 'self' + let selfParameter: TranslatedParameter? + if case .instance(let swiftSelf) = swiftSignature.selfParameter { + selfParameter = try self.translate( + swiftParam: swiftSelf, + loweredParam: loweredFunctionSignature.selfParameter!, + parameterName: swiftSelf.parameterName ?? "self" + ) + } else { + selfParameter = nil + } + + // Regular parameters. + let parameters: [TranslatedParameter] = try swiftSignature.parameters.enumerated() + .map { (idx, swiftParam) in + let loweredParam = loweredFunctionSignature.parameters[idx] + let parameterName = swiftParam.parameterName ?? "_\(idx)" + return try self.translate( + swiftParam: swiftParam, + loweredParam: loweredParam, + parameterName: parameterName + ) + } + + // Result. + let result = try self.translate( + swiftResult: swiftSignature.result, + loweredResult: loweredFunctionSignature.result + ) + + return TranslatedFunctionSignature( + loweredSignature: loweredFunctionSignature, + selfParameter: selfParameter, + parameters: parameters, + result: result + ) + } + + /// Translate + func translate( + swiftParam: SwiftParameter, + loweredParam: LoweredParameter, + parameterName: String + ) throws -> TranslatedParameter { + let swiftType = swiftParam.type + + // If there is a 1:1 mapping between this Swift type and a C type, that can + // be expressed as a Java primitive type. + if let cType = try? CType(cdeclType: swiftType) { + let javaType = cType.javaType + return TranslatedParameter( + javaParameters: [ + JavaParameter( + type: javaType, + name: loweredParam.cdeclParameters[0].parameterName! + ) + ], + conversion: .pass + ) + } + + switch swiftType { + case .metatype: + // Metatype are expressed as 'org.swift.swiftkit.SwiftAnyType' + return TranslatedParameter( + javaParameters: [ + JavaParameter( + type: JavaType.class(package: "org.swift.swiftkit", name: "SwiftAnyType"), + name: loweredParam.cdeclParameters[0].parameterName!) + ], + conversion: .swiftValueSelfSegment + ) + + case .nominal(let swiftNominalType): + if let knownType = swiftNominalType.nominalTypeDecl.knownStandardLibraryType { + if swiftParam.convention == .inout { + // FIXME: Support non-trivial 'inout' for builtin types. + throw JavaTranslationError.inoutNotSupported(swiftType) + } + switch knownType { + case .unsafePointer, .unsafeMutablePointer: + // FIXME: Implement + throw JavaTranslationError.unhandledType(swiftType) + case .unsafeBufferPointer, .unsafeMutableBufferPointer: + // FIXME: Implement + throw JavaTranslationError.unhandledType(swiftType) + + case .string: + return TranslatedParameter( + javaParameters: [ + JavaParameter( + type: .javaLangString, + name: loweredParam.cdeclParameters[0].parameterName! + ) + ], + conversion: .call(function: "SwiftKit.toCString", withArena: true) + ) + + default: + throw JavaTranslationError.unhandledType(swiftType) + } + } + + // Generic types are not supported yet. + guard swiftNominalType.genericArguments == nil else { + throw JavaTranslationError.unhandledType(swiftType) + } + + return TranslatedParameter( + javaParameters: [ + JavaParameter( + type: try translate(swiftType: swiftType), + name: loweredParam.cdeclParameters[0].parameterName! + ) + ], + conversion: .swiftValueSelfSegment + ) + + case .tuple: + // TODO: Implement. + throw JavaTranslationError.unhandledType(swiftType) + + case .function(let fn) where fn.parameters.isEmpty && fn.resultType.isVoid: + return TranslatedParameter( + javaParameters: [ + JavaParameter( + type: JavaType.class(package: "java.lang", name: "Runnable"), + name: loweredParam.cdeclParameters[0].parameterName!) + ], + conversion: .call(function: "SwiftKit.toUpcallStub", withArena: true) + ) + + case .optional, .function: + throw JavaTranslationError.unhandledType(swiftType) + } + } + + func translate( + swiftResult: SwiftResult, + loweredResult: LoweredResult + ) throws -> TranslatedResult { + let swiftType = swiftResult.type + + // If there is a 1:1 mapping between this Swift type and a C type, that can + // be expressed as a Java primitive type. + if let cType = try? CType(cdeclType: swiftType) { + let javaType = cType.javaType + return TranslatedResult( + javaResultType: javaType, + outParameters: [], + conversion: .cast(javaType) + ) + } + + switch swiftType { + case .metatype(_): + // Metatype are expressed as 'org.swift.swiftkit.SwiftAnyType' + let javaType = JavaType.class(package: "org.swift.swiftkit", name: "SwiftAnyType") + return TranslatedResult( + javaResultType: javaType, + outParameters: [], + conversion: .construct(javaType) + ) + + case .nominal(let swiftNominalType): + if let knownType = swiftNominalType.nominalTypeDecl.knownStandardLibraryType { + switch knownType { + case .unsafePointer, .unsafeMutablePointer: + // FIXME: Implement + throw JavaTranslationError.unhandledType(swiftType) + case .unsafeBufferPointer, .unsafeMutableBufferPointer: + // FIXME: Implement + throw JavaTranslationError.unhandledType(swiftType) + case .string: + // FIXME: Implement + throw JavaTranslationError.unhandledType(swiftType) + default: + throw JavaTranslationError.unhandledType(swiftType) + } + } + + // Generic types are not supported yet. + guard swiftNominalType.genericArguments == nil else { + throw JavaTranslationError.unhandledType(swiftType) + } + + let javaType: JavaType = .class(package: nil, name: swiftNominalType.nominalTypeDecl.name) + return TranslatedResult( + javaResultType: javaType, + outParameters: [ + JavaParameter(type: javaType, name: "") + ], + conversion: .constructSwiftValue(javaType) + ) + + case .tuple: + // TODO: Implement. + throw JavaTranslationError.unhandledType(swiftType) + + case .optional, .function: + throw JavaTranslationError.unhandledType(swiftType) + } + + } + + func translate( + swiftType: SwiftType + ) throws -> JavaType { + guard let nominalName = swiftType.asNominalTypeDeclaration?.name else { + throw JavaTranslationError.unhandledType(swiftType) + } + return .class(package: nil, name: nominalName) + } +} + +/// Describes how to convert values between Java types and FFM types. +enum JavaConversionStep { + // Pass through. + case pass + + // 'value.$memorySegment()' + case swiftValueSelfSegment + + // call specified function using the placeholder as arguments. + // If `withArena` is true, `arena$` argument is added. + case call(function: String, withArena: Bool) + + // Call 'new \(Type)(\(placeholder), swiftArena$)'. + case constructSwiftValue(JavaType) + + // Construct the type using the placeholder as arguments. + case construct(JavaType) + + // Casting the placeholder to the certain type. + case cast(JavaType) +} + +extension CType { + /// Map lowered C type to Java type for FFM binding. + var javaType: JavaType { + switch self { + case .void: return .void + + case .integral(.bool): return .boolean + case .integral(.signed(bits: 8)): return .byte + case .integral(.signed(bits: 16)): return .short + case .integral(.signed(bits: 32)): return .int + case .integral(.signed(bits: 64)): return .long + case .integral(.unsigned(bits: 8)): return .byte + case .integral(.unsigned(bits: 16)): return .short + case .integral(.unsigned(bits: 32)): return .int + case .integral(.unsigned(bits: 64)): return .long + + case .floating(.float): return .float + case .floating(.double): return .double + + // FIXME: 32 bit consideration. + // The 'FunctionDescriptor' uses 'SWIFT_INT' which relies on the running + // machine arch. That means users can't pass Java 'long' values to the + // function without casting. But how do we generate code that runs both + // 32 and 64 bit machine? + case .integral(.ptrdiff_t), .integral(.size_t): + return .long + + case .pointer(_), .function(resultType: _, parameters: _, variadic: _): + return .javaForeignMemorySegment + + case .qualified(const: _, volatile: _, let inner): + return inner.javaType + + case .tag(_): + fatalError("unsupported") + case .integral(.signed(bits: _)), .integral(.unsigned(bits: _)): + fatalError("unreachable") + } + } + + /// Map lowered C type to FFM ValueLayout. + var foreignValueLayout: ForeignValueLayout { + switch self { + case .integral(.bool): return .SwiftBool + case .integral(.signed(bits: 8)): return .SwiftInt8 + case .integral(.signed(bits: 16)): return .SwiftInt16 + case .integral(.signed(bits: 32)): return .SwiftInt32 + case .integral(.signed(bits: 64)): return .SwiftInt64 + + case .integral(.unsigned(bits: 8)): return .SwiftInt8 + case .integral(.unsigned(bits: 16)): return .SwiftInt16 + case .integral(.unsigned(bits: 32)): return .SwiftInt32 + case .integral(.unsigned(bits: 64)): return .SwiftInt64 + + case .floating(.double): return .SwiftDouble + case .floating(.float): return .SwiftFloat + + case .integral(.ptrdiff_t), .integral(.size_t): + return .SwiftInt + + case .pointer(_), .function(resultType: _, parameters: _, variadic: _): + return .SwiftPointer + + case .qualified(const: _, volatile: _, type: let inner): + return inner.foreignValueLayout + + case .tag(_): + fatalError("unsupported") + case .void, .integral(.signed(bits: _)), .integral(.unsigned(bits: _)): + fatalError("unreachable") + } + } +} + +enum JavaTranslationError: Error { + case inoutNotSupported(SwiftType) + case unhandledType(SwiftType) +} diff --git a/Sources/JExtractSwift/Swift2JavaTranslator+MemoryLayouts.swift b/Sources/JExtractSwift/Swift2JavaTranslator+MemoryLayouts.swift deleted file mode 100644 index fa5b6318..00000000 --- a/Sources/JExtractSwift/Swift2JavaTranslator+MemoryLayouts.swift +++ /dev/null @@ -1,48 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of Swift.org project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -import Foundation -import SwiftBasicFormat -import SwiftParser -import SwiftSyntax - -extension Swift2JavaTranslator { - - public func javaMemoryLayoutDescriptors( - forParametersOf decl: ImportedFunc, - paramPassingStyle: SelfParameterVariant? - ) -> [ForeignValueLayout] { - var layouts: [ForeignValueLayout] = [] - layouts.reserveCapacity(decl.parameters.count + 1) - - for param in decl.effectiveParameters(paramPassingStyle: paramPassingStyle) { - if param.type.cCompatibleJavaMemoryLayout == CCompatibleJavaMemoryLayout.primitive(.void) { - continue - } - - var layout = param.type.foreignValueLayout - layout.inlineComment = "\(param.effectiveValueName)" - layouts.append(layout) - } - - // an indirect return passes the buffer as the last parameter to our thunk - if decl.isIndirectReturn { - var layout = ForeignValueLayout.SwiftPointer - layout.inlineComment = "indirect return buffer" - layouts.append(layout) - } - - return layouts - } -} diff --git a/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift b/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift index 30dc3fb7..98b3c767 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift @@ -12,10 +12,9 @@ // //===----------------------------------------------------------------------===// -import Foundation -import SwiftBasicFormat -import SwiftParser +import JavaTypes import SwiftSyntax +import SwiftSyntaxBuilder // ==== --------------------------------------------------------------------------------------------------------------- // MARK: File writing @@ -32,16 +31,16 @@ extension Swift2JavaTranslator { public func writeExportedJavaSources(outputDirectory: String, printer: inout CodePrinter) throws { for (_, ty) in importedTypes.sorted(by: { (lhs, rhs) in lhs.key < rhs.key }) { - let filename = "\(ty.javaClassName).java" + let filename = "\(ty.swiftNominal.name).java" log.info("Printing contents: \(filename)") - printImportedClass(&printer, ty) + printImportedNominal(&printer, ty) if let outputFile = try printer.writeContents( outputDirectory: outputDirectory, javaPackagePath: javaPackagePath, filename: filename ) { - print("[swift-java] Generated: \(ty.javaClassName.bold).java (at \(outputFile))") + print("[swift-java] Generated: \(ty.swiftNominal.name.bold).java (at \(outputFile))") } } @@ -55,119 +54,10 @@ extension Swift2JavaTranslator { javaPackagePath: javaPackagePath, filename: filename) { - print("[swift-java] Generated: \(self.swiftModuleName).java (at \(outputFile)") + print("[swift-java] Generated: \(self.swiftModuleName).java (at \(outputFile))") } } } - - public func writeSwiftThunkSources(outputDirectory: String) throws { - var printer = CodePrinter() - - try writeSwiftThunkSources(outputDirectory: outputDirectory, printer: &printer) - } - - public func writeSwiftThunkSources(outputDirectory: String, printer: inout CodePrinter) throws { - let moduleFilenameBase = "\(self.swiftModuleName)Module+SwiftJava" - let moduleFilename = "\(moduleFilenameBase).swift" - do { - log.info("Printing contents: \(moduleFilename)") - - try printGlobalSwiftThunkSources(&printer) - - if let outputFile = try printer.writeContents( - outputDirectory: outputDirectory, - javaPackagePath: nil, - filename: moduleFilename) - { - print("[swift-java] Generated: \(moduleFilenameBase.bold).swift (at \(outputFile)") - } - } catch { - log.warning("Failed to write to Swift thunks: \(moduleFilename)") - } - - // === All types - for (_, ty) in importedTypes.sorted(by: { (lhs, rhs) in lhs.key < rhs.key }) { - let fileNameBase = "\(ty.swiftNominal.qualifiedName)+SwiftJava" - let filename = "\(fileNameBase).swift" - log.info("Printing contents: \(filename)") - - do { - try printSwiftThunkSources(&printer, ty: ty) - - if let outputFile = try printer.writeContents( - outputDirectory: outputDirectory, - javaPackagePath: nil, - filename: filename) - { - print("[swift-java] Generated: \(fileNameBase.bold).swift (at \(outputFile)") - } - } catch { - log.warning("Failed to write to Swift thunks: \(filename)") - } - } - } - - public func printGlobalSwiftThunkSources(_ printer: inout CodePrinter) throws { - let stt = SwiftThunkTranslator(self) - - printer.print( - """ - // Generated by swift-java - - import SwiftKitSwift - """) - - for thunk in stt.renderGlobalThunks() { - printer.print(thunk) - printer.println() - } - } - - public func printSwiftThunkSources(_ printer: inout CodePrinter, decl: ImportedFunc) { - let stt = SwiftThunkTranslator(self) - - for thunk in stt.render(forFunc: decl) { - printer.print(thunk) - printer.println() - } - } - - package func printSwiftThunkSources(_ printer: inout CodePrinter, ty: ImportedNominalType) throws { - let stt = SwiftThunkTranslator(self) - - printer.print( - """ - // Generated by swift-java - - import SwiftKitSwift - - """ - ) - - for thunk in stt.renderThunks(forType: ty) { - printer.print("\(thunk)") - printer.print("") - } - } - - /// A module contains all static and global functions from the Swift module, - /// potentially from across multiple swift interfaces. - public func writeExportedJavaModule(outputDirectory: String) throws { - var printer = CodePrinter() - try writeExportedJavaModule(outputDirectory: outputDirectory, printer: &printer) - } - - public func writeExportedJavaModule(outputDirectory: String, printer: inout CodePrinter) throws { - printModule(&printer) - - if let file = try printer.writeContents( - outputDirectory: outputDirectory, - javaPackagePath: javaPackagePath, - filename: "\(swiftModuleName).java" - ) { - self.log.info("Generated: \(file): \("done".green).") - } - } } // ==== --------------------------------------------------------------------------------------------------------------- @@ -192,21 +82,12 @@ extension Swift2JavaTranslator { } } - package func printImportedClass(_ printer: inout CodePrinter, _ decl: ImportedNominalType) { + package func printImportedNominal(_ printer: inout CodePrinter, _ decl: ImportedNominalType) { printHeader(&printer) printPackage(&printer) printImports(&printer) printNominal(&printer, decl) { printer in - // Prepare type metadata, we're going to need these when invoking e.g. initializers so cache them in a static. - // We call into source swift-java source generated accessors which give us the type of the Swift object: - // TODO: seems we no longer need the mangled name per se, so avoiding such constant and downcall - // printer.printParts( - // "public static final String TYPE_MANGLED_NAME = ", - // SwiftKitPrinting.renderCallGetSwiftTypeMangledName(module: self.swiftModuleName, nominal: decl), - // ";" - // ) - // We use a static field to abuse the initialization order such that by the time we get type metadata, // we already have loaded the library where it will be obtained from. printer.printParts( @@ -234,14 +115,22 @@ extension Swift2JavaTranslator { printer.print("") + printer.print( + """ + public \(decl.swiftNominal.name)(MemorySegment segment, SwiftArena arena) { + super(segment, arena); + } + """ + ) + // Initializers for initDecl in decl.initializers { - printClassConstructors(&printer, initDecl) + printInitializerDowncallConstructors(&printer, initDecl) } // Properties - for varDecl in decl.variables { - printVariableDowncallMethods(&printer, varDecl) + for accessorDecl in decl.variables { + printFunctionDowncallMethods(&printer, accessorDecl) } // Methods @@ -250,7 +139,7 @@ extension Swift2JavaTranslator { } // Helper methods and default implementations - printHeapObjectToStringMethod(&printer, decl) + printToStringMethod(&printer, decl) } } @@ -284,15 +173,14 @@ extension Swift2JavaTranslator { _ printer: inout CodePrinter, _ decl: ImportedNominalType, body: (inout CodePrinter) -> Void ) { let parentProtocol: String - if decl.isReferenceType { + if decl.swiftNominal.isReferenceType { parentProtocol = "SwiftHeapObject" } else { parentProtocol = "SwiftValue" } - printer.printTypeDecl("public final class \(decl.javaClassName) extends SwiftInstance implements \(parentProtocol)") { + printer.printBraceBlock("public final class \(decl.swiftNominal.name) extends SwiftInstance implements \(parentProtocol)") { printer in - // Constants printClassConstants(printer: &printer) @@ -301,7 +189,7 @@ extension Swift2JavaTranslator { } public func printModuleClass(_ printer: inout CodePrinter, body: (inout CodePrinter) -> Void) { - printer.printTypeDecl("public final class \(swiftModuleName)") { printer in + printer.printBraceBlock("public final class \(swiftModuleName)") { printer in printPrivateConstructor(&printer, swiftModuleName) // Constants @@ -400,8 +288,7 @@ extension Swift2JavaTranslator { private func printClassMemoryLayout(_ printer: inout CodePrinter, _ decl: ImportedNominalType) { printer.print( """ - private static final GroupLayout $LAYOUT = (GroupLayout) SwiftValueWitnessTable.layoutOfSwiftType(TYPE_METADATA.$memorySegment()); - + public static final GroupLayout $LAYOUT = (GroupLayout) SwiftValueWitnessTable.layoutOfSwiftType(TYPE_METADATA.$memorySegment()); public final GroupLayout $layout() { return $LAYOUT; } @@ -409,594 +296,19 @@ extension Swift2JavaTranslator { ) } - public func printClassConstructors(_ printer: inout CodePrinter, _ decl: ImportedFunc) { - guard let parentName = decl.parent else { - fatalError("init must be inside a parent type! Was: \(decl)") - } - printer.printSeparator(decl.identifier) - - let descClassIdentifier = renderDescClassName(decl) - printer.printTypeDecl("private static class \(descClassIdentifier)") { printer in - printFunctionDescriptorValue(&printer, decl) - printAccessorFunctionAddr(&printer, decl) - printMethodDowncallHandleForAddrDesc(&printer) - } - - printNominalInitializerConstructors(&printer, decl, parentName: parentName) - } - - public func printNominalInitializerConstructors( - _ printer: inout CodePrinter, - _ decl: ImportedFunc, - parentName: TranslatedType - ) { - let descClassIdentifier = renderDescClassName(decl) - - printer.print( - """ - /** - * Create an instance of {@code \(parentName.unqualifiedJavaTypeName)}. - * This instance is managed by the passed in {@link SwiftArena} and may not outlive the arena's lifetime. - * - \(decl.renderCommentSnippet ?? " *") - */ - public \(parentName.unqualifiedJavaTypeName)(\(renderJavaParamDecls(decl, paramPassingStyle: .wrapper)), SwiftArena arena) { - super(() -> { - var mh$ = \(descClassIdentifier).HANDLE; - try { - MemorySegment _result = arena.allocate($LAYOUT); - - if (SwiftKit.TRACE_DOWNCALLS) { - SwiftKit.traceDowncall(\(renderForwardJavaParams(decl, paramPassingStyle: nil))); - } - mh$.invokeExact( - \(renderForwardJavaParams(decl, paramPassingStyle: nil)), - /* indirect return buffer */_result - ); - return _result; - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - }, arena); - } - """ - ) - } - - public func printFunctionDowncallMethods(_ printer: inout CodePrinter, _ decl: ImportedFunc) { - printer.printSeparator(decl.identifier) - - printer.printTypeDecl("private static class \(decl.baseIdentifier)") { printer in - printFunctionDescriptorValue(&printer, decl) - printAccessorFunctionAddr(&printer, decl) - printMethodDowncallHandleForAddrDesc(&printer) - } - - printFunctionDescriptorMethod(&printer, decl: decl) - printFunctionMethodHandleMethod(&printer, decl: decl) - printFunctionAddressMethod(&printer, decl: decl) - - // Render the basic "make the downcall" function - if decl.hasParent { - printFuncDowncallMethod(&printer, decl: decl, paramPassingStyle: .memorySegment) - printFuncDowncallMethod(&printer, decl: decl, paramPassingStyle: .wrapper) - } else { - printFuncDowncallMethod(&printer, decl: decl, paramPassingStyle: nil) - } - } - - private func printFunctionAddressMethod( - _ printer: inout CodePrinter, - decl: ImportedFunc, - accessorKind: VariableAccessorKind? = nil - ) { - - let addrName = accessorKind.renderAddrFieldName - let methodNameSegment = accessorKind.renderMethodNameSegment - let snippet = decl.renderCommentSnippet ?? "* " - - printer.print( - """ - /** - * Address for: - \(snippet) - */ - public static MemorySegment \(decl.baseIdentifier)\(methodNameSegment)$address() { - return \(decl.baseIdentifier).\(addrName); - } - """ - ) - } - - private func printFunctionMethodHandleMethod( - _ printer: inout CodePrinter, - decl: ImportedFunc, - accessorKind: VariableAccessorKind? = nil - ) { - let handleName = accessorKind.renderHandleFieldName - let methodNameSegment = accessorKind.renderMethodNameSegment - let snippet = decl.renderCommentSnippet ?? "* " - - printer.print( - """ - /** - * Downcall method handle for: - \(snippet) - */ - public static MethodHandle \(decl.baseIdentifier)\(methodNameSegment)$handle() { - return \(decl.baseIdentifier).\(handleName); - } - """ - ) - } - - private func printFunctionDescriptorMethod( - _ printer: inout CodePrinter, - decl: ImportedFunc, - accessorKind: VariableAccessorKind? = nil - ) { - let descName = accessorKind.renderDescFieldName - let methodNameSegment = accessorKind.renderMethodNameSegment - let snippet = decl.renderCommentSnippet ?? "* " - - printer.print( - """ - /** - * Function descriptor for: - \(snippet) - */ - public static FunctionDescriptor \(decl.baseIdentifier)\(methodNameSegment)$descriptor() { - return \(decl.baseIdentifier).\(descName); - } - """ - ) - } - - public func printVariableDowncallMethods(_ printer: inout CodePrinter, _ decl: ImportedVariable) { - printer.printSeparator(decl.identifier) - - printer.printTypeDecl("private static class \(decl.baseIdentifier)") { printer in - for accessorKind in decl.supportedAccessorKinds { - guard let accessor = decl.accessorFunc(kind: accessorKind) else { - log.warning("Skip print for \(accessorKind) of \(decl.identifier)!") - continue - } - - printFunctionDescriptorValue(&printer, accessor, accessorKind: accessorKind) - printAccessorFunctionAddr(&printer, accessor, accessorKind: accessorKind) - printMethodDowncallHandleForAddrDesc(&printer, accessorKind: accessorKind) - } - } - - // First print all the supporting infra - for accessorKind in decl.supportedAccessorKinds { - guard let accessor = decl.accessorFunc(kind: accessorKind) else { - log.warning("Skip print for \(accessorKind) of \(decl.identifier)!") - continue - } - printFunctionDescriptorMethod(&printer, decl: accessor, accessorKind: accessorKind) - printFunctionMethodHandleMethod(&printer, decl: accessor, accessorKind: accessorKind) - printFunctionAddressMethod(&printer, decl: accessor, accessorKind: accessorKind) - } - - // Then print the actual downcall methods - for accessorKind in decl.supportedAccessorKinds { - guard let accessor = decl.accessorFunc(kind: accessorKind) else { - log.warning("Skip print for \(accessorKind) of \(decl.identifier)!") - continue - } - - // Render the basic "make the downcall" function - if decl.hasParent { - printFuncDowncallMethod( - &printer, decl: accessor, paramPassingStyle: .memorySegment, accessorKind: accessorKind) - printFuncDowncallMethod( - &printer, decl: accessor, paramPassingStyle: .wrapper, accessorKind: accessorKind) - } else { - printFuncDowncallMethod( - &printer, decl: accessor, paramPassingStyle: nil, accessorKind: accessorKind) - } - } - } - - func printAccessorFunctionAddr( - _ printer: inout CodePrinter, _ decl: ImportedFunc, - accessorKind: VariableAccessorKind? = nil - ) { - let thunkName = thunkNameRegistry.functionThunkName(module: self.swiftModuleName, decl: decl) - printer.print( - """ - public static final MemorySegment \(accessorKind.renderAddrFieldName) = - \(self.swiftModuleName).findOrThrow("\(thunkName)"); - """ - ) - } - - func printMethodDowncallHandleForAddrDesc( - _ printer: inout CodePrinter, accessorKind: VariableAccessorKind? = nil - ) { - printer.print( - """ - public static final MethodHandle \(accessorKind.renderHandleFieldName) = Linker.nativeLinker().downcallHandle(\(accessorKind.renderAddrFieldName), \(accessorKind.renderDescFieldName)); - """ - ) - } - - public func printFuncDowncallMethod( - _ printer: inout CodePrinter, - decl: ImportedFunc, - paramPassingStyle: SelfParameterVariant?, - accessorKind: VariableAccessorKind? = nil - ) { - let returnTy = decl.returnType.javaType - - let maybeReturnCast: String - if decl.returnType.javaType == .void { - maybeReturnCast = "" // nothing to return or cast to - } else { - maybeReturnCast = "return (\(returnTy))" - } - - // TODO: we could copy the Swift method's documentation over here, that'd be great UX - let javaDocComment: String = - """ - /** - * Downcall to Swift: - \(decl.renderCommentSnippet ?? "* ") - */ - """ - - // An identifier may be "getX", "setX" or just the plain method name - let identifier = accessorKind.renderMethodName(decl) - - if paramPassingStyle == SelfParameterVariant.wrapper { - let guardFromDestroyedObjectCalls: String = - if decl.hasParent { - """ - $ensureAlive(); - """ - } else { "" } - - // delegate to the MemorySegment "self" accepting overload - printer.print( - """ - \(javaDocComment) - public \(returnTy) \(identifier)(\(renderJavaParamDecls(decl, paramPassingStyle: .wrapper))) { - \(guardFromDestroyedObjectCalls) - \(maybeReturnCast) \(identifier)(\(renderForwardJavaParams(decl, paramPassingStyle: .wrapper))); - } - """ - ) - return - } - - let needsArena = downcallNeedsConfinedArena(decl) - let handleName = accessorKind.renderHandleFieldName - - printer.printParts( - """ - \(javaDocComment) - public static \(returnTy) \(identifier)(\(renderJavaParamDecls(decl, paramPassingStyle: paramPassingStyle))) { - var mh$ = \(decl.baseIdentifier).\(handleName); - \(renderTry(withArena: needsArena)) - """, - renderUpcallHandles(decl), - renderParameterDowncallConversions(decl), - """ - if (SwiftKit.TRACE_DOWNCALLS) { - SwiftKit.traceDowncall(\(renderForwardJavaParams(decl, paramPassingStyle: .memorySegment))); - } - \(maybeReturnCast) mh$.invokeExact(\(renderForwardJavaParams(decl, paramPassingStyle: paramPassingStyle))); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - } - """ - ) - } - - public func printPropertyAccessorDowncallMethod( - _ printer: inout CodePrinter, - decl: ImportedFunc, - paramPassingStyle: SelfParameterVariant? - ) { - let returnTy = decl.returnType.javaType - - let maybeReturnCast: String - if decl.returnType.javaType == .void { - maybeReturnCast = "" // nothing to return or cast to - } else { - maybeReturnCast = "return (\(returnTy))" - } - - if paramPassingStyle == SelfParameterVariant.wrapper { - // delegate to the MemorySegment "self" accepting overload - printer.print( - """ - /** - * {@snippet lang=swift : - * \(/*TODO: make a printSnippet func*/decl.syntax ?? "") - * } - */ - public \(returnTy) \(decl.baseIdentifier)(\(renderJavaParamDecls(decl, paramPassingStyle: .wrapper))) { - \(maybeReturnCast) \(decl.baseIdentifier)(\(renderForwardJavaParams(decl, paramPassingStyle: .wrapper))); - } - """ - ) - return - } - - printer.print( - """ - /** - * {@snippet lang=swift : - * \(/*TODO: make a printSnippet func*/decl.syntax ?? "") - * } - */ - public static \(returnTy) \(decl.baseIdentifier)(\(renderJavaParamDecls(decl, paramPassingStyle: paramPassingStyle))) { - var mh$ = \(decl.baseIdentifier).HANDLE; - try { - if (SwiftKit.TRACE_DOWNCALLS) { - SwiftKit.traceDowncall(\(renderForwardJavaParams(decl, paramPassingStyle: .memorySegment))); - } - \(maybeReturnCast) mh$.invokeExact(\(renderForwardJavaParams(decl, paramPassingStyle: paramPassingStyle))); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - } - """ - ) - } - - /// Given a function like `init(cap:name:)`, renders a name like `init_cap_name` - public func renderDescClassName(_ decl: ImportedFunc) -> String { - var ps: [String] = [decl.baseIdentifier] - var pCounter = 0 - - func nextUniqueParamName() -> String { - pCounter += 1 - return "p\(pCounter)" - } - - for p in decl.effectiveParameters(paramPassingStyle: nil) { - let param = "\(p.effectiveName ?? nextUniqueParamName())" - ps.append(param) - } - - let res = ps.joined(separator: "_") - return res - } - - /// Do we need to construct an inline confined arena for the duration of the downcall? - public func downcallNeedsConfinedArena(_ decl: ImportedFunc) -> Bool { - for p in decl.parameters { - // We need to detect if any of the parameters is a closure we need to prepare - // an upcall handle for. - if p.type.javaType.isSwiftClosure { - return true - } - - if p.type.javaType.isString { - return true - } - } - - return false - } - - public func renderTry(withArena: Bool) -> String { - if withArena { - "try (var arena = Arena.ofConfined()) {" - } else { - "try {" - } - } - - public func renderJavaParamDecls(_ decl: ImportedFunc, paramPassingStyle: SelfParameterVariant?) -> String { - var ps: [String] = [] - var pCounter = 0 - - func nextUniqueParamName() -> String { - pCounter += 1 - return "p\(pCounter)" - } - - for p in decl.effectiveParameters(paramPassingStyle: paramPassingStyle) { - let param = "\(p.type.javaType.description) \(p.effectiveName ?? nextUniqueParamName())" - ps.append(param) - } - - let res = ps.joined(separator: ", ") - return res - } - - // TODO: these are stateless, find new place for them? - public func renderSwiftParamDecls( - _ decl: ImportedFunc, - paramPassingStyle: SelfParameterVariant?, - style: ParameterVariant? = nil - ) -> String { - var ps: [String] = [] - var pCounter = 0 - - func nextUniqueParamName() -> String { - pCounter += 1 - return "p\(pCounter)" - } - - for p in decl.effectiveParameters(paramPassingStyle: paramPassingStyle) { - let firstName = p.firstName ?? "_" - let secondName = p.secondName ?? p.firstName ?? nextUniqueParamName() - - let paramTy: String = - if style == .cDeclThunk, p.type.javaType.isString { - "UnsafeMutablePointer" // TODO: is this ok? - } else if paramPassingStyle == .swiftThunkSelf { - "\(p.type.cCompatibleSwiftType)" - } else { - p.type.swiftTypeName.description - } - - let param = - if firstName == secondName { - // We have to do this to avoid a 'extraneous duplicate parameter name; 'number' already has an argument label' warning - "\(firstName): \(paramTy)" - } else { - "\(firstName) \(secondName): \(paramTy)" - } - ps.append(param) - } - - if paramPassingStyle == .swiftThunkSelf { - ps.append("_self: UnsafeMutableRawPointer") - } - - let res = ps.joined(separator: ", ") - return res - } - - public func renderUpcallHandles(_ decl: ImportedFunc) -> String { - var printer = CodePrinter() - for p in decl.parameters where p.type.javaType.isSwiftClosure { - if p.type.javaType == .javaLangRunnable { - let paramName = p.secondName ?? p.firstName ?? "_" - let handleDesc = p.type.javaType.prepareClosureDowncallHandle( - decl: decl, parameter: paramName) - printer.print(handleDesc) - } - } - - return printer.contents - } - - public func renderParameterDowncallConversions(_ decl: ImportedFunc) -> String { - var printer = CodePrinter() - for p in decl.parameters { - if p.type.javaType.isString { - printer.print( - """ - var \(p.effectiveValueName)$ = arena.allocateFrom(\(p.effectiveValueName)); - """ - ) - } - } - - return printer.contents - } - - public func renderForwardJavaParams( - _ decl: ImportedFunc, paramPassingStyle: SelfParameterVariant? - ) -> String { - var ps: [String] = [] - var pCounter = 0 - - func nextUniqueParamName() -> String { - pCounter += 1 - return "p\(pCounter)" - } - - for p in decl.effectiveParameters(paramPassingStyle: paramPassingStyle) { - // FIXME: fix the handling here we're already a memory segment - let param: String - if p.effectiveName == "self$" { - precondition(paramPassingStyle == .memorySegment) - param = "self$" - } else if p.type.javaType.isString { - // TODO: make this less one-off and maybe call it "was adapted"? - if paramPassingStyle == .wrapper { - // pass it raw, we're not performing adaptation here it seems as we're passing wrappers around - param = "\(p.effectiveValueName)" - } else { - param = "\(p.effectiveValueName)$" - } - } else { - param = "\(p.renderParameterForwarding() ?? nextUniqueParamName())" - } - ps.append(param) - } - - // Add the forwarding "self" - if paramPassingStyle == .wrapper && !decl.isInit { - ps.append("$memorySegment()") - } - - return ps.joined(separator: ", ") - } - - // TODO: these are stateless, find new place for them? - public func renderForwardSwiftParams( - _ decl: ImportedFunc, paramPassingStyle: SelfParameterVariant? - ) -> String { - var ps: [String] = [] - - for p in decl.effectiveParameters(paramPassingStyle: paramPassingStyle) { - if let firstName = p.firstName { - ps.append("\(firstName): \(p.effectiveValueName)") - } else { - ps.append("\(p.effectiveValueName)") - } - } - - return ps.joined(separator: ", ") - } - - public func printFunctionDescriptorValue( - _ printer: inout CodePrinter, - _ decl: ImportedFunc, - accessorKind: VariableAccessorKind? = nil - ) { - let fieldName = accessorKind.renderDescFieldName - printer.start("public static final FunctionDescriptor \(fieldName) = ") - - let isIndirectReturn = decl.isIndirectReturn - - let parameterLayoutDescriptors: [ForeignValueLayout] = javaMemoryLayoutDescriptors( - forParametersOf: decl, - paramPassingStyle: .pointer - ) - - if decl.returnType.javaType == .void || isIndirectReturn { - printer.print("FunctionDescriptor.ofVoid(") - printer.indent() - } else { - printer.print("FunctionDescriptor.of(") - printer.indent() - - // Write return type - let returnTyIsLastTy = decl.parameters.isEmpty && !decl.hasParent - if decl.isInit { - // when initializing, we return a pointer to the newly created object - printer.print( - "/* -> */\(ForeignValueLayout.SwiftPointer)", .parameterNewlineSeparator(returnTyIsLastTy) - ) - } else { - var returnDesc = decl.returnType.foreignValueLayout - returnDesc.inlineComment = " -> " - printer.print(returnDesc, .parameterNewlineSeparator(returnTyIsLastTy)) - } - } - - // Write all parameters (including synthesized ones, like self) - for (desc, isLast) in parameterLayoutDescriptors.withIsLast { - printer.print(desc, .parameterNewlineSeparator(isLast)) - } - - printer.outdent() - printer.print(");") - } - - package func printHeapObjectToStringMethod( + package func printToStringMethod( _ printer: inout CodePrinter, _ decl: ImportedNominalType ) { printer.print( """ @Override public String toString() { - return getClass().getSimpleName() + "(" + - SwiftKit.nameOfSwiftType($swiftType().$memorySegment(), true) + - ")@" + $memorySegment(); + return getClass().getSimpleName() + + "(" + + SwiftKit.nameOfSwiftType($swiftType().$memorySegment(), true) + + ")@" + + $memorySegment(); } """) } - } diff --git a/Sources/JExtractSwift/Swift2JavaTranslator.swift b/Sources/JExtractSwift/Swift2JavaTranslator.swift index 25fd3e44..c8ed5bbe 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator.swift @@ -42,6 +42,8 @@ public final class Swift2JavaTranslator { // ==== Output state + package var importedGlobalVariables: [ImportedFunc] = [] + package var importedGlobalFuncs: [ImportedFunc] = [] /// A mapping from Swift type names (e.g., A.B) over to the imported nominal @@ -50,9 +52,9 @@ public final class Swift2JavaTranslator { package var swiftStdlibTypes: SwiftStandardLibraryTypes - let symbolTable: SwiftSymbolTable + package let symbolTable: SwiftSymbolTable - var thunkNameRegistry: ThunkNameRegistry = ThunkNameRegistry() + package var thunkNameRegistry: ThunkNameRegistry = ThunkNameRegistry() /// The name of the Swift module being translated. var swiftModuleName: String { @@ -175,12 +177,15 @@ extension Swift2JavaTranslator { guard let swiftNominalDecl = swiftType.asNominalTypeDeclaration else { return nil } + + // Whether to import this extension? guard let nominalNode = symbolTable.parsedModule.nominalTypeSyntaxNodes[swiftNominalDecl] else { return nil } guard nominalNode.shouldImport(log: log) else { return nil } + return importedNominalType(swiftNominalDecl) } @@ -191,24 +196,7 @@ extension Swift2JavaTranslator { return alreadyImported } - // Determine the nominal type kind. - let kind: NominalTypeKind - switch nominal.kind { - case .actor: kind = .actor - case .class: kind = .class - case .enum: kind = .enum - case .struct: kind = .struct - default: return nil - } - - let importedNominal = ImportedNominalType( - swiftNominal: nominal, - javaType: .class( - package: javaPackage, - name: nominal.qualifiedName - ), - kind: kind - ) + let importedNominal = ImportedNominalType(swiftNominal: nominal) importedTypes[fullName] = importedNominal return importedNominal diff --git a/Sources/JExtractSwift/Swift2JavaVisitor.swift b/Sources/JExtractSwift/Swift2JavaVisitor.swift index 3df49782..e51a7115 100644 --- a/Sources/JExtractSwift/Swift2JavaVisitor.swift +++ b/Sources/JExtractSwift/Swift2JavaVisitor.swift @@ -32,6 +32,11 @@ final class Swift2JavaVisitor: SyntaxVisitor { /// Innermost type context. var currentType: ImportedNominalType? { typeContext.last?.type } + var currentSwiftType: SwiftType? { + guard let currentType else { return nil } + return .nominal(SwiftNominalType(nominalTypeDecl: currentType.swiftNominal)) + } + /// The current type name as a nested name like A.B.C. var currentTypeName: String? { self.currentType?.swiftNominal.qualifiedName } @@ -114,49 +119,33 @@ final class Swift2JavaVisitor: SyntaxVisitor { return .skipChildren } - self.log.debug("Import function: \(node.kind) \(node.name)") - - let returnTy: TypeSyntax - if let returnClause = node.signature.returnClause { - returnTy = returnClause.type - } else { - returnTy = "Swift.Void" - } + self.log.debug("Import function: '\(node.qualifiedNameForDebug)'") - let params: [ImportedParam] - let javaResultType: TranslatedType + let translatedSignature: TranslatedFunctionSignature do { - params = try node.signature.parameterClause.parameters.map { param in - // TODO: more robust parameter handling - // TODO: More robust type handling - ImportedParam( - syntax: param, - type: try cCompatibleType(for: param.type) - ) - } - - javaResultType = try cCompatibleType(for: returnTy) + let swiftSignature = try SwiftFunctionSignature( + node, + enclosingType: self.currentSwiftType, + symbolTable: self.translator.symbolTable + ) + translatedSignature = try translator.translate(swiftSignature: swiftSignature, as: .function) } catch { - self.log.info("Unable to import function \(node.name) - \(error)") + self.log.debug("Failed to translate: '\(node.qualifiedNameForDebug)'; \(error)") return .skipChildren } - let fullName = "\(node.name.text)" - - let funcDecl = ImportedFunc( - module: self.translator.swiftModuleName, - decl: node.trimmed, - parent: currentTypeName.map { translator.importedTypes[$0] }??.translatedType, - identifier: fullName, - returnType: javaResultType, - parameters: params + let imported = ImportedFunc( + module: translator.swiftModuleName, + swiftDecl: node, + name: node.name.text, + translatedSignature: translatedSignature ) - if let currentTypeName { - log.debug("Record method in \(currentTypeName)") - translator.importedTypes[currentTypeName]?.methods.append(funcDecl) + log.debug("Record imported method \(node.qualifiedNameForDebug)") + if let currentType { + currentType.methods.append(imported) } else { - translator.importedGlobalFuncs.append(funcDecl) + translator.importedGlobalFuncs.append(imported) } return .skipChildren @@ -171,54 +160,58 @@ final class Swift2JavaVisitor: SyntaxVisitor { return .skipChildren } - let fullName = "\(binding.pattern.trimmed)" - - // TODO: filter out kinds of variables we cannot import + let varName = "\(binding.pattern.trimmed)" self.log.debug("Import variable: \(node.kind) '\(node.qualifiedNameForDebug)'") - let returnTy: TypeSyntax - if let typeAnnotation = binding.typeAnnotation { - returnTy = typeAnnotation.type - } else { - returnTy = "Swift.Void" + func importAccessor(kind: SwiftAPIKind) throws { + let translatedSignature: TranslatedFunctionSignature + do { + let swiftSignature = try SwiftFunctionSignature( + node, + isSet: kind == .setter, + enclosingType: self.currentSwiftType, + symbolTable: self.translator.symbolTable + ) + translatedSignature = try translator.translate(swiftSignature: swiftSignature, as: kind) + } catch { + self.log.debug("Failed to translate: \(node.qualifiedNameForDebug); \(error)") + throw error + } + + let imported = ImportedFunc( + module: translator.swiftModuleName, + swiftDecl: node, + name: varName, + translatedSignature: translatedSignature + ) + + log.debug("Record imported variable accessor \(kind == .getter ? "getter" : "setter"):\(node.qualifiedNameForDebug)") + if let currentType { + currentType.variables.append(imported) + } else { + translator.importedGlobalVariables.append(imported) + } } - let javaResultType: TranslatedType do { - javaResultType = try cCompatibleType(for: returnTy) + let supportedAccessors = node.supportedAccessorKinds(binding: binding) + if supportedAccessors.contains(.get) { + try importAccessor(kind: .getter) + } + if supportedAccessors.contains(.set) { + try importAccessor(kind: .setter) + } } catch { - log.info("Unable to import variable '\(node.qualifiedNameForDebug)' - \(error)") + self.log.debug("Failed to translate: \(node.qualifiedNameForDebug); \(error)") return .skipChildren } - var varDecl = ImportedVariable( - module: self.translator.swiftModuleName, - parentName: currentTypeName.map { translator.importedTypes[$0] }??.translatedType, - identifier: fullName, - returnType: javaResultType - ) - varDecl.syntax = node.trimmed - - // Retrieve the mangled name, if available. - if let mangledName = node.mangledNameFromComment { - varDecl.swiftMangledName = mangledName - } - - if let currentTypeName { - log.debug("Record variable in \(currentTypeName)") - translator.importedTypes[currentTypeName]!.variables.append(varDecl) - } else { - fatalError("Global variables are not supported yet: \(node.qualifiedNameForDebug)") - } - return .skipChildren } override func visit(_ node: InitializerDeclSyntax) -> SyntaxVisitorContinueKind { - guard let currentTypeName, - let currentType = translator.importedTypes[currentTypeName] - else { + guard let currentType else { fatalError("Initializer must be within a current type, was: \(node)") } guard node.shouldImport(log: log) else { @@ -226,37 +219,27 @@ final class Swift2JavaVisitor: SyntaxVisitor { } self.log.debug("Import initializer: \(node.kind) '\(node.qualifiedNameForDebug)'") - let params: [ImportedParam] + + let translatedSignature: TranslatedFunctionSignature do { - params = try node.signature.parameterClause.parameters.map { param in - // TODO: more robust parameter handling - // TODO: More robust type handling - return ImportedParam( - syntax: param, - type: try cCompatibleType(for: param.type) - ) - } + let swiftSignature = try SwiftFunctionSignature( + node, + enclosingType: self.currentSwiftType, + symbolTable: self.translator.symbolTable + ) + translatedSignature = try translator.translate(swiftSignature: swiftSignature, as: .initializer) } catch { - self.log.info("Unable to import initializer due to \(error)") + self.log.debug("Failed to translate: \(node.qualifiedNameForDebug); \(error)") return .skipChildren } - - let initIdentifier = - "init(\(String(params.flatMap { "\($0.effectiveName ?? "_"):" })))" - - var funcDecl = ImportedFunc( - module: self.translator.swiftModuleName, - decl: node.trimmed, - parent: currentType.translatedType, - identifier: initIdentifier, - returnType: currentType.translatedType, - parameters: params + let imported = ImportedFunc( + module: translator.swiftModuleName, + swiftDecl: node, + name: "init", + translatedSignature: translatedSignature ) - funcDecl.isInit = true - log.debug( - "Record initializer method in \(currentType.javaType.description): \(funcDecl.identifier)") - translator.importedTypes[currentTypeName]!.initializers.append(funcDecl) + currentType.initializers.append(imported) return .skipChildren } @@ -289,23 +272,3 @@ extension DeclSyntaxProtocol where Self: WithModifiersSyntax & WithAttributesSyn return true } } - -private let mangledNameCommentPrefix = "MANGLED NAME: " - -extension SyntaxProtocol { - /// Look in the comment text prior to the node to find a mangled name - /// identified by "// MANGLED NAME: ". - var mangledNameFromComment: String? { - for triviaPiece in leadingTrivia { - guard case .lineComment(let comment) = triviaPiece, - let matchRange = comment.range(of: mangledNameCommentPrefix) - else { - continue - } - - return String(comment[matchRange.upperBound...]) - } - - return nil - } -} diff --git a/Sources/JExtractSwift/SwiftThunkTranslator.swift b/Sources/JExtractSwift/SwiftThunkTranslator.swift index f72f0c58..5676e3d5 100644 --- a/Sources/JExtractSwift/SwiftThunkTranslator.swift +++ b/Sources/JExtractSwift/SwiftThunkTranslator.swift @@ -12,10 +12,101 @@ // //===----------------------------------------------------------------------===// -import Foundation -import SwiftBasicFormat -import SwiftParser import SwiftSyntax +import SwiftSyntaxBuilder + +extension Swift2JavaTranslator { + public func writeSwiftThunkSources(outputDirectory: String) throws { + var printer = CodePrinter() + + try writeSwiftThunkSources(outputDirectory: outputDirectory, printer: &printer) + } + + public func writeSwiftThunkSources(outputDirectory: String, printer: inout CodePrinter) throws { + let moduleFilenameBase = "\(self.swiftModuleName)Module+SwiftJava" + let moduleFilename = "\(moduleFilenameBase).swift" + do { + log.info("Printing contents: \(moduleFilename)") + + try printGlobalSwiftThunkSources(&printer) + + if let outputFile = try printer.writeContents( + outputDirectory: outputDirectory, + javaPackagePath: nil, + filename: moduleFilename) + { + print("[swift-java] Generated: \(moduleFilenameBase.bold).swift (at \(outputFile)") + } + } catch { + log.warning("Failed to write to Swift thunks: \(moduleFilename)") + } + + // === All types + for (_, ty) in importedTypes.sorted(by: { (lhs, rhs) in lhs.key < rhs.key }) { + let fileNameBase = "\(ty.swiftNominal.qualifiedName)+SwiftJava" + let filename = "\(fileNameBase).swift" + log.info("Printing contents: \(filename)") + + do { + try printSwiftThunkSources(&printer, ty: ty) + + if let outputFile = try printer.writeContents( + outputDirectory: outputDirectory, + javaPackagePath: nil, + filename: filename) + { + print("[swift-java] Generated: \(fileNameBase.bold).swift (at \(outputFile)") + } + } catch { + log.warning("Failed to write to Swift thunks: \(filename)") + } + } + } + + public func printGlobalSwiftThunkSources(_ printer: inout CodePrinter) throws { + let stt = SwiftThunkTranslator(self) + + printer.print( + """ + // Generated by swift-java + + import SwiftKitSwift + + """) + + for thunk in stt.renderGlobalThunks() { + printer.print(thunk) + printer.println() + } + } + + public func printSwiftThunkSources(_ printer: inout CodePrinter, decl: ImportedFunc) { + let stt = SwiftThunkTranslator(self) + + for thunk in stt.render(forFunc: decl) { + printer.print(thunk) + printer.println() + } + } + + package func printSwiftThunkSources(_ printer: inout CodePrinter, ty: ImportedNominalType) throws { + let stt = SwiftThunkTranslator(self) + + printer.print( + """ + // Generated by swift-java + + import SwiftKitSwift + + """ + ) + + for thunk in stt.renderThunks(forType: ty) { + printer.print("\(thunk)") + printer.print("") + } + } +} struct SwiftThunkTranslator { @@ -27,6 +118,13 @@ struct SwiftThunkTranslator { func renderGlobalThunks() -> [DeclSyntax] { var decls: [DeclSyntax] = [] + decls.reserveCapacity( + st.importedGlobalVariables.count + st.importedGlobalFuncs.count + ) + + for decl in st.importedGlobalVariables { + decls.append(contentsOf: render(forFunc: decl)) + } for decl in st.importedGlobalFuncs { decls.append(contentsOf: render(forFunc: decl)) @@ -38,27 +136,23 @@ struct SwiftThunkTranslator { /// Render all the thunks that make Swift methods accessible to Java. func renderThunks(forType nominal: ImportedNominalType) -> [DeclSyntax] { var decls: [DeclSyntax] = [] - decls.reserveCapacity(nominal.initializers.count + nominal.methods.count) + decls.reserveCapacity( + 1 + nominal.initializers.count + nominal.variables.count + nominal.methods.count + ) decls.append(renderSwiftTypeAccessor(nominal)) for decl in nominal.initializers { - decls.append(contentsOf: renderSwiftInitAccessor(decl)) + decls.append(contentsOf: render(forFunc: decl)) } - for decl in nominal.methods { + for decl in nominal.variables { decls.append(contentsOf: render(forFunc: decl)) } - // TODO: handle variables - // for v in nominal.variables { - // if let acc = v.accessorFunc(kind: .get) { - // decls.append(contentsOf: render(forFunc: acc)) - // } - // if let acc = v.accessorFunc(kind: .set) { - // decls.append(contentsOf: render(forFunc: acc)) - // } - // } + for decl in nominal.methods { + decls.append(contentsOf: render(forFunc: decl)) + } return decls } @@ -78,107 +172,14 @@ struct SwiftThunkTranslator { """ } - func renderSwiftInitAccessor(_ function: ImportedFunc) -> [DeclSyntax] { - guard let parent = function.parent else { - fatalError( - "Cannot render initializer accessor if init function has no parent! Was: \(function)") - } - - let thunkName = self.st.thunkNameRegistry.functionThunkName( - module: st.swiftModuleName, decl: function) - - let cDecl = - """ - @_cdecl("\(thunkName)") - """ - let typeName = "\(parent.swiftTypeName)" - - return [ - """ - \(raw: cDecl) - public func \(raw: thunkName)( - \(raw: st.renderSwiftParamDecls(function, paramPassingStyle: nil)), - resultBuffer: /* \(raw: typeName) */ UnsafeMutableRawPointer - ) { - var _self = \(raw: typeName)(\(raw: st.renderForwardSwiftParams(function, paramPassingStyle: nil))) - resultBuffer.assumingMemoryBound(to: \(raw: typeName).self).initialize(to: _self) - } - """ - ] - } - func render(forFunc decl: ImportedFunc) -> [DeclSyntax] { - st.log.trace("Rendering thunks for: \(decl.baseIdentifier)") - let thunkName = st.thunkNameRegistry.functionThunkName(module: st.swiftModuleName, decl: decl) - - let returnArrowTy = - if decl.returnType.cCompatibleJavaMemoryLayout == .primitive(.void) { - "/* \(decl.returnType.swiftTypeName) */" - } else { - "-> \(decl.returnType.cCompatibleSwiftType) /* \(decl.returnType.swiftTypeName) */" - } - - // Do we need to pass a self parameter? - let paramPassingStyle: SelfParameterVariant? - let callBase: String - let callBaseDot: String - if let parent = decl.parent { - paramPassingStyle = .swiftThunkSelf - callBase = - "var self$ = _self.assumingMemoryBound(to: \(parent.originalSwiftType).self).pointee" - callBaseDot = "self$." - } else { - paramPassingStyle = nil - callBase = "" - callBaseDot = "" - } - - // FIXME: handle in thunk: errors - - let returnStatement: String - if decl.returnType.javaType.isString { - returnStatement = - """ - let adaptedReturnValue = fatalError("Not implemented: adapting return types in Swift thunks") - return adaptedReturnValue - """ - } else { - returnStatement = "return returnValue" - } - - let declParams = st.renderSwiftParamDecls( - decl, - paramPassingStyle: paramPassingStyle, - style: .cDeclThunk + st.log.trace("Rendering thunks for: \(decl.displayName)") + let thunkName = st.thunkNameRegistry.functionThunkName(decl: decl) + let thunkFunc = decl.loweredSignature.cdeclThunk( + cName: thunkName, + swiftAPIName: decl.name, + stdlibTypes: st.swiftStdlibTypes ) - return - [ - """ - @_cdecl("\(raw: thunkName)") - public func \(raw: thunkName)(\(raw: declParams)) \(raw: returnArrowTy) { - \(raw: adaptArgumentsInThunk(decl)) - \(raw: callBase) - let returnValue = \(raw: callBaseDot)\(raw: decl.baseIdentifier)(\(raw: st.renderForwardSwiftParams(decl, paramPassingStyle: paramPassingStyle))) - \(raw: returnStatement) - } - """ - ] - } - - func adaptArgumentsInThunk(_ decl: ImportedFunc) -> String { - var lines: [String] = [] - for p in decl.parameters { - if p.type.javaType.isString { - // FIXME: is there a way we can avoid the copying here? - let adaptedType = - """ - let \(p.effectiveValueName) = String(cString: \(p.effectiveValueName)) - """ - - lines += [adaptedType] - } - } - - return lines.joined(separator: "\n") + return [DeclSyntax(thunkFunc)] } } diff --git a/Sources/JExtractSwift/SwiftTypes/SwiftType.swift b/Sources/JExtractSwift/SwiftTypes/SwiftType.swift index 4e17e32d..5b0d8961 100644 --- a/Sources/JExtractSwift/SwiftTypes/SwiftType.swift +++ b/Sources/JExtractSwift/SwiftTypes/SwiftType.swift @@ -290,3 +290,14 @@ extension SwiftType { return "\(type).self" } } + +enum TypeTranslationError: Error { + /// We haven't yet implemented support for this type. + case unimplementedType(TypeSyntax) + + /// Missing generic arguments. + case missingGenericArguments(TypeSyntax) + + /// Unknown nominal type. + case unknown(TypeSyntax) +} diff --git a/Sources/JExtractSwift/ThunkNameRegistry.swift b/Sources/JExtractSwift/ThunkNameRegistry.swift index 92f1397d..87bf1d70 100644 --- a/Sources/JExtractSwift/ThunkNameRegistry.swift +++ b/Sources/JExtractSwift/ThunkNameRegistry.swift @@ -12,8 +12,6 @@ // //===----------------------------------------------------------------------===// -import SwiftSyntax - /// Registry of names we've already emitted as @_cdecl and must be kept unique. /// In order to avoid duplicate symbols, the registry can append some unique identifier to duplicated names package struct ThunkNameRegistry { @@ -25,28 +23,30 @@ package struct ThunkNameRegistry { package init() {} package mutating func functionThunkName( - module: String, decl: ImportedFunc, - file: String = #fileID, line: UInt = #line) -> String { + decl: ImportedFunc, + file: String = #fileID, line: UInt = #line + ) -> String { if let existingName = self.registry[decl] { return existingName } - let params = decl.effectiveParameters(paramPassingStyle: .swiftThunkSelf) - var paramsPart = "" - if !params.isEmpty { - paramsPart = "_" + params.map { param in - param.firstName ?? "_" - }.joined(separator: "_") + let suffix: String + switch decl.kind { + case .getter: + suffix = "$get" + case .setter: + suffix = "$set" + default: + suffix = decl.swiftSignature.parameters + .map { "_" + ($0.argumentLabel ?? "_") } + .joined() } - - - let name = - if let parent = decl.parent { - "swiftjava_\(module)_\(parent.swiftTypeName)_\(decl.baseIdentifier)\(paramsPart)" - } else { - "swiftjava_\(module)_\(decl.baseIdentifier)\(paramsPart)" - } + let name = if let parent = decl.parentType { + "swiftjava_\(decl.module)_\(parent)_\(decl.name)\(suffix)" + } else { + "swiftjava_\(decl.module)_\(decl.name)\(suffix)" + } let emittedCount = self.duplicateNames[name, default: 0] defer { self.duplicateNames[name] = emittedCount + 1 } diff --git a/Sources/JExtractSwift/TranslatedType.swift b/Sources/JExtractSwift/TranslatedType.swift deleted file mode 100644 index 19c38ce6..00000000 --- a/Sources/JExtractSwift/TranslatedType.swift +++ /dev/null @@ -1,332 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of Swift.org project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -import JavaTypes -import SwiftSyntax - -extension Swift2JavaVisitor { - /// Produce the C-compatible type for the given type, or throw an error if - /// there is no such type. - func cCompatibleType(for type: TypeSyntax) throws -> TranslatedType { - switch type.as(TypeSyntaxEnum.self) { - case .arrayType, .attributedType, .classRestrictionType, .compositionType, - .dictionaryType, .implicitlyUnwrappedOptionalType, .metatypeType, - .missingType, .namedOpaqueReturnType, - .optionalType, .packElementType, .packExpansionType, .someOrAnyType, - .suppressedType, .tupleType: - throw TypeTranslationError.unimplementedType(type) - - case .functionType(let functionType): - // FIXME: Temporary hack to keep existing code paths working. - if functionType.trimmedDescription == "() -> ()" { - return TranslatedType( - cCompatibleConvention: .direct, - originalSwiftType: type, - originalSwiftTypeKind: .function, - cCompatibleSwiftType: "@convention(c) () -> Void", - cCompatibleJavaMemoryLayout: .cFunction, - javaType: .javaLangRunnable - ) - } - - throw TypeTranslationError.unimplementedType(type) - - case .memberType(let memberType): - // If the parent type isn't a known module, translate it. - // FIXME: Need a more reasonable notion of which names are module names - // for this to work. - let parentType: TranslatedType? - if memberType.baseType.trimmedDescription == "Swift" { - parentType = nil - } else { - parentType = try cCompatibleType(for: memberType.baseType) - } - - // Translate the generic arguments to the C-compatible types. - let genericArgs = try memberType.genericArgumentClause.map { genericArgumentClause in - try genericArgumentClause.arguments.map { argument in - try cCompatibleType(for: argument.argument) - } - } - - // Resolve the C-compatible type by name. - return try translateType( - for: type, - parent: parentType, - name: memberType.name.text, - kind: nil, - genericArguments: genericArgs - ) - - case .identifierType(let identifierType): - // Translate the generic arguments to the C-compatible types. - let genericArgs = try identifierType.genericArgumentClause.map { genericArgumentClause in - try genericArgumentClause.arguments.map { argument in - try cCompatibleType(for: argument.argument) - } - } - - // Resolve the C-compatible type by name. - return try translateType( - for: type, - parent: nil, - name: identifierType.name.text, - kind: nil, - genericArguments: genericArgs - ) - } - } - - /// Produce the C compatible type by performing name lookup on the Swift type. - func translateType( - for type: TypeSyntax, - parent: TranslatedType?, - name: String, - kind: NominalTypeKind?, - genericArguments: [TranslatedType]? - ) throws -> TranslatedType { - // Look for a primitive type with this name. - if parent == nil, let primitiveType = JavaType(swiftTypeName: name) { - return TranslatedType( - cCompatibleConvention: .direct, - originalSwiftType: "\(raw: name)", - originalSwiftTypeKind: .primitive, - cCompatibleSwiftType: "Swift.\(raw: name)", - cCompatibleJavaMemoryLayout: .primitive(primitiveType), - javaType: primitiveType - ) - } - - // If this is the Swift "Int" type, it's primitive in Java but might - // map to either "int" or "long" depending whether the platform is - // 32-bit or 64-bit. - if parent == nil, name == "Int" { - return TranslatedType( - cCompatibleConvention: .direct, - originalSwiftType: "\(raw: name)", - originalSwiftTypeKind: .primitive, - cCompatibleSwiftType: "Swift.\(raw: name)", - cCompatibleJavaMemoryLayout: .int, - javaType: translator.javaPrimitiveForSwiftInt - ) - } - - // We special handle String types - if parent == nil, name == "String" { - return TranslatedType( - cCompatibleConvention: .direct, - originalSwiftType: "\(raw: name)", - originalSwiftTypeKind: kind, - cCompatibleSwiftType: "Swift.\(raw: name)", - cCompatibleJavaMemoryLayout: .heapObject, // FIXME: or specialize string? - javaType: .javaLangString - ) - } - - // Identify the various pointer types from the standard library. - if let (requiresArgument, _, hasCount) = name.isNameOfSwiftPointerType, !hasCount { - // Dig out the pointee type if needed. - if requiresArgument { - guard let genericArguments else { - throw TypeTranslationError.missingGenericArguments(type) - } - - guard genericArguments.count == 1 else { - throw TypeTranslationError.missingGenericArguments(type) - } - } else if let genericArguments { - throw TypeTranslationError.unexpectedGenericArguments(type, genericArguments) - } - - return TranslatedType( - cCompatibleConvention: .direct, - originalSwiftType: type, - cCompatibleSwiftType: "UnsafeMutableRawPointer", - cCompatibleJavaMemoryLayout: .heapObject, - javaType: .javaForeignMemorySegment - ) - } - - // FIXME: Generic types aren't mapped into Java. - if let genericArguments { - throw TypeTranslationError.unexpectedGenericArguments(type, genericArguments) - } - - // Look up the imported types by name to resolve it to a nominal type. - guard let importedNominal = translator.importedNominalType(type) else { - throw TypeTranslationError.unknown(type) - } - - return importedNominal.translatedType - } -} - -extension String { - /// Determine whether this string names one of the Swift pointer types. - /// - /// - Returns: a tuple describing three pieces of information: - /// 1. Whether the pointer type requires a generic argument for the - /// pointee. - /// 2. Whether the memory referenced by the pointer is mutable. - /// 3. Whether the pointer type has a `count` property describing how - /// many elements it points to. - var isNameOfSwiftPointerType: (requiresArgument: Bool, mutable: Bool, hasCount: Bool)? { - switch self { - case "COpaquePointer", "UnsafeRawPointer": - return (requiresArgument: false, mutable: true, hasCount: false) - - case "UnsafeMutableRawPointer": - return (requiresArgument: false, mutable: true, hasCount: false) - - case "UnsafePointer": - return (requiresArgument: true, mutable: false, hasCount: false) - - case "UnsafeMutablePointer": - return (requiresArgument: true, mutable: true, hasCount: false) - - case "UnsafeBufferPointer": - return (requiresArgument: true, mutable: false, hasCount: true) - - case "UnsafeMutableBufferPointer": - return (requiresArgument: true, mutable: false, hasCount: true) - - case "UnsafeRawBufferPointer": - return (requiresArgument: false, mutable: false, hasCount: true) - - case "UnsafeMutableRawBufferPointer": - return (requiresArgument: false, mutable: true, hasCount: true) - - default: - return nil - } - } -} - -enum ParameterConvention { - case direct - case indirect -} - -public struct TranslatedType { - /// How a parameter of this type will be passed through C functions. - var cCompatibleConvention: ParameterConvention - - /// The original Swift type, as written in the source. - var originalSwiftType: TypeSyntax - - /// - var originalSwiftTypeKind: NominalTypeKind? - - /// The C-compatible Swift type that should be used in any C -> Swift thunks - /// emitted in Swift. - var cCompatibleSwiftType: TypeSyntax - - /// The Java MemoryLayout constant that is used to describe the layout of - /// the type in memory. - var cCompatibleJavaMemoryLayout: CCompatibleJavaMemoryLayout - - /// The Java type that is used to present these values in Java. - var javaType: JavaType - - /// Produce a Swift type name to reference this type. - var swiftTypeName: String { - originalSwiftType.trimmedDescription - } - - /// Produce the "unqualified" Java type name. - var unqualifiedJavaTypeName: String { - switch javaType { - case .class(package: _, let name): name - default: javaType.description - } - } - - var isReferenceType: Bool { - originalSwiftTypeKind == .class || originalSwiftTypeKind == .actor - } - - var isValueType: Bool { - originalSwiftTypeKind == .struct || originalSwiftTypeKind == .enum - } -} - -extension TranslatedType { - public static var void: Self { - TranslatedType( - cCompatibleConvention: .direct, - originalSwiftType: "Void", - originalSwiftTypeKind: .void, - cCompatibleSwiftType: "Swift.Void", - cCompatibleJavaMemoryLayout: .primitive(.void), - javaType: JavaType.void) - } -} - -/// Describes the C-compatible layout as it should be referenced from Java. -enum CCompatibleJavaMemoryLayout: Hashable { - /// A primitive Java type that has a direct counterpart in C. - case primitive(JavaType) - - /// The Swift "Int" type, which may be either a Java int (32-bit platforms) or - /// Java long (64-bit platforms). - case int - - /// A Swift heap object, which is treated as a pointer for interoperability - /// purposes but must be retained/released to keep it alive. - case heapObject - - /// A C function pointer. In Swift, this will be a @convention(c) function. - /// In Java, a downcall handle to a function. - case cFunction -} - -enum SwiftTypeKind { - case `class` - case `actor` - case `enum` - case `struct` - case primitive - case `void` -} - -extension TranslatedType { - /// Determine the foreign value layout to use for the translated type with - /// the Java Foreign Function and Memory API. - var foreignValueLayout: ForeignValueLayout { - switch cCompatibleJavaMemoryLayout { - case .primitive(let javaType): - return ForeignValueLayout(javaType: javaType)! - - case .int: - return .SwiftInt - - case .heapObject, .cFunction: - return .SwiftPointer - } - } -} - -enum TypeTranslationError: Error { - /// We haven't yet implemented support for this type. - case unimplementedType(TypeSyntax) - - /// Unexpected generic arguments. - case unexpectedGenericArguments(TypeSyntax, [TranslatedType]) - - /// Missing generic arguments. - case missingGenericArguments(TypeSyntax) - - /// Unknown nominal type. - case unknown(TypeSyntax) -} diff --git a/Tests/JExtractSwiftTests/ClassPrintingTests.swift b/Tests/JExtractSwiftTests/ClassPrintingTests.swift index 768f1480..94cd8a40 100644 --- a/Tests/JExtractSwiftTests/ClassPrintingTests.swift +++ b/Tests/JExtractSwiftTests/ClassPrintingTests.swift @@ -54,7 +54,7 @@ struct ClassPrintingTests { return TYPE_METADATA; } - private static final GroupLayout $LAYOUT = (GroupLayout) SwiftValueWitnessTable.layoutOfSwiftType(TYPE_METADATA.$memorySegment()); + public static final GroupLayout $LAYOUT = (GroupLayout) SwiftValueWitnessTable.layoutOfSwiftType(TYPE_METADATA.$memorySegment()); public final GroupLayout $layout() { return $LAYOUT; } diff --git a/Tests/JExtractSwiftTests/FuncCallbackImportTests.swift b/Tests/JExtractSwiftTests/FuncCallbackImportTests.swift index 739cbb79..4bcb4e05 100644 --- a/Tests/JExtractSwiftTests/FuncCallbackImportTests.swift +++ b/Tests/JExtractSwiftTests/FuncCallbackImportTests.swift @@ -29,7 +29,6 @@ final class FuncCallbackImportTests { import _StringProcessing import _SwiftConcurrencyShims - // MANGLED NAME: $mockName public func callMe(callback: () -> ()) """ @@ -43,10 +42,10 @@ final class FuncCallbackImportTests { try st.analyze(file: "Fake.swift", text: Self.class_interfaceFile) - let funcDecl = st.importedGlobalFuncs.first { $0.baseIdentifier == "callMe" }! + let funcDecl = st.importedGlobalFuncs.first { $0.name == "callMe" }! let output = CodePrinter.toString { printer in - st.printFuncDowncallMethod(&printer, decl: funcDecl, paramPassingStyle: nil) + st.printFuncDowncallMethod(&printer, funcDecl) } assertOutput( @@ -60,23 +59,16 @@ final class FuncCallbackImportTests { * } */ public static void callMe(java.lang.Runnable callback) { - var mh$ = callMe.HANDLE; - try (var arena = Arena.ofConfined()) { - FunctionDescriptor callMe_callback_desc$ = FunctionDescriptor.ofVoid(); - MethodHandle callMe_callback_handle$ = MethodHandles.lookup() - .findVirtual(Runnable.class, "run", - callMe_callback_desc$.toMethodType()); - callMe_callback_handle$ = callMe_callback_handle$.bindTo(callback); - Linker linker = Linker.nativeLinker(); - MemorySegment callback$ = linker.upcallStub(callMe_callback_handle$, callMe_callback_desc$, arena); - if (SwiftKit.TRACE_DOWNCALLS) { - SwiftKit.traceDowncall(callback$); - } - - mh$.invokeExact(callback$); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + var mh$ = swiftjava___FakeModule_callMe_callback.HANDLE; + try(var arena$ = Arena.ofConfined()) { + var callback$ = SwiftKit.toUpcallStub(callback, arena$); + if (SwiftKit.TRACE_DOWNCALLS) { + SwiftKit.traceDowncall(callback$); } + mh$.invokeExact(callback$); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } } """ ) diff --git a/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift b/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift index 5c190388..dea63d4e 100644 --- a/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift +++ b/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift @@ -29,26 +29,17 @@ final class FunctionDescriptorTests { import _StringProcessing import _SwiftConcurrencyShims - // MANGLED NAME: $s14MySwiftLibrary10helloWorldyyF public func helloWorld() - // MANGLED NAME: $s14MySwiftLibrary13globalTakeInt1iySi_tF public func globalTakeInt(i: Swift.Int) - // MANGLED NAME: $s14MySwiftLibrary23globalTakeLongIntString1l3i321sys5Int64V_s5Int32VSStF public func globalTakeLongInt(l: Int64, i32: Int32) - // MANGLED NAME: $s14MySwiftLibrary7echoInt1iS2i_tFs public func echoInt(i: Int) -> Int - // MANGLED NAME: $s14MySwiftLibrary0aB5ClassCMa public class MySwiftClass { - // MANGLED NAME: $s14MySwiftLibrary0aB5ClassC3len3capACSi_SitcfC public init(len: Swift.Int, cap: Swift.Int) @objc deinit - // #MySwiftClass.counter!getter: (MySwiftClass) -> () -> Int32 : @$s14MySwiftLibrary0aB5ClassC7counters5Int32Vvg\t// MySwiftClass.counter.getter - // #MySwiftClass.counter!setter: (MySwiftClass) -> (Int32) -> () : @$s14MySwiftLibrary0aB5ClassC7counters5Int32Vvs\t// MySwiftClass.counter.setter - // #MySwiftClass.counter!modify: (MySwiftClass) -> () -> () : @$s14MySwiftLibrary0aB5ClassC7counters5Int32VvM\t// MySwiftClass.counter.modify public var counter: Int32 } """ @@ -61,7 +52,7 @@ final class FunctionDescriptorTests { expected: """ public static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( - /*i*/SwiftValueLayout.SWIFT_INT + /* i: */SwiftValueLayout.SWIFT_INT ); """ ) @@ -76,8 +67,8 @@ final class FunctionDescriptorTests { expected: """ public static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( - /*l*/SwiftValueLayout.SWIFT_INT64, - /*i32*/SwiftValueLayout.SWIFT_INT32 + /* l: */SwiftValueLayout.SWIFT_INT64, + /* i32: */SwiftValueLayout.SWIFT_INT32 ); """ ) @@ -93,7 +84,7 @@ final class FunctionDescriptorTests { """ public static final FunctionDescriptor DESC = FunctionDescriptor.of( /* -> */SwiftValueLayout.SWIFT_INT, - /*i*/SwiftValueLayout.SWIFT_INT + /* i: */SwiftValueLayout.SWIFT_INT ); """ ) @@ -102,14 +93,14 @@ final class FunctionDescriptorTests { @Test func FunctionDescriptor_class_counter_get() throws { - try variableAccessorDescriptorTest("counter", .get) { output in + try variableAccessorDescriptorTest("counter", .getter) { output in assertOutput( output, expected: """ - public static final FunctionDescriptor DESC_GET = FunctionDescriptor.of( + public static final FunctionDescriptor DESC = FunctionDescriptor.of( /* -> */SwiftValueLayout.SWIFT_INT32, - /*self$*/SwiftValueLayout.SWIFT_POINTER + /* self: */SwiftValueLayout.SWIFT_POINTER ); """ ) @@ -117,14 +108,14 @@ final class FunctionDescriptorTests { } @Test func FunctionDescriptor_class_counter_set() throws { - try variableAccessorDescriptorTest("counter", .set) { output in + try variableAccessorDescriptorTest("counter", .setter) { output in assertOutput( output, expected: """ - public static final FunctionDescriptor DESC_SET = FunctionDescriptor.ofVoid( - /*newValue*/SwiftValueLayout.SWIFT_INT32, - /*self$*/SwiftValueLayout.SWIFT_POINTER + public static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( + /* newValue: */SwiftValueLayout.SWIFT_INT32, + /* self: */SwiftValueLayout.SWIFT_POINTER ); """ ) @@ -151,11 +142,13 @@ extension FunctionDescriptorTests { try st.analyze(file: "/fake/Sample.swiftinterface", text: interfaceFile) let funcDecl = st.importedGlobalFuncs.first { - $0.baseIdentifier == methodIdentifier + $0.name == methodIdentifier }! + let thunkName = st.thunkNameRegistry.functionThunkName(decl: funcDecl) + let cFunc = funcDecl.cFunctionDecl(cName: thunkName) let output = CodePrinter.toString { printer in - st.printFunctionDescriptorValue(&printer, funcDecl) + st.printFunctionDescriptorValue(&printer, cFunc) } try body(output) @@ -163,7 +156,7 @@ extension FunctionDescriptorTests { func variableAccessorDescriptorTest( _ identifier: String, - _ accessorKind: VariableAccessorKind, + _ accessorKind: SwiftAPIKind, javaPackage: String = "com.example.swift", swiftModuleName: String = "SwiftModule", logLevel: Logger.Level = .trace, @@ -177,22 +170,22 @@ extension FunctionDescriptorTests { try st.analyze(file: "/fake/Sample.swiftinterface", text: interfaceFile) - let varDecl: ImportedVariable? = + let accessorDecl: ImportedFunc? = st.importedTypes.values.compactMap { $0.variables.first { - $0.identifier == identifier + $0.name == identifier && $0.kind == accessorKind } }.first - guard let varDecl else { + guard let accessorDecl else { fatalError("Cannot find descriptor of: \(identifier)") } + let thunkName = st.thunkNameRegistry.functionThunkName(decl: accessorDecl) + let cFunc = accessorDecl.cFunctionDecl(cName: thunkName) let getOutput = CodePrinter.toString { printer in - st.printFunctionDescriptorValue( - &printer, varDecl.accessorFunc(kind: accessorKind)!, accessorKind: accessorKind) + st.printFunctionDescriptorValue(&printer, cFunc) } try body(getOutput) } - } diff --git a/Tests/JExtractSwiftTests/MethodImportTests.swift b/Tests/JExtractSwiftTests/MethodImportTests.swift index b7d00e89..3cb69808 100644 --- a/Tests/JExtractSwiftTests/MethodImportTests.swift +++ b/Tests/JExtractSwiftTests/MethodImportTests.swift @@ -28,25 +28,19 @@ final class MethodImportTests { import _StringProcessing import _SwiftConcurrencyShims - // MANGLED NAME: $s14MySwiftLibrary10helloWorldyyF public func helloWorld() - // MANGLED NAME: $s14MySwiftLibrary13globalTakeInt1iySi_tF public func globalTakeInt(i: Int) - // MANGLED NAME: $s14MySwiftLibrary23globalTakeLongIntString1l3i321sys5Int64V_s5Int32VSStF public func globalTakeIntLongString(i32: Int32, l: Int64, s: String) extension MySwiftClass { public func helloMemberInExtension() } - // MANGLED NAME: $s14MySwiftLibrary0aB5ClassCMa public class MySwiftClass { - // MANGLED NAME: $s14MySwiftLibrary0aB5ClassC3len3capACSi_SitcfC public init(len: Swift.Int, cap: Swift.Int) - // MANGLED NAME: $s14MySwiftLibrary0aB5ClassC19helloMemberFunctionyyF public func helloMemberFunction() public func makeInt() -> Int @@ -69,10 +63,10 @@ final class MethodImportTests { try st.analyze(file: "Fake.swift", text: class_interfaceFile) - let funcDecl = st.importedGlobalFuncs.first { $0.baseIdentifier == "helloWorld" }! + let funcDecl = st.importedGlobalFuncs.first { $0.name == "helloWorld" }! let output = CodePrinter.toString { printer in - st.printFuncDowncallMethod(&printer, decl: funcDecl, paramPassingStyle: nil) + st.printFuncDowncallMethod(&printer, funcDecl) } assertOutput( @@ -86,7 +80,7 @@ final class MethodImportTests { * } */ public static void helloWorld() { - var mh$ = helloWorld.HANDLE; + var mh$ = swiftjava___FakeModule_helloWorld.HANDLE; try { if (SwiftKit.TRACE_DOWNCALLS) { SwiftKit.traceDowncall(); @@ -112,11 +106,11 @@ final class MethodImportTests { try st.analyze(file: "Fake.swift", text: class_interfaceFile) let funcDecl = st.importedGlobalFuncs.first { - $0.baseIdentifier == "globalTakeInt" + $0.name == "globalTakeInt" }! let output = CodePrinter.toString { printer in - st.printFuncDowncallMethod(&printer, decl: funcDecl, paramPassingStyle: nil) + st.printFuncDowncallMethod(&printer, funcDecl) } assertOutput( @@ -130,12 +124,11 @@ final class MethodImportTests { * } */ public static void globalTakeInt(long i) { - var mh$ = globalTakeInt.HANDLE; + var mh$ = swiftjava___FakeModule_globalTakeInt_i.HANDLE; try { if (SwiftKit.TRACE_DOWNCALLS) { SwiftKit.traceDowncall(i); } - mh$.invokeExact(i); } catch (Throwable ex$) { throw new AssertionError("should not reach here", ex$); @@ -156,11 +149,11 @@ final class MethodImportTests { try st.analyze(file: "Fake.swift", text: class_interfaceFile) let funcDecl = st.importedGlobalFuncs.first { - $0.baseIdentifier == "globalTakeIntLongString" + $0.name == "globalTakeIntLongString" }! let output = CodePrinter.toString { printer in - st.printFuncDowncallMethod(&printer, decl: funcDecl, paramPassingStyle: .memorySegment) + st.printFuncDowncallMethod(&printer, funcDecl) } assertOutput( @@ -175,13 +168,12 @@ final class MethodImportTests { * } */ public static void globalTakeIntLongString(int i32, long l, java.lang.String s) { - var mh$ = globalTakeIntLongString.HANDLE; - try (var arena = Arena.ofConfined()) { - var s$ = arena.allocateFrom(s); + var mh$ = swiftjava___FakeModule_globalTakeIntLongString_i32_l_s.HANDLE; + try(var arena$ = Arena.ofConfined()) { + var s$ = SwiftKit.toCString(s, arena$); if (SwiftKit.TRACE_DOWNCALLS) { SwiftKit.traceDowncall(i32, l, s$); } - mh$.invokeExact(i32, l, s$); } catch (Throwable ex$) { throw new AssertionError("should not reach here", ex$); @@ -192,7 +184,7 @@ final class MethodImportTests { } @Test - func method_class_helloMemberFunction_self_memorySegment() throws { + func method_class_helloMemberFunction() throws { let st = Swift2JavaTranslator( javaPackage: "com.example.swift", swiftModuleName: "__FakeModule" @@ -202,11 +194,11 @@ final class MethodImportTests { try st.analyze(file: "Fake.swift", text: class_interfaceFile) let funcDecl: ImportedFunc = st.importedTypes["MySwiftClass"]!.methods.first { - $0.baseIdentifier == "helloMemberFunction" + $0.name == "helloMemberFunction" }! let output = CodePrinter.toString { printer in - st.printFuncDowncallMethod(&printer, decl: funcDecl, paramPassingStyle: .memorySegment) + st.printFuncDowncallMethod(&printer, funcDecl) } assertOutput( @@ -219,56 +211,14 @@ final class MethodImportTests { * public func helloMemberFunction() * } */ - public static void helloMemberFunction(java.lang.foreign.MemorySegment self$) { - var mh$ = helloMemberFunction.HANDLE; - try { - if (SwiftKit.TRACE_DOWNCALLS) { - SwiftKit.traceDowncall(self$); - } - mh$.invokeExact(self$); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - } - """ - ) - } - - @Test - func method_class_helloMemberFunction_self_wrapper() throws { - let st = Swift2JavaTranslator( - javaPackage: "com.example.swift", - swiftModuleName: "__FakeModule" - ) - st.log.logLevel = .error - - try st.analyze(file: "Fake.swift", text: class_interfaceFile) - - let funcDecl: ImportedFunc = st.importedTypes["MySwiftClass"]!.methods.first { - $0.baseIdentifier == "helloMemberInExtension" - }! - - let output = CodePrinter.toString { printer in - st.printFuncDowncallMethod(&printer, decl: funcDecl, paramPassingStyle: .memorySegment) - } - - assertOutput( - output, - expected: - """ - /** - * Downcall to Swift: - * {@snippet lang=swift : - * public func helloMemberInExtension() - * } - */ - public static void helloMemberInExtension(java.lang.foreign.MemorySegment self$) { - var mh$ = helloMemberInExtension.HANDLE; + public void helloMemberFunction() { + $ensureAlive() + var mh$ = swiftjava___FakeModule_MySwiftClass_helloMemberFunction.HANDLE; try { if (SwiftKit.TRACE_DOWNCALLS) { - SwiftKit.traceDowncall(self$); + SwiftKit.traceDowncall(this.$memorySegment()); } - mh$.invokeExact(self$); + mh$.invokeExact(this.$memorySegment()); } catch (Throwable ex$) { throw new AssertionError("should not reach here", ex$); } @@ -278,7 +228,7 @@ final class MethodImportTests { } @Test - func test_method_class_helloMemberFunction_self_wrapper() throws { + func method_class_makeInt() throws { let st = Swift2JavaTranslator( javaPackage: "com.example.swift", swiftModuleName: "__FakeModule" @@ -288,11 +238,11 @@ final class MethodImportTests { try st.analyze(file: "Fake.swift", text: class_interfaceFile) let funcDecl: ImportedFunc = st.importedTypes["MySwiftClass"]!.methods.first { - $0.baseIdentifier == "helloMemberFunction" + $0.name == "makeInt" }! let output = CodePrinter.toString { printer in - st.printFuncDowncallMethod(&printer, decl: funcDecl, paramPassingStyle: .memorySegment) + st.printFuncDowncallMethod(&printer, funcDecl) } assertOutput( @@ -302,16 +252,17 @@ final class MethodImportTests { /** * Downcall to Swift: * {@snippet lang=swift : - * public func helloMemberFunction() + * public func makeInt() -> Int * } */ - public static void helloMemberFunction(java.lang.foreign.MemorySegment self$) { - var mh$ = helloMemberFunction.HANDLE; + public long makeInt() { + $ensureAlive() + var mh$ = swiftjava___FakeModule_MySwiftClass_makeInt.HANDLE; try { if (SwiftKit.TRACE_DOWNCALLS) { - SwiftKit.traceDowncall(self$); + SwiftKit.traceDowncall(this.$memorySegment()); } - mh$.invokeExact(self$); + return (long) mh$.invokeExact(this.$memorySegment()); } catch (Throwable ex$) { throw new AssertionError("should not reach here", ex$); } @@ -320,79 +271,6 @@ final class MethodImportTests { ) } - @Test - func method_class_helloMemberFunction_wrapper() throws { - let st = Swift2JavaTranslator( - javaPackage: "com.example.swift", - swiftModuleName: "__FakeModule" - ) - st.log.logLevel = .info - - try st.analyze(file: "Fake.swift", text: class_interfaceFile) - - let funcDecl: ImportedFunc = st.importedTypes["MySwiftClass"]!.methods.first { - $0.baseIdentifier == "helloMemberFunction" - }! - - let output = CodePrinter.toString { printer in - st.printFuncDowncallMethod(&printer, decl: funcDecl, paramPassingStyle: .wrapper) - } - - assertOutput( - output, - expected: - """ - /** - * Downcall to Swift: - * {@snippet lang=swift : - * public func helloMemberFunction() - * } - */ - public void helloMemberFunction() { - $ensureAlive(); - helloMemberFunction($memorySegment()); - } - """ - ) - } - - @Test - func method_class_makeInt_wrapper() throws { - let st = Swift2JavaTranslator( - javaPackage: "com.example.swift", - swiftModuleName: "__FakeModule" - ) - st.log.logLevel = .info - - try st.analyze(file: "Fake.swift", text: class_interfaceFile) - - let funcDecl: ImportedFunc = st.importedTypes["MySwiftClass"]!.methods.first { - $0.baseIdentifier == "makeInt" - }! - - let output = CodePrinter.toString { printer in - st.printFuncDowncallMethod(&printer, decl: funcDecl, paramPassingStyle: .wrapper) - } - - assertOutput( - output, - expected: - """ - /** - * Downcall to Swift: - * {@snippet lang=swift : - * public func makeInt() -> Int - * } - */ - public long makeInt() { - $ensureAlive(); - - return (long) makeInt($memorySegment()); - } - """ - ) - } - @Test func class_constructor() throws { let st = Swift2JavaTranslator( @@ -404,11 +282,11 @@ final class MethodImportTests { try st.analyze(file: "Fake.swift", text: class_interfaceFile) let initDecl: ImportedFunc = st.importedTypes["MySwiftClass"]!.initializers.first { - $0.identifier == "init(len:cap:)" + $0.name == "init" }! let output = CodePrinter.toString { printer in - st.printNominalInitializerConstructors(&printer, initDecl, parentName: initDecl.parent!) + st.printInitializerDowncallConstructor(&printer, initDecl) } assertOutput( @@ -417,29 +295,25 @@ final class MethodImportTests { """ /** * Create an instance of {@code MySwiftClass}. - * This instance is managed by the passed in {@link SwiftArena} and may not outlive the arena's lifetime. * * {@snippet lang=swift : * public init(len: Swift.Int, cap: Swift.Int) * } */ - public MySwiftClass(long len, long cap, SwiftArena arena) { + public MySwiftClass(long len, long cap, SwiftArena swiftArena$) { super(() -> { - var mh$ = init_len_cap.HANDLE; + var mh$ = swiftjava___FakeModule_MySwiftClass_init_len_cap.HANDLE; try { - MemorySegment _result = arena.allocate($LAYOUT); + MemorySegment _result = swiftArena$.allocate(MySwiftClass.$LAYOUT); if (SwiftKit.TRACE_DOWNCALLS) { - SwiftKit.traceDowncall(len, cap); + SwiftKit.traceDowncall(len, cap, _result); } - mh$.invokeExact( - len, cap, - /* indirect return buffer */_result - ); + mh$.invokeExact(len, cap, _result); return _result; } catch (Throwable ex$) { throw new AssertionError("should not reach here", ex$); } - }, arena); + }, swiftArena$); } """ ) @@ -456,11 +330,11 @@ final class MethodImportTests { try st.analyze(file: "Fake.swift", text: class_interfaceFile) let initDecl: ImportedFunc = st.importedTypes["MySwiftStruct"]!.initializers.first { - $0.identifier == "init(len:cap:)" + $0.name == "init" }! let output = CodePrinter.toString { printer in - st.printNominalInitializerConstructors(&printer, initDecl, parentName: initDecl.parent!) + st.printInitializerDowncallConstructor(&printer, initDecl) } assertOutput( @@ -469,29 +343,25 @@ final class MethodImportTests { """ /** * Create an instance of {@code MySwiftStruct}. - * This instance is managed by the passed in {@link SwiftArena} and may not outlive the arena's lifetime. * * {@snippet lang=swift : * public init(len: Swift.Int, cap: Swift.Int) * } */ - public MySwiftStruct(long len, long cap, SwiftArena arena) { + public MySwiftStruct(long len, long cap, SwiftArena swiftArena$) { super(() -> { - var mh$ = init_len_cap.HANDLE; + var mh$ = swiftjava___FakeModule_MySwiftStruct_init_len_cap.HANDLE; try { - MemorySegment _result = arena.allocate($LAYOUT); + MemorySegment _result = swiftArena$.allocate(MySwiftStruct.$LAYOUT); if (SwiftKit.TRACE_DOWNCALLS) { - SwiftKit.traceDowncall(len, cap); + SwiftKit.traceDowncall(len, cap, _result); } - mh$.invokeExact( - len, cap, - /* indirect return buffer */_result - ); + mh$.invokeExact(len, cap, _result); return _result; } catch (Throwable ex$) { throw new AssertionError("should not reach here", ex$); } - }, arena); + }, swiftArena$); } """ ) diff --git a/Tests/JExtractSwiftTests/MethodThunkTests.swift b/Tests/JExtractSwiftTests/MethodThunkTests.swift index 7de47816..d57e449e 100644 --- a/Tests/JExtractSwiftTests/MethodThunkTests.swift +++ b/Tests/JExtractSwiftTests/MethodThunkTests.swift @@ -20,8 +20,14 @@ final class MethodThunkTests { """ import Swift + public var globalVar: MyClass = MyClass() public func globalFunc(a: Int32, b: Int64) {} public func globalFunc(a: Double, b: Int64) {} + + public class MyClass { + public var property: Int + public init(arg: Int32) {} + } """ @Test("Thunk overloads: globalFunc(a: Int32, b: Int64) & globalFunc(i32: Int32, l: Int64)") @@ -37,18 +43,52 @@ final class MethodThunkTests { detectChunkByInitialLines: 1, expectedChunks: [ + """ + @_cdecl("swiftjava_FakeModule_globalVar$get") + public func swiftjava_FakeModule_globalVar$get(_ _result: UnsafeMutableRawPointer) { + _result.assumingMemoryBound(to: MyClass.self).initialize(to: globalVar) + } + """, + """ + @_cdecl("swiftjava_FakeModule_globalVar$set") + public func swiftjava_FakeModule_globalVar$set(_ newValue: UnsafeRawPointer) { + globalVar = newValue.assumingMemoryBound(to: MyClass.self).pointee + } + """, """ @_cdecl("swiftjava_FakeModule_globalFunc_a_b") - public func swiftjava_FakeModule_globalFunc_a_b(a: Int32, b: Int64) /* Void */ { - let returnValue = globalFunc(a: a, b: b) - return returnValue + public func swiftjava_FakeModule_globalFunc_a_b(_ a: Int32, _ b: Int64) { + globalFunc(a: a, b: b) } """, """ @_cdecl("swiftjava_FakeModule_globalFunc_a_b$1") - public func swiftjava_FakeModule_globalFunc_a_b$1(a: Double, b: Int64) /* Void */ { - let returnValue = globalFunc(a: a, b: b) - return returnValue + public func swiftjava_FakeModule_globalFunc_a_b$1(_ a: Double, _ b: Int64) { + globalFunc(a: a, b: b) + } + """, + """ + @_cdecl("swiftjava_getType_FakeModule_MyClass") + public func swiftjava_getType_FakeModule_MyClass() -> UnsafeMutableRawPointer /* Any.Type */ { + return unsafeBitCast(MyClass.self, to: UnsafeMutableRawPointer.self) + } + """, + """ + @_cdecl("swiftjava_FakeModule_MyClass_init_arg") + public func swiftjava_FakeModule_MyClass_init_arg(_ arg: Int32, _ _result: UnsafeMutableRawPointer) { + _result.assumingMemoryBound(to: MyClass.self).initialize(to: MyClass(arg: arg)) + } + """, + """ + @_cdecl("swiftjava_FakeModule_MyClass_property$get") + public func swiftjava_FakeModule_MyClass_property$get(_ self: UnsafeRawPointer) -> Int { + return self.assumingMemoryBound(to: MyClass.self).pointee.property + } + """, + """ + @_cdecl("swiftjava_FakeModule_MyClass_property$set") + public func swiftjava_FakeModule_MyClass_property$set(_ newValue: Int, _ self: UnsafeRawPointer) { + self.assumingMemoryBound(to: MyClass.self).pointee.property = newValue } """ ] diff --git a/Tests/JExtractSwiftTests/StringPassingTests.swift b/Tests/JExtractSwiftTests/StringPassingTests.swift index cc488dfc..21f0584c 100644 --- a/Tests/JExtractSwiftTests/StringPassingTests.swift +++ b/Tests/JExtractSwiftTests/StringPassingTests.swift @@ -36,10 +36,16 @@ final class StringPassingTests { detectChunkByInitialLines: 1, expectedChunks: [ """ + /** + * Downcall to Swift: + * {@snippet lang=swift : + * public func writeString(string: String) -> Int + * } + */ public static long writeString(java.lang.String string) { - var mh$ = writeString.HANDLE; - try (var arena = Arena.ofConfined()) { - var string$ = arena.allocateFrom(string); + var mh$ = swiftjava___FakeModule_writeString_string.HANDLE; + try(var arena$ = Arena.ofConfined()) { + var string$ = SwiftKit.toCString(string, arena$); if (SwiftKit.TRACE_DOWNCALLS) { SwiftKit.traceDowncall(string$); } diff --git a/Tests/JExtractSwiftTests/VariableImportTests.swift b/Tests/JExtractSwiftTests/VariableImportTests.swift index 3665d277..e407b234 100644 --- a/Tests/JExtractSwiftTests/VariableImportTests.swift +++ b/Tests/JExtractSwiftTests/VariableImportTests.swift @@ -46,108 +46,14 @@ final class VariableImportTests { detectChunkByInitialLines: 7, expectedChunks: [ """ - private static class counterInt { - public static final FunctionDescriptor DESC_GET = FunctionDescriptor.of( - /* -> */SwiftValueLayout.SWIFT_INT, - /*self$*/SwiftValueLayout.SWIFT_POINTER + private static class swiftjava_FakeModule_MySwiftClass_counterInt$get { + public static final FunctionDescriptor DESC = FunctionDescriptor.of( + /* -> */SwiftValueLayout.SWIFT_INT, + /* self: */SwiftValueLayout.SWIFT_POINTER ); - public static final MemorySegment ADDR_GET = - FakeModule.findOrThrow("swiftjava_FakeModule_MySwiftClass_counterInt"); - - public static final MethodHandle HANDLE_GET = Linker.nativeLinker().downcallHandle(ADDR_GET, DESC_GET); - public static final FunctionDescriptor DESC_SET = FunctionDescriptor.ofVoid( - /*newValue*/SwiftValueLayout.SWIFT_INT, - /*self$*/SwiftValueLayout.SWIFT_POINTER - ); - public static final MemorySegment ADDR_SET = - FakeModule.findOrThrow("swiftjava_FakeModule_MySwiftClass_counterInt"); - - public static final MethodHandle HANDLE_SET = Linker.nativeLinker().downcallHandle(ADDR_SET, DESC_SET); - } - """, - """ - /** - * Function descriptor for: - * {@snippet lang=swift : - * public var counterInt: Int - * } - */ - public static FunctionDescriptor counterInt$get$descriptor() { - return counterInt.DESC_GET; - } - """, - """ - /** - * Downcall method handle for: - * {@snippet lang=swift : - * public var counterInt: Int - * } - */ - public static MethodHandle counterInt$get$handle() { - return counterInt.HANDLE_GET; - } - """, - """ - /** - * Address for: - * {@snippet lang=swift : - * public var counterInt: Int - * } - */ - public static MemorySegment counterInt$get$address() { - return counterInt.ADDR_GET; - } - """, - """ - /** - * Function descriptor for: - * {@snippet lang=swift : - * public var counterInt: Int - * } - */ - public static FunctionDescriptor counterInt$set$descriptor() { - return counterInt.DESC_SET; - } - """, - """ - /** - * Downcall method handle for: - * {@snippet lang=swift : - * public var counterInt: Int - * } - */ - public static MethodHandle counterInt$set$handle() { - return counterInt.HANDLE_SET; - } - """, - """ - /** - * Address for: - * {@snippet lang=swift : - * public var counterInt: Int - * } - */ - public static MemorySegment counterInt$set$address() { - return counterInt.ADDR_SET; - } - """, - """ - /** - * Downcall to Swift: - * {@snippet lang=swift : - * public var counterInt: Int - * } - */ - public static long getCounterInt(java.lang.foreign.MemorySegment self$) { - var mh$ = counterInt.HANDLE_GET; - try { - if (SwiftKit.TRACE_DOWNCALLS) { - SwiftKit.traceDowncall(self$); - } - return (long) mh$.invokeExact(self$); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } + public static final MemorySegment ADDR = + FakeModule.findOrThrow("swiftjava_FakeModule_MySwiftClass_counterInt$get"); + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } """, """ @@ -159,29 +65,29 @@ final class VariableImportTests { */ public long getCounterInt() { $ensureAlive(); - return (long) getCounterInt($memorySegment()); - } - """, - """ - /** - * Downcall to Swift: - * {@snippet lang=swift : - * public var counterInt: Int - * } - */ - public static void setCounterInt(long newValue, java.lang.foreign.MemorySegment self$) { - var mh$ = counterInt.HANDLE_SET; + var mh$ = swiftjava_FakeModule_MySwiftClass_counterInt$get.HANDLE; try { if (SwiftKit.TRACE_DOWNCALLS) { - SwiftKit.traceDowncall(newValue, self$); + SwiftKit.traceDowncall(this.$memorySegment()); } - mh$.invokeExact(newValue, self$); + return (long) mh$.invokeExact(this.$memorySegment()); } catch (Throwable ex$) { throw new AssertionError("should not reach here", ex$); } } """, """ + private static class swiftjava_FakeModule_MySwiftClass_counterInt$set { + public static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( + /* newValue: */SwiftValueLayout.SWIFT_INT, + /* self: */SwiftValueLayout.SWIFT_POINTER + ); + public static final MemorySegment ADDR = + FakeModule.findOrThrow("swiftjava_FakeModule_MySwiftClass_counterInt$set"); + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + } + """, + """ /** * Downcall to Swift: * {@snippet lang=swift : @@ -190,7 +96,15 @@ final class VariableImportTests { */ public void setCounterInt(long newValue) { $ensureAlive(); - setCounterInt(newValue, $memorySegment()); + var mh$ = swiftjava_FakeModule_MySwiftClass_counterInt$set.HANDLE; + try { + if (SwiftKit.TRACE_DOWNCALLS) { + SwiftKit.traceDowncall(newValue, this.$memorySegment()); + } + mh$.invokeExact(newValue, this.$memorySegment()); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } } """, ] From f9ae3429fc1c78eb5d6929ee5536d71ef9de3890 Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Wed, 4 Jun 2025 11:03:41 -0700 Subject: [PATCH 252/426] [JExtract] Fix methods returning imported type E.g. func createMyClass(arg: Int) -> MyClass The actual downcall was not printed. --- .../com/example/swift/HelloJava2Swift.java | 3 ++ ...2JavaTranslator+JavaBindingsPrinting.swift | 8 ++-- .../MethodImportTests.swift | 48 +++++++++++++++++++ 3 files changed, 56 insertions(+), 3 deletions(-) diff --git a/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java b/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java index f94a2abb..56ac4d21 100644 --- a/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java +++ b/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java @@ -62,6 +62,9 @@ static void examples() { obj.voidMethod(); obj.takeIntMethod(42); + MySwiftClass otherObj = MySwiftClass.factory(12, 42, arena); + otherObj.voidMethod(); + MySwiftStruct swiftValue = new MySwiftStruct(2222, 1111, arena); SwiftKit.trace("swiftValue.capacity = " + swiftValue.getCapacity()); } diff --git a/Sources/JExtractSwift/Swift2JavaTranslator+JavaBindingsPrinting.swift b/Sources/JExtractSwift/Swift2JavaTranslator+JavaBindingsPrinting.swift index 15fd56e3..f96d3904 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator+JavaBindingsPrinting.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator+JavaBindingsPrinting.swift @@ -259,11 +259,13 @@ extension Swift2JavaTranslator { } else if decl.translatedSignature.result.javaResultType == .void { printer.print("\(downCall);") } else { - let placeholder = if decl.translatedSignature.result.outParameters.isEmpty { - downCall + let placeholder: String + if decl.translatedSignature.result.outParameters.isEmpty { + placeholder = downCall } else { // FIXME: Support cdecl thunk returning a value while populating the out parameters. - "_result" + printer.print("\(downCall);") + placeholder = "_result" } let result = decl.translatedSignature.result.conversion.render(&printer, placeholder) diff --git a/Tests/JExtractSwiftTests/MethodImportTests.swift b/Tests/JExtractSwiftTests/MethodImportTests.swift index 3cb69808..34fda1d4 100644 --- a/Tests/JExtractSwiftTests/MethodImportTests.swift +++ b/Tests/JExtractSwiftTests/MethodImportTests.swift @@ -33,6 +33,8 @@ final class MethodImportTests { public func globalTakeInt(i: Int) public func globalTakeIntLongString(i32: Int32, l: Int64, s: String) + + public func globalReturnClass() -> MySwiftClass extension MySwiftClass { public func helloMemberInExtension() @@ -183,6 +185,52 @@ final class MethodImportTests { ) } + @Test("Import: public func globalReturnClass() -> MySwiftClass") + func func_globalReturnClass() throws { + let st = Swift2JavaTranslator( + javaPackage: "com.example.swift", + swiftModuleName: "__FakeModule" + ) + st.log.logLevel = .error + + try st.analyze(file: "Fake.swift", text: class_interfaceFile) + + let funcDecl = st.importedGlobalFuncs.first { + $0.name == "globalReturnClass" + }! + + let output = CodePrinter.toString { printer in + st.printFuncDowncallMethod(&printer, funcDecl) + } + + assertOutput( + dump: true, + output, + expected: + """ + /** + * Downcall to Swift: + * {@snippet lang=swift : + * public func globalReturnClass() -> MySwiftClass + * } + */ + public static MySwiftClass globalReturnClass(SwiftArena swiftArena$) { + var mh$ = swiftjava___FakeModule_globalReturnClass.HANDLE; + try { + MemorySegment _result = swiftArena$.allocate(MySwiftClass.$LAYOUT); + if (SwiftKit.TRACE_DOWNCALLS) { + SwiftKit.traceDowncall(_result); + } + mh$.invokeExact(_result); + return new MySwiftClass(_result, swiftArena$); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + """ + ) + } + @Test func method_class_helloMemberFunction() throws { let st = Swift2JavaTranslator( From a8fa30224a87c029c4ae99216be20ebcde79d79b Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Wed, 4 Jun 2025 11:27:33 -0700 Subject: [PATCH 253/426] [JExtract] Import initializers as static methods Preparation for importing failable initializers. Since Java 'new' operator can't express 'nil' result from failable initializers importing initializer as 'init' static method is a reasonable choice. --- .../swift/swiftkit/JavaToSwiftBenchmark.java | 2 +- .../com/example/swift/HelloJava2Swift.java | 2 +- .../com/example/swift/MySwiftClassTest.java | 6 +- .../org/swift/swiftkit/MySwiftClassTest.java | 2 +- .../org/swift/swiftkit/SwiftArenaTest.java | 2 +- .../swift/swiftkit/JavaToSwiftBenchmark.java | 2 +- .../swiftkit/StringPassingBenchmark.java | 2 +- .../com/example/swift/HelloJava2Swift.java | 4 +- .../com/example/swift/MySwiftClassTest.java | 6 +- .../org/swift/swiftkit/MySwiftClassTest.java | 2 +- .../org/swift/swiftkit/MySwiftStructTest.java | 2 +- .../org/swift/swiftkit/SwiftArenaTest.java | 6 +- ...2JavaTranslator+JavaBindingsPrinting.swift | 63 ++----------------- .../Swift2JavaTranslator+Printing.swift | 2 +- .../org/swift/swiftkit/SwiftInstance.java | 13 ---- .../MethodImportTests.swift | 56 ++++++++--------- 16 files changed, 49 insertions(+), 123 deletions(-) diff --git a/Samples/SwiftAndJavaJarSampleLib/src/jmh/java/org/swift/swiftkit/JavaToSwiftBenchmark.java b/Samples/SwiftAndJavaJarSampleLib/src/jmh/java/org/swift/swiftkit/JavaToSwiftBenchmark.java index aba652cb..4e3edf03 100644 --- a/Samples/SwiftAndJavaJarSampleLib/src/jmh/java/org/swift/swiftkit/JavaToSwiftBenchmark.java +++ b/Samples/SwiftAndJavaJarSampleLib/src/jmh/java/org/swift/swiftkit/JavaToSwiftBenchmark.java @@ -45,7 +45,7 @@ public void beforeALl() { System.setProperty("jextract.trace.downcalls", "false"); arena = SwiftArena.ofConfined(); - obj = new MySwiftClass(1, 2, arena); + obj = MySwiftClass.init(1, 2, arena); } @TearDown(Level.Trial) diff --git a/Samples/SwiftAndJavaJarSampleLib/src/main/java/com/example/swift/HelloJava2Swift.java b/Samples/SwiftAndJavaJarSampleLib/src/main/java/com/example/swift/HelloJava2Swift.java index 42aa1d0c..cd8af700 100644 --- a/Samples/SwiftAndJavaJarSampleLib/src/main/java/com/example/swift/HelloJava2Swift.java +++ b/Samples/SwiftAndJavaJarSampleLib/src/main/java/com/example/swift/HelloJava2Swift.java @@ -44,7 +44,7 @@ static void examples() { // Example of using an arena; MyClass.deinit is run at end of scope try (var arena = SwiftArena.ofConfined()) { - MySwiftClass obj = new MySwiftClass(2222, 7777, arena); + MySwiftClass obj = MySwiftClass.init(2222, 7777, arena); // just checking retains/releases work SwiftKit.retain(obj); diff --git a/Samples/SwiftAndJavaJarSampleLib/src/test/java/com/example/swift/MySwiftClassTest.java b/Samples/SwiftAndJavaJarSampleLib/src/test/java/com/example/swift/MySwiftClassTest.java index 47416f06..bb46ef3d 100644 --- a/Samples/SwiftAndJavaJarSampleLib/src/test/java/com/example/swift/MySwiftClassTest.java +++ b/Samples/SwiftAndJavaJarSampleLib/src/test/java/com/example/swift/MySwiftClassTest.java @@ -43,7 +43,7 @@ void checkPaths(Throwable throwable) { @Test void test_MySwiftClass_voidMethod() { try(var arena = SwiftArena.ofConfined()) { - MySwiftClass o = new MySwiftClass(12, 42, arena); + MySwiftClass o = MySwiftClass.init(12, 42, arena); o.voidMethod(); } catch (Throwable throwable) { checkPaths(throwable); @@ -53,7 +53,7 @@ void test_MySwiftClass_voidMethod() { @Test void test_MySwiftClass_makeIntMethod() { try(var arena = SwiftArena.ofConfined()) { - MySwiftClass o = new MySwiftClass(12, 42, arena); + MySwiftClass o = MySwiftClass.init(12, 42, arena); var got = o.makeIntMethod(); assertEquals(12, got); } @@ -63,7 +63,7 @@ void test_MySwiftClass_makeIntMethod() { @Disabled // TODO: Need var mangled names in interfaces void test_MySwiftClass_property_len() { try(var arena = SwiftArena.ofConfined()) { - MySwiftClass o = new MySwiftClass(12, 42, arena); + MySwiftClass o = MySwiftClass.init(12, 42, arena); var got = o.getLen(); assertEquals(12, got); } diff --git a/Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/MySwiftClassTest.java b/Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/MySwiftClassTest.java index 3d9a360b..78da5a64 100644 --- a/Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/MySwiftClassTest.java +++ b/Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/MySwiftClassTest.java @@ -25,7 +25,7 @@ public class MySwiftClassTest { @Test void call_retain_retainCount_release() { var arena = SwiftArena.ofConfined(); - var obj = new MySwiftClass(1, 2, arena); + var obj = MySwiftClass.init(1, 2, arena); assertEquals(1, SwiftKit.retainCount(obj)); // TODO: test directly on SwiftHeapObject inheriting obj diff --git a/Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/SwiftArenaTest.java b/Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/SwiftArenaTest.java index 43c03808..e8b1ac04 100644 --- a/Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/SwiftArenaTest.java +++ b/Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/SwiftArenaTest.java @@ -39,7 +39,7 @@ static boolean isAmd64() { @DisabledIf("isAmd64") public void arena_releaseClassOnClose_class_ok() { try (var arena = SwiftArena.ofConfined()) { - var obj = new MySwiftClass(1, 2, arena); + var obj = MySwiftClass.init(1, 2, arena); retain(obj); assertEquals(2, retainCount(obj)); diff --git a/Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/JavaToSwiftBenchmark.java b/Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/JavaToSwiftBenchmark.java index 70f8102c..ff313fc6 100644 --- a/Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/JavaToSwiftBenchmark.java +++ b/Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/JavaToSwiftBenchmark.java @@ -37,7 +37,7 @@ public static class BenchmarkState { @Setup(Level.Trial) public void beforeAll() { arena = SwiftArena.ofConfined(); - obj = new MySwiftClass(1, 2, arena); + obj = MySwiftClass.init(1, 2, arena); } @TearDown(Level.Trial) diff --git a/Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/StringPassingBenchmark.java b/Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/StringPassingBenchmark.java index b7cb45ff..0e686fb4 100644 --- a/Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/StringPassingBenchmark.java +++ b/Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/StringPassingBenchmark.java @@ -46,7 +46,7 @@ public class StringPassingBenchmark { @Setup(Level.Trial) public void beforeAll() { arena = SwiftArena.ofConfined(); - obj = new MySwiftClass(1, 2, arena); + obj = MySwiftClass.init(1, 2, arena); string = makeString(stringLen); } diff --git a/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java b/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java index 56ac4d21..e20ac378 100644 --- a/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java +++ b/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java @@ -47,7 +47,7 @@ static void examples() { // Example of using an arena; MyClass.deinit is run at end of scope try (var arena = SwiftArena.ofConfined()) { - MySwiftClass obj = new MySwiftClass(2222, 7777, arena); + MySwiftClass obj = MySwiftClass.init(2222, 7777, arena); // just checking retains/releases work SwiftKit.trace("retainCount = " + SwiftKit.retainCount(obj)); @@ -65,7 +65,7 @@ static void examples() { MySwiftClass otherObj = MySwiftClass.factory(12, 42, arena); otherObj.voidMethod(); - MySwiftStruct swiftValue = new MySwiftStruct(2222, 1111, arena); + MySwiftStruct swiftValue = MySwiftStruct.init(2222, 1111, arena); SwiftKit.trace("swiftValue.capacity = " + swiftValue.getCapacity()); } diff --git a/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/MySwiftClassTest.java b/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/MySwiftClassTest.java index 71598eed..6c0ceb1e 100644 --- a/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/MySwiftClassTest.java +++ b/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/MySwiftClassTest.java @@ -42,7 +42,7 @@ void checkPaths(Throwable throwable) { @Test void test_MySwiftClass_voidMethod() { try(var arena = SwiftArena.ofConfined()) { - MySwiftClass o = new MySwiftClass(12, 42, arena); + MySwiftClass o = MySwiftClass.init(12, 42, arena); o.voidMethod(); } catch (Throwable throwable) { checkPaths(throwable); @@ -52,7 +52,7 @@ void test_MySwiftClass_voidMethod() { @Test void test_MySwiftClass_makeIntMethod() { try(var arena = SwiftArena.ofConfined()) { - MySwiftClass o = new MySwiftClass(12, 42, arena); + MySwiftClass o = MySwiftClass.init(12, 42, arena); var got = o.makeIntMethod(); assertEquals(12, got); } @@ -62,7 +62,7 @@ void test_MySwiftClass_makeIntMethod() { @Disabled // TODO: Need var mangled names in interfaces void test_MySwiftClass_property_len() { try(var arena = SwiftArena.ofConfined()) { - MySwiftClass o = new MySwiftClass(12, 42, arena); + MySwiftClass o = MySwiftClass.init(12, 42, arena); var got = o.getLen(); assertEquals(12, got); } diff --git a/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/MySwiftClassTest.java b/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/MySwiftClassTest.java index 3d9a360b..78da5a64 100644 --- a/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/MySwiftClassTest.java +++ b/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/MySwiftClassTest.java @@ -25,7 +25,7 @@ public class MySwiftClassTest { @Test void call_retain_retainCount_release() { var arena = SwiftArena.ofConfined(); - var obj = new MySwiftClass(1, 2, arena); + var obj = MySwiftClass.init(1, 2, arena); assertEquals(1, SwiftKit.retainCount(obj)); // TODO: test directly on SwiftHeapObject inheriting obj diff --git a/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/MySwiftStructTest.java b/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/MySwiftStructTest.java index 53390da7..843551a5 100644 --- a/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/MySwiftStructTest.java +++ b/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/MySwiftStructTest.java @@ -26,7 +26,7 @@ void create_struct() { try (var arena = SwiftArena.ofConfined()) { long cap = 12; long len = 34; - var struct = new MySwiftStruct(cap, len, arena); + var struct = MySwiftStruct.init(cap, len, arena); assertEquals(cap, struct.getCapacity()); assertEquals(len, struct.getLength()); diff --git a/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/SwiftArenaTest.java b/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/SwiftArenaTest.java index f7832b48..0d900a62 100644 --- a/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/SwiftArenaTest.java +++ b/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/SwiftArenaTest.java @@ -40,7 +40,7 @@ static boolean isAmd64() { @DisabledIf("isAmd64") public void arena_releaseClassOnClose_class_ok() { try (var arena = SwiftArena.ofConfined()) { - var obj = new MySwiftClass(1, 2, arena); + var obj = MySwiftClass.init(1, 2, arena); retain(obj); assertEquals(2, retainCount(obj)); @@ -57,7 +57,7 @@ public void arena_markAsDestroyed_preventUseAfterFree_class() { MySwiftClass unsafelyEscapedOutsideArenaScope = null; try (var arena = SwiftArena.ofConfined()) { - var obj = new MySwiftClass(1, 2, arena); + var obj = MySwiftClass.init(1, 2, arena); unsafelyEscapedOutsideArenaScope = obj; } @@ -76,7 +76,7 @@ public void arena_markAsDestroyed_preventUseAfterFree_struct() { MySwiftStruct unsafelyEscapedOutsideArenaScope = null; try (var arena = SwiftArena.ofConfined()) { - var s = new MySwiftStruct(1, 2, arena); + var s = MySwiftStruct.init(1, 2, arena); unsafelyEscapedOutsideArenaScope = s; } diff --git a/Sources/JExtractSwift/Swift2JavaTranslator+JavaBindingsPrinting.swift b/Sources/JExtractSwift/Swift2JavaTranslator+JavaBindingsPrinting.swift index f96d3904..27869695 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator+JavaBindingsPrinting.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator+JavaBindingsPrinting.swift @@ -15,18 +15,6 @@ import JavaTypes extension Swift2JavaTranslator { - public func printInitializerDowncallConstructors( - _ printer: inout CodePrinter, - _ decl: ImportedFunc - ) { - printer.printSeparator(decl.displayName) - - printJavaBindingDescriptorClass(&printer, decl) - - // Render the "make the downcall" functions. - printInitializerDowncallConstructor(&printer, decl) - } - public func printFunctionDowncallMethods( _ printer: inout CodePrinter, _ decl: ImportedFunc @@ -86,43 +74,6 @@ extension Swift2JavaTranslator { printer.print(");") } - public func printInitializerDowncallConstructor( - _ printer: inout CodePrinter, - _ decl: ImportedFunc - ) { - guard let className = decl.parentType?.asNominalTypeDeclaration?.name else { - return - } - let modifiers = "public" - - var paramDecls = decl.translatedSignature.parameters - .flatMap(\.javaParameters) - .map { "\($0.type) \($0.name)" } - - assert(decl.translatedSignature.requiresSwiftArena, "constructor always require the SwiftArena") - paramDecls.append("SwiftArena swiftArena$") - - printer.printBraceBlock( - """ - /** - * Create an instance of {@code \(className)}. - * - * {@snippet lang=swift : - * \(decl.signatureString) - * } - */ - \(modifiers) \(className)(\(paramDecls.joined(separator: ", "))) - """ - ) { printer in - // Call super constructor `SwiftValue(Supplier , SwiftArena)`. - printer.print("super(() -> {") - printer.indent() - printDowncall(&printer, decl, isConstructor: true) - printer.outdent() - printer.print("}, swiftArena$);") - } - } - /// Print the calling body that forwards all the parameters to the `methodName`, /// with adding `SwiftArena.ofAuto()` at the end. public func printFuncDowncallMethod( @@ -131,13 +82,12 @@ extension Swift2JavaTranslator { let methodName: String = switch decl.kind { case .getter: "get\(decl.name.toCamelCase)" case .setter: "set\(decl.name.toCamelCase)" - case .function: decl.name - case .initializer: fatalError("initializers must use printInitializerDowncallConstructor()") + case .function, .initializer: decl.name } var modifiers = "public" switch decl.swiftSignature.selfParameter { - case .staticMethod(_), nil: + case .staticMethod, .initializer, nil: modifiers.append(" static") default: break @@ -178,8 +128,7 @@ extension Swift2JavaTranslator { /// This assumes that all the parameters are passed-in with appropriate names. package func printDowncall( _ printer: inout CodePrinter, - _ decl: ImportedFunc, - isConstructor: Bool = false + _ decl: ImportedFunc ) { //=== Part 1: MethodHandle let descriptorClassIdentifier = thunkNameRegistry.functionThunkName(decl: decl) @@ -252,11 +201,7 @@ extension Swift2JavaTranslator { let downCall = "mh$.invokeExact(\(downCallArguments.joined(separator: ", ")))" //=== Part 4: Convert the return value. - if isConstructor { - // For constructors, the caller expects the "self" memory segment. - printer.print("\(downCall);") - printer.print("return _result;") - } else if decl.translatedSignature.result.javaResultType == .void { + if decl.translatedSignature.result.javaResultType == .void { printer.print("\(downCall);") } else { let placeholder: String diff --git a/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift b/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift index 98b3c767..13e337e0 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift @@ -125,7 +125,7 @@ extension Swift2JavaTranslator { // Initializers for initDecl in decl.initializers { - printInitializerDowncallConstructors(&printer, initDecl) + printFunctionDowncallMethods(&printer, initDecl) } // Properties diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftInstance.java b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftInstance.java index 2725966d..5b8ff700 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftInstance.java +++ b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftInstance.java @@ -66,19 +66,6 @@ protected SwiftInstance(MemorySegment segment, SwiftArena arena) { arena.register(this); } - /** - * Convenience constructor subclasses can call like: - * {@snippet : - * super(() -> { ...; return segment; }, swiftArena$) - * } - * - * @param segmentSupplier Should return the memory segment of the value - * @param arena the arena where the supplied segment belongs to. When the arena goes out of scope, this value is destroyed. - */ - protected SwiftInstance(Supplier segmentSupplier, SwiftArena arena) { - this(segmentSupplier.get(), arena); - } - /** * Ensures that this instance has not been destroyed. *

diff --git a/Tests/JExtractSwiftTests/MethodImportTests.swift b/Tests/JExtractSwiftTests/MethodImportTests.swift index 34fda1d4..bad1025e 100644 --- a/Tests/JExtractSwiftTests/MethodImportTests.swift +++ b/Tests/JExtractSwiftTests/MethodImportTests.swift @@ -334,7 +334,7 @@ final class MethodImportTests { }! let output = CodePrinter.toString { printer in - st.printInitializerDowncallConstructor(&printer, initDecl) + st.printFuncDowncallMethod(&printer, initDecl) } assertOutput( @@ -342,26 +342,23 @@ final class MethodImportTests { expected: """ /** - * Create an instance of {@code MySwiftClass}. - * + * Downcall to Swift: * {@snippet lang=swift : * public init(len: Swift.Int, cap: Swift.Int) * } */ - public MySwiftClass(long len, long cap, SwiftArena swiftArena$) { - super(() -> { - var mh$ = swiftjava___FakeModule_MySwiftClass_init_len_cap.HANDLE; - try { - MemorySegment _result = swiftArena$.allocate(MySwiftClass.$LAYOUT); - if (SwiftKit.TRACE_DOWNCALLS) { - SwiftKit.traceDowncall(len, cap, _result); - } - mh$.invokeExact(len, cap, _result); - return _result; - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + public static MySwiftClass init(long len, long cap, SwiftArena swiftArena$) { + var mh$ = swiftjava___FakeModule_MySwiftClass_init_len_cap.HANDLE; + try { + MemorySegment _result = swiftArena$.allocate(MySwiftClass.$LAYOUT); + if (SwiftKit.TRACE_DOWNCALLS) { + SwiftKit.traceDowncall(len, cap, _result); } - }, swiftArena$); + mh$.invokeExact(len, cap, _result); + return new MySwiftClass(_result, swiftArena$); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } } """ ) @@ -382,7 +379,7 @@ final class MethodImportTests { }! let output = CodePrinter.toString { printer in - st.printInitializerDowncallConstructor(&printer, initDecl) + st.printFuncDowncallMethod(&printer, initDecl) } assertOutput( @@ -390,26 +387,23 @@ final class MethodImportTests { expected: """ /** - * Create an instance of {@code MySwiftStruct}. - * + * Downcall to Swift: * {@snippet lang=swift : * public init(len: Swift.Int, cap: Swift.Int) * } */ - public MySwiftStruct(long len, long cap, SwiftArena swiftArena$) { - super(() -> { - var mh$ = swiftjava___FakeModule_MySwiftStruct_init_len_cap.HANDLE; - try { - MemorySegment _result = swiftArena$.allocate(MySwiftStruct.$LAYOUT); - if (SwiftKit.TRACE_DOWNCALLS) { + public static MySwiftStruct init(long len, long cap, SwiftArena swiftArena$) { + var mh$ = swiftjava___FakeModule_MySwiftStruct_init_len_cap.HANDLE; + try { + MemorySegment _result = swiftArena$.allocate(MySwiftStruct.$LAYOUT); + if (SwiftKit.TRACE_DOWNCALLS) { SwiftKit.traceDowncall(len, cap, _result); - } - mh$.invokeExact(len, cap, _result); - return _result; - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); } - }, swiftArena$); + mh$.invokeExact(len, cap, _result); + return new MySwiftStruct(_result, swiftArena$); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } } """ ) From 719379cda33561288165af9fc950890f4c43e021 Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Wed, 4 Jun 2025 20:39:48 -0700 Subject: [PATCH 254/426] [JExtract] Static 'call' method in binding descriptor classes * Add a static call method to each binding descriptor class to handle the actual downcall. * Refactor wrapper methods to delegate to the binding descriptor's call method. * Clearly separate responsibilities: each binding descriptor class now encapsulates the complete lowered Cdecl thunk, while wrapper methods focus on Java-to-Cdecl type conversion. --- ...2JavaTranslator+JavaBindingsPrinting.swift | 101 +++++++----- ...Swift2JavaTranslator+JavaTranslation.swift | 2 +- .../FuncCallbackImportTests.swift | 11 +- .../FunctionDescriptorImportTests.swift | 146 +++++++++++++++--- .../MethodImportTests.swift | 102 +++--------- .../StringPassingTests.swift | 36 +++-- .../VariableImportTests.swift | 40 ++--- 7 files changed, 251 insertions(+), 187 deletions(-) diff --git a/Sources/JExtractSwift/Swift2JavaTranslator+JavaBindingsPrinting.swift b/Sources/JExtractSwift/Swift2JavaTranslator+JavaBindingsPrinting.swift index 27869695..a592e89e 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator+JavaBindingsPrinting.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator+JavaBindingsPrinting.swift @@ -24,18 +24,27 @@ extension Swift2JavaTranslator { printJavaBindingDescriptorClass(&printer, decl) // Render the "make the downcall" functions. - printFuncDowncallMethod(&printer, decl) + printJavaBindingWrapperMethod(&printer, decl) } /// Print FFM Java binding descriptors for the imported Swift API. - func printJavaBindingDescriptorClass( + package func printJavaBindingDescriptorClass( _ printer: inout CodePrinter, _ decl: ImportedFunc ) { let thunkName = thunkNameRegistry.functionThunkName(decl: decl) let cFunc = decl.cFunctionDecl(cName: thunkName) - printer.printBraceBlock("private static class \(cFunc.name)") { printer in + printer.printBraceBlock( + """ + /** + * {@snippet lang=c : + * \(cFunc.description) + * } + */ + private static class \(cFunc.name) + """ + ) { printer in printFunctionDescriptorValue(&printer, cFunc) printer.print( """ @@ -44,11 +53,12 @@ extension Swift2JavaTranslator { public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); """ ) + printJavaBindingDowncallMethod(&printer, cFunc) } } /// Print the 'FunctionDescriptor' of the lowered cdecl thunk. - public func printFunctionDescriptorValue( + func printFunctionDescriptorValue( _ printer: inout CodePrinter, _ cFunc: CFunction ) { @@ -74,9 +84,42 @@ extension Swift2JavaTranslator { printer.print(");") } + func printJavaBindingDowncallMethod( + _ printer: inout CodePrinter, + _ cFunc: CFunction + ) { + let returnTy = cFunc.resultType.javaType + let maybeReturn = cFunc.resultType.isVoid ? "" : "return (\(returnTy)) " + + var params: [String] = [] + var args: [String] = [] + for param in cFunc.parameters { + // ! unwrapping because cdecl lowering guarantees the parameter named. + params.append("\(param.type.javaType) \(param.name!)") + args.append(param.name!) + } + let paramsStr = params.joined(separator: ", ") + let argsStr = args.joined(separator: ", ") + + printer.print( + """ + public static \(returnTy) call(\(paramsStr)) { + try { + if (SwiftKit.TRACE_DOWNCALLS) { + SwiftKit.traceDowncall(\(argsStr)); + } + \(maybeReturn)HANDLE.invokeExact(\(argsStr)); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + """ + ) + } + /// Print the calling body that forwards all the parameters to the `methodName`, /// with adding `SwiftArena.ofAuto()` at the end. - public func printFuncDowncallMethod( + public func printJavaBindingWrapperMethod( _ printer: inout CodePrinter, _ decl: ImportedFunc) { let methodName: String = switch decl.kind { @@ -130,19 +173,11 @@ extension Swift2JavaTranslator { _ printer: inout CodePrinter, _ decl: ImportedFunc ) { - //=== Part 1: MethodHandle - let descriptorClassIdentifier = thunkNameRegistry.functionThunkName(decl: decl) - printer.print( - "var mh$ = \(descriptorClassIdentifier).HANDLE;" - ) - - let tryHead = if decl.translatedSignature.requiresTemporaryArena { - "try(var arena$ = Arena.ofConfined()) {" - } else { - "try {" + //=== Part 1: prepare temporary arena if needed. + if decl.translatedSignature.requiresTemporaryArena { + printer.print("try(var arena$ = Arena.ofConfined()) {") + printer.indent(); } - printer.print(tryHead); - printer.indent(); //=== Part 2: prepare all arguments. var downCallArguments: [String] = [] @@ -151,15 +186,7 @@ extension Swift2JavaTranslator { for (i, parameter) in decl.translatedSignature.parameters.enumerated() { let original = decl.swiftSignature.parameters[i] let parameterName = original.parameterName ?? "_\(i)" - let converted = parameter.conversion.render(&printer, parameterName) - let lowered: String - if parameter.conversion.isTrivial { - lowered = converted - } else { - // Store the conversion to a temporary variable. - lowered = "\(parameterName)$" - printer.print("var \(lowered) = \(converted);") - } + let lowered = parameter.conversion.render(&printer, parameterName) downCallArguments.append(lowered) } @@ -191,14 +218,8 @@ extension Swift2JavaTranslator { } //=== Part 3: Downcall. - printer.print( - """ - if (SwiftKit.TRACE_DOWNCALLS) { - SwiftKit.traceDowncall(\(downCallArguments.joined(separator: ", "))); - } - """ - ) - let downCall = "mh$.invokeExact(\(downCallArguments.joined(separator: ", ")))" + let thunkName = thunkNameRegistry.functionThunkName(decl: decl) + let downCall = "\(thunkName).call(\(downCallArguments.joined(separator: ", ")))" //=== Part 4: Convert the return value. if decl.translatedSignature.result.javaResultType == .void { @@ -221,14 +242,10 @@ extension Swift2JavaTranslator { } } - printer.outdent() - printer.print( - """ - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } - """ - ) + if decl.translatedSignature.requiresTemporaryArena { + printer.outdent() + printer.print("}") + } } func renderMemoryLayoutValue(for javaType: JavaType) -> String { diff --git a/Sources/JExtractSwift/Swift2JavaTranslator+JavaTranslation.swift b/Sources/JExtractSwift/Swift2JavaTranslator+JavaTranslation.swift index 4d5fc80a..e126ca8a 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator+JavaTranslation.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator+JavaTranslation.swift @@ -270,7 +270,7 @@ struct JavaTranslation { return TranslatedResult( javaResultType: javaType, outParameters: [], - conversion: .cast(javaType) + conversion: .pass ) } diff --git a/Tests/JExtractSwiftTests/FuncCallbackImportTests.swift b/Tests/JExtractSwiftTests/FuncCallbackImportTests.swift index 4bcb4e05..50022c55 100644 --- a/Tests/JExtractSwiftTests/FuncCallbackImportTests.swift +++ b/Tests/JExtractSwiftTests/FuncCallbackImportTests.swift @@ -45,7 +45,7 @@ final class FuncCallbackImportTests { let funcDecl = st.importedGlobalFuncs.first { $0.name == "callMe" }! let output = CodePrinter.toString { printer in - st.printFuncDowncallMethod(&printer, funcDecl) + st.printJavaBindingWrapperMethod(&printer, funcDecl) } assertOutput( @@ -59,15 +59,8 @@ final class FuncCallbackImportTests { * } */ public static void callMe(java.lang.Runnable callback) { - var mh$ = swiftjava___FakeModule_callMe_callback.HANDLE; try(var arena$ = Arena.ofConfined()) { - var callback$ = SwiftKit.toUpcallStub(callback, arena$); - if (SwiftKit.TRACE_DOWNCALLS) { - SwiftKit.traceDowncall(callback$); - } - mh$.invokeExact(callback$); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + swiftjava___FakeModule_callMe_callback.call(SwiftKit.toUpcallStub(callback, arena$)) } } """ diff --git a/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift b/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift index dea63d4e..44385b0a 100644 --- a/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift +++ b/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift @@ -51,9 +51,29 @@ final class FunctionDescriptorTests { output, expected: """ - public static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( - /* i: */SwiftValueLayout.SWIFT_INT - ); + /** + * {@snippet lang=c : + * void swiftjava_SwiftModule_globalTakeInt_i(ptrdiff_t i) + * } + */ + private static class swiftjava_SwiftModule_globalTakeInt_i { + public static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( + /* i: */SwiftValueLayout.SWIFT_INT + ); + public static final MemorySegment ADDR = + SwiftModule.findOrThrow("swiftjava_SwiftModule_globalTakeInt_i"); + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + public static void call(long i) { + try { + if (SwiftKit.TRACE_DOWNCALLS) { + SwiftKit.traceDowncall(i); + } + HANDLE.invokeExact(i); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + } """ ) } @@ -66,10 +86,30 @@ final class FunctionDescriptorTests { output, expected: """ - public static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( - /* l: */SwiftValueLayout.SWIFT_INT64, - /* i32: */SwiftValueLayout.SWIFT_INT32 - ); + /** + * {@snippet lang=c : + * void swiftjava_SwiftModule_globalTakeLongInt_l_i32(int64_t l, int32_t i32) + * } + */ + private static class swiftjava_SwiftModule_globalTakeLongInt_l_i32 { + public static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( + /* l: */SwiftValueLayout.SWIFT_INT64, + /* i32: */SwiftValueLayout.SWIFT_INT32 + ); + public static final MemorySegment ADDR = + SwiftModule.findOrThrow("swiftjava_SwiftModule_globalTakeLongInt_l_i32"); + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + public static void call(long l, int i32) { + try { + if (SwiftKit.TRACE_DOWNCALLS) { + SwiftKit.traceDowncall(l, i32); + } + HANDLE.invokeExact(l, i32); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + } """ ) } @@ -82,10 +122,30 @@ final class FunctionDescriptorTests { output, expected: """ - public static final FunctionDescriptor DESC = FunctionDescriptor.of( - /* -> */SwiftValueLayout.SWIFT_INT, - /* i: */SwiftValueLayout.SWIFT_INT - ); + /** + * {@snippet lang=c : + * ptrdiff_t swiftjava_SwiftModule_echoInt_i(ptrdiff_t i) + * } + */ + private static class swiftjava_SwiftModule_echoInt_i { + public static final FunctionDescriptor DESC = FunctionDescriptor.of( + /* -> */SwiftValueLayout.SWIFT_INT, + /* i: */SwiftValueLayout.SWIFT_INT + ); + public static final MemorySegment ADDR = + SwiftModule.findOrThrow("swiftjava_SwiftModule_echoInt_i"); + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + public static long call(long i) { + try { + if (SwiftKit.TRACE_DOWNCALLS) { + SwiftKit.traceDowncall(i); + } + return (long) HANDLE.invokeExact(i); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + } """ ) } @@ -98,10 +158,30 @@ final class FunctionDescriptorTests { output, expected: """ - public static final FunctionDescriptor DESC = FunctionDescriptor.of( - /* -> */SwiftValueLayout.SWIFT_INT32, - /* self: */SwiftValueLayout.SWIFT_POINTER - ); + /** + * {@snippet lang=c : + * int32_t swiftjava_SwiftModule_MySwiftClass_counter$get(const void *self) + * } + */ + private static class swiftjava_SwiftModule_MySwiftClass_counter$get { + public static final FunctionDescriptor DESC = FunctionDescriptor.of( + /* -> */SwiftValueLayout.SWIFT_INT32, + /* self: */SwiftValueLayout.SWIFT_POINTER + ); + public static final MemorySegment ADDR = + SwiftModule.findOrThrow("swiftjava_SwiftModule_MySwiftClass_counter$get"); + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + public static int call(java.lang.foreign.MemorySegment self) { + try { + if (SwiftKit.TRACE_DOWNCALLS) { + SwiftKit.traceDowncall(self); + } + return (int) HANDLE.invokeExact(self); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + } """ ) } @@ -113,10 +193,30 @@ final class FunctionDescriptorTests { output, expected: """ - public static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( - /* newValue: */SwiftValueLayout.SWIFT_INT32, - /* self: */SwiftValueLayout.SWIFT_POINTER - ); + /** + * {@snippet lang=c : + * void swiftjava_SwiftModule_MySwiftClass_counter$set(int32_t newValue, const void *self) + * } + */ + private static class swiftjava_SwiftModule_MySwiftClass_counter$set { + public static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( + /* newValue: */SwiftValueLayout.SWIFT_INT32, + /* self: */SwiftValueLayout.SWIFT_POINTER + ); + public static final MemorySegment ADDR = + SwiftModule.findOrThrow("swiftjava_SwiftModule_MySwiftClass_counter$set"); + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + public static void call(int newValue, java.lang.foreign.MemorySegment self) { + try { + if (SwiftKit.TRACE_DOWNCALLS) { + SwiftKit.traceDowncall(newValue, self); + } + HANDLE.invokeExact(newValue, self); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + } """ ) } @@ -145,10 +245,8 @@ extension FunctionDescriptorTests { $0.name == methodIdentifier }! - let thunkName = st.thunkNameRegistry.functionThunkName(decl: funcDecl) - let cFunc = funcDecl.cFunctionDecl(cName: thunkName) let output = CodePrinter.toString { printer in - st.printFunctionDescriptorValue(&printer, cFunc) + st.printJavaBindingDescriptorClass(&printer, funcDecl) } try body(output) @@ -180,10 +278,8 @@ extension FunctionDescriptorTests { fatalError("Cannot find descriptor of: \(identifier)") } - let thunkName = st.thunkNameRegistry.functionThunkName(decl: accessorDecl) - let cFunc = accessorDecl.cFunctionDecl(cName: thunkName) let getOutput = CodePrinter.toString { printer in - st.printFunctionDescriptorValue(&printer, cFunc) + st.printJavaBindingDescriptorClass(&printer, accessorDecl) } try body(getOutput) diff --git a/Tests/JExtractSwiftTests/MethodImportTests.swift b/Tests/JExtractSwiftTests/MethodImportTests.swift index bad1025e..526faece 100644 --- a/Tests/JExtractSwiftTests/MethodImportTests.swift +++ b/Tests/JExtractSwiftTests/MethodImportTests.swift @@ -68,7 +68,7 @@ final class MethodImportTests { let funcDecl = st.importedGlobalFuncs.first { $0.name == "helloWorld" }! let output = CodePrinter.toString { printer in - st.printFuncDowncallMethod(&printer, funcDecl) + st.printJavaBindingWrapperMethod(&printer, funcDecl) } assertOutput( @@ -82,16 +82,7 @@ final class MethodImportTests { * } */ public static void helloWorld() { - var mh$ = swiftjava___FakeModule_helloWorld.HANDLE; - try { - if (SwiftKit.TRACE_DOWNCALLS) { - SwiftKit.traceDowncall(); - } - - mh$.invokeExact(); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } + swiftjava___FakeModule_helloWorld.call(); } """ ) @@ -112,7 +103,7 @@ final class MethodImportTests { }! let output = CodePrinter.toString { printer in - st.printFuncDowncallMethod(&printer, funcDecl) + st.printJavaBindingWrapperMethod(&printer, funcDecl) } assertOutput( @@ -126,15 +117,7 @@ final class MethodImportTests { * } */ public static void globalTakeInt(long i) { - var mh$ = swiftjava___FakeModule_globalTakeInt_i.HANDLE; - try { - if (SwiftKit.TRACE_DOWNCALLS) { - SwiftKit.traceDowncall(i); - } - mh$.invokeExact(i); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } + swiftjava___FakeModule_globalTakeInt_i.call(i); } """ ) @@ -155,7 +138,7 @@ final class MethodImportTests { }! let output = CodePrinter.toString { printer in - st.printFuncDowncallMethod(&printer, funcDecl) + st.printJavaBindingWrapperMethod(&printer, funcDecl) } assertOutput( @@ -170,15 +153,8 @@ final class MethodImportTests { * } */ public static void globalTakeIntLongString(int i32, long l, java.lang.String s) { - var mh$ = swiftjava___FakeModule_globalTakeIntLongString_i32_l_s.HANDLE; try(var arena$ = Arena.ofConfined()) { - var s$ = SwiftKit.toCString(s, arena$); - if (SwiftKit.TRACE_DOWNCALLS) { - SwiftKit.traceDowncall(i32, l, s$); - } - mh$.invokeExact(i32, l, s$); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + swiftjava___FakeModule_globalTakeIntLongString_i32_l_s.call(i32, l, SwiftKit.toCString(s, arena$)); } } """ @@ -200,7 +176,7 @@ final class MethodImportTests { }! let output = CodePrinter.toString { printer in - st.printFuncDowncallMethod(&printer, funcDecl) + st.printJavaBindingWrapperMethod(&printer, funcDecl) } assertOutput( @@ -215,17 +191,9 @@ final class MethodImportTests { * } */ public static MySwiftClass globalReturnClass(SwiftArena swiftArena$) { - var mh$ = swiftjava___FakeModule_globalReturnClass.HANDLE; - try { - MemorySegment _result = swiftArena$.allocate(MySwiftClass.$LAYOUT); - if (SwiftKit.TRACE_DOWNCALLS) { - SwiftKit.traceDowncall(_result); - } - mh$.invokeExact(_result); - return new MySwiftClass(_result, swiftArena$); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } + MemorySegment _result = swiftArena$.allocate(MySwiftClass.$LAYOUT); + swiftjava___FakeModule_globalReturnClass.call(_result); + return new MySwiftClass(_result, swiftArena$); } """ ) @@ -246,7 +214,7 @@ final class MethodImportTests { }! let output = CodePrinter.toString { printer in - st.printFuncDowncallMethod(&printer, funcDecl) + st.printJavaBindingWrapperMethod(&printer, funcDecl) } assertOutput( @@ -261,15 +229,7 @@ final class MethodImportTests { */ public void helloMemberFunction() { $ensureAlive() - var mh$ = swiftjava___FakeModule_MySwiftClass_helloMemberFunction.HANDLE; - try { - if (SwiftKit.TRACE_DOWNCALLS) { - SwiftKit.traceDowncall(this.$memorySegment()); - } - mh$.invokeExact(this.$memorySegment()); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } + swiftjava___FakeModule_MySwiftClass_helloMemberFunction.call(this.$memorySegment()); } """ ) @@ -290,7 +250,7 @@ final class MethodImportTests { }! let output = CodePrinter.toString { printer in - st.printFuncDowncallMethod(&printer, funcDecl) + st.printJavaBindingWrapperMethod(&printer, funcDecl) } assertOutput( @@ -304,16 +264,8 @@ final class MethodImportTests { * } */ public long makeInt() { - $ensureAlive() - var mh$ = swiftjava___FakeModule_MySwiftClass_makeInt.HANDLE; - try { - if (SwiftKit.TRACE_DOWNCALLS) { - SwiftKit.traceDowncall(this.$memorySegment()); - } - return (long) mh$.invokeExact(this.$memorySegment()); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } + $ensureAlive(); + return swiftjava___FakeModule_MySwiftClass_makeInt.call(this.$memorySegment()); } """ ) @@ -334,7 +286,7 @@ final class MethodImportTests { }! let output = CodePrinter.toString { printer in - st.printFuncDowncallMethod(&printer, initDecl) + st.printJavaBindingWrapperMethod(&printer, initDecl) } assertOutput( @@ -348,17 +300,9 @@ final class MethodImportTests { * } */ public static MySwiftClass init(long len, long cap, SwiftArena swiftArena$) { - var mh$ = swiftjava___FakeModule_MySwiftClass_init_len_cap.HANDLE; - try { MemorySegment _result = swiftArena$.allocate(MySwiftClass.$LAYOUT); - if (SwiftKit.TRACE_DOWNCALLS) { - SwiftKit.traceDowncall(len, cap, _result); - } - mh$.invokeExact(len, cap, _result); + swiftjava___FakeModule_MySwiftClass_init_len_cap.call(len, cap, _result) return new MySwiftClass(_result, swiftArena$); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } } """ ) @@ -379,7 +323,7 @@ final class MethodImportTests { }! let output = CodePrinter.toString { printer in - st.printFuncDowncallMethod(&printer, initDecl) + st.printJavaBindingWrapperMethod(&printer, initDecl) } assertOutput( @@ -393,17 +337,9 @@ final class MethodImportTests { * } */ public static MySwiftStruct init(long len, long cap, SwiftArena swiftArena$) { - var mh$ = swiftjava___FakeModule_MySwiftStruct_init_len_cap.HANDLE; - try { MemorySegment _result = swiftArena$.allocate(MySwiftStruct.$LAYOUT); - if (SwiftKit.TRACE_DOWNCALLS) { - SwiftKit.traceDowncall(len, cap, _result); - } - mh$.invokeExact(len, cap, _result); + swiftjava___FakeModule_MySwiftStruct_init_len_cap.call(len, cap, _result) return new MySwiftStruct(_result, swiftArena$); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } } """ ) diff --git a/Tests/JExtractSwiftTests/StringPassingTests.swift b/Tests/JExtractSwiftTests/StringPassingTests.swift index 21f0584c..08190399 100644 --- a/Tests/JExtractSwiftTests/StringPassingTests.swift +++ b/Tests/JExtractSwiftTests/StringPassingTests.swift @@ -33,8 +33,33 @@ final class StringPassingTests { try assertOutput( st, input: class_interfaceFile, .java, - detectChunkByInitialLines: 1, expectedChunks: [ + """ + /** + * {@snippet lang=c : + * ptrdiff_t swiftjava___FakeModule_writeString_string(const int8_t *string) + * } + */ + private static class swiftjava___FakeModule_writeString_string { + public static final FunctionDescriptor DESC = FunctionDescriptor.of( + /* -> */SwiftValueLayout.SWIFT_INT, + /* string: */SwiftValueLayout.SWIFT_POINTER + ); + public static final MemorySegment ADDR = + __FakeModule.findOrThrow("swiftjava___FakeModule_writeString_string"); + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + public static long call(java.lang.foreign.MemorySegment string) { + try { + if (SwiftKit.TRACE_DOWNCALLS) { + SwiftKit.traceDowncall(string); + } + return (long) HANDLE.invokeExact(string); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + } + """, """ /** * Downcall to Swift: @@ -43,15 +68,8 @@ final class StringPassingTests { * } */ public static long writeString(java.lang.String string) { - var mh$ = swiftjava___FakeModule_writeString_string.HANDLE; try(var arena$ = Arena.ofConfined()) { - var string$ = SwiftKit.toCString(string, arena$); - if (SwiftKit.TRACE_DOWNCALLS) { - SwiftKit.traceDowncall(string$); - } - return (long) mh$.invokeExact(string$); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + return swiftjava___FakeModule_writeString_string.call(SwiftKit.toCString(string, arena$)); } } """ diff --git a/Tests/JExtractSwiftTests/VariableImportTests.swift b/Tests/JExtractSwiftTests/VariableImportTests.swift index e407b234..55724293 100644 --- a/Tests/JExtractSwiftTests/VariableImportTests.swift +++ b/Tests/JExtractSwiftTests/VariableImportTests.swift @@ -54,6 +54,16 @@ final class VariableImportTests { public static final MemorySegment ADDR = FakeModule.findOrThrow("swiftjava_FakeModule_MySwiftClass_counterInt$get"); public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + public static long call(java.lang.foreign.MemorySegment self) { + try { + if (SwiftKit.TRACE_DOWNCALLS) { + SwiftKit.traceDowncall(self); + } + return (long) HANDLE.invokeExact(self); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } } """, """ @@ -65,15 +75,7 @@ final class VariableImportTests { */ public long getCounterInt() { $ensureAlive(); - var mh$ = swiftjava_FakeModule_MySwiftClass_counterInt$get.HANDLE; - try { - if (SwiftKit.TRACE_DOWNCALLS) { - SwiftKit.traceDowncall(this.$memorySegment()); - } - return (long) mh$.invokeExact(this.$memorySegment()); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } + return swiftjava_FakeModule_MySwiftClass_counterInt$get.call(this.$memorySegment()); } """, """ @@ -85,6 +87,16 @@ final class VariableImportTests { public static final MemorySegment ADDR = FakeModule.findOrThrow("swiftjava_FakeModule_MySwiftClass_counterInt$set"); public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + public static void call(long newValue, java.lang.foreign.MemorySegment self) { + try { + if (SwiftKit.TRACE_DOWNCALLS) { + SwiftKit.traceDowncall(newValue, self); + } + HANDLE.invokeExact(newValue, self); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } } """, """ @@ -96,15 +108,7 @@ final class VariableImportTests { */ public void setCounterInt(long newValue) { $ensureAlive(); - var mh$ = swiftjava_FakeModule_MySwiftClass_counterInt$set.HANDLE; - try { - if (SwiftKit.TRACE_DOWNCALLS) { - SwiftKit.traceDowncall(newValue, this.$memorySegment()); - } - mh$.invokeExact(newValue, this.$memorySegment()); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } + swiftjava_FakeModule_MySwiftClass_counterInt$set.call(newValue, this.$memorySegment()) } """, ] From 99fc99c7b06f0cd28a229f842fc9f2b57bc3b4e4 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Thu, 5 Jun 2025 18:41:01 +0900 Subject: [PATCH 255/426] Delete Makefile (#247) --- Makefile | 110 ------------------------------------------------------- 1 file changed, 110 deletions(-) delete mode 100644 Makefile diff --git a/Makefile b/Makefile deleted file mode 100644 index 4b24b5a3..00000000 --- a/Makefile +++ /dev/null @@ -1,110 +0,0 @@ -#===----------------------------------------------------------------------===# -# -# This source file is part of the Swift.org open source project -# -# Copyright (c) 2024 Apple Inc. and the Swift.org project authors -# Licensed under Apache License v2.0 -# -# See LICENSE.txt for license information -# See CONTRIBUTORS.txt for the list of Swift project authors -# -# SPDX-License-Identifier: Apache-2.0 -# -#===----------------------------------------------------------------------===# - -.PHONY: run clean all - -ARCH := $(shell arch) -UNAME := $(shell uname) - -ifeq ($(UNAME), Linux) -ifeq ($(ARCH), 'i386') - ARCH_SUBDIR := x86_64 -else - ARCH_SUBDIR := aarch64 -endif -BUILD_DIR := .build/$(ARCH_SUBDIR)-unknown-linux-gnu -LIB_SUFFIX := so -endif - -ifeq ($(UNAME), Darwin) -ifeq ($(ARCH), 'i386') - ARCH_SUBDIR := x86_64 -else - ARCH_SUBDIR := arm64 -endif -BUILD_DIR := .build/$(ARCH_SUBDIR)-apple-macosx -LIB_SUFFIX := dylib -endif - -ifeq ($(UNAME), Darwin) -ifeq ("${TOOLCHAINS}", "") - SWIFTC := "xcrun swiftc" -else - SWIFTC := "xcrun ${TOOLCHAINS}/usr/bin/swiftc" -endif -else -ifeq ("${TOOLCHAINS}", "") - SWIFTC := "swiftc" -else - SWIFTC := "${TOOLCHAINS}/usr/bin/swiftc" -endif -endif - -SAMPLES_DIR := "Samples" - -all: - @echo "Welcome to swift-java! There are several makefile targets to choose from:" - @echo " javakit-run: Run the JavaKit example program that uses Java libraries from Swift." - @echo " javakit-generate: Regenerate the Swift wrapper code for the various JavaKit libraries from Java. This only has to be done when changing the Java2Swift tool." - -$(BUILD_DIR)/debug/libJavaKit.$(LIB_SUFFIX) $(BUILD_DIR)/debug/Java2Swift: - swift build - -javakit-run: - cd Samples/JavaKitSampleApp && swift build && java -cp .build/plugins/outputs/javakitsampleapp/JavaKitExample/destination/JavaCompilerPlugin/Java -Djava.library.path=.build/debug com.example.swift.JavaKitSampleMain - -Java2Swift: $(BUILD_DIR)/debug/Java2Swift - -generate-JavaKit: Java2Swift - mkdir -p Sources/JavaKit/generated - $(BUILD_DIR)/debug/Java2Swift --module-name JavaKit -o Sources/JavaKit/generated Sources/JavaKit/swift-java.config - -generate-JavaKitCollection: Java2Swift - mkdir -p Sources/JavaKitCollection/generated - $(BUILD_DIR)/debug/Java2Swift --module-name JavaKitCollection --depends-on JavaKit=Sources/JavaKit/swift-java.config -o Sources/JavaKitCollection/generated Sources/JavaKitCollection/swift-java.config - -generate-JavaKitFunction: Java2Swift - mkdir -p Sources/JavaKitFunction/generated - $(BUILD_DIR)/debug/Java2Swift --module-name JavaKitFunction --depends-on JavaKit=Sources/JavaKit/swift-java.config -o Sources/JavaKitFunction/generated Sources/JavaKitFunction/swift-java.config - -generate-JavaKitReflection: Java2Swift generate-JavaKit generate-JavaKitCollection - mkdir -p Sources/JavaKitReflection/generated - $(BUILD_DIR)/debug/Java2Swift --module-name JavaKitReflection --depends-on JavaKit=Sources/JavaKit/swift-java.config --depends-on JavaKitCollection=Sources/JavaKitCollection/swift-java.config -o Sources/JavaKitReflection/generated Sources/JavaKitReflection/swift-java.config - -generate-JavaKitJar: Java2Swift generate-JavaKit generate-JavaKitCollection - mkdir -p Sources/JavaKitJar/generated - $(BUILD_DIR)/debug/Java2Swift --module-name JavaKitJar --depends-on JavaKit=Sources/JavaKit/swift-java.config --depends-on JavaKitCollection=Sources/JavaKitCollection/swift-java.config -o Sources/JavaKitJar/generated Sources/JavaKitJar/swift-java.config - -generate-JavaKitNetwork: Java2Swift generate-JavaKit generate-JavaKitCollection - mkdir -p Sources/JavaKitNetwork/generated - $(BUILD_DIR)/debug/Java2Swift --module-name JavaKitNetwork --depends-on JavaKit=Sources/JavaKit/swift-java.config --depends-on JavaKitCollection=Sources/JavaKitCollection/swift-java.config -o Sources/JavaKitNetwork/generated Sources/JavaKitNetwork/swift-java.config - -javakit-generate: generate-JavaKit generate-JavaKitReflection generate-JavaKitJar generate-JavaKitNetwork - -clean: - rm -rf .build; \ - rm -rf build; \ - rm -rf Samples/JExtractPluginSampleApp/.build; \ - rm -rf Samples/JExtractPluginSampleApp/build; \ - rm -rf Samples/SwiftKitExampleApp/src/generated/java/* - -format: - swift format --recursive . -i - -################################################# -### "SwiftKit" is the "call swift from java" ### -################################################# - -jextract-run: jextract-generate - ./gradlew Samples:SwiftKitSampleApp:run From c7fe4988108b17415fcf965c71c4db95dc2ac507 Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Thu, 5 Jun 2025 10:22:57 -0700 Subject: [PATCH 256/426] [JExtract] Santize trivia for declartion signature string Introduce `triviaSanitizedDescription` that prints tokens with trivia condensed into a single whitespace, or removed after opening or before closing parentheses. --- .../Convenience/SwiftSyntax+Extensions.swift | 54 ++++++++++++++++--- Sources/JExtractSwift/ImportedDecls.swift | 1 - .../MethodImportTests.swift | 9 +++- 3 files changed, 54 insertions(+), 10 deletions(-) diff --git a/Sources/JExtractSwift/Convenience/SwiftSyntax+Extensions.swift b/Sources/JExtractSwift/Convenience/SwiftSyntax+Extensions.swift index 848797a4..b732b9f8 100644 --- a/Sources/JExtractSwift/Convenience/SwiftSyntax+Extensions.swift +++ b/Sources/JExtractSwift/Convenience/SwiftSyntax+Extensions.swift @@ -177,17 +177,19 @@ extension DeclSyntaxProtocol { var signatureString: String { return switch DeclSyntax(self.detached).as(DeclSyntaxEnum.self) { case .functionDecl(let node): - node.with(\.body, nil).trimmedDescription + node.with(\.body, nil).triviaSanitizedDescription case .initializerDecl(let node): - node.with(\.body, nil).trimmedDescription + node.with(\.body, nil).triviaSanitizedDescription case .classDecl(let node): - node.with(\.memberBlock, "").trimmedDescription + node.with(\.memberBlock, "").triviaSanitizedDescription case .structDecl(let node): - node.with(\.memberBlock, "").trimmedDescription + node.with(\.memberBlock, "").triviaSanitizedDescription case .protocolDecl(let node): - node.with(\.memberBlock, "").trimmedDescription + node.with(\.memberBlock, "").triviaSanitizedDescription case .accessorDecl(let node): - node.with(\.body, nil).trimmedDescription + node.with(\.body, nil).triviaSanitizedDescription + case .subscriptDecl(let node): + node.with(\.accessorBlock, nil).triviaSanitizedDescription case .variableDecl(let node): node .with(\.bindings, PatternBindingListSyntax( @@ -197,9 +199,47 @@ extension DeclSyntaxProtocol { .with(\.initializer, nil) } )) - .trimmedDescription + .triviaSanitizedDescription default: fatalError("unimplemented \(self.kind)") } } + + /// Syntax text but without unnecessary trivia. + /// + /// Connective trivia are condensed into a single whitespace, but no space + /// after opening or before closing parentheses + var triviaSanitizedDescription: String { + let visitor = TriviaSanitizingDescriptionVisitor(viewMode: .sourceAccurate) + visitor.walk(self.trimmed) + return visitor.result + } +} + +class TriviaSanitizingDescriptionVisitor: SyntaxVisitor { + var result: String = "" + + var prevTokenKind: TokenKind = .endOfFile + var prevHadTrailingSpace: Bool = false + + override func visit(_ node: TokenSyntax) -> SyntaxVisitorContinueKind { + let tokenKind = node.tokenKind + switch (prevTokenKind, tokenKind) { + case + // No whitespace after open parentheses. + (.leftAngle, _), (.leftParen, _), (.leftSquare, _), (.endOfFile, _), + // No whitespace before close parentheses. + (_, .rightAngle), (_, .rightParen), (_, .rightSquare): + break + default: + if prevHadTrailingSpace || !node.leadingTrivia.isEmpty { + result += " " + } + } + result += node.text + prevTokenKind = tokenKind + prevHadTrailingSpace = !node.trailingTrivia.isEmpty + + return .skipChildren + } } diff --git a/Sources/JExtractSwift/ImportedDecls.swift b/Sources/JExtractSwift/ImportedDecls.swift index c29e3d5a..04a28d9e 100644 --- a/Sources/JExtractSwift/ImportedDecls.swift +++ b/Sources/JExtractSwift/ImportedDecls.swift @@ -50,7 +50,6 @@ public final class ImportedFunc: ImportedDecl, CustomStringConvertible { var translatedSignature: TranslatedFunctionSignature public var signatureString: String { - // FIXME: Remove comments and normalize trivia. self.swiftDecl.signatureString } diff --git a/Tests/JExtractSwiftTests/MethodImportTests.swift b/Tests/JExtractSwiftTests/MethodImportTests.swift index 526faece..25c028ce 100644 --- a/Tests/JExtractSwiftTests/MethodImportTests.swift +++ b/Tests/JExtractSwiftTests/MethodImportTests.swift @@ -28,11 +28,16 @@ final class MethodImportTests { import _StringProcessing import _SwiftConcurrencyShims - public func helloWorld() + /// Hello World! + public func /*comment*/helloWorld() public func globalTakeInt(i: Int) - public func globalTakeIntLongString(i32: Int32, l: Int64, s: String) + public func globalTakeIntLongString( + i32: Int32, + l: Int64, + s: String + ) public func globalReturnClass() -> MySwiftClass From 72bf28fd7ce765a5c1389ea539497f0fdcb952b1 Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Thu, 5 Jun 2025 12:53:13 -0700 Subject: [PATCH 257/426] [JExtract] Move 'apiKind' property to 'ImportedFunc' It was weird "the lowered signature" being the owner of the API kind information, and it was only used for rendering. Move it to `ImportedFunc` and pass it to `LoweredFunctionSignature.cdeclThunk()` API. --- ...wift2JavaTranslator+FunctionLowering.swift | 24 ++++++------------- Sources/JExtractSwift/ImportedDecls.swift | 19 +++++++++------ ...2JavaTranslator+JavaBindingsPrinting.swift | 2 +- ...Swift2JavaTranslator+JavaTranslation.swift | 5 ++-- Sources/JExtractSwift/Swift2JavaVisitor.swift | 9 ++++--- .../JExtractSwift/SwiftThunkTranslator.swift | 1 + Sources/JExtractSwift/ThunkNameRegistry.swift | 2 +- .../Asserts/LoweringAssertions.swift | 5 ++++ .../FunctionDescriptorImportTests.swift | 2 +- 9 files changed, 36 insertions(+), 33 deletions(-) diff --git a/Sources/JExtractSwift/CDeclLowering/Swift2JavaTranslator+FunctionLowering.swift b/Sources/JExtractSwift/CDeclLowering/Swift2JavaTranslator+FunctionLowering.swift index 17e461aa..671f373e 100644 --- a/Sources/JExtractSwift/CDeclLowering/Swift2JavaTranslator+FunctionLowering.swift +++ b/Sources/JExtractSwift/CDeclLowering/Swift2JavaTranslator+FunctionLowering.swift @@ -29,7 +29,7 @@ extension Swift2JavaTranslator { enclosingType: try enclosingType.map { try SwiftType($0, symbolTable: symbolTable) }, symbolTable: symbolTable ) - return try CdeclLowering(swiftStdlibTypes: swiftStdlibTypes).lowerFunctionSignature(signature, apiKind: .function) + return try CdeclLowering(swiftStdlibTypes: swiftStdlibTypes).lowerFunctionSignature(signature) } /// Lower the given initializer to a C-compatible entrypoint, @@ -46,7 +46,7 @@ extension Swift2JavaTranslator { symbolTable: symbolTable ) - return try CdeclLowering(swiftStdlibTypes: swiftStdlibTypes).lowerFunctionSignature(signature, apiKind: .initializer) + return try CdeclLowering(swiftStdlibTypes: swiftStdlibTypes).lowerFunctionSignature(signature) } /// Lower the given variable decl to a C-compatible entrypoint, @@ -69,7 +69,7 @@ extension Swift2JavaTranslator { enclosingType: try enclosingType.map { try SwiftType($0, symbolTable: symbolTable) }, symbolTable: symbolTable ) - return try CdeclLowering(swiftStdlibTypes: swiftStdlibTypes).lowerFunctionSignature(signature, apiKind: isSet ? .setter : .getter) + return try CdeclLowering(swiftStdlibTypes: swiftStdlibTypes).lowerFunctionSignature(signature) } } @@ -82,8 +82,7 @@ struct CdeclLowering { /// /// Throws an error if this function cannot be lowered for any reason. func lowerFunctionSignature( - _ signature: SwiftFunctionSignature, - apiKind: SwiftAPIKind + _ signature: SwiftFunctionSignature ) throws -> LoweredFunctionSignature { // Lower the self parameter. let loweredSelf: LoweredParameter? = switch signature.selfParameter { @@ -111,7 +110,6 @@ struct CdeclLowering { return LoweredFunctionSignature( original: signature, - apiKind: apiKind, selfParameter: loweredSelf, parameters: loweredParameters, result: loweredResult @@ -436,13 +434,6 @@ struct CdeclLowering { } } -package enum SwiftAPIKind { - case function - case initializer - case getter - case setter -} - /// Represent a Swift parameter in the cdecl thunk. struct LoweredParameter: Equatable { /// Lowered parameters in cdecl thunk. @@ -487,8 +478,6 @@ extension LoweredResult { public struct LoweredFunctionSignature: Equatable { var original: SwiftFunctionSignature - var apiKind: SwiftAPIKind - var selfParameter: LoweredParameter? var parameters: [LoweredParameter] var result: LoweredResult @@ -520,9 +509,10 @@ public struct LoweredFunctionSignature: Equatable { extension LoweredFunctionSignature { /// Produce the `@_cdecl` thunk for this lowered function signature that will /// call into the original function. - public func cdeclThunk( + package func cdeclThunk( cName: String, swiftAPIName: String, + as apiKind: SwiftAPIKind, stdlibTypes: SwiftStandardLibraryTypes ) -> FunctionDeclSyntax { @@ -563,7 +553,7 @@ extension LoweredFunctionSignature { // Build callee expression. let callee: ExprSyntax = if let selfExpr { - if case .initializer = self.apiKind { + if case .initializer = apiKind { // Don't bother to create explicit ${Self}.init expression. selfExpr } else { diff --git a/Sources/JExtractSwift/ImportedDecls.swift b/Sources/JExtractSwift/ImportedDecls.swift index c29e3d5a..904f0fba 100644 --- a/Sources/JExtractSwift/ImportedDecls.swift +++ b/Sources/JExtractSwift/ImportedDecls.swift @@ -17,7 +17,12 @@ import SwiftSyntax /// Any imported (Swift) declaration protocol ImportedDecl: AnyObject {} -public typealias JavaPackage = String +package enum SwiftAPIKind { + case function + case initializer + case getter + case setter +} /// Describes a Swift nominal type (e.g., a class, struct, enum) that has been /// imported and is being translated into Java. @@ -49,6 +54,8 @@ public final class ImportedFunc: ImportedDecl, CustomStringConvertible { var translatedSignature: TranslatedFunctionSignature + package var apiKind: SwiftAPIKind + public var signatureString: String { // FIXME: Remove comments and normalize trivia. self.swiftDecl.signatureString @@ -67,10 +74,6 @@ public final class ImportedFunc: ImportedDecl, CustomStringConvertible { try! loweredSignature.cFunctionDecl(cName: cName) } - package var kind: SwiftAPIKind { - loweredSignature.apiKind - } - var parentType: SwiftType? { guard let selfParameter = swiftSignature.selfParameter else { return nil @@ -94,7 +97,7 @@ public final class ImportedFunc: ImportedDecl, CustomStringConvertible { /// A display name to use to refer to the Swift declaration with its /// enclosing type, if there is one. public var displayName: String { - let prefix = switch self.kind { + let prefix = switch self.apiKind { case .getter: "getter:" case .setter: "setter:" case .function, .initializer: "" @@ -113,18 +116,20 @@ public final class ImportedFunc: ImportedDecl, CustomStringConvertible { module: String, swiftDecl: any DeclSyntaxProtocol, name: String, + apiKind: SwiftAPIKind, translatedSignature: TranslatedFunctionSignature ) { self.module = module self.name = name self.swiftDecl = swiftDecl + self.apiKind = apiKind self.translatedSignature = translatedSignature } public var description: String { """ ImportedFunc { - kind: \(kind) + apiKind: \(apiKind) module: \(module) name: \(name) signature: \(self.swiftDecl.signatureString) diff --git a/Sources/JExtractSwift/Swift2JavaTranslator+JavaBindingsPrinting.swift b/Sources/JExtractSwift/Swift2JavaTranslator+JavaBindingsPrinting.swift index a592e89e..0403ddf3 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator+JavaBindingsPrinting.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator+JavaBindingsPrinting.swift @@ -122,7 +122,7 @@ extension Swift2JavaTranslator { public func printJavaBindingWrapperMethod( _ printer: inout CodePrinter, _ decl: ImportedFunc) { - let methodName: String = switch decl.kind { + let methodName: String = switch decl.apiKind { case .getter: "get\(decl.name.toCamelCase)" case .setter: "set\(decl.name.toCamelCase)" case .function, .initializer: decl.name diff --git a/Sources/JExtractSwift/Swift2JavaTranslator+JavaTranslation.swift b/Sources/JExtractSwift/Swift2JavaTranslator+JavaTranslation.swift index e126ca8a..31935290 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator+JavaTranslation.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator+JavaTranslation.swift @@ -16,11 +16,10 @@ import JavaTypes extension Swift2JavaTranslator { func translate( - swiftSignature: SwiftFunctionSignature, - as apiKind: SwiftAPIKind + swiftSignature: SwiftFunctionSignature ) throws -> TranslatedFunctionSignature { let lowering = CdeclLowering(swiftStdlibTypes: self.swiftStdlibTypes) - let loweredSignature = try lowering.lowerFunctionSignature(swiftSignature, apiKind: apiKind) + let loweredSignature = try lowering.lowerFunctionSignature(swiftSignature) let translation = JavaTranslation(swiftStdlibTypes: self.swiftStdlibTypes) let translated = try translation.translate(loweredFunctionSignature: loweredSignature) diff --git a/Sources/JExtractSwift/Swift2JavaVisitor.swift b/Sources/JExtractSwift/Swift2JavaVisitor.swift index e51a7115..0c433e78 100644 --- a/Sources/JExtractSwift/Swift2JavaVisitor.swift +++ b/Sources/JExtractSwift/Swift2JavaVisitor.swift @@ -128,7 +128,7 @@ final class Swift2JavaVisitor: SyntaxVisitor { enclosingType: self.currentSwiftType, symbolTable: self.translator.symbolTable ) - translatedSignature = try translator.translate(swiftSignature: swiftSignature, as: .function) + translatedSignature = try translator.translate(swiftSignature: swiftSignature) } catch { self.log.debug("Failed to translate: '\(node.qualifiedNameForDebug)'; \(error)") return .skipChildren @@ -138,6 +138,7 @@ final class Swift2JavaVisitor: SyntaxVisitor { module: translator.swiftModuleName, swiftDecl: node, name: node.name.text, + apiKind: .function, translatedSignature: translatedSignature ) @@ -173,7 +174,7 @@ final class Swift2JavaVisitor: SyntaxVisitor { enclosingType: self.currentSwiftType, symbolTable: self.translator.symbolTable ) - translatedSignature = try translator.translate(swiftSignature: swiftSignature, as: kind) + translatedSignature = try translator.translate(swiftSignature: swiftSignature) } catch { self.log.debug("Failed to translate: \(node.qualifiedNameForDebug); \(error)") throw error @@ -183,6 +184,7 @@ final class Swift2JavaVisitor: SyntaxVisitor { module: translator.swiftModuleName, swiftDecl: node, name: varName, + apiKind: kind, translatedSignature: translatedSignature ) @@ -227,7 +229,7 @@ final class Swift2JavaVisitor: SyntaxVisitor { enclosingType: self.currentSwiftType, symbolTable: self.translator.symbolTable ) - translatedSignature = try translator.translate(swiftSignature: swiftSignature, as: .initializer) + translatedSignature = try translator.translate(swiftSignature: swiftSignature) } catch { self.log.debug("Failed to translate: \(node.qualifiedNameForDebug); \(error)") return .skipChildren @@ -236,6 +238,7 @@ final class Swift2JavaVisitor: SyntaxVisitor { module: translator.swiftModuleName, swiftDecl: node, name: "init", + apiKind: .initializer, translatedSignature: translatedSignature ) diff --git a/Sources/JExtractSwift/SwiftThunkTranslator.swift b/Sources/JExtractSwift/SwiftThunkTranslator.swift index 5676e3d5..7db4c50b 100644 --- a/Sources/JExtractSwift/SwiftThunkTranslator.swift +++ b/Sources/JExtractSwift/SwiftThunkTranslator.swift @@ -178,6 +178,7 @@ struct SwiftThunkTranslator { let thunkFunc = decl.loweredSignature.cdeclThunk( cName: thunkName, swiftAPIName: decl.name, + as: decl.apiKind, stdlibTypes: st.swiftStdlibTypes ) return [DeclSyntax(thunkFunc)] diff --git a/Sources/JExtractSwift/ThunkNameRegistry.swift b/Sources/JExtractSwift/ThunkNameRegistry.swift index 87bf1d70..222958e7 100644 --- a/Sources/JExtractSwift/ThunkNameRegistry.swift +++ b/Sources/JExtractSwift/ThunkNameRegistry.swift @@ -31,7 +31,7 @@ package struct ThunkNameRegistry { } let suffix: String - switch decl.kind { + switch decl.apiKind { case .getter: suffix = "$get" case .setter: diff --git a/Tests/JExtractSwiftTests/Asserts/LoweringAssertions.swift b/Tests/JExtractSwiftTests/Asserts/LoweringAssertions.swift index f0d3ce2d..cbdcc6dd 100644 --- a/Tests/JExtractSwiftTests/Asserts/LoweringAssertions.swift +++ b/Tests/JExtractSwiftTests/Asserts/LoweringAssertions.swift @@ -43,6 +43,7 @@ func assertLoweredFunction( translator.prepareForTranslation() let swiftFunctionName: String + let apiKind: SwiftAPIKind let loweredFunction: LoweredFunctionSignature if let inputFunction = inputDecl.as(FunctionDeclSyntax.self) { loweredFunction = try translator.lowerFunctionSignature( @@ -50,12 +51,14 @@ func assertLoweredFunction( enclosingType: enclosingType ) swiftFunctionName = inputFunction.name.text + apiKind = .function } else if let inputInitializer = inputDecl.as(InitializerDeclSyntax.self) { loweredFunction = try translator.lowerFunctionSignature( inputInitializer, enclosingType: enclosingType ) swiftFunctionName = "init" + apiKind = .initializer } else { fatalError("Unhandling declaration kind for lowering") } @@ -63,6 +66,7 @@ func assertLoweredFunction( let loweredCDecl = loweredFunction.cdeclThunk( cName: "c_\(swiftFunctionName)", swiftAPIName: swiftFunctionName, + as: apiKind, stdlibTypes: translator.swiftStdlibTypes ) @@ -124,6 +128,7 @@ func assertLoweredVariableAccessor( let loweredCDecl = loweredFunction?.cdeclThunk( cName: "c_\(swiftVariableName)", swiftAPIName: swiftVariableName, + as: isSet ? .setter : .getter, stdlibTypes: translator.swiftStdlibTypes ) diff --git a/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift b/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift index 44385b0a..9cdcdf58 100644 --- a/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift +++ b/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift @@ -271,7 +271,7 @@ extension FunctionDescriptorTests { let accessorDecl: ImportedFunc? = st.importedTypes.values.compactMap { $0.variables.first { - $0.name == identifier && $0.kind == accessorKind + $0.name == identifier && $0.apiKind == accessorKind } }.first guard let accessorDecl else { From 0f07f4a6585820b9276c5ed918d34ad286797888 Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Thu, 5 Jun 2025 13:33:27 -0700 Subject: [PATCH 258/426] [JExtract] Lazy Cdecl lowering and Java translation Make `Swift2JavaTranslator.analyze()` analyze only Swift signatures. Postpone Cdecl lowering and Java translation for cleaner separation of responsibilities. --- Sources/JExtractSwift/ImportedDecls.swift | 24 +++-------- ...2JavaTranslator+JavaBindingsPrinting.swift | 42 ++++++++++++------- ...Swift2JavaTranslator+JavaTranslation.swift | 25 +++++++---- ...t2JavaTranslator+SwiftThunkPrinting.swift} | 7 +++- .../JExtractSwift/Swift2JavaTranslator.swift | 3 ++ Sources/JExtractSwift/Swift2JavaVisitor.swift | 41 +++++++----------- Sources/JExtractSwift/ThunkNameRegistry.swift | 2 +- 7 files changed, 76 insertions(+), 68 deletions(-) rename Sources/JExtractSwift/{SwiftThunkTranslator.swift => Swift2JavaTranslator+SwiftThunkPrinting.swift} (96%) diff --git a/Sources/JExtractSwift/ImportedDecls.swift b/Sources/JExtractSwift/ImportedDecls.swift index 904f0fba..2a2e0cba 100644 --- a/Sources/JExtractSwift/ImportedDecls.swift +++ b/Sources/JExtractSwift/ImportedDecls.swift @@ -52,30 +52,18 @@ public final class ImportedFunc: ImportedDecl, CustomStringConvertible { public var swiftDecl: any DeclSyntaxProtocol - var translatedSignature: TranslatedFunctionSignature - package var apiKind: SwiftAPIKind + var functionSignature: SwiftFunctionSignature + public var signatureString: String { // FIXME: Remove comments and normalize trivia. self.swiftDecl.signatureString } - var loweredSignature: LoweredFunctionSignature { - translatedSignature.loweredSignature - } - - var swiftSignature: SwiftFunctionSignature { - loweredSignature.original - } - - package func cFunctionDecl(cName: String) -> CFunction { - // 'try!' because we know 'loweredSignature' can be described with C. - try! loweredSignature.cFunctionDecl(cName: cName) - } var parentType: SwiftType? { - guard let selfParameter = swiftSignature.selfParameter else { + guard let selfParameter = functionSignature.selfParameter else { return nil } switch selfParameter { @@ -92,7 +80,7 @@ public final class ImportedFunc: ImportedDecl, CustomStringConvertible { /// this will contain that declaration's imported name. /// /// This is necessary when rendering accessor Java code we need the type that "self" is expecting to have. - public var hasParent: Bool { translatedSignature.selfParameter != nil } + public var hasParent: Bool { functionSignature.selfParameter != nil } /// A display name to use to refer to the Swift declaration with its /// enclosing type, if there is one. @@ -117,13 +105,13 @@ public final class ImportedFunc: ImportedDecl, CustomStringConvertible { swiftDecl: any DeclSyntaxProtocol, name: String, apiKind: SwiftAPIKind, - translatedSignature: TranslatedFunctionSignature + functionSignature: SwiftFunctionSignature ) { self.module = module self.name = name self.swiftDecl = swiftDecl self.apiKind = apiKind - self.translatedSignature = translatedSignature + self.functionSignature = functionSignature } public var description: String { diff --git a/Sources/JExtractSwift/Swift2JavaTranslator+JavaBindingsPrinting.swift b/Sources/JExtractSwift/Swift2JavaTranslator+JavaBindingsPrinting.swift index 0403ddf3..90f98577 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator+JavaBindingsPrinting.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator+JavaBindingsPrinting.swift @@ -19,6 +19,11 @@ extension Swift2JavaTranslator { _ printer: inout CodePrinter, _ decl: ImportedFunc ) { + guard let _ = translatedSignature(for: decl) else { + // Failed to translate. Skip. + return + } + printer.printSeparator(decl.displayName) printJavaBindingDescriptorClass(&printer, decl) @@ -33,7 +38,9 @@ extension Swift2JavaTranslator { _ decl: ImportedFunc ) { let thunkName = thunkNameRegistry.functionThunkName(decl: decl) - let cFunc = decl.cFunctionDecl(cName: thunkName) + let translatedSignature = self.translatedSignature(for: decl)! + // 'try!' because we know 'loweredSignature' can be described with C. + let cFunc = try! translatedSignature.loweredSignature.cFunctionDecl(cName: thunkName) printer.printBraceBlock( """ @@ -129,19 +136,20 @@ extension Swift2JavaTranslator { } var modifiers = "public" - switch decl.swiftSignature.selfParameter { + switch decl.functionSignature.selfParameter { case .staticMethod, .initializer, nil: modifiers.append(" static") default: break } - let returnTy = decl.translatedSignature.result.javaResultType + let translatedSignature = self.translatedSignature(for: decl)! + let returnTy = translatedSignature.result.javaResultType - var paramDecls = decl.translatedSignature.parameters + var paramDecls = translatedSignature.parameters .flatMap(\.javaParameters) .map { "\($0.type) \($0.name)" } - if decl.translatedSignature.requiresSwiftArena { + if translatedSignature.requiresSwiftArena { paramDecls.append("SwiftArena swiftArena$") } @@ -157,7 +165,7 @@ extension Swift2JavaTranslator { \(modifiers) \(returnTy) \(methodName)(\(paramDecls.joined(separator: ", "))) """ ) { printer in - if case .instance(_) = decl.swiftSignature.selfParameter { + if case .instance(_) = decl.functionSignature.selfParameter { // Make sure the object has not been destroyed. printer.print("$ensureAlive();") } @@ -174,7 +182,9 @@ extension Swift2JavaTranslator { _ decl: ImportedFunc ) { //=== Part 1: prepare temporary arena if needed. - if decl.translatedSignature.requiresTemporaryArena { + let translatedSignature = self.translatedSignature(for: decl)! + + if translatedSignature.requiresTemporaryArena { printer.print("try(var arena$ = Arena.ofConfined()) {") printer.indent(); } @@ -183,21 +193,21 @@ extension Swift2JavaTranslator { var downCallArguments: [String] = [] // Regular parameters. - for (i, parameter) in decl.translatedSignature.parameters.enumerated() { - let original = decl.swiftSignature.parameters[i] + for (i, parameter) in translatedSignature.parameters.enumerated() { + let original = decl.functionSignature.parameters[i] let parameterName = original.parameterName ?? "_\(i)" let lowered = parameter.conversion.render(&printer, parameterName) downCallArguments.append(lowered) } // 'self' parameter. - if let selfParameter = decl.translatedSignature.selfParameter { + if let selfParameter = translatedSignature.selfParameter { let lowered = selfParameter.conversion.render(&printer, "this") downCallArguments.append(lowered) } // Indirect return receivers. - for outParameter in decl.translatedSignature.result.outParameters { + for outParameter in translatedSignature.result.outParameters { let memoryLayout = renderMemoryLayoutValue(for: outParameter.type) let arena = if let className = outParameter.type.className, @@ -222,27 +232,27 @@ extension Swift2JavaTranslator { let downCall = "\(thunkName).call(\(downCallArguments.joined(separator: ", ")))" //=== Part 4: Convert the return value. - if decl.translatedSignature.result.javaResultType == .void { + if translatedSignature.result.javaResultType == .void { printer.print("\(downCall);") } else { let placeholder: String - if decl.translatedSignature.result.outParameters.isEmpty { + if translatedSignature.result.outParameters.isEmpty { placeholder = downCall } else { // FIXME: Support cdecl thunk returning a value while populating the out parameters. printer.print("\(downCall);") placeholder = "_result" } - let result = decl.translatedSignature.result.conversion.render(&printer, placeholder) + let result = translatedSignature.result.conversion.render(&printer, placeholder) - if decl.translatedSignature.result.javaResultType != .void { + if translatedSignature.result.javaResultType != .void { printer.print("return \(result);") } else { printer.print("\(result);") } } - if decl.translatedSignature.requiresTemporaryArena { + if translatedSignature.requiresTemporaryArena { printer.outdent() printer.print("}") } diff --git a/Sources/JExtractSwift/Swift2JavaTranslator+JavaTranslation.swift b/Sources/JExtractSwift/Swift2JavaTranslator+JavaTranslation.swift index 31935290..bf1cd9d2 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator+JavaTranslation.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator+JavaTranslation.swift @@ -15,15 +15,26 @@ import JavaTypes extension Swift2JavaTranslator { - func translate( - swiftSignature: SwiftFunctionSignature - ) throws -> TranslatedFunctionSignature { - let lowering = CdeclLowering(swiftStdlibTypes: self.swiftStdlibTypes) - let loweredSignature = try lowering.lowerFunctionSignature(swiftSignature) + func translatedSignature( + for decl: ImportedFunc + ) -> TranslatedFunctionSignature? { + if let cached = translatedSignatures[decl] { + return cached + } - let translation = JavaTranslation(swiftStdlibTypes: self.swiftStdlibTypes) - let translated = try translation.translate(loweredFunctionSignature: loweredSignature) + let translated: TranslatedFunctionSignature? + do { + let lowering = CdeclLowering(swiftStdlibTypes: self.swiftStdlibTypes) + let loweredSignature = try lowering.lowerFunctionSignature(decl.functionSignature) + + let translation = JavaTranslation(swiftStdlibTypes: self.swiftStdlibTypes) + translated = try translation.translate(loweredFunctionSignature: loweredSignature) + } catch { + self.log.info("Failed to translate: '\(decl.swiftDecl.qualifiedNameForDebug)'; \(error)") + translated = nil + } + translatedSignatures[decl] = translated return translated } } diff --git a/Sources/JExtractSwift/SwiftThunkTranslator.swift b/Sources/JExtractSwift/Swift2JavaTranslator+SwiftThunkPrinting.swift similarity index 96% rename from Sources/JExtractSwift/SwiftThunkTranslator.swift rename to Sources/JExtractSwift/Swift2JavaTranslator+SwiftThunkPrinting.swift index 7db4c50b..51547ba8 100644 --- a/Sources/JExtractSwift/SwiftThunkTranslator.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator+SwiftThunkPrinting.swift @@ -174,8 +174,13 @@ struct SwiftThunkTranslator { func render(forFunc decl: ImportedFunc) -> [DeclSyntax] { st.log.trace("Rendering thunks for: \(decl.displayName)") + let thunkName = st.thunkNameRegistry.functionThunkName(decl: decl) - let thunkFunc = decl.loweredSignature.cdeclThunk( + guard let translatedSignatures = st.translatedSignature(for: decl) else { + return [] + } + + let thunkFunc = translatedSignatures.loweredSignature.cdeclThunk( cName: thunkName, swiftAPIName: decl.name, as: decl.apiKind, diff --git a/Sources/JExtractSwift/Swift2JavaTranslator.swift b/Sources/JExtractSwift/Swift2JavaTranslator.swift index c8ed5bbe..496c9b44 100644 --- a/Sources/JExtractSwift/Swift2JavaTranslator.swift +++ b/Sources/JExtractSwift/Swift2JavaTranslator.swift @@ -56,6 +56,9 @@ public final class Swift2JavaTranslator { package var thunkNameRegistry: ThunkNameRegistry = ThunkNameRegistry() + /// Cached Java translation result. 'nil' indicates failed translation. + var translatedSignatures: [ImportedFunc: TranslatedFunctionSignature?] = [:] + /// The name of the Swift module being translated. var swiftModuleName: String { symbolTable.moduleName diff --git a/Sources/JExtractSwift/Swift2JavaVisitor.swift b/Sources/JExtractSwift/Swift2JavaVisitor.swift index 0c433e78..4bb85a46 100644 --- a/Sources/JExtractSwift/Swift2JavaVisitor.swift +++ b/Sources/JExtractSwift/Swift2JavaVisitor.swift @@ -121,16 +121,15 @@ final class Swift2JavaVisitor: SyntaxVisitor { self.log.debug("Import function: '\(node.qualifiedNameForDebug)'") - let translatedSignature: TranslatedFunctionSignature + let signature: SwiftFunctionSignature do { - let swiftSignature = try SwiftFunctionSignature( + signature = try SwiftFunctionSignature( node, enclosingType: self.currentSwiftType, symbolTable: self.translator.symbolTable ) - translatedSignature = try translator.translate(swiftSignature: swiftSignature) } catch { - self.log.debug("Failed to translate: '\(node.qualifiedNameForDebug)'; \(error)") + self.log.debug("Failed to import: '\(node.qualifiedNameForDebug)'; \(error)") return .skipChildren } @@ -139,7 +138,7 @@ final class Swift2JavaVisitor: SyntaxVisitor { swiftDecl: node, name: node.name.text, apiKind: .function, - translatedSignature: translatedSignature + functionSignature: signature ) log.debug("Record imported method \(node.qualifiedNameForDebug)") @@ -166,26 +165,19 @@ final class Swift2JavaVisitor: SyntaxVisitor { self.log.debug("Import variable: \(node.kind) '\(node.qualifiedNameForDebug)'") func importAccessor(kind: SwiftAPIKind) throws { - let translatedSignature: TranslatedFunctionSignature - do { - let swiftSignature = try SwiftFunctionSignature( - node, - isSet: kind == .setter, - enclosingType: self.currentSwiftType, - symbolTable: self.translator.symbolTable - ) - translatedSignature = try translator.translate(swiftSignature: swiftSignature) - } catch { - self.log.debug("Failed to translate: \(node.qualifiedNameForDebug); \(error)") - throw error - } + let signature = try SwiftFunctionSignature( + node, + isSet: kind == .setter, + enclosingType: self.currentSwiftType, + symbolTable: self.translator.symbolTable + ) let imported = ImportedFunc( module: translator.swiftModuleName, swiftDecl: node, name: varName, apiKind: kind, - translatedSignature: translatedSignature + functionSignature: signature ) log.debug("Record imported variable accessor \(kind == .getter ? "getter" : "setter"):\(node.qualifiedNameForDebug)") @@ -205,7 +197,7 @@ final class Swift2JavaVisitor: SyntaxVisitor { try importAccessor(kind: .setter) } } catch { - self.log.debug("Failed to translate: \(node.qualifiedNameForDebug); \(error)") + self.log.debug("Failed to import: \(node.qualifiedNameForDebug); \(error)") return .skipChildren } @@ -222,16 +214,15 @@ final class Swift2JavaVisitor: SyntaxVisitor { self.log.debug("Import initializer: \(node.kind) '\(node.qualifiedNameForDebug)'") - let translatedSignature: TranslatedFunctionSignature + let signature: SwiftFunctionSignature do { - let swiftSignature = try SwiftFunctionSignature( + signature = try SwiftFunctionSignature( node, enclosingType: self.currentSwiftType, symbolTable: self.translator.symbolTable ) - translatedSignature = try translator.translate(swiftSignature: swiftSignature) } catch { - self.log.debug("Failed to translate: \(node.qualifiedNameForDebug); \(error)") + self.log.debug("Failed to import: \(node.qualifiedNameForDebug); \(error)") return .skipChildren } let imported = ImportedFunc( @@ -239,7 +230,7 @@ final class Swift2JavaVisitor: SyntaxVisitor { swiftDecl: node, name: "init", apiKind: .initializer, - translatedSignature: translatedSignature + functionSignature: signature ) currentType.initializers.append(imported) diff --git a/Sources/JExtractSwift/ThunkNameRegistry.swift b/Sources/JExtractSwift/ThunkNameRegistry.swift index 222958e7..3369ec62 100644 --- a/Sources/JExtractSwift/ThunkNameRegistry.swift +++ b/Sources/JExtractSwift/ThunkNameRegistry.swift @@ -37,7 +37,7 @@ package struct ThunkNameRegistry { case .setter: suffix = "$set" default: - suffix = decl.swiftSignature.parameters + suffix = decl.functionSignature.parameters .map { "_" + ($0.argumentLabel ?? "_") } .joined() } From eb86790ea5b686579ca6d95936a35b9ede2772f3 Mon Sep 17 00:00:00 2001 From: Alsey Coleman Miller Date: Sat, 7 Jun 2025 23:44:06 -0400 Subject: [PATCH 259/426] Don't link `jvm` on Android --- Package.swift | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Package.swift b/Package.swift index 42b74041..e7cbf76f 100644 --- a/Package.swift +++ b/Package.swift @@ -207,7 +207,10 @@ let package = Package( "-L\(javaHome)/lib" ], .when(platforms: [.windows])), - .linkedLibrary("jvm"), + .linkedLibrary( + "jvm", + .when(platforms: [.linux, .macOS, .windows]) + ), ] ), .target( From bfc521e8719b0215ed10ca283404a7400f2a7b26 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Mon, 9 Jun 2025 15:15:12 +0900 Subject: [PATCH 260/426] Try out validating samples in individual jobs This way we get more parallelism and easier to spot signal which sample breaks when it does. Since the samples are our primary test drivers given all the source generation and fetching, giving them individual jobs I think is reasonable. --- .github/workflows/pull_request.yml | 104 +++++++++++++++++++++++++++-- 1 file changed, 97 insertions(+), 7 deletions(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 2aaa845b..8fa774bd 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -64,8 +64,8 @@ jobs: - name: Swift Test run: "swift test" - verify-samples: - name: Verify Samples (swift:${{ matrix.swift_version }} jdk:${{matrix.jdk_vendor}} os:${{ matrix.os_version }}) + verify-sample-01: + name: Verify Sample JavaDependencySampleApp (swift:${{ matrix.swift_version }} jdk:${{matrix.jdk_vendor}} os:${{ matrix.os_version }}) runs-on: ubuntu-latest strategy: fail-fast: false @@ -84,15 +84,105 @@ jobs: uses: ./.github/actions/prepare_env - name: "Verify Sample: JavaDependencySampleApp" run: .github/scripts/validate_sample.sh Samples/JavaDependencySampleApp - - name: "Verify Sample: JavaKitSampleApp" + verify-sample-02: + name: Verify Sample JavaKitSampleApp (swift:${{ matrix.swift_version }} jdk:${{matrix.jdk_vendor}} os:${{ matrix.os_version }}) + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + # swift_version: ['nightly-main'] + swift_version: ['6.0.2'] + os_version: ['jammy'] + jdk_vendor: ['Corretto'] + container: + image: ${{ (contains(matrix.swift_version, 'nightly') && 'swiftlang/swift') || 'swift' }}:${{ matrix.swift_version }}-${{ matrix.os_version }} + env: + JAVA_HOME: "/usr/lib/jvm/default-jdk" + steps: + - uses: actions/checkout@v4 + - name: Prepare CI Environment + uses: ./.github/actions/prepare_env + - name: "Verify Sample" run: .github/scripts/validate_sample.sh Samples/JavaKitSampleApp - - name: "Verify Sample: JavaProbablyPrime" + verify-sample-03: + name: Verify Sample JavaProbablyPrime (swift:${{ matrix.swift_version }} jdk:${{matrix.jdk_vendor}} os:${{ matrix.os_version }}) + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + # swift_version: ['nightly-main'] + swift_version: ['6.0.2'] + os_version: ['jammy'] + jdk_vendor: ['Corretto'] + container: + image: ${{ (contains(matrix.swift_version, 'nightly') && 'swiftlang/swift') || 'swift' }}:${{ matrix.swift_version }}-${{ matrix.os_version }} + env: + JAVA_HOME: "/usr/lib/jvm/default-jdk" + steps: + - uses: actions/checkout@v4 + - name: Prepare CI Environment + uses: ./.github/actions/prepare_env + - name: "Verify Sample" run: .github/scripts/validate_sample.sh Samples/JavaProbablyPrime - - name: "Verify Sample: JavaSieve" + verify-sample-04: + name: Verify Sample JavaSieve (swift:${{ matrix.swift_version }} jdk:${{matrix.jdk_vendor}} os:${{ matrix.os_version }}) + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + # swift_version: ['nightly-main'] + swift_version: ['6.0.2'] + os_version: ['jammy'] + jdk_vendor: ['Corretto'] + container: + image: ${{ (contains(matrix.swift_version, 'nightly') && 'swiftlang/swift') || 'swift' }}:${{ matrix.swift_version }}-${{ matrix.os_version }} + env: + JAVA_HOME: "/usr/lib/jvm/default-jdk" + steps: + - uses: actions/checkout@v4 + - name: Prepare CI Environment + uses: ./.github/actions/prepare_env + - name: "Verify Sample" run: .github/scripts/validate_sample.sh Samples/JavaSieve - - name: "Verify Sample: SwiftAndJavaJarSampleLib" + verify-sample-05: + name: Verify Sample SwiftAndJavaJarSampleLib (swift:${{ matrix.swift_version }} jdk:${{matrix.jdk_vendor}} os:${{ matrix.os_version }}) + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + # swift_version: ['nightly-main'] + swift_version: ['6.0.2'] + os_version: ['jammy'] + jdk_vendor: ['Corretto'] + container: + image: ${{ (contains(matrix.swift_version, 'nightly') && 'swiftlang/swift') || 'swift' }}:${{ matrix.swift_version }}-${{ matrix.os_version }} + env: + JAVA_HOME: "/usr/lib/jvm/default-jdk" + steps: + - uses: actions/checkout@v4 + - name: Prepare CI Environment + uses: ./.github/actions/prepare_env + - name: "Verify Sample" run: .github/scripts/validate_sample.sh Samples/SwiftAndJavaJarSampleLib - - name: "Verify Sample: SwiftKitSampleApp" + verify-sample-06: + name: Verify Sample SwiftKitSampleApp (swift:${{ matrix.swift_version }} jdk:${{matrix.jdk_vendor}} os:${{ matrix.os_version }}) + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + # swift_version: ['nightly-main'] + swift_version: ['6.0.2'] + os_version: ['jammy'] + jdk_vendor: ['Corretto'] + container: + image: ${{ (contains(matrix.swift_version, 'nightly') && 'swiftlang/swift') || 'swift' }}:${{ matrix.swift_version }}-${{ matrix.os_version }} + env: + JAVA_HOME: "/usr/lib/jvm/default-jdk" + steps: + - uses: actions/checkout@v4 + - name: Prepare CI Environment + uses: ./.github/actions/prepare_env + - name: "Verify Sample" run: .github/scripts/validate_sample.sh Samples/SwiftKitSampleApp # TODO: Benchmark compile crashes in CI, enable when nightly toolchains in better shape. # - name: Build (Swift) Benchmarks From 50350bb4785e321e7a113b15b9361bd38e5368c9 Mon Sep 17 00:00:00 2001 From: Konrad 'ktoso' Malawski Date: Thu, 5 Jun 2025 14:59:28 +0900 Subject: [PATCH 261/426] rename Java2SwiftLib to SwiftJavaLib --- Package.swift | 16 ++++++++-------- .../JavaClassTranslator.swift | 0 .../JavaTranslator+Configuration.swift | 0 .../JavaTranslator+Validation.swift | 0 .../JavaTranslator.swift | 0 .../MethodVariance.swift | 0 .../OptionalKind.swift | 0 .../StringExtras.swift | 0 .../TranslationError.swift | 0 .../String+Extensions.swift | 4 ++-- .../SwiftJava+EmitConfiguration.swift} | 5 ++--- .../SwiftJava+FetchDependencies.swift} | 6 +++--- .../SwiftJava+GenerateWrappers.swift} | 6 +++--- .../SwiftJava.swift} | 8 ++++---- .../Java2SwiftTests.swift | 2 +- .../JavaTranslatorValidationTests.swift | 2 +- 16 files changed, 24 insertions(+), 25 deletions(-) rename Sources/{Java2SwiftLib => SwiftJavaLib}/JavaClassTranslator.swift (100%) rename Sources/{Java2SwiftLib => SwiftJavaLib}/JavaTranslator+Configuration.swift (100%) rename Sources/{Java2SwiftLib => SwiftJavaLib}/JavaTranslator+Validation.swift (100%) rename Sources/{Java2SwiftLib => SwiftJavaLib}/JavaTranslator.swift (100%) rename Sources/{Java2SwiftLib => SwiftJavaLib}/MethodVariance.swift (100%) rename Sources/{Java2SwiftLib => SwiftJavaLib}/OptionalKind.swift (100%) rename Sources/{Java2SwiftLib => SwiftJavaLib}/StringExtras.swift (100%) rename Sources/{Java2SwiftLib => SwiftJavaLib}/TranslationError.swift (100%) rename Sources/{Java2Swift => SwiftJavaTool}/String+Extensions.swift (97%) rename Sources/{Java2Swift/JavaToSwift+EmitConfiguration.swift => SwiftJavaTool/SwiftJava+EmitConfiguration.swift} (98%) rename Sources/{Java2Swift/JavaToSwift+FetchDependencies.swift => SwiftJavaTool/SwiftJava+FetchDependencies.swift} (99%) rename Sources/{Java2Swift/JavaToSwift+GenerateWrappers.swift => SwiftJavaTool/SwiftJava+GenerateWrappers.swift} (98%) rename Sources/{Java2Swift/JavaToSwift.swift => SwiftJavaTool/SwiftJava.swift} (99%) rename Tests/{Java2SwiftTests => SwiftJavaTests}/Java2SwiftTests.swift (99%) rename Tests/{Java2SwiftTests => SwiftJavaTests}/JavaTranslatorValidationTests.swift (98%) diff --git a/Package.swift b/Package.swift index 42b74041..05cd4309 100644 --- a/Package.swift +++ b/Package.swift @@ -92,8 +92,8 @@ let package = Package( ), .executable( - name: "Java2Swift", - targets: ["Java2Swift"] + name: "swift-java", + targets: ["SwiftJavaTool"] ), // ==== Plugin for building Java code @@ -274,7 +274,7 @@ let package = Package( name: "Java2SwiftPlugin", capability: .buildTool(), dependencies: [ - "Java2Swift" + "SwiftJavaTool" ] ), @@ -312,7 +312,7 @@ let package = Package( ), .target( - name: "Java2SwiftLib", + name: "SwiftJavaLib", dependencies: [ .product(name: "SwiftBasicFormat", package: "swift-syntax"), .product(name: "SwiftSyntax", package: "swift-syntax"), @@ -334,7 +334,7 @@ let package = Package( ), .executableTarget( - name: "Java2Swift", + name: "SwiftJavaTool", dependencies: [ .product(name: "SwiftBasicFormat", package: "swift-syntax"), .product(name: "SwiftSyntax", package: "swift-syntax"), @@ -343,7 +343,7 @@ let package = Package( "JavaKit", "JavaKitJar", "JavaKitNetwork", - "Java2SwiftLib", + "SwiftJavaLib", "JavaKitShared", ], @@ -427,8 +427,8 @@ let package = Package( ), .testTarget( - name: "Java2SwiftTests", - dependencies: ["Java2SwiftLib"], + name: "SwiftJavaTests", + dependencies: ["SwiftJavaLib"], swiftSettings: [ .swiftLanguageMode(.v5), .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) diff --git a/Sources/Java2SwiftLib/JavaClassTranslator.swift b/Sources/SwiftJavaLib/JavaClassTranslator.swift similarity index 100% rename from Sources/Java2SwiftLib/JavaClassTranslator.swift rename to Sources/SwiftJavaLib/JavaClassTranslator.swift diff --git a/Sources/Java2SwiftLib/JavaTranslator+Configuration.swift b/Sources/SwiftJavaLib/JavaTranslator+Configuration.swift similarity index 100% rename from Sources/Java2SwiftLib/JavaTranslator+Configuration.swift rename to Sources/SwiftJavaLib/JavaTranslator+Configuration.swift diff --git a/Sources/Java2SwiftLib/JavaTranslator+Validation.swift b/Sources/SwiftJavaLib/JavaTranslator+Validation.swift similarity index 100% rename from Sources/Java2SwiftLib/JavaTranslator+Validation.swift rename to Sources/SwiftJavaLib/JavaTranslator+Validation.swift diff --git a/Sources/Java2SwiftLib/JavaTranslator.swift b/Sources/SwiftJavaLib/JavaTranslator.swift similarity index 100% rename from Sources/Java2SwiftLib/JavaTranslator.swift rename to Sources/SwiftJavaLib/JavaTranslator.swift diff --git a/Sources/Java2SwiftLib/MethodVariance.swift b/Sources/SwiftJavaLib/MethodVariance.swift similarity index 100% rename from Sources/Java2SwiftLib/MethodVariance.swift rename to Sources/SwiftJavaLib/MethodVariance.swift diff --git a/Sources/Java2SwiftLib/OptionalKind.swift b/Sources/SwiftJavaLib/OptionalKind.swift similarity index 100% rename from Sources/Java2SwiftLib/OptionalKind.swift rename to Sources/SwiftJavaLib/OptionalKind.swift diff --git a/Sources/Java2SwiftLib/StringExtras.swift b/Sources/SwiftJavaLib/StringExtras.swift similarity index 100% rename from Sources/Java2SwiftLib/StringExtras.swift rename to Sources/SwiftJavaLib/StringExtras.swift diff --git a/Sources/Java2SwiftLib/TranslationError.swift b/Sources/SwiftJavaLib/TranslationError.swift similarity index 100% rename from Sources/Java2SwiftLib/TranslationError.swift rename to Sources/SwiftJavaLib/TranslationError.swift diff --git a/Sources/Java2Swift/String+Extensions.swift b/Sources/SwiftJavaTool/String+Extensions.swift similarity index 97% rename from Sources/Java2Swift/String+Extensions.swift rename to Sources/SwiftJavaTool/String+Extensions.swift index 26a20241..f2bb9e72 100644 --- a/Sources/Java2Swift/String+Extensions.swift +++ b/Sources/SwiftJavaTool/String+Extensions.swift @@ -14,10 +14,10 @@ import Foundation import ArgumentParser -import Java2SwiftLib +import SwiftJavaLib import JavaKit import JavaKitJar -import Java2SwiftLib +import SwiftJavaLib import JavaKitConfigurationShared extension String { diff --git a/Sources/Java2Swift/JavaToSwift+EmitConfiguration.swift b/Sources/SwiftJavaTool/SwiftJava+EmitConfiguration.swift similarity index 98% rename from Sources/Java2Swift/JavaToSwift+EmitConfiguration.swift rename to Sources/SwiftJavaTool/SwiftJava+EmitConfiguration.swift index 6754d381..e029d2db 100644 --- a/Sources/Java2Swift/JavaToSwift+EmitConfiguration.swift +++ b/Sources/SwiftJavaTool/SwiftJava+EmitConfiguration.swift @@ -14,13 +14,12 @@ import Foundation import ArgumentParser -import Java2SwiftLib +import SwiftJavaLib import JavaKit import JavaKitJar -import Java2SwiftLib import JavaKitConfigurationShared -extension JavaToSwift { +extension SwiftJava { // TODO: make this perhaps "emit type mappings" mutating func emitConfiguration( diff --git a/Sources/Java2Swift/JavaToSwift+FetchDependencies.swift b/Sources/SwiftJavaTool/SwiftJava+FetchDependencies.swift similarity index 99% rename from Sources/Java2Swift/JavaToSwift+FetchDependencies.swift rename to Sources/SwiftJavaTool/SwiftJava+FetchDependencies.swift index 2a9694c0..47570b19 100644 --- a/Sources/Java2Swift/JavaToSwift+FetchDependencies.swift +++ b/Sources/SwiftJavaTool/SwiftJava+FetchDependencies.swift @@ -13,16 +13,16 @@ //===----------------------------------------------------------------------===// import Foundation -import Java2SwiftLib +import SwiftJavaLib import JavaKit import Foundation import JavaKitJar -import Java2SwiftLib +import SwiftJavaLib import JavaKitConfigurationShared import JavaKitShared import _Subprocess -extension JavaToSwift { +extension SwiftJava { var SwiftJavaClasspathPrefix: String { "SWIFT_JAVA_CLASSPATH:" } diff --git a/Sources/Java2Swift/JavaToSwift+GenerateWrappers.swift b/Sources/SwiftJavaTool/SwiftJava+GenerateWrappers.swift similarity index 98% rename from Sources/Java2Swift/JavaToSwift+GenerateWrappers.swift rename to Sources/SwiftJavaTool/SwiftJava+GenerateWrappers.swift index 67aa3f9c..a57644de 100644 --- a/Sources/Java2Swift/JavaToSwift+GenerateWrappers.swift +++ b/Sources/SwiftJavaTool/SwiftJava+GenerateWrappers.swift @@ -14,13 +14,13 @@ import Foundation import ArgumentParser -import Java2SwiftLib +import SwiftJavaLib import JavaKit import JavaKitJar -import Java2SwiftLib +import SwiftJavaLib import JavaKitConfigurationShared -extension JavaToSwift { +extension SwiftJava { mutating func generateWrappers( config: Configuration, classpath: String, diff --git a/Sources/Java2Swift/JavaToSwift.swift b/Sources/SwiftJavaTool/SwiftJava.swift similarity index 99% rename from Sources/Java2Swift/JavaToSwift.swift rename to Sources/SwiftJavaTool/SwiftJava.swift index 536b3fd1..c8be85a5 100644 --- a/Sources/Java2Swift/JavaToSwift.swift +++ b/Sources/SwiftJavaTool/SwiftJava.swift @@ -14,7 +14,7 @@ import ArgumentParser import Foundation -import Java2SwiftLib +import SwiftJavaLib import JavaKit import JavaKitJar import JavaKitNetwork @@ -26,8 +26,8 @@ import JavaKitShared /// Command-line utility to drive the export of Java classes into Swift types. @main -struct JavaToSwift: AsyncParsableCommand { - static var _commandName: String { "Java2Swift" } +struct SwiftJava: AsyncParsableCommand { + static var _commandName: String { "swift-java" } @Option(help: "The name of the Swift module into which the resulting Swift types will be generated.") var moduleName: String? @@ -382,7 +382,7 @@ struct JavaToSwift: AsyncParsableCommand { } } -extension JavaToSwift { +extension SwiftJava { /// Get base configuration, depending on if we are to 'amend' or 'overwrite' the existing configuration. package func getBaseConfigurationForWrite() throws -> (Bool, Configuration) { guard let actualOutputDirectory = self.actualOutputDirectory else { diff --git a/Tests/Java2SwiftTests/Java2SwiftTests.swift b/Tests/SwiftJavaTests/Java2SwiftTests.swift similarity index 99% rename from Tests/Java2SwiftTests/Java2SwiftTests.swift rename to Tests/SwiftJavaTests/Java2SwiftTests.swift index 48440522..e2b68a34 100644 --- a/Tests/Java2SwiftTests/Java2SwiftTests.swift +++ b/Tests/SwiftJavaTests/Java2SwiftTests.swift @@ -14,7 +14,7 @@ @_spi(Testing) import JavaKit -import Java2SwiftLib +import SwiftJavaLib import XCTest // NOTE: Workaround for https://github.com/swiftlang/swift-java/issues/43 /// Handy reference to the JVM abstraction. diff --git a/Tests/Java2SwiftTests/JavaTranslatorValidationTests.swift b/Tests/SwiftJavaTests/JavaTranslatorValidationTests.swift similarity index 98% rename from Tests/Java2SwiftTests/JavaTranslatorValidationTests.swift rename to Tests/SwiftJavaTests/JavaTranslatorValidationTests.swift index e5c3a951..a203486a 100644 --- a/Tests/Java2SwiftTests/JavaTranslatorValidationTests.swift +++ b/Tests/SwiftJavaTests/JavaTranslatorValidationTests.swift @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -import Java2SwiftLib +import SwiftJavaLib import XCTest final class JavaTranslatorValidationTests: XCTestCase { From 929c6c45f7a62b1f999ff90baf5915518b7d6e6c Mon Sep 17 00:00:00 2001 From: Konrad 'ktoso' Malawski Date: Thu, 5 Jun 2025 17:15:57 +0900 Subject: [PATCH 262/426] rename swift2java plugin to SwiftJavaPlugin --- Package.swift | 6 +++--- .../SwiftJavaPlugin.swift} | 6 +++--- .../{Java2SwiftPlugin => SwiftJavaPlugin}/_PluginsShared | 0 Samples/JavaDependencySampleApp/Package.swift | 4 ++-- Samples/JavaKitSampleApp/Package.swift | 2 +- Samples/JavaProbablyPrime/Package.swift | 2 +- Samples/JavaSieve/Package.swift | 4 ++-- 7 files changed, 12 insertions(+), 12 deletions(-) rename Plugins/{Java2SwiftPlugin/Java2SwiftPlugin.swift => SwiftJavaPlugin/SwiftJavaPlugin.swift} (97%) rename Plugins/{Java2SwiftPlugin => SwiftJavaPlugin}/_PluginsShared (100%) diff --git a/Package.swift b/Package.swift index 05cd4309..48abbdb8 100644 --- a/Package.swift +++ b/Package.swift @@ -106,9 +106,9 @@ let package = Package( // ==== Plugin for wrapping Java classes in Swift .plugin( - name: "Java2SwiftPlugin", + name: "SwiftJavaPlugin", targets: [ - "Java2SwiftPlugin" + "SwiftJavaPlugin" ] ), @@ -271,7 +271,7 @@ let package = Package( ), .plugin( - name: "Java2SwiftPlugin", + name: "SwiftJavaPlugin", capability: .buildTool(), dependencies: [ "SwiftJavaTool" diff --git a/Plugins/Java2SwiftPlugin/Java2SwiftPlugin.swift b/Plugins/SwiftJavaPlugin/SwiftJavaPlugin.swift similarity index 97% rename from Plugins/Java2SwiftPlugin/Java2SwiftPlugin.swift rename to Plugins/SwiftJavaPlugin/SwiftJavaPlugin.swift index 88507f2e..05e6db0d 100644 --- a/Plugins/Java2SwiftPlugin/Java2SwiftPlugin.swift +++ b/Plugins/SwiftJavaPlugin/SwiftJavaPlugin.swift @@ -18,7 +18,7 @@ import PackagePlugin fileprivate let SwiftJavaConfigFileName = "swift-java.config" @main -struct Java2SwiftBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin { +struct SwiftJavaBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin { var pluginName: String = "swift-java" var verbose: Bool = getEnvironmentBool("SWIFT_JAVA_VERBOSE") @@ -27,7 +27,7 @@ struct Java2SwiftBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin { log("Create build commands for target '\(target.name)'") guard let sourceModule = target.sourceModule else { return [] } - let executable = try context.tool(named: "Java2Swift").url + let executable = try context.tool(named: "SwiftJavaTool").url var commands: [Command] = [] // Note: Target doesn't have a directoryURL counterpart to directory, @@ -199,7 +199,7 @@ struct Java2SwiftBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin { } } -extension Java2SwiftBuildToolPlugin { +extension SwiftJavaBuildToolPlugin { func argumentsModuleName(sourceModule: Target) -> [String] { return [ "--module-name", sourceModule.name diff --git a/Plugins/Java2SwiftPlugin/_PluginsShared b/Plugins/SwiftJavaPlugin/_PluginsShared similarity index 100% rename from Plugins/Java2SwiftPlugin/_PluginsShared rename to Plugins/SwiftJavaPlugin/_PluginsShared diff --git a/Samples/JavaDependencySampleApp/Package.swift b/Samples/JavaDependencySampleApp/Package.swift index 2b5ae361..b39e7b81 100644 --- a/Samples/JavaDependencySampleApp/Package.swift +++ b/Samples/JavaDependencySampleApp/Package.swift @@ -76,7 +76,7 @@ let package = Package( .swiftLanguageMode(.v5), ], plugins: [ - .plugin(name: "Java2SwiftPlugin", package: "swift-java"), + .plugin(name: "SwiftJavaPlugin", package: "swift-java"), ] ), @@ -96,7 +96,7 @@ let package = Package( ], plugins: [ // .plugin(name: "SwiftJavaBootstrapJavaPlugin", package: "swift-java"), - .plugin(name: "Java2SwiftPlugin", package: "swift-java"), + .plugin(name: "SwiftJavaPlugin", package: "swift-java"), ] ), diff --git a/Samples/JavaKitSampleApp/Package.swift b/Samples/JavaKitSampleApp/Package.swift index e51867cc..0956290c 100644 --- a/Samples/JavaKitSampleApp/Package.swift +++ b/Samples/JavaKitSampleApp/Package.swift @@ -77,7 +77,7 @@ let package = Package( plugins: [ .plugin(name: "JavaCompilerPlugin", package: "swift-java"), .plugin(name: "JExtractSwiftPlugin", package: "swift-java"), - .plugin(name: "Java2SwiftPlugin", package: "swift-java"), + .plugin(name: "SwiftJavaPlugin", package: "swift-java"), ] ), ] diff --git a/Samples/JavaProbablyPrime/Package.swift b/Samples/JavaProbablyPrime/Package.swift index e837bfdb..4cc887f8 100644 --- a/Samples/JavaProbablyPrime/Package.swift +++ b/Samples/JavaProbablyPrime/Package.swift @@ -34,7 +34,7 @@ let package = Package( .swiftLanguageMode(.v5) ], plugins: [ - .plugin(name: "Java2SwiftPlugin", package: "swift-java"), + .plugin(name: "SwiftJavaPlugin", package: "swift-java"), ] ), ] diff --git a/Samples/JavaSieve/Package.swift b/Samples/JavaSieve/Package.swift index 35dcd19c..cd65f82e 100644 --- a/Samples/JavaSieve/Package.swift +++ b/Samples/JavaSieve/Package.swift @@ -58,7 +58,7 @@ let package = Package( .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) ], plugins: [ - .plugin(name: "Java2SwiftPlugin", package: "swift-java"), + .plugin(name: "SwiftJavaPlugin", package: "swift-java"), ] ), @@ -75,7 +75,7 @@ let package = Package( .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) ], plugins: [ - .plugin(name: "Java2SwiftPlugin", package: "swift-java"), + .plugin(name: "SwiftJavaPlugin", package: "swift-java"), ] ), ] From 67fd870912e4bd7774fa185a8d0d633a81dd8987 Mon Sep 17 00:00:00 2001 From: Konrad 'ktoso' Malawski Date: Thu, 5 Jun 2025 17:21:08 +0900 Subject: [PATCH 263/426] rename JExtractSwift to JExtractSwiftLib as we'll depend on it in SwiftJava --- Package.swift | 10 +- .../CDeclLowering/CRepresentation.swift | 0 ...wift2JavaTranslator+FunctionLowering.swift | 0 .../CTypes/CEnum.swift | 0 .../CTypes/CFunction.swift | 0 .../CTypes/CParameter.swift | 0 .../CTypes/CStruct.swift | 0 .../CTypes/CTag.swift | 0 .../CTypes/CType.swift | 0 .../CTypes/CUnion.swift | 0 .../CodePrinter.swift | 0 .../Convenience/Collection+Extensions.swift | 0 .../Convenience/String+Extensions.swift | 0 .../Convenience/SwiftSyntax+Extensions.swift | 0 .../ConversionStep.swift | 0 .../ImportedDecls.swift | 0 .../JavaConstants/ForeignValueLayouts.swift | 0 .../JavaConstants/JavaTypes.swift | 0 .../Logger.swift | 0 .../Swift2Java.swift | 0 ...2JavaTranslator+JavaBindingsPrinting.swift | 0 ...Swift2JavaTranslator+JavaTranslation.swift | 0 .../Swift2JavaTranslator+Printing.swift | 0 ...ft2JavaTranslator+SwiftThunkPrinting.swift | 0 .../Swift2JavaTranslator.swift | 0 .../Swift2JavaVisitor.swift | 0 .../SwiftKit+Printing.swift | 0 .../SwiftThunkTranslator.swift | 191 ++++++++++++++++++ .../SwiftTypes/SwiftFunctionSignature.swift | 0 .../SwiftTypes/SwiftFunctionType.swift | 0 .../SwiftTypes/SwiftModuleSymbolTable.swift | 0 .../SwiftNominalTypeDeclaration.swift | 0 .../SwiftTypes/SwiftParameter.swift | 0 .../SwiftParsedModuleSymbolTable.swift | 0 .../SwiftTypes/SwiftResult.swift | 0 .../SwiftStandardLibraryTypes.swift | 0 .../SwiftTypes/SwiftSymbolTable.swift | 0 .../SwiftTypes/SwiftType.swift | 0 .../ThunkNameRegistry.swift | 0 .../Asserts/LoweringAssertions.swift | 2 +- .../Asserts/TextAssertions.swift | 2 +- Tests/JExtractSwiftTests/CTypeTests.swift | 2 +- .../ClassPrintingTests.swift | 2 +- .../FuncCallbackImportTests.swift | 2 +- .../FunctionDescriptorImportTests.swift | 2 +- .../FunctionLoweringTests.swift | 2 +- .../MethodImportTests.swift | 2 +- .../JExtractSwiftTests/MethodThunkTests.swift | 2 +- .../StringPassingTests.swift | 2 +- .../SwiftSymbolTableTests.swift | 2 +- .../VariableImportTests.swift | 2 +- 51 files changed, 208 insertions(+), 17 deletions(-) rename Sources/{JExtractSwift => JExtractSwiftLib}/CDeclLowering/CRepresentation.swift (100%) rename Sources/{JExtractSwift => JExtractSwiftLib}/CDeclLowering/Swift2JavaTranslator+FunctionLowering.swift (100%) rename Sources/{JExtractSwift => JExtractSwiftLib}/CTypes/CEnum.swift (100%) rename Sources/{JExtractSwift => JExtractSwiftLib}/CTypes/CFunction.swift (100%) rename Sources/{JExtractSwift => JExtractSwiftLib}/CTypes/CParameter.swift (100%) rename Sources/{JExtractSwift => JExtractSwiftLib}/CTypes/CStruct.swift (100%) rename Sources/{JExtractSwift => JExtractSwiftLib}/CTypes/CTag.swift (100%) rename Sources/{JExtractSwift => JExtractSwiftLib}/CTypes/CType.swift (100%) rename Sources/{JExtractSwift => JExtractSwiftLib}/CTypes/CUnion.swift (100%) rename Sources/{JExtractSwift => JExtractSwiftLib}/CodePrinter.swift (100%) rename Sources/{JExtractSwift => JExtractSwiftLib}/Convenience/Collection+Extensions.swift (100%) rename Sources/{JExtractSwift => JExtractSwiftLib}/Convenience/String+Extensions.swift (100%) rename Sources/{JExtractSwift => JExtractSwiftLib}/Convenience/SwiftSyntax+Extensions.swift (100%) rename Sources/{JExtractSwift => JExtractSwiftLib}/ConversionStep.swift (100%) rename Sources/{JExtractSwift => JExtractSwiftLib}/ImportedDecls.swift (100%) rename Sources/{JExtractSwift => JExtractSwiftLib}/JavaConstants/ForeignValueLayouts.swift (100%) rename Sources/{JExtractSwift => JExtractSwiftLib}/JavaConstants/JavaTypes.swift (100%) rename Sources/{JExtractSwift => JExtractSwiftLib}/Logger.swift (100%) rename Sources/{JExtractSwift => JExtractSwiftLib}/Swift2Java.swift (100%) rename Sources/{JExtractSwift => JExtractSwiftLib}/Swift2JavaTranslator+JavaBindingsPrinting.swift (100%) rename Sources/{JExtractSwift => JExtractSwiftLib}/Swift2JavaTranslator+JavaTranslation.swift (100%) rename Sources/{JExtractSwift => JExtractSwiftLib}/Swift2JavaTranslator+Printing.swift (100%) rename Sources/{JExtractSwift => JExtractSwiftLib}/Swift2JavaTranslator+SwiftThunkPrinting.swift (100%) rename Sources/{JExtractSwift => JExtractSwiftLib}/Swift2JavaTranslator.swift (100%) rename Sources/{JExtractSwift => JExtractSwiftLib}/Swift2JavaVisitor.swift (100%) rename Sources/{JExtractSwift => JExtractSwiftLib}/SwiftKit+Printing.swift (100%) create mode 100644 Sources/JExtractSwiftLib/SwiftThunkTranslator.swift rename Sources/{JExtractSwift => JExtractSwiftLib}/SwiftTypes/SwiftFunctionSignature.swift (100%) rename Sources/{JExtractSwift => JExtractSwiftLib}/SwiftTypes/SwiftFunctionType.swift (100%) rename Sources/{JExtractSwift => JExtractSwiftLib}/SwiftTypes/SwiftModuleSymbolTable.swift (100%) rename Sources/{JExtractSwift => JExtractSwiftLib}/SwiftTypes/SwiftNominalTypeDeclaration.swift (100%) rename Sources/{JExtractSwift => JExtractSwiftLib}/SwiftTypes/SwiftParameter.swift (100%) rename Sources/{JExtractSwift => JExtractSwiftLib}/SwiftTypes/SwiftParsedModuleSymbolTable.swift (100%) rename Sources/{JExtractSwift => JExtractSwiftLib}/SwiftTypes/SwiftResult.swift (100%) rename Sources/{JExtractSwift => JExtractSwiftLib}/SwiftTypes/SwiftStandardLibraryTypes.swift (100%) rename Sources/{JExtractSwift => JExtractSwiftLib}/SwiftTypes/SwiftSymbolTable.swift (100%) rename Sources/{JExtractSwift => JExtractSwiftLib}/SwiftTypes/SwiftType.swift (100%) rename Sources/{JExtractSwift => JExtractSwiftLib}/ThunkNameRegistry.swift (100%) diff --git a/Package.swift b/Package.swift index 48abbdb8..c2580296 100644 --- a/Package.swift +++ b/Package.swift @@ -127,8 +127,8 @@ let package = Package( ), .library( - name: "JExtractSwift", - targets: ["JExtractSwift"] + name: "JExtractSwiftLib", + targets: ["JExtractSwiftLib"] ), // ==== Plugin for wrapping Java classes in Swift @@ -355,7 +355,7 @@ let package = Package( ), .target( - name: "JExtractSwift", + name: "JExtractSwiftLib", dependencies: [ .product(name: "SwiftBasicFormat", package: "swift-syntax"), .product(name: "SwiftSyntax", package: "swift-syntax"), @@ -373,7 +373,7 @@ let package = Package( .executableTarget( name: "JExtractSwiftTool", dependencies: [ - "JExtractSwift", + "JExtractSwiftLib", ], swiftSettings: [ .swiftLanguageMode(.v5) @@ -438,7 +438,7 @@ let package = Package( .testTarget( name: "JExtractSwiftTests", dependencies: [ - "JExtractSwift" + "JExtractSwiftLib" ], swiftSettings: [ .swiftLanguageMode(.v5), diff --git a/Sources/JExtractSwift/CDeclLowering/CRepresentation.swift b/Sources/JExtractSwiftLib/CDeclLowering/CRepresentation.swift similarity index 100% rename from Sources/JExtractSwift/CDeclLowering/CRepresentation.swift rename to Sources/JExtractSwiftLib/CDeclLowering/CRepresentation.swift diff --git a/Sources/JExtractSwift/CDeclLowering/Swift2JavaTranslator+FunctionLowering.swift b/Sources/JExtractSwiftLib/CDeclLowering/Swift2JavaTranslator+FunctionLowering.swift similarity index 100% rename from Sources/JExtractSwift/CDeclLowering/Swift2JavaTranslator+FunctionLowering.swift rename to Sources/JExtractSwiftLib/CDeclLowering/Swift2JavaTranslator+FunctionLowering.swift diff --git a/Sources/JExtractSwift/CTypes/CEnum.swift b/Sources/JExtractSwiftLib/CTypes/CEnum.swift similarity index 100% rename from Sources/JExtractSwift/CTypes/CEnum.swift rename to Sources/JExtractSwiftLib/CTypes/CEnum.swift diff --git a/Sources/JExtractSwift/CTypes/CFunction.swift b/Sources/JExtractSwiftLib/CTypes/CFunction.swift similarity index 100% rename from Sources/JExtractSwift/CTypes/CFunction.swift rename to Sources/JExtractSwiftLib/CTypes/CFunction.swift diff --git a/Sources/JExtractSwift/CTypes/CParameter.swift b/Sources/JExtractSwiftLib/CTypes/CParameter.swift similarity index 100% rename from Sources/JExtractSwift/CTypes/CParameter.swift rename to Sources/JExtractSwiftLib/CTypes/CParameter.swift diff --git a/Sources/JExtractSwift/CTypes/CStruct.swift b/Sources/JExtractSwiftLib/CTypes/CStruct.swift similarity index 100% rename from Sources/JExtractSwift/CTypes/CStruct.swift rename to Sources/JExtractSwiftLib/CTypes/CStruct.swift diff --git a/Sources/JExtractSwift/CTypes/CTag.swift b/Sources/JExtractSwiftLib/CTypes/CTag.swift similarity index 100% rename from Sources/JExtractSwift/CTypes/CTag.swift rename to Sources/JExtractSwiftLib/CTypes/CTag.swift diff --git a/Sources/JExtractSwift/CTypes/CType.swift b/Sources/JExtractSwiftLib/CTypes/CType.swift similarity index 100% rename from Sources/JExtractSwift/CTypes/CType.swift rename to Sources/JExtractSwiftLib/CTypes/CType.swift diff --git a/Sources/JExtractSwift/CTypes/CUnion.swift b/Sources/JExtractSwiftLib/CTypes/CUnion.swift similarity index 100% rename from Sources/JExtractSwift/CTypes/CUnion.swift rename to Sources/JExtractSwiftLib/CTypes/CUnion.swift diff --git a/Sources/JExtractSwift/CodePrinter.swift b/Sources/JExtractSwiftLib/CodePrinter.swift similarity index 100% rename from Sources/JExtractSwift/CodePrinter.swift rename to Sources/JExtractSwiftLib/CodePrinter.swift diff --git a/Sources/JExtractSwift/Convenience/Collection+Extensions.swift b/Sources/JExtractSwiftLib/Convenience/Collection+Extensions.swift similarity index 100% rename from Sources/JExtractSwift/Convenience/Collection+Extensions.swift rename to Sources/JExtractSwiftLib/Convenience/Collection+Extensions.swift diff --git a/Sources/JExtractSwift/Convenience/String+Extensions.swift b/Sources/JExtractSwiftLib/Convenience/String+Extensions.swift similarity index 100% rename from Sources/JExtractSwift/Convenience/String+Extensions.swift rename to Sources/JExtractSwiftLib/Convenience/String+Extensions.swift diff --git a/Sources/JExtractSwift/Convenience/SwiftSyntax+Extensions.swift b/Sources/JExtractSwiftLib/Convenience/SwiftSyntax+Extensions.swift similarity index 100% rename from Sources/JExtractSwift/Convenience/SwiftSyntax+Extensions.swift rename to Sources/JExtractSwiftLib/Convenience/SwiftSyntax+Extensions.swift diff --git a/Sources/JExtractSwift/ConversionStep.swift b/Sources/JExtractSwiftLib/ConversionStep.swift similarity index 100% rename from Sources/JExtractSwift/ConversionStep.swift rename to Sources/JExtractSwiftLib/ConversionStep.swift diff --git a/Sources/JExtractSwift/ImportedDecls.swift b/Sources/JExtractSwiftLib/ImportedDecls.swift similarity index 100% rename from Sources/JExtractSwift/ImportedDecls.swift rename to Sources/JExtractSwiftLib/ImportedDecls.swift diff --git a/Sources/JExtractSwift/JavaConstants/ForeignValueLayouts.swift b/Sources/JExtractSwiftLib/JavaConstants/ForeignValueLayouts.swift similarity index 100% rename from Sources/JExtractSwift/JavaConstants/ForeignValueLayouts.swift rename to Sources/JExtractSwiftLib/JavaConstants/ForeignValueLayouts.swift diff --git a/Sources/JExtractSwift/JavaConstants/JavaTypes.swift b/Sources/JExtractSwiftLib/JavaConstants/JavaTypes.swift similarity index 100% rename from Sources/JExtractSwift/JavaConstants/JavaTypes.swift rename to Sources/JExtractSwiftLib/JavaConstants/JavaTypes.swift diff --git a/Sources/JExtractSwift/Logger.swift b/Sources/JExtractSwiftLib/Logger.swift similarity index 100% rename from Sources/JExtractSwift/Logger.swift rename to Sources/JExtractSwiftLib/Logger.swift diff --git a/Sources/JExtractSwift/Swift2Java.swift b/Sources/JExtractSwiftLib/Swift2Java.swift similarity index 100% rename from Sources/JExtractSwift/Swift2Java.swift rename to Sources/JExtractSwiftLib/Swift2Java.swift diff --git a/Sources/JExtractSwift/Swift2JavaTranslator+JavaBindingsPrinting.swift b/Sources/JExtractSwiftLib/Swift2JavaTranslator+JavaBindingsPrinting.swift similarity index 100% rename from Sources/JExtractSwift/Swift2JavaTranslator+JavaBindingsPrinting.swift rename to Sources/JExtractSwiftLib/Swift2JavaTranslator+JavaBindingsPrinting.swift diff --git a/Sources/JExtractSwift/Swift2JavaTranslator+JavaTranslation.swift b/Sources/JExtractSwiftLib/Swift2JavaTranslator+JavaTranslation.swift similarity index 100% rename from Sources/JExtractSwift/Swift2JavaTranslator+JavaTranslation.swift rename to Sources/JExtractSwiftLib/Swift2JavaTranslator+JavaTranslation.swift diff --git a/Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift b/Sources/JExtractSwiftLib/Swift2JavaTranslator+Printing.swift similarity index 100% rename from Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift rename to Sources/JExtractSwiftLib/Swift2JavaTranslator+Printing.swift diff --git a/Sources/JExtractSwift/Swift2JavaTranslator+SwiftThunkPrinting.swift b/Sources/JExtractSwiftLib/Swift2JavaTranslator+SwiftThunkPrinting.swift similarity index 100% rename from Sources/JExtractSwift/Swift2JavaTranslator+SwiftThunkPrinting.swift rename to Sources/JExtractSwiftLib/Swift2JavaTranslator+SwiftThunkPrinting.swift diff --git a/Sources/JExtractSwift/Swift2JavaTranslator.swift b/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift similarity index 100% rename from Sources/JExtractSwift/Swift2JavaTranslator.swift rename to Sources/JExtractSwiftLib/Swift2JavaTranslator.swift diff --git a/Sources/JExtractSwift/Swift2JavaVisitor.swift b/Sources/JExtractSwiftLib/Swift2JavaVisitor.swift similarity index 100% rename from Sources/JExtractSwift/Swift2JavaVisitor.swift rename to Sources/JExtractSwiftLib/Swift2JavaVisitor.swift diff --git a/Sources/JExtractSwift/SwiftKit+Printing.swift b/Sources/JExtractSwiftLib/SwiftKit+Printing.swift similarity index 100% rename from Sources/JExtractSwift/SwiftKit+Printing.swift rename to Sources/JExtractSwiftLib/SwiftKit+Printing.swift diff --git a/Sources/JExtractSwiftLib/SwiftThunkTranslator.swift b/Sources/JExtractSwiftLib/SwiftThunkTranslator.swift new file mode 100644 index 00000000..51547ba8 --- /dev/null +++ b/Sources/JExtractSwiftLib/SwiftThunkTranslator.swift @@ -0,0 +1,191 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import SwiftSyntax +import SwiftSyntaxBuilder + +extension Swift2JavaTranslator { + public func writeSwiftThunkSources(outputDirectory: String) throws { + var printer = CodePrinter() + + try writeSwiftThunkSources(outputDirectory: outputDirectory, printer: &printer) + } + + public func writeSwiftThunkSources(outputDirectory: String, printer: inout CodePrinter) throws { + let moduleFilenameBase = "\(self.swiftModuleName)Module+SwiftJava" + let moduleFilename = "\(moduleFilenameBase).swift" + do { + log.info("Printing contents: \(moduleFilename)") + + try printGlobalSwiftThunkSources(&printer) + + if let outputFile = try printer.writeContents( + outputDirectory: outputDirectory, + javaPackagePath: nil, + filename: moduleFilename) + { + print("[swift-java] Generated: \(moduleFilenameBase.bold).swift (at \(outputFile)") + } + } catch { + log.warning("Failed to write to Swift thunks: \(moduleFilename)") + } + + // === All types + for (_, ty) in importedTypes.sorted(by: { (lhs, rhs) in lhs.key < rhs.key }) { + let fileNameBase = "\(ty.swiftNominal.qualifiedName)+SwiftJava" + let filename = "\(fileNameBase).swift" + log.info("Printing contents: \(filename)") + + do { + try printSwiftThunkSources(&printer, ty: ty) + + if let outputFile = try printer.writeContents( + outputDirectory: outputDirectory, + javaPackagePath: nil, + filename: filename) + { + print("[swift-java] Generated: \(fileNameBase.bold).swift (at \(outputFile)") + } + } catch { + log.warning("Failed to write to Swift thunks: \(filename)") + } + } + } + + public func printGlobalSwiftThunkSources(_ printer: inout CodePrinter) throws { + let stt = SwiftThunkTranslator(self) + + printer.print( + """ + // Generated by swift-java + + import SwiftKitSwift + + """) + + for thunk in stt.renderGlobalThunks() { + printer.print(thunk) + printer.println() + } + } + + public func printSwiftThunkSources(_ printer: inout CodePrinter, decl: ImportedFunc) { + let stt = SwiftThunkTranslator(self) + + for thunk in stt.render(forFunc: decl) { + printer.print(thunk) + printer.println() + } + } + + package func printSwiftThunkSources(_ printer: inout CodePrinter, ty: ImportedNominalType) throws { + let stt = SwiftThunkTranslator(self) + + printer.print( + """ + // Generated by swift-java + + import SwiftKitSwift + + """ + ) + + for thunk in stt.renderThunks(forType: ty) { + printer.print("\(thunk)") + printer.print("") + } + } +} + +struct SwiftThunkTranslator { + + let st: Swift2JavaTranslator + + init(_ st: Swift2JavaTranslator) { + self.st = st + } + + func renderGlobalThunks() -> [DeclSyntax] { + var decls: [DeclSyntax] = [] + decls.reserveCapacity( + st.importedGlobalVariables.count + st.importedGlobalFuncs.count + ) + + for decl in st.importedGlobalVariables { + decls.append(contentsOf: render(forFunc: decl)) + } + + for decl in st.importedGlobalFuncs { + decls.append(contentsOf: render(forFunc: decl)) + } + + return decls + } + + /// Render all the thunks that make Swift methods accessible to Java. + func renderThunks(forType nominal: ImportedNominalType) -> [DeclSyntax] { + var decls: [DeclSyntax] = [] + decls.reserveCapacity( + 1 + nominal.initializers.count + nominal.variables.count + nominal.methods.count + ) + + decls.append(renderSwiftTypeAccessor(nominal)) + + for decl in nominal.initializers { + decls.append(contentsOf: render(forFunc: decl)) + } + + for decl in nominal.variables { + decls.append(contentsOf: render(forFunc: decl)) + } + + for decl in nominal.methods { + decls.append(contentsOf: render(forFunc: decl)) + } + + return decls + } + + /// Accessor to get the `T.self` of the Swift type, without having to rely on mangled name lookups. + func renderSwiftTypeAccessor(_ nominal: ImportedNominalType) -> DeclSyntax { + let funcName = SwiftKitPrinting.Names.getType( + module: st.swiftModuleName, + nominal: nominal) + + return + """ + @_cdecl("\(raw: funcName)") + public func \(raw: funcName)() -> UnsafeMutableRawPointer /* Any.Type */ { + return unsafeBitCast(\(raw: nominal.swiftNominal.qualifiedName).self, to: UnsafeMutableRawPointer.self) + } + """ + } + + func render(forFunc decl: ImportedFunc) -> [DeclSyntax] { + st.log.trace("Rendering thunks for: \(decl.displayName)") + + let thunkName = st.thunkNameRegistry.functionThunkName(decl: decl) + guard let translatedSignatures = st.translatedSignature(for: decl) else { + return [] + } + + let thunkFunc = translatedSignatures.loweredSignature.cdeclThunk( + cName: thunkName, + swiftAPIName: decl.name, + as: decl.apiKind, + stdlibTypes: st.swiftStdlibTypes + ) + return [DeclSyntax(thunkFunc)] + } +} diff --git a/Sources/JExtractSwift/SwiftTypes/SwiftFunctionSignature.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftFunctionSignature.swift similarity index 100% rename from Sources/JExtractSwift/SwiftTypes/SwiftFunctionSignature.swift rename to Sources/JExtractSwiftLib/SwiftTypes/SwiftFunctionSignature.swift diff --git a/Sources/JExtractSwift/SwiftTypes/SwiftFunctionType.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftFunctionType.swift similarity index 100% rename from Sources/JExtractSwift/SwiftTypes/SwiftFunctionType.swift rename to Sources/JExtractSwiftLib/SwiftTypes/SwiftFunctionType.swift diff --git a/Sources/JExtractSwift/SwiftTypes/SwiftModuleSymbolTable.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftModuleSymbolTable.swift similarity index 100% rename from Sources/JExtractSwift/SwiftTypes/SwiftModuleSymbolTable.swift rename to Sources/JExtractSwiftLib/SwiftTypes/SwiftModuleSymbolTable.swift diff --git a/Sources/JExtractSwift/SwiftTypes/SwiftNominalTypeDeclaration.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftNominalTypeDeclaration.swift similarity index 100% rename from Sources/JExtractSwift/SwiftTypes/SwiftNominalTypeDeclaration.swift rename to Sources/JExtractSwiftLib/SwiftTypes/SwiftNominalTypeDeclaration.swift diff --git a/Sources/JExtractSwift/SwiftTypes/SwiftParameter.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftParameter.swift similarity index 100% rename from Sources/JExtractSwift/SwiftTypes/SwiftParameter.swift rename to Sources/JExtractSwiftLib/SwiftTypes/SwiftParameter.swift diff --git a/Sources/JExtractSwift/SwiftTypes/SwiftParsedModuleSymbolTable.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftParsedModuleSymbolTable.swift similarity index 100% rename from Sources/JExtractSwift/SwiftTypes/SwiftParsedModuleSymbolTable.swift rename to Sources/JExtractSwiftLib/SwiftTypes/SwiftParsedModuleSymbolTable.swift diff --git a/Sources/JExtractSwift/SwiftTypes/SwiftResult.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftResult.swift similarity index 100% rename from Sources/JExtractSwift/SwiftTypes/SwiftResult.swift rename to Sources/JExtractSwiftLib/SwiftTypes/SwiftResult.swift diff --git a/Sources/JExtractSwift/SwiftTypes/SwiftStandardLibraryTypes.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftStandardLibraryTypes.swift similarity index 100% rename from Sources/JExtractSwift/SwiftTypes/SwiftStandardLibraryTypes.swift rename to Sources/JExtractSwiftLib/SwiftTypes/SwiftStandardLibraryTypes.swift diff --git a/Sources/JExtractSwift/SwiftTypes/SwiftSymbolTable.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftSymbolTable.swift similarity index 100% rename from Sources/JExtractSwift/SwiftTypes/SwiftSymbolTable.swift rename to Sources/JExtractSwiftLib/SwiftTypes/SwiftSymbolTable.swift diff --git a/Sources/JExtractSwift/SwiftTypes/SwiftType.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftType.swift similarity index 100% rename from Sources/JExtractSwift/SwiftTypes/SwiftType.swift rename to Sources/JExtractSwiftLib/SwiftTypes/SwiftType.swift diff --git a/Sources/JExtractSwift/ThunkNameRegistry.swift b/Sources/JExtractSwiftLib/ThunkNameRegistry.swift similarity index 100% rename from Sources/JExtractSwift/ThunkNameRegistry.swift rename to Sources/JExtractSwiftLib/ThunkNameRegistry.swift diff --git a/Tests/JExtractSwiftTests/Asserts/LoweringAssertions.swift b/Tests/JExtractSwiftTests/Asserts/LoweringAssertions.swift index cbdcc6dd..b306689d 100644 --- a/Tests/JExtractSwiftTests/Asserts/LoweringAssertions.swift +++ b/Tests/JExtractSwiftTests/Asserts/LoweringAssertions.swift @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -@_spi(Testing) import JExtractSwift +@_spi(Testing) import JExtractSwiftLib import SwiftSyntax import Testing diff --git a/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift b/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift index 1686f0ab..3923cf3e 100644 --- a/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift +++ b/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -import JExtractSwift +import JExtractSwiftLib import Testing import struct Foundation.CharacterSet diff --git a/Tests/JExtractSwiftTests/CTypeTests.swift b/Tests/JExtractSwiftTests/CTypeTests.swift index 569296d6..a2339e34 100644 --- a/Tests/JExtractSwiftTests/CTypeTests.swift +++ b/Tests/JExtractSwiftTests/CTypeTests.swift @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -import JExtractSwift +import JExtractSwiftLib import Testing @Suite("C type system tests") diff --git a/Tests/JExtractSwiftTests/ClassPrintingTests.swift b/Tests/JExtractSwiftTests/ClassPrintingTests.swift index 94cd8a40..1edcdaf0 100644 --- a/Tests/JExtractSwiftTests/ClassPrintingTests.swift +++ b/Tests/JExtractSwiftTests/ClassPrintingTests.swift @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -import JExtractSwift +import JExtractSwiftLib import Testing struct ClassPrintingTests { diff --git a/Tests/JExtractSwiftTests/FuncCallbackImportTests.swift b/Tests/JExtractSwiftTests/FuncCallbackImportTests.swift index 50022c55..8b401ce3 100644 --- a/Tests/JExtractSwiftTests/FuncCallbackImportTests.swift +++ b/Tests/JExtractSwiftTests/FuncCallbackImportTests.swift @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -import JExtractSwift +import JExtractSwiftLib import Testing final class FuncCallbackImportTests { diff --git a/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift b/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift index 9cdcdf58..2963ce9e 100644 --- a/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift +++ b/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -import JExtractSwift +import JExtractSwiftLib import Testing @Suite diff --git a/Tests/JExtractSwiftTests/FunctionLoweringTests.swift b/Tests/JExtractSwiftTests/FunctionLoweringTests.swift index dce594ae..b7855e43 100644 --- a/Tests/JExtractSwiftTests/FunctionLoweringTests.swift +++ b/Tests/JExtractSwiftTests/FunctionLoweringTests.swift @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -import JExtractSwift +import JExtractSwiftLib import SwiftSyntax import Testing diff --git a/Tests/JExtractSwiftTests/MethodImportTests.swift b/Tests/JExtractSwiftTests/MethodImportTests.swift index 25c028ce..48515ff2 100644 --- a/Tests/JExtractSwiftTests/MethodImportTests.swift +++ b/Tests/JExtractSwiftTests/MethodImportTests.swift @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -import JExtractSwift +import JExtractSwiftLib import Testing final class MethodImportTests { diff --git a/Tests/JExtractSwiftTests/MethodThunkTests.swift b/Tests/JExtractSwiftTests/MethodThunkTests.swift index d57e449e..f6f5ce71 100644 --- a/Tests/JExtractSwiftTests/MethodThunkTests.swift +++ b/Tests/JExtractSwiftTests/MethodThunkTests.swift @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -import JExtractSwift +import JExtractSwiftLib import Testing final class MethodThunkTests { diff --git a/Tests/JExtractSwiftTests/StringPassingTests.swift b/Tests/JExtractSwiftTests/StringPassingTests.swift index 08190399..ae131b94 100644 --- a/Tests/JExtractSwiftTests/StringPassingTests.swift +++ b/Tests/JExtractSwiftTests/StringPassingTests.swift @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -import JExtractSwift +import JExtractSwiftLib import Testing final class StringPassingTests { diff --git a/Tests/JExtractSwiftTests/SwiftSymbolTableTests.swift b/Tests/JExtractSwiftTests/SwiftSymbolTableTests.swift index 5d1e5e2b..2bbaa913 100644 --- a/Tests/JExtractSwiftTests/SwiftSymbolTableTests.swift +++ b/Tests/JExtractSwiftTests/SwiftSymbolTableTests.swift @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -@_spi(Testing) import JExtractSwift +@_spi(Testing) import JExtractSwiftLib import SwiftSyntax import SwiftParser import Testing diff --git a/Tests/JExtractSwiftTests/VariableImportTests.swift b/Tests/JExtractSwiftTests/VariableImportTests.swift index 55724293..9d8650b4 100644 --- a/Tests/JExtractSwiftTests/VariableImportTests.swift +++ b/Tests/JExtractSwiftTests/VariableImportTests.swift @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -import JExtractSwift +import JExtractSwiftLib import Testing final class VariableImportTests { From 1c927ce551d727dbf11df952c2d6dd28d545aff2 Mon Sep 17 00:00:00 2001 From: Konrad 'ktoso' Malawski Date: Thu, 5 Jun 2025 17:24:42 +0900 Subject: [PATCH 264/426] remove JExtractSwiftTool and move it into SwiftJava tool --- Package.swift | 17 ----------------- .../JExtractSwiftTool.swift | 2 +- 2 files changed, 1 insertion(+), 18 deletions(-) rename Sources/{JExtractSwiftTool => SwiftJavaTool}/JExtractSwiftTool.swift (96%) diff --git a/Package.swift b/Package.swift index c2580296..21c71671 100644 --- a/Package.swift +++ b/Package.swift @@ -112,13 +112,6 @@ let package = Package( ] ), - // ==== jextract-swift (extract Java accessors from Swift interface files) - - .executable( - name: "jextract-swift", - targets: ["JExtractSwiftTool"] - ), - // Support library written in Swift for SwiftKit "Java" .library( name: "SwiftKitSwift", @@ -370,16 +363,6 @@ let package = Package( ] ), - .executableTarget( - name: "JExtractSwiftTool", - dependencies: [ - "JExtractSwiftLib", - ], - swiftSettings: [ - .swiftLanguageMode(.v5) - ] - ), - .plugin( name: "JExtractSwiftPlugin", capability: .buildTool(), diff --git a/Sources/JExtractSwiftTool/JExtractSwiftTool.swift b/Sources/SwiftJavaTool/JExtractSwiftTool.swift similarity index 96% rename from Sources/JExtractSwiftTool/JExtractSwiftTool.swift rename to Sources/SwiftJavaTool/JExtractSwiftTool.swift index f219cc8c..615ad4c5 100644 --- a/Sources/JExtractSwiftTool/JExtractSwiftTool.swift +++ b/Sources/SwiftJavaTool/JExtractSwiftTool.swift @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -import JExtractSwift +import JExtractSwiftLib @main struct JExtractSwift { From 9185bfed4250d8de9d5d767b2bf4f1fcce13c266 Mon Sep 17 00:00:00 2001 From: Konrad 'ktoso' Malawski Date: Thu, 5 Jun 2025 17:45:21 +0900 Subject: [PATCH 265/426] WIP start introducing jextract mode in swift-java tool --- Package.swift | 5 ++- .../JExtractSwiftCommandPlugin.swift | 2 +- .../JExtractSwiftPlugin.swift | 2 +- .../Configuration.swift | 4 ++ ...iftTool.swift => SwiftJava+JExtract.swift} | 27 +++++++++--- Sources/SwiftJavaTool/SwiftJava.swift | 43 ++++++++++++++++--- 6 files changed, 68 insertions(+), 15 deletions(-) rename Sources/SwiftJavaTool/{JExtractSwiftTool.swift => SwiftJava+JExtract.swift} (50%) diff --git a/Package.swift b/Package.swift index 21c71671..dc5dc974 100644 --- a/Package.swift +++ b/Package.swift @@ -337,6 +337,7 @@ let package = Package( "JavaKitJar", "JavaKitNetwork", "SwiftJavaLib", + "JExtractSwiftLib", "JavaKitShared", ], @@ -367,7 +368,7 @@ let package = Package( name: "JExtractSwiftPlugin", capability: .buildTool(), dependencies: [ - "JExtractSwiftTool" + "SwiftJavaTool" ] ), .plugin( @@ -377,7 +378,7 @@ let package = Package( permissions: [ ]), dependencies: [ - "JExtractSwiftTool" + "SwiftJavaTool" ] ), diff --git a/Plugins/JExtractSwiftCommandPlugin/JExtractSwiftCommandPlugin.swift b/Plugins/JExtractSwiftCommandPlugin/JExtractSwiftCommandPlugin.swift index d6cfb7cb..1eed7bd3 100644 --- a/Plugins/JExtractSwiftCommandPlugin/JExtractSwiftCommandPlugin.swift +++ b/Plugins/JExtractSwiftCommandPlugin/JExtractSwiftCommandPlugin.swift @@ -130,7 +130,7 @@ final class JExtractSwiftCommandPlugin: SwiftJavaPluginProtocol, BuildToolPlugin func runExtract(context: PluginContext, target: Target, arguments: [String]) throws { let process = Process() - process.executableURL = try context.tool(named: "JExtractSwiftTool").url + process.executableURL = try context.tool(named: "SwiftJavaTool").url process.arguments = arguments do { diff --git a/Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift b/Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift index f4255ff5..30f8019b 100644 --- a/Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift +++ b/Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift @@ -22,7 +22,7 @@ struct JExtractSwiftBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin { var verbose: Bool = getEnvironmentBool("SWIFT_JAVA_VERBOSE") func createBuildCommands(context: PluginContext, target: Target) throws -> [Command] { - let toolURL = try context.tool(named: "JExtractSwiftTool").url + let toolURL = try context.tool(named: "SwiftJavaTool").url guard let sourceModule = target.sourceModule else { return [] } diff --git a/Sources/JavaKitConfigurationShared/Configuration.swift b/Sources/JavaKitConfigurationShared/Configuration.swift index 13c7fd9b..21d0b03b 100644 --- a/Sources/JavaKitConfigurationShared/Configuration.swift +++ b/Sources/JavaKitConfigurationShared/Configuration.swift @@ -27,6 +27,10 @@ public struct Configuration: Codable { public var javaPackage: String? + public var inputSwift: String? + public var outputSwift: String? + public var outputJava: String? + // ==== java 2 swift --------------------------------------------------------- /// The Java class path that should be passed along to the Java2Swift tool. diff --git a/Sources/SwiftJavaTool/JExtractSwiftTool.swift b/Sources/SwiftJavaTool/SwiftJava+JExtract.swift similarity index 50% rename from Sources/SwiftJavaTool/JExtractSwiftTool.swift rename to Sources/SwiftJavaTool/SwiftJava+JExtract.swift index 615ad4c5..7cb15c8e 100644 --- a/Sources/SwiftJavaTool/JExtractSwiftTool.swift +++ b/Sources/SwiftJavaTool/SwiftJava+JExtract.swift @@ -12,12 +12,29 @@ // //===----------------------------------------------------------------------===// +import Foundation +import ArgumentParser +import SwiftJavaLib +import JavaKit +import JavaKitJar +import SwiftJavaLib import JExtractSwiftLib +import JavaKitConfigurationShared + +/// Extract Java bindings from Swift sources or interface files. +/// +/// Example usage: +/// ``` +/// > swift-java --input-swift Sources/SwiftyBusiness \ +/// --output-swift .build/.../outputs/SwiftyBusiness \ +/// --output-Java .build/.../outputs/Java +/// ``` +extension SwiftJava { + + mutating func jextractSwift( + config: Configuration + ) throws { -@main -struct JExtractSwift { - static func main() throws { - let command = SwiftToJava.parseOrExit(CommandLine.arguments) - try command.run() } + } diff --git a/Sources/SwiftJavaTool/SwiftJava.swift b/Sources/SwiftJavaTool/SwiftJava.swift index c8be85a5..a877575b 100644 --- a/Sources/SwiftJavaTool/SwiftJava.swift +++ b/Sources/SwiftJavaTool/SwiftJava.swift @@ -59,10 +59,19 @@ struct SwiftJava: AsyncParsableCommand { ) var swiftNativeImplementation: [String] = [] - @Option(name: .shortAndLong, help: "The directory in which to output the generated Swift files or the Java2Swift configuration file.") + @Option(name: .shortAndLong, help: "Directory containing Swift files which should be extracted into Java bindings. Also known as 'jextract' mode. Must be paired with --output-java and --output-swift.") + var inputSwift: String? = nil + + @Option(name: .shortAndLong, help: "The directory where generated Swift files should be written. Generally used with jextract mode.") + var outputSwift: String? = nil + + @Option(name: .shortAndLong, help: "The directory where generated Java files should be written. Generally used with jextract mode.") + var outputJava: String? = nil + + // TODO: clarify this vs outputSwift (history: outputSwift is jextract, and this was java2swift) + @Option(name: .shortAndLong, help: "The directory in which to output the generated Swift files or the SwiftJava configuration file.") var outputDirectory: String? = nil - @Option(name: .shortAndLong, help: "Directory where to write cached values (e.g. swift-java.classpath files)") var cacheDirectory: String? = nil @@ -87,8 +96,7 @@ struct SwiftJava: AsyncParsableCommand { var javaPackageFilter: String? = nil @Argument( - help: - "The input file, which is either a Java2Swift configuration file or (if '-jar' was specified) a Jar file." + help: "The input file, which is either a Java2Swift configuration file or (if '-jar' was specified) a Jar file." ) var input: String @@ -163,6 +171,9 @@ struct SwiftJava: AsyncParsableCommand { /// Fetch dependencies for a module case fetchDependencies + + /// Extract Java bindings from provided Swift sources. + case jextract // TODO: carry jextract specific config here? } mutating func run() async { @@ -172,7 +183,24 @@ struct SwiftJava: AsyncParsableCommand { // Determine the mode in which we'll execute. let toolMode: ToolMode - if jar { + // TODO: some options are exclusive to eachother so we should detect that + if let inputSwift { + guard let outputSwift else { + print("[swift-java] --input-swift enabled 'jextract' mode, however no --output-swift directory was provided!") + return + } + guard let outputJava else { + print("[swift-java] --input-swift enabled 'jextract' mode, however no --output-java directory was provided!") + return + } + var c = Configuration() + c.inputSwift = inputSwift + c.outputSwift = outputSwift + c.outputJava = outputJava + config = c + + toolMode = .jextract + } else if jar { if let moduleBaseDir { config = try readConfiguration(sourceDir: moduleBaseDir.path) } else { @@ -251,7 +279,7 @@ struct SwiftJava: AsyncParsableCommand { // print("[debug][swift-java] Found cached dependency resolver classpath: \(dependencyResolverClasspath)") // classpathEntries += dependencyResolverClasspath // } - case .classWrappers: + case .classWrappers, .jextract: break; } @@ -310,6 +338,9 @@ struct SwiftJava: AsyncParsableCommand { moduleName: moduleName, cacheDir: effectiveCacheDirectory, resolvedClasspath: dependencyClasspath) + + case .jextract: + try jextractSwift(config: config) } } catch { // We fail like this since throwing out of the run often ends up hiding the failure reason when it is executed as SwiftPM plugin (!) From 668cd4bfdc7f1ffede411bc52d23eb90b6e33b57 Mon Sep 17 00:00:00 2001 From: Konrad 'ktoso' Malawski Date: Fri, 6 Jun 2025 13:47:03 +0900 Subject: [PATCH 266/426] [Package.swift] improve detecting JAVA_HOME on macos by using java_home --- Package.swift | 47 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 2 deletions(-) diff --git a/Package.swift b/Package.swift index dc5dc974..16c8a1a3 100644 --- a/Package.swift +++ b/Package.swift @@ -4,8 +4,7 @@ import CompilerPluginSupport import PackageDescription -import class Foundation.FileManager -import class Foundation.ProcessInfo +import Foundation // Note: the JAVA_HOME environment variable must be set to point to where // Java is installed, e.g., @@ -25,9 +24,53 @@ func findJavaHome() -> String { return home } + + if let home = getJavaHomeFromLibexecJavaHome(), + !home.isEmpty { + return home + } fatalError("Please set the JAVA_HOME environment variable to point to where Java is installed.") } + +/// On MacOS we can use the java_home tool as a fallback if we can't find JAVA_HOME environment variable. +func getJavaHomeFromLibexecJavaHome() -> String? { + let task = Process() + task.executableURL = URL(fileURLWithPath: "/usr/libexec/java_home") + + // Check if the executable exists before trying to run it + guard FileManager.default.fileExists(atPath: task.executableURL!.path) else { + print("/usr/libexec/java_home does not exist") + return nil + } + + let pipe = Pipe() + task.standardOutput = pipe + task.standardError = pipe // Redirect standard error to the same pipe for simplicity + + do { + try task.run() + task.waitUntilExit() + + let data = pipe.fileHandleForReading.readDataToEndOfFile() + let output = String(data: data, encoding: .utf8)?.trimmingCharacters(in: .whitespacesAndNewlines) + + if task.terminationStatus == 0 { + return output + } else { + print("java_home terminated with status: \(task.terminationStatus)") + // Optionally, log the error output for debugging + if let errorOutput = String(data: pipe.fileHandleForReading.readDataToEndOfFile(), encoding: .utf8) { + print("Error output: \(errorOutput)") + } + return nil + } + } catch { + print("Error running java_home: \(error)") + return nil + } +} + let javaHome = findJavaHome() let javaIncludePath = "\(javaHome)/include" From 772c21af2ffe9b763a5603bbe3c23a832971aa54 Mon Sep 17 00:00:00 2001 From: Konrad 'ktoso' Malawski Date: Fri, 6 Jun 2025 16:46:54 +0900 Subject: [PATCH 267/426] Final cleanups connectign jextract to the swift-java tools --- .../JExtractSwiftCommandPlugin.swift | 16 +-- .../JExtractSwiftPlugin.swift | 19 ++-- Plugins/PluginsShared/PluginUtils.swift | 4 +- Sources/JExtractSwiftLib/Logger.swift | 46 ++------ Sources/JExtractSwiftLib/Swift2Java.swift | 85 +++++++------- .../Configuration.swift | 59 +++++++++- .../SwiftJavaTool/SwiftJava+JExtract.swift | 2 +- Sources/SwiftJavaTool/SwiftJava.swift | 104 +++++++++++++----- 8 files changed, 198 insertions(+), 137 deletions(-) diff --git a/Plugins/JExtractSwiftCommandPlugin/JExtractSwiftCommandPlugin.swift b/Plugins/JExtractSwiftCommandPlugin/JExtractSwiftCommandPlugin.swift index 1eed7bd3..01201de6 100644 --- a/Plugins/JExtractSwiftCommandPlugin/JExtractSwiftCommandPlugin.swift +++ b/Plugins/JExtractSwiftCommandPlugin/JExtractSwiftCommandPlugin.swift @@ -69,21 +69,21 @@ final class JExtractSwiftCommandPlugin: SwiftJavaPluginProtocol, BuildToolPlugin let sourceDir = target.directory.string let configuration = try readConfiguration(sourceDir: "\(sourceDir)") - guard let javaPackage = configuration.javaPackage else { - throw SwiftJavaPluginError.missingConfiguration(sourceDir: "\(sourceDir)", key: "javaPackage") - } var arguments: [String] = [ - "--swift-module", sourceModule.name, - "--package-name", javaPackage, - "--output-directory-java", context.outputDirectoryJava.path(percentEncoded: false), - "--output-directory-swift", context.outputDirectorySwift.path(percentEncoded: false), + "--input-swift", sourceDir, + "--module-name", sourceModule.name, + "--output-java", context.outputJavaDirectory.path(percentEncoded: false), + "--output-swift", context.outputSwiftDirectory.path(percentEncoded: false), // TODO: "--build-cache-directory", ... // Since plugins cannot depend on libraries we cannot detect what the output files will be, // as it depends on the contents of the input files. Therefore we have to implement this as a prebuild plugin. // We'll have to make up some caching inside the tool so we don't re-parse files which have not changed etc. ] - arguments.append(sourceDir) + // arguments.append(sourceDir) // TODO: we could do this shape maybe? to have the dirs last? + if let package = configuration.javaPackage, !package.isEmpty { + ["--java-package", package] + } return arguments } diff --git a/Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift b/Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift index 30f8019b..8b0c7d9d 100644 --- a/Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift +++ b/Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift @@ -50,20 +50,23 @@ struct JExtractSwiftBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin { // We use the the usual maven-style structure of "src/[generated|main|test]/java/..." // that is common in JVM ecosystem - let outputDirectoryJava = context.outputDirectoryJava - let outputDirectorySwift = context.outputDirectorySwift + let outputJavaDirectory = context.outputJavaDirectory + let outputSwiftDirectory = context.outputSwiftDirectory var arguments: [String] = [ - "--swift-module", sourceModule.name, - "--package-name", javaPackage, - "--output-directory-java", outputDirectoryJava.path(percentEncoded: false), - "--output-directory-swift", outputDirectorySwift.path(percentEncoded: false), + "--input-swift", sourceDir, + "--module-name", sourceModule.name, + "--output-java", outputJavaDirectory.path(percentEncoded: false), + "--output-swift", outputSwiftDirectory.path(percentEncoded: false), // TODO: "--build-cache-directory", ... // Since plugins cannot depend on libraries we cannot detect what the output files will be, // as it depends on the contents of the input files. Therefore we have to implement this as a prebuild plugin. // We'll have to make up some caching inside the tool so we don't re-parse files which have not changed etc. ] - arguments.append(sourceDir) + // arguments.append(sourceDir) + if !javaPackage.isEmpty { + arguments.append(contentsOf: ["--java-package", javaPackage]) + } return [ .prebuildCommand( @@ -72,7 +75,7 @@ struct JExtractSwiftBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin { arguments: arguments, // inputFiles: [ configFile ] + swiftFiles, // outputFiles: outputJavaFiles - outputFilesDirectory: outputDirectorySwift + outputFilesDirectory: outputSwiftDirectory ) ] } diff --git a/Plugins/PluginsShared/PluginUtils.swift b/Plugins/PluginsShared/PluginUtils.swift index 6932253a..691d3375 100644 --- a/Plugins/PluginsShared/PluginUtils.swift +++ b/Plugins/PluginsShared/PluginUtils.swift @@ -60,14 +60,14 @@ func getEnvironmentBool(_ name: String) -> Bool { } extension PluginContext { - var outputDirectoryJava: URL { + var outputJavaDirectory: URL { self.pluginWorkDirectoryURL .appending(path: "src") .appending(path: "generated") .appending(path: "java") } - var outputDirectorySwift: URL { + var outputSwiftDirectory: URL { self.pluginWorkDirectoryURL .appending(path: "Sources") } diff --git a/Sources/JExtractSwiftLib/Logger.swift b/Sources/JExtractSwiftLib/Logger.swift index 9aceb201..180ffb54 100644 --- a/Sources/JExtractSwiftLib/Logger.swift +++ b/Sources/JExtractSwiftLib/Logger.swift @@ -14,6 +14,8 @@ import Foundation import SwiftSyntax +import ArgumentParser +import JavaKitConfigurationShared // Placeholder for some better logger, we could depend on swift-log public struct Logger { @@ -95,47 +97,17 @@ public struct Logger { } extension Logger { - public enum Level: String, Hashable { - case trace = "trace" - case debug = "debug" - case info = "info" - case notice = "notice" - case warning = "warning" - case error = "error" - case critical = "critical" - } + public typealias Level = JavaKitConfigurationShared.LogLevel } -extension Logger.Level { - public init(from decoder: any Decoder) throws { - var container = try decoder.unkeyedContainer() - let string = try container.decode(String.self) - switch string { - case "trace": self = .trace - case "debug": self = .debug - case "info": self = .info - case "notice": self = .notice - case "warning": self = .warning - case "error": self = .error - case "critical": self = .critical - default: fatalError("Unknown value for \(Logger.Level.self): \(string)") - } +extension Logger.Level: ExpressibleByArgument { + public var defaultValueDescription: String { + "log level" } + public private(set) static var allValueStrings: [String] = + ["trace", "debug", "info", "notice", "warning", "error", "critical"] - public func encode(to encoder: any Encoder) throws { - var container = encoder.singleValueContainer() - let text = - switch self { - case .trace: "trace" - case .debug: "debug" - case .info: "info" - case .notice: "notice" - case .warning: "warning" - case .error: "error" - case .critical: "critical" - } - try container.encode(text) - } + public private(set) static var defaultCompletionKind: CompletionKind = .default } extension Logger.Level { diff --git a/Sources/JExtractSwiftLib/Swift2Java.swift b/Sources/JExtractSwiftLib/Swift2Java.swift index 6525fc0a..79cb0fec 100644 --- a/Sources/JExtractSwiftLib/Swift2Java.swift +++ b/Sources/JExtractSwiftLib/Swift2Java.swift @@ -12,57 +12,49 @@ // //===----------------------------------------------------------------------===// -import ArgumentParser import Foundation import SwiftSyntax import SwiftSyntaxBuilder import JavaKitShared +import JavaKitConfigurationShared // TODO: this should become SwiftJavaConfigurationShared -/// Command-line utility, similar to `jextract` to export Swift types to Java. -public struct SwiftToJava: ParsableCommand { - public init() {} +public struct SwiftToJava { + let config: Configuration - public static var _commandName: String { - "jextract-swift" + public init(config: Configuration) { + self.config = config } - @Option(help: "The package the generated Java code should be emitted into.") - var packageName: String - - @Option( - name: .shortAndLong, - help: "The directory in which to output the generated Swift files and manifest.") - var outputDirectoryJava: String = ".build/jextract-swift/generated" - - @Option(help: "Swift output directory") - var outputDirectorySwift: String - - @Option( - name: .long, - help: "Name of the Swift module to import (and the swift interface files belong to)") - var swiftModule: String - - @Option(name: .shortAndLong, help: "Configure the level of lots that should be printed") - var logLevel: Logger.Level = .info - - @Argument(help: "The Swift files or directories to recursively export to Java.") - var input: [String] - public func run() throws { - let inputPaths = self.input.dropFirst().map { URL(string: $0)! } + guard let swiftModule = config.swiftModule else { + fatalError("Missing '--swift-module' name.") + } let translator = Swift2JavaTranslator( - javaPackage: packageName, + javaPackage: config.javaPackage ?? "", // no package is ok, we'd generate all into top level swiftModuleName: swiftModule ) - translator.log.logLevel = logLevel + translator.log.logLevel = config.logLevel ?? .info + + if config.javaPackage == nil || config.javaPackage!.isEmpty { + translator.log.warning("Configured java package is '', consider specifying concrete package for generated sources.") + } + + print("===== CONFIG ==== \(config)") + + guard let inputSwift = config.inputSwiftDirectory else { + fatalError("Missing '--swift-input' directory!") + } + + let inputPaths = inputSwift.split(separator: ",").map { URL(string: String($0))! } + translator.log.info("Input paths = \(inputPaths)") var allFiles: [URL] = [] let fileManager = FileManager.default let log = translator.log - + for path in inputPaths { - log.debug("Input path: \(path)") + log.info("Input path: \(path)") if isDirectory(url: path) { if let enumerator = fileManager.enumerator(at: path, includingPropertiesForKeys: nil) { for case let fileURL as URL in enumerator { @@ -88,10 +80,21 @@ public struct SwiftToJava: ParsableCommand { translator.add(filePath: file.path, text: text) } + guard let outputSwiftDirectory = config.outputSwiftDirectory else { + fatalError("Missing --output-swift directory!") + } + guard let outputJavaDirectory = config.outputJavaDirectory else { + fatalError("Missing --output-java directory!") + } + try translator.analyze() - try translator.writeSwiftThunkSources(outputDirectory: outputDirectorySwift) - try translator.writeExportedJavaSources(outputDirectory: outputDirectoryJava) - print("[swift-java] Generated Java sources (\(packageName)) in: \(outputDirectoryJava)/") + + try translator.writeSwiftThunkSources(outputDirectory: outputSwiftDirectory) + print("[swift-java] Generated Swift sources (module: '\(config.swiftModule ?? "")') in: \(outputSwiftDirectory)/") + + try translator.writeExportedJavaSources(outputDirectory: outputJavaDirectory) + print("[swift-java] Generated Java sources (package: '\(config.javaPackage ?? "")') in: \(outputJavaDirectory)/") + print("[swift-java] Imported Swift module '\(swiftModule)': " + "done.".green) } @@ -102,16 +105,6 @@ public struct SwiftToJava: ParsableCommand { } -extension Logger.Level: ExpressibleByArgument { - public var defaultValueDescription: String { - "log level" - } - public private(set) static var allValueStrings: [String] = - ["trace", "debug", "info", "notice", "warning", "error", "critical"] - - public private(set) static var defaultCompletionKind: CompletionKind = .default -} - func isDirectory(url: URL) -> Bool { var isDirectory: ObjCBool = false _ = FileManager.default.fileExists(atPath: url.path, isDirectory: &isDirectory) diff --git a/Sources/JavaKitConfigurationShared/Configuration.swift b/Sources/JavaKitConfigurationShared/Configuration.swift index 21d0b03b..5771b53f 100644 --- a/Sources/JavaKitConfigurationShared/Configuration.swift +++ b/Sources/JavaKitConfigurationShared/Configuration.swift @@ -21,15 +21,22 @@ import Foundation public typealias JavaVersion = Int -/// Configuration for the SwiftJava plugins, provided on a per-target basis. +/// Configuration for the SwiftJava tools and plugins, provided on a per-target basis. public struct Configuration: Codable { - // ==== swift 2 java --------------------------------------------------------- + + public var logLevel: LogLevel? + + // ==== swift 2 java / jextract swift --------------------------------------- public var javaPackage: String? - public var inputSwift: String? - public var outputSwift: String? - public var outputJava: String? + public var swiftModule: String? + + public var inputSwiftDirectory: String? + + public var outputSwiftDirectory: String? + + public var outputJavaDirectory: String? // ==== java 2 swift --------------------------------------------------------- @@ -204,3 +211,45 @@ public struct ConfigurationError: Error { self.line = line } } + +public enum LogLevel: String, Codable, Hashable { + case trace = "trace" + case debug = "debug" + case info = "info" + case notice = "notice" + case warning = "warning" + case error = "error" + case critical = "critical" +} + +extension LogLevel { + public init(from decoder: any Decoder) throws { + var container = try decoder.unkeyedContainer() + let string = try container.decode(String.self) + switch string { + case "trace": self = .trace + case "debug": self = .debug + case "info": self = .info + case "notice": self = .notice + case "warning": self = .warning + case "error": self = .error + case "critical": self = .critical + default: fatalError("Unknown value for \(LogLevel.self): \(string)") + } + } + + public func encode(to encoder: any Encoder) throws { + var container = encoder.singleValueContainer() + let text = + switch self { + case .trace: "trace" + case .debug: "debug" + case .info: "info" + case .notice: "notice" + case .warning: "warning" + case .error: "error" + case .critical: "critical" + } + try container.encode(text) + } +} \ No newline at end of file diff --git a/Sources/SwiftJavaTool/SwiftJava+JExtract.swift b/Sources/SwiftJavaTool/SwiftJava+JExtract.swift index 7cb15c8e..79c96d3e 100644 --- a/Sources/SwiftJavaTool/SwiftJava+JExtract.swift +++ b/Sources/SwiftJavaTool/SwiftJava+JExtract.swift @@ -34,7 +34,7 @@ extension SwiftJava { mutating func jextractSwift( config: Configuration ) throws { - + try SwiftToJava(config: config).run() } } diff --git a/Sources/SwiftJavaTool/SwiftJava.swift b/Sources/SwiftJavaTool/SwiftJava.swift index a877575b..b8e29ed8 100644 --- a/Sources/SwiftJavaTool/SwiftJava.swift +++ b/Sources/SwiftJavaTool/SwiftJava.swift @@ -15,6 +15,7 @@ import ArgumentParser import Foundation import SwiftJavaLib +import JExtractSwiftLib import JavaKit import JavaKitJar import JavaKitNetwork @@ -30,7 +31,7 @@ struct SwiftJava: AsyncParsableCommand { static var _commandName: String { "swift-java" } @Option(help: "The name of the Swift module into which the resulting Swift types will be generated.") - var moduleName: String? + var moduleName: String? // TODO: rename to --swift-module? @Option( help: @@ -59,22 +60,28 @@ struct SwiftJava: AsyncParsableCommand { ) var swiftNativeImplementation: [String] = [] - @Option(name: .shortAndLong, help: "Directory containing Swift files which should be extracted into Java bindings. Also known as 'jextract' mode. Must be paired with --output-java and --output-swift.") + @Option(help: "Directory containing Swift files which should be extracted into Java bindings. Also known as 'jextract' mode. Must be paired with --output-java and --output-swift.") var inputSwift: String? = nil - @Option(name: .shortAndLong, help: "The directory where generated Swift files should be written. Generally used with jextract mode.") + @Option(help: "The directory where generated Swift files should be written. Generally used with jextract mode.") var outputSwift: String? = nil - @Option(name: .shortAndLong, help: "The directory where generated Java files should be written. Generally used with jextract mode.") + @Option(help: "The directory where generated Java files should be written. Generally used with jextract mode.") var outputJava: String? = nil + @Option(help: "The Java package the generated Java code should be emitted into.") + var javaPackage: String? = nil + // TODO: clarify this vs outputSwift (history: outputSwift is jextract, and this was java2swift) @Option(name: .shortAndLong, help: "The directory in which to output the generated Swift files or the SwiftJava configuration file.") var outputDirectory: String? = nil @Option(name: .shortAndLong, help: "Directory where to write cached values (e.g. swift-java.classpath files)") var cacheDirectory: String? = nil - + + @Option(name: .shortAndLong, help: "Configure the level of logs that should be printed") + var logLevel: Logger.Level = .info + var effectiveCacheDirectory: String? { if let cacheDirectory { return cacheDirectory @@ -98,7 +105,7 @@ struct SwiftJava: AsyncParsableCommand { @Argument( help: "The input file, which is either a Java2Swift configuration file or (if '-jar' was specified) a Jar file." ) - var input: String + var input: String? /// Whether we have ensured that the output directory exists. var createdOutputDirectory: Bool = false @@ -151,6 +158,7 @@ struct SwiftJava: AsyncParsableCommand { // The configuration file goes at the top level. let outputDir: Foundation.URL if jar { + precondition(self.input != nil, "-jar mode requires path to jar to be specified as input path") outputDir = baseDir } else { outputDir = baseDir @@ -179,35 +187,48 @@ struct SwiftJava: AsyncParsableCommand { mutating func run() async { print("[info][swift-java] Run: \(CommandLine.arguments.joined(separator: " "))") do { - let config: Configuration - + var config: Configuration = Configuration() + if let moduleBaseDir { + print("[debug][swift-java] Load config from module base directory: \(moduleBaseDir.path)") + config = try readConfiguration(sourceDir: moduleBaseDir.path) + } else if let inputSwift { + print("[debug][swift-java] Load config from module swift input directory: \(inputSwift)") + config = try readConfiguration(sourceDir: inputSwift) + } + + config.logLevel = self.logLevel + if let javaPackage { + config.javaPackage = javaPackage + } + assert(config.javaPackage != nil, "java-package was nil!") + // Determine the mode in which we'll execute. let toolMode: ToolMode - // TODO: some options are exclusive to eachother so we should detect that + // TODO: some options are exclusive to each other so we should detect that if let inputSwift { guard let outputSwift else { - print("[swift-java] --input-swift enabled 'jextract' mode, however no --output-swift directory was provided!") + print("[swift-java] --input-swift enabled 'jextract' mode, however no --output-swift directory was provided!\n\(Self.helpMessage())") return } guard let outputJava else { - print("[swift-java] --input-swift enabled 'jextract' mode, however no --output-java directory was provided!") + print("[swift-java] --input-swift enabled 'jextract' mode, however no --output-java directory was provided!\n\(Self.helpMessage())") return } - var c = Configuration() - c.inputSwift = inputSwift - c.outputSwift = outputSwift - c.outputJava = outputJava - config = c + config.swiftModule = self.moduleName // FIXME: rename the moduleName + config.inputSwiftDirectory = self.inputSwift + config.outputSwiftDirectory = self.outputSwift + config.outputJavaDirectory = self.outputJava toolMode = .jextract } else if jar { - if let moduleBaseDir { - config = try readConfiguration(sourceDir: moduleBaseDir.path) - } else { - config = Configuration() + guard let input else { + fatalError("Mode -jar requires path\n\(Self.helpMessage())") } toolMode = .configuration(extraClasspath: input) } else if fetch { + guard let input else { + fatalError("Mode -jar requires path\n\(Self.helpMessage())") + } config = try JavaTranslator.readConfiguration(from: URL(fileURLWithPath: input)) guard let dependencies = config.dependencies else { print("[swift-java] Running in 'fetch dependencies' mode but dependencies list was empty!") @@ -216,13 +237,23 @@ struct SwiftJava: AsyncParsableCommand { } toolMode = .fetchDependencies } else { + guard let input else { + fatalError("Mode -jar requires path\n\(Self.helpMessage())") + } config = try JavaTranslator.readConfiguration(from: URL(fileURLWithPath: input)) toolMode = .classWrappers } - let moduleName = self.moduleName ?? - input.split(separator: "/").dropLast().last.map(String.init) ?? - "__UnknownModule" + print("[debug][swift-java] Running swift-java in mode: " + "\(toolMode.prettyName)".bold) + + let moduleName: String = + if let name = self.moduleName { + name + } else if let input { + input.split(separator: "/").dropLast().last.map(String.init) ?? "__UnknownModule" + } else { + "__UnknownModule" + } // Load all of the dependent configurations and associate them with Swift // modules. @@ -283,14 +314,20 @@ struct SwiftJava: AsyncParsableCommand { break; } - // Bring up the Java VM. + // Bring up the Java VM when necessary // TODO: print only in verbose mode let classpath = classpathEntries.joined(separator: ":") - print("[debug][swift-java] Initialize JVM with classpath: \(classpath)") - let jvm = try JavaVirtualMachine.shared(classpath: classpathEntries) + let jvm: JavaVirtualMachine! + switch toolMode { + case .configuration, .classWrappers: + print("[debug][swift-java] Initialize JVM with classpath: \(classpath)") + jvm = try JavaVirtualMachine.shared(classpath: classpathEntries) + default: + jvm = nil + } - // * Classespaths from all dependent configuration files + // * Classpaths from all dependent configuration files for (_, config) in dependentConfigs { // TODO: may need to resolve the dependent configs rather than just get their configs // TODO: We should cache the resolved classpaths as well so we don't do it many times @@ -320,9 +357,6 @@ struct SwiftJava: AsyncParsableCommand { guard let dependencies = config.dependencies else { fatalError("Configuration for fetching dependencies must have 'dependencies' defined!") } - guard let moduleName = self.moduleName else { - fatalError("Fetching dependencies must specify module name (--module-name)!") - } guard let effectiveCacheDirectory else { fatalError("Fetching dependencies must effective cache directory! Specify --output-directory or --cache-directory") } @@ -456,3 +490,13 @@ extension JavaClass { public func getSystemClassLoader() -> ClassLoader? } +extension SwiftJava.ToolMode { + var prettyName: String { + switch self { + case .configuration: "Configuration" + case .fetchDependencies: "Fetch dependencies" + case .classWrappers: "Wrap Java classes" + case .jextract: "JExtract Swift for Java" + } + } +} From 896b2bee13018c6ecd2670d098a02ff497467445 Mon Sep 17 00:00:00 2001 From: Konrad 'ktoso' Malawski Date: Mon, 9 Jun 2025 15:42:42 +0900 Subject: [PATCH 268/426] fix JavaDependencySampleApp in swift-java cli mode --- .../JExtractSwiftCommandPlugin.swift | 2 +- .../JExtractSwiftPlugin.swift | 2 +- Plugins/SwiftJavaPlugin/SwiftJavaPlugin.swift | 2 +- .../SwiftThunkTranslator.swift | 191 ------------------ .../Configuration.swift | 11 +- Sources/SwiftJavaTool/SwiftJava.swift | 16 +- 6 files changed, 21 insertions(+), 203 deletions(-) delete mode 100644 Sources/JExtractSwiftLib/SwiftThunkTranslator.swift diff --git a/Plugins/JExtractSwiftCommandPlugin/JExtractSwiftCommandPlugin.swift b/Plugins/JExtractSwiftCommandPlugin/JExtractSwiftCommandPlugin.swift index 01201de6..3ea89886 100644 --- a/Plugins/JExtractSwiftCommandPlugin/JExtractSwiftCommandPlugin.swift +++ b/Plugins/JExtractSwiftCommandPlugin/JExtractSwiftCommandPlugin.swift @@ -81,7 +81,7 @@ final class JExtractSwiftCommandPlugin: SwiftJavaPluginProtocol, BuildToolPlugin // We'll have to make up some caching inside the tool so we don't re-parse files which have not changed etc. ] // arguments.append(sourceDir) // TODO: we could do this shape maybe? to have the dirs last? - if let package = configuration.javaPackage, !package.isEmpty { + if let package = configuration?.javaPackage, !package.isEmpty { ["--java-package", package] } diff --git a/Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift b/Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift index 8b0c7d9d..a2cda352 100644 --- a/Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift +++ b/Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift @@ -42,7 +42,7 @@ struct JExtractSwiftBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin { let sourceDir = target.directory.string let configuration = try readConfiguration(sourceDir: "\(sourceDir)") - guard let javaPackage = configuration.javaPackage else { + guard let javaPackage = configuration?.javaPackage else { // throw SwiftJavaPluginError.missingConfiguration(sourceDir: "\(sourceDir)", key: "javaPackage") log("Skipping jextract step, no 'javaPackage' configuration in \(getSwiftJavaConfigPath(target: target) ?? "")") return [] diff --git a/Plugins/SwiftJavaPlugin/SwiftJavaPlugin.swift b/Plugins/SwiftJavaPlugin/SwiftJavaPlugin.swift index 05e6db0d..77d7058d 100644 --- a/Plugins/SwiftJavaPlugin/SwiftJavaPlugin.swift +++ b/Plugins/SwiftJavaPlugin/SwiftJavaPlugin.swift @@ -38,7 +38,7 @@ struct SwiftJavaBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin { // which we are generating Swift wrappers for Java classes. let configFile = URL(filePath: sourceDir) .appending(path: SwiftJavaConfigFileName) - let config = try readConfiguration(sourceDir: sourceDir) + let config = try readConfiguration(sourceDir: sourceDir) ?? Configuration() log("Config on path: \(configFile.path(percentEncoded: false))") log("Config was: \(config)") diff --git a/Sources/JExtractSwiftLib/SwiftThunkTranslator.swift b/Sources/JExtractSwiftLib/SwiftThunkTranslator.swift deleted file mode 100644 index 51547ba8..00000000 --- a/Sources/JExtractSwiftLib/SwiftThunkTranslator.swift +++ /dev/null @@ -1,191 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of Swift.org project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -import SwiftSyntax -import SwiftSyntaxBuilder - -extension Swift2JavaTranslator { - public func writeSwiftThunkSources(outputDirectory: String) throws { - var printer = CodePrinter() - - try writeSwiftThunkSources(outputDirectory: outputDirectory, printer: &printer) - } - - public func writeSwiftThunkSources(outputDirectory: String, printer: inout CodePrinter) throws { - let moduleFilenameBase = "\(self.swiftModuleName)Module+SwiftJava" - let moduleFilename = "\(moduleFilenameBase).swift" - do { - log.info("Printing contents: \(moduleFilename)") - - try printGlobalSwiftThunkSources(&printer) - - if let outputFile = try printer.writeContents( - outputDirectory: outputDirectory, - javaPackagePath: nil, - filename: moduleFilename) - { - print("[swift-java] Generated: \(moduleFilenameBase.bold).swift (at \(outputFile)") - } - } catch { - log.warning("Failed to write to Swift thunks: \(moduleFilename)") - } - - // === All types - for (_, ty) in importedTypes.sorted(by: { (lhs, rhs) in lhs.key < rhs.key }) { - let fileNameBase = "\(ty.swiftNominal.qualifiedName)+SwiftJava" - let filename = "\(fileNameBase).swift" - log.info("Printing contents: \(filename)") - - do { - try printSwiftThunkSources(&printer, ty: ty) - - if let outputFile = try printer.writeContents( - outputDirectory: outputDirectory, - javaPackagePath: nil, - filename: filename) - { - print("[swift-java] Generated: \(fileNameBase.bold).swift (at \(outputFile)") - } - } catch { - log.warning("Failed to write to Swift thunks: \(filename)") - } - } - } - - public func printGlobalSwiftThunkSources(_ printer: inout CodePrinter) throws { - let stt = SwiftThunkTranslator(self) - - printer.print( - """ - // Generated by swift-java - - import SwiftKitSwift - - """) - - for thunk in stt.renderGlobalThunks() { - printer.print(thunk) - printer.println() - } - } - - public func printSwiftThunkSources(_ printer: inout CodePrinter, decl: ImportedFunc) { - let stt = SwiftThunkTranslator(self) - - for thunk in stt.render(forFunc: decl) { - printer.print(thunk) - printer.println() - } - } - - package func printSwiftThunkSources(_ printer: inout CodePrinter, ty: ImportedNominalType) throws { - let stt = SwiftThunkTranslator(self) - - printer.print( - """ - // Generated by swift-java - - import SwiftKitSwift - - """ - ) - - for thunk in stt.renderThunks(forType: ty) { - printer.print("\(thunk)") - printer.print("") - } - } -} - -struct SwiftThunkTranslator { - - let st: Swift2JavaTranslator - - init(_ st: Swift2JavaTranslator) { - self.st = st - } - - func renderGlobalThunks() -> [DeclSyntax] { - var decls: [DeclSyntax] = [] - decls.reserveCapacity( - st.importedGlobalVariables.count + st.importedGlobalFuncs.count - ) - - for decl in st.importedGlobalVariables { - decls.append(contentsOf: render(forFunc: decl)) - } - - for decl in st.importedGlobalFuncs { - decls.append(contentsOf: render(forFunc: decl)) - } - - return decls - } - - /// Render all the thunks that make Swift methods accessible to Java. - func renderThunks(forType nominal: ImportedNominalType) -> [DeclSyntax] { - var decls: [DeclSyntax] = [] - decls.reserveCapacity( - 1 + nominal.initializers.count + nominal.variables.count + nominal.methods.count - ) - - decls.append(renderSwiftTypeAccessor(nominal)) - - for decl in nominal.initializers { - decls.append(contentsOf: render(forFunc: decl)) - } - - for decl in nominal.variables { - decls.append(contentsOf: render(forFunc: decl)) - } - - for decl in nominal.methods { - decls.append(contentsOf: render(forFunc: decl)) - } - - return decls - } - - /// Accessor to get the `T.self` of the Swift type, without having to rely on mangled name lookups. - func renderSwiftTypeAccessor(_ nominal: ImportedNominalType) -> DeclSyntax { - let funcName = SwiftKitPrinting.Names.getType( - module: st.swiftModuleName, - nominal: nominal) - - return - """ - @_cdecl("\(raw: funcName)") - public func \(raw: funcName)() -> UnsafeMutableRawPointer /* Any.Type */ { - return unsafeBitCast(\(raw: nominal.swiftNominal.qualifiedName).self, to: UnsafeMutableRawPointer.self) - } - """ - } - - func render(forFunc decl: ImportedFunc) -> [DeclSyntax] { - st.log.trace("Rendering thunks for: \(decl.displayName)") - - let thunkName = st.thunkNameRegistry.functionThunkName(decl: decl) - guard let translatedSignatures = st.translatedSignature(for: decl) else { - return [] - } - - let thunkFunc = translatedSignatures.loweredSignature.cdeclThunk( - cName: thunkName, - swiftAPIName: decl.name, - as: decl.apiKind, - stdlibTypes: st.swiftStdlibTypes - ) - return [DeclSyntax(thunkFunc)] - } -} diff --git a/Sources/JavaKitConfigurationShared/Configuration.swift b/Sources/JavaKitConfigurationShared/Configuration.swift index 5771b53f..1c4fad56 100644 --- a/Sources/JavaKitConfigurationShared/Configuration.swift +++ b/Sources/JavaKitConfigurationShared/Configuration.swift @@ -113,7 +113,7 @@ public struct JavaDependencyDescriptor: Hashable, Codable { } } -public func readConfiguration(sourceDir: String, file: String = #fileID, line: UInt = #line) throws -> Configuration { +public func readConfiguration(sourceDir: String, file: String = #fileID, line: UInt = #line) throws -> Configuration? { // Workaround since filePath is macOS 13 let sourcePath = if sourceDir.hasPrefix("file://") { sourceDir } else { "file://" + sourceDir } @@ -122,12 +122,15 @@ public func readConfiguration(sourceDir: String, file: String = #fileID, line: U return try readConfiguration(configPath: configPath, file: file, line: line) } -public func readConfiguration(configPath: URL, file: String = #fileID, line: UInt = #line) throws -> Configuration { +public func readConfiguration(configPath: URL, file: String = #fileID, line: UInt = #line) throws -> Configuration? { + guard let configData = try? Data(contentsOf: configPath) else { + return nil + } + do { - let configData = try Data(contentsOf: configPath) return try JSONDecoder().decode(Configuration.self, from: configData) } catch { - throw ConfigurationError(message: "Failed to parse SwiftJava configuration at '\(configPath.absoluteURL)'!", error: error, + throw ConfigurationError(message: "Failed to parse SwiftJava configuration at '\(configPath.absoluteURL)'! \(#fileID):\(#line)", error: error, file: file, line: line) } } diff --git a/Sources/SwiftJavaTool/SwiftJava.swift b/Sources/SwiftJavaTool/SwiftJava.swift index b8e29ed8..badd5455 100644 --- a/Sources/SwiftJavaTool/SwiftJava.swift +++ b/Sources/SwiftJavaTool/SwiftJava.swift @@ -116,6 +116,7 @@ struct SwiftJava: AsyncParsableCommand { return nil } + print("[debug][swift-java] Module base directory based on outputDirectory!") return URL(fileURLWithPath: outputDirectory) } @@ -186,21 +187,23 @@ struct SwiftJava: AsyncParsableCommand { mutating func run() async { print("[info][swift-java] Run: \(CommandLine.arguments.joined(separator: " "))") + print("[info][swift-java] Current work directory: \(URL(fileURLWithPath: "."))") + print("[info][swift-java] Module base directory: \(moduleBaseDir)") do { - var config: Configuration = Configuration() + var earlyConfig: Configuration? if let moduleBaseDir { print("[debug][swift-java] Load config from module base directory: \(moduleBaseDir.path)") - config = try readConfiguration(sourceDir: moduleBaseDir.path) + earlyConfig = try readConfiguration(sourceDir: moduleBaseDir.path) } else if let inputSwift { print("[debug][swift-java] Load config from module swift input directory: \(inputSwift)") - config = try readConfiguration(sourceDir: inputSwift) + earlyConfig = try readConfiguration(sourceDir: inputSwift) } + var config = earlyConfig ?? Configuration() config.logLevel = self.logLevel if let javaPackage { config.javaPackage = javaPackage } - assert(config.javaPackage != nil, "java-package was nil!") // Determine the mode in which we'll execute. let toolMode: ToolMode @@ -461,7 +464,10 @@ extension SwiftJava { return (false, .init()) case .amend: let configPath = actualOutputDirectory - return (true, try readConfiguration(sourceDir: configPath.path)) + guard let config = try readConfiguration(sourceDir: configPath.path) else { + return (false, .init()) + } + return (true, config) } } } From 3913ed8e357bfd9d096a0ce0aa631162b62bd11e Mon Sep 17 00:00:00 2001 From: Konrad 'ktoso' Malawski Date: Mon, 9 Jun 2025 16:07:17 +0900 Subject: [PATCH 269/426] CLI: don't crash if no mode selected, just print the USAGE --- Sources/SwiftJavaTool/SwiftJava.swift | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Sources/SwiftJavaTool/SwiftJava.swift b/Sources/SwiftJavaTool/SwiftJava.swift index badd5455..a0ba75dc 100644 --- a/Sources/SwiftJavaTool/SwiftJava.swift +++ b/Sources/SwiftJavaTool/SwiftJava.swift @@ -186,6 +186,12 @@ struct SwiftJava: AsyncParsableCommand { } mutating func run() async { + guard CommandLine.arguments.count > 1 else { + // there's no "default" command, print USAGE when no arguments/parameters are passed. + print("Must specify run mode.\n\(Self.helpMessage())") + return + } + print("[info][swift-java] Run: \(CommandLine.arguments.joined(separator: " "))") print("[info][swift-java] Current work directory: \(URL(fileURLWithPath: "."))") print("[info][swift-java] Module base directory: \(moduleBaseDir)") @@ -230,7 +236,7 @@ struct SwiftJava: AsyncParsableCommand { toolMode = .configuration(extraClasspath: input) } else if fetch { guard let input else { - fatalError("Mode -jar requires path\n\(Self.helpMessage())") + fatalError("Mode 'fetch' requires path\n\(Self.helpMessage())") } config = try JavaTranslator.readConfiguration(from: URL(fileURLWithPath: input)) guard let dependencies = config.dependencies else { From 91f12b1fbd14c7fff741f374e4f57afd07dbaf3c Mon Sep 17 00:00:00 2001 From: Mads Odgaard Date: Thu, 5 Jun 2025 12:01:53 +0200 Subject: [PATCH 270/426] refactor FFM generation into protocol backed implementation --- .editorconfig | 6 ++ Sources/JExtractSwiftLib/AnalysisResult.swift | 4 + Sources/JExtractSwiftLib/CodePrinter.swift | 2 + ...2JavaGenerator+JavaBindingsPrinting.swift} | 8 +- ...Swift2JavaGenerator+JavaTranslation.swift} | 0 .../FFMSwift2JavaGenerator.swift} | 101 ++++++++++++++---- Sources/JExtractSwiftLib/Swift2Java.swift | 13 +++ .../Swift2JavaGenerator.swift | 3 + .../Swift2JavaTranslator.swift | 31 ++---- 9 files changed, 117 insertions(+), 51 deletions(-) create mode 100644 .editorconfig create mode 100644 Sources/JExtractSwiftLib/AnalysisResult.swift rename Sources/JExtractSwiftLib/{Swift2JavaTranslator+JavaBindingsPrinting.swift => FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift} (98%) rename Sources/JExtractSwiftLib/{Swift2JavaTranslator+JavaTranslation.swift => FFM/FFMSwift2JavaGenerator+JavaTranslation.swift} (100%) rename Sources/JExtractSwiftLib/{Swift2JavaTranslator+Printing.swift => FFM/FFMSwift2JavaGenerator.swift} (76%) create mode 100644 Sources/JExtractSwiftLib/Swift2JavaGenerator.swift diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..9c71277f --- /dev/null +++ b/.editorconfig @@ -0,0 +1,6 @@ +root = true + +[*] +indent_style = space +indent_size = 2 +insert_final_newline = true diff --git a/Sources/JExtractSwiftLib/AnalysisResult.swift b/Sources/JExtractSwiftLib/AnalysisResult.swift new file mode 100644 index 00000000..578093d9 --- /dev/null +++ b/Sources/JExtractSwiftLib/AnalysisResult.swift @@ -0,0 +1,4 @@ +struct AnalysisResult { + let importedTypes: [String: ImportedNominalType] + let importedGlobalFuncs: [ImportedFunc] +} diff --git a/Sources/JExtractSwiftLib/CodePrinter.swift b/Sources/JExtractSwiftLib/CodePrinter.swift index db823aa2..449cab3d 100644 --- a/Sources/JExtractSwiftLib/CodePrinter.swift +++ b/Sources/JExtractSwiftLib/CodePrinter.swift @@ -14,6 +14,8 @@ import Foundation +let PATH_SEPARATOR = "/" // TODO: Windows + public struct CodePrinter { var contents: String = "" diff --git a/Sources/JExtractSwiftLib/Swift2JavaTranslator+JavaBindingsPrinting.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift similarity index 98% rename from Sources/JExtractSwiftLib/Swift2JavaTranslator+JavaBindingsPrinting.swift rename to Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift index 90f98577..db02a9cf 100644 --- a/Sources/JExtractSwiftLib/Swift2JavaTranslator+JavaBindingsPrinting.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift @@ -14,8 +14,8 @@ import JavaTypes -extension Swift2JavaTranslator { - public func printFunctionDowncallMethods( +extension FFMSwift2JavaGenerator { + func printFunctionDowncallMethods( _ printer: inout CodePrinter, _ decl: ImportedFunc ) { @@ -33,7 +33,7 @@ extension Swift2JavaTranslator { } /// Print FFM Java binding descriptors for the imported Swift API. - package func printJavaBindingDescriptorClass( + func printJavaBindingDescriptorClass( _ printer: inout CodePrinter, _ decl: ImportedFunc ) { @@ -211,7 +211,7 @@ extension Swift2JavaTranslator { let memoryLayout = renderMemoryLayoutValue(for: outParameter.type) let arena = if let className = outParameter.type.className, - self.importedTypes[className] != nil { + analysis.importedTypes[className] != nil { // Use passed-in 'SwiftArena' for 'SwiftValue'. "swiftArena$" } else { diff --git a/Sources/JExtractSwiftLib/Swift2JavaTranslator+JavaTranslation.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift similarity index 100% rename from Sources/JExtractSwiftLib/Swift2JavaTranslator+JavaTranslation.swift rename to Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift diff --git a/Sources/JExtractSwiftLib/Swift2JavaTranslator+Printing.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift similarity index 76% rename from Sources/JExtractSwiftLib/Swift2JavaTranslator+Printing.swift rename to Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift index 13e337e0..1f9d8610 100644 --- a/Sources/JExtractSwiftLib/Swift2JavaTranslator+Printing.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift @@ -16,27 +16,81 @@ import JavaTypes import SwiftSyntax import SwiftSyntaxBuilder +class FFMSwift2JavaGenerator: Swift2JavaGenerator { + private let log = Logger(label: "ffm-generator", logLevel: .info) + + let analysis: AnalysisResult + let swiftModuleName: String + let javaPackage: String + let swiftOutputDirectory: String + let javaOutputDirectory: String + let swiftStdlibTypes: SwiftStandardLibraryTypes + + var javaPackagePath: String { + javaPackage.replacingOccurrences(of: ".", with: "/") + } + + var thunkNameRegistry: ThunkNameRegistry = ThunkNameRegistry() + + init( + analysis: AnalysisResult, + swiftModuleName: String, + javaPackage: String, + swiftOutputDirectory: String, + javaOutputDirectory: String + ) { + self.analysis = analysis + self.swiftModuleName = swiftModuleName + self.javaPackage = javaPackage + self.swiftOutputDirectory = swiftOutputDirectory + self.javaOutputDirectory = javaOutputDirectory + + var parsedSwiftModule = SwiftParsedModuleSymbolTable(moduleName: "Swift") + self.swiftStdlibTypes = SwiftStandardLibraryTypes(into: &parsedSwiftModule) + } + + func generate() throws { + try writeExportedJavaSources() + } +} + +// ===== -------------------------------------------------------------------------------------------------------------- +// MARK: Defaults + +extension FFMSwift2JavaGenerator { + + /// Default set Java imports for every generated file + static let defaultJavaImports: Array = [ + "org.swift.swiftkit.*", + "org.swift.swiftkit.SwiftKit", + "org.swift.swiftkit.util.*", + + // Necessary for native calls and type mapping + "java.lang.foreign.*", + "java.lang.invoke.*", + "java.util.Arrays", + "java.util.stream.Collectors", + "java.util.concurrent.atomic.*", + "java.nio.charset.StandardCharsets", + ] +} + // ==== --------------------------------------------------------------------------------------------------------------- // MARK: File writing -let PATH_SEPARATOR = "/" // TODO: Windows -extension Swift2JavaTranslator { +extension FFMSwift2JavaGenerator { /// Every imported public type becomes a public class in its own file in Java. - public func writeExportedJavaSources(outputDirectory: String) throws { + func writeExportedJavaSources() throws { var printer = CodePrinter() - try writeExportedJavaSources(outputDirectory: outputDirectory, printer: &printer) - } - - public func writeExportedJavaSources(outputDirectory: String, printer: inout CodePrinter) throws { - for (_, ty) in importedTypes.sorted(by: { (lhs, rhs) in lhs.key < rhs.key }) { + for (_, ty) in analysis.importedTypes.sorted(by: { (lhs, rhs) in lhs.key < rhs.key }) { let filename = "\(ty.swiftNominal.name).java" log.info("Printing contents: \(filename)") printImportedNominal(&printer, ty) if let outputFile = try printer.writeContents( - outputDirectory: outputDirectory, + outputDirectory: javaOutputDirectory, javaPackagePath: javaPackagePath, filename: filename ) { @@ -50,7 +104,7 @@ extension Swift2JavaTranslator { printModule(&printer) if let outputFile = try printer.writeContents( - outputDirectory: outputDirectory, + outputDirectory: javaOutputDirectory, javaPackagePath: javaPackagePath, filename: filename) { @@ -63,26 +117,26 @@ extension Swift2JavaTranslator { // ==== --------------------------------------------------------------------------------------------------------------- // MARK: Java/text printing -extension Swift2JavaTranslator { +extension FFMSwift2JavaGenerator { /// Render the Java file contents for an imported Swift module. /// /// This includes any Swift global functions in that module, and some general type information and helpers. - public func printModule(_ printer: inout CodePrinter) { + func printModule(_ printer: inout CodePrinter) { printHeader(&printer) printPackage(&printer) printImports(&printer) printModuleClass(&printer) { printer in // TODO: print all "static" methods - for decl in importedGlobalFuncs { + for decl in analysis.importedGlobalFuncs { self.log.trace("Print imported decl: \(decl)") printFunctionDowncallMethods(&printer, decl) } } } - package func printImportedNominal(_ printer: inout CodePrinter, _ decl: ImportedNominalType) { + func printImportedNominal(_ printer: inout CodePrinter, _ decl: ImportedNominalType) { printHeader(&printer) printPackage(&printer) printImports(&printer) @@ -143,7 +197,7 @@ extension Swift2JavaTranslator { } } - public func printHeader(_ printer: inout CodePrinter) { + func printHeader(_ printer: inout CodePrinter) { printer.print( """ // Generated by jextract-swift @@ -153,7 +207,7 @@ extension Swift2JavaTranslator { ) } - public func printPackage(_ printer: inout CodePrinter) { + func printPackage(_ printer: inout CodePrinter) { printer.print( """ package \(javaPackage); @@ -162,14 +216,14 @@ extension Swift2JavaTranslator { ) } - public func printImports(_ printer: inout CodePrinter) { - for i in Swift2JavaTranslator.defaultJavaImports { + func printImports(_ printer: inout CodePrinter) { + for i in FFMSwift2JavaGenerator.defaultJavaImports { printer.print("import \(i);") } printer.print("") } - package func printNominal( + func printNominal( _ printer: inout CodePrinter, _ decl: ImportedNominalType, body: (inout CodePrinter) -> Void ) { let parentProtocol: String @@ -188,7 +242,7 @@ extension Swift2JavaTranslator { } } - public func printModuleClass(_ printer: inout CodePrinter, body: (inout CodePrinter) -> Void) { + func printModuleClass(_ printer: inout CodePrinter, body: (inout CodePrinter) -> Void) { printer.printBraceBlock("public final class \(swiftModuleName)") { printer in printPrivateConstructor(&printer, swiftModuleName) @@ -261,7 +315,7 @@ extension Swift2JavaTranslator { } } - private func printClassConstants(printer: inout CodePrinter) { + func printClassConstants(printer: inout CodePrinter) { printer.print( """ static final String LIB_NAME = "\(swiftModuleName)"; @@ -270,7 +324,7 @@ extension Swift2JavaTranslator { ) } - private func printPrivateConstructor(_ printer: inout CodePrinter, _ typeName: String) { + func printPrivateConstructor(_ printer: inout CodePrinter, _ typeName: String) { printer.print( """ private \(typeName)() { @@ -296,7 +350,7 @@ extension Swift2JavaTranslator { ) } - package func printToStringMethod( + func printToStringMethod( _ printer: inout CodePrinter, _ decl: ImportedNominalType ) { printer.print( @@ -312,3 +366,4 @@ extension Swift2JavaTranslator { """) } } + diff --git a/Sources/JExtractSwiftLib/Swift2Java.swift b/Sources/JExtractSwiftLib/Swift2Java.swift index 79cb0fec..a793ae25 100644 --- a/Sources/JExtractSwiftLib/Swift2Java.swift +++ b/Sources/JExtractSwiftLib/Swift2Java.swift @@ -89,6 +89,19 @@ public struct SwiftToJava { try translator.analyze() + let generator = FFMSwift2JavaGenerator( + analysis: translator.result, + swiftModuleName: self.swiftModule, + javaPackage: self.packageName, + swiftOutputDirectory: outputDirectorySwift, + javaOutputDirectory: outputDirectoryJava + ) + + try generator.generate() + + + print("[swift-java] Generated Java sources (\(packageName)) in: \(outputDirectoryJava)/") + try translator.writeSwiftThunkSources(outputDirectory: outputSwiftDirectory) print("[swift-java] Generated Swift sources (module: '\(config.swiftModule ?? "")') in: \(outputSwiftDirectory)/") diff --git a/Sources/JExtractSwiftLib/Swift2JavaGenerator.swift b/Sources/JExtractSwiftLib/Swift2JavaGenerator.swift new file mode 100644 index 00000000..e78598e5 --- /dev/null +++ b/Sources/JExtractSwiftLib/Swift2JavaGenerator.swift @@ -0,0 +1,3 @@ +protocol Swift2JavaGenerator { + func generate() throws +} diff --git a/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift b/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift index 496c9b44..f53820bd 100644 --- a/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift +++ b/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift @@ -91,6 +91,13 @@ extension Swift2JavaTranslator { /// a checked truncation operation at the Java/Swift board. var javaPrimitiveForSwiftInt: JavaType { .long } + var result: AnalysisResult { + AnalysisResult( + importedTypes: self.importedTypes, + importedGlobalFuncs: self.importedGlobalFuncs + ) + } + package func add(filePath: String, text: String) { log.trace("Adding: \(filePath)") let sourceFileSyntax = Parser.parse(source: text) @@ -128,30 +135,6 @@ extension Swift2JavaTranslator { } } -// ===== -------------------------------------------------------------------------------------------------------------- -// MARK: Defaults - -extension Swift2JavaTranslator { - /// Default formatting options. - static let defaultFormat = BasicFormat(indentationWidth: .spaces(2)) - - /// Default set Java imports for every generated file - static let defaultJavaImports: Array = [ - "org.swift.swiftkit.*", - "org.swift.swiftkit.SwiftKit", - "org.swift.swiftkit.util.*", - - // Necessary for native calls and type mapping - "java.lang.foreign.*", - "java.lang.invoke.*", - "java.util.Arrays", - "java.util.stream.Collectors", - "java.util.concurrent.atomic.*", - "java.nio.charset.StandardCharsets", - ] - -} - // ==== ---------------------------------------------------------------------------------------------------------------- // MARK: Type translation extension Swift2JavaTranslator { From 9393a3a443610fe3437788d990b2e36ffead8617 Mon Sep 17 00:00:00 2001 From: Mads Odgaard Date: Sat, 7 Jun 2025 15:25:17 +0200 Subject: [PATCH 271/426] fix tests --- Sources/JExtractSwiftLib/AnalysisResult.swift | 1 + .../CDeclLowering/CRepresentation.swift | 0 ...wift2JavaGenerator+FunctionLowering.swift} | 2 +- .../{ => FFM}/ConversionStep.swift | 0 ...t2JavaGenerator+JavaBindingsPrinting.swift | 2 +- ...MSwift2JavaGenerator+JavaTranslation.swift | 2 +- ...ft2JavaGenerator+SwiftThunkPrinting.swift} | 25 +++--- .../FFM/FFMSwift2JavaGenerator.swift | 32 +++++--- Sources/JExtractSwiftLib/GenerationMode.swift | 6 ++ Sources/JExtractSwiftLib/Swift2Java.swift | 20 ++--- .../Swift2JavaTranslator.swift | 30 +------ .../JExtractSwiftLib/Swift2JavaVisitor.swift | 11 +-- .../Asserts/LoweringAssertions.swift | 22 +++-- .../Asserts/TextAssertions.swift | 11 ++- .../ClassPrintingTests.swift | 1 - .../FuncCallbackImportTests.swift | 10 ++- .../FunctionDescriptorImportTests.swift | 20 ++++- .../MethodImportTests.swift | 80 +++++++++++++++---- .../JExtractSwiftTests/MethodThunkTests.swift | 1 - .../StringPassingTests.swift | 1 - .../VariableImportTests.swift | 1 - 21 files changed, 169 insertions(+), 109 deletions(-) rename Sources/JExtractSwiftLib/{ => FFM}/CDeclLowering/CRepresentation.swift (100%) rename Sources/JExtractSwiftLib/{CDeclLowering/Swift2JavaTranslator+FunctionLowering.swift => FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift} (99%) rename Sources/JExtractSwiftLib/{ => FFM}/ConversionStep.swift (100%) rename Sources/JExtractSwiftLib/{Swift2JavaTranslator+SwiftThunkPrinting.swift => FFM/FFMSwift2JavaGenerator+SwiftThunkPrinting.swift} (87%) create mode 100644 Sources/JExtractSwiftLib/GenerationMode.swift diff --git a/Sources/JExtractSwiftLib/AnalysisResult.swift b/Sources/JExtractSwiftLib/AnalysisResult.swift index 578093d9..1e37d5c5 100644 --- a/Sources/JExtractSwiftLib/AnalysisResult.swift +++ b/Sources/JExtractSwiftLib/AnalysisResult.swift @@ -1,4 +1,5 @@ struct AnalysisResult { let importedTypes: [String: ImportedNominalType] + let importedGlobalVariables: [ImportedFunc] let importedGlobalFuncs: [ImportedFunc] } diff --git a/Sources/JExtractSwiftLib/CDeclLowering/CRepresentation.swift b/Sources/JExtractSwiftLib/FFM/CDeclLowering/CRepresentation.swift similarity index 100% rename from Sources/JExtractSwiftLib/CDeclLowering/CRepresentation.swift rename to Sources/JExtractSwiftLib/FFM/CDeclLowering/CRepresentation.swift diff --git a/Sources/JExtractSwiftLib/CDeclLowering/Swift2JavaTranslator+FunctionLowering.swift b/Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift similarity index 99% rename from Sources/JExtractSwiftLib/CDeclLowering/Swift2JavaTranslator+FunctionLowering.swift rename to Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift index 671f373e..cd5ea0a2 100644 --- a/Sources/JExtractSwiftLib/CDeclLowering/Swift2JavaTranslator+FunctionLowering.swift +++ b/Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift @@ -15,7 +15,7 @@ import JavaTypes import SwiftSyntax -extension Swift2JavaTranslator { +extension FFMSwift2JavaGenerator { /// Lower the given function declaration to a C-compatible entrypoint, /// providing all of the mappings between the parameter and result types /// of the original function and its `@_cdecl` counterpart. diff --git a/Sources/JExtractSwiftLib/ConversionStep.swift b/Sources/JExtractSwiftLib/FFM/ConversionStep.swift similarity index 100% rename from Sources/JExtractSwiftLib/ConversionStep.swift rename to Sources/JExtractSwiftLib/FFM/ConversionStep.swift diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift index db02a9cf..77ab9a81 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift @@ -33,7 +33,7 @@ extension FFMSwift2JavaGenerator { } /// Print FFM Java binding descriptors for the imported Swift API. - func printJavaBindingDescriptorClass( + package func printJavaBindingDescriptorClass( _ printer: inout CodePrinter, _ decl: ImportedFunc ) { diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift index bf1cd9d2..56eb606d 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift @@ -14,7 +14,7 @@ import JavaTypes -extension Swift2JavaTranslator { +extension FFMSwift2JavaGenerator { func translatedSignature( for decl: ImportedFunc ) -> TranslatedFunctionSignature? { diff --git a/Sources/JExtractSwiftLib/Swift2JavaTranslator+SwiftThunkPrinting.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+SwiftThunkPrinting.swift similarity index 87% rename from Sources/JExtractSwiftLib/Swift2JavaTranslator+SwiftThunkPrinting.swift rename to Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+SwiftThunkPrinting.swift index 51547ba8..416bc851 100644 --- a/Sources/JExtractSwiftLib/Swift2JavaTranslator+SwiftThunkPrinting.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+SwiftThunkPrinting.swift @@ -15,14 +15,13 @@ import SwiftSyntax import SwiftSyntaxBuilder -extension Swift2JavaTranslator { - public func writeSwiftThunkSources(outputDirectory: String) throws { +extension FFMSwift2JavaGenerator { + package func writeSwiftThunkSources() throws { var printer = CodePrinter() - - try writeSwiftThunkSources(outputDirectory: outputDirectory, printer: &printer) + try writeSwiftThunkSources(printer: &printer) } - public func writeSwiftThunkSources(outputDirectory: String, printer: inout CodePrinter) throws { + package func writeSwiftThunkSources(printer: inout CodePrinter) throws { let moduleFilenameBase = "\(self.swiftModuleName)Module+SwiftJava" let moduleFilename = "\(moduleFilenameBase).swift" do { @@ -31,7 +30,7 @@ extension Swift2JavaTranslator { try printGlobalSwiftThunkSources(&printer) if let outputFile = try printer.writeContents( - outputDirectory: outputDirectory, + outputDirectory: self.swiftOutputDirectory, javaPackagePath: nil, filename: moduleFilename) { @@ -42,7 +41,7 @@ extension Swift2JavaTranslator { } // === All types - for (_, ty) in importedTypes.sorted(by: { (lhs, rhs) in lhs.key < rhs.key }) { + for (_, ty) in self.analysis.importedTypes.sorted(by: { (lhs, rhs) in lhs.key < rhs.key }) { let fileNameBase = "\(ty.swiftNominal.qualifiedName)+SwiftJava" let filename = "\(fileNameBase).swift" log.info("Printing contents: \(filename)") @@ -51,7 +50,7 @@ extension Swift2JavaTranslator { try printSwiftThunkSources(&printer, ty: ty) if let outputFile = try printer.writeContents( - outputDirectory: outputDirectory, + outputDirectory: self.swiftOutputDirectory, javaPackagePath: nil, filename: filename) { @@ -110,23 +109,23 @@ extension Swift2JavaTranslator { struct SwiftThunkTranslator { - let st: Swift2JavaTranslator + let st: FFMSwift2JavaGenerator - init(_ st: Swift2JavaTranslator) { + init(_ st: FFMSwift2JavaGenerator) { self.st = st } func renderGlobalThunks() -> [DeclSyntax] { var decls: [DeclSyntax] = [] decls.reserveCapacity( - st.importedGlobalVariables.count + st.importedGlobalFuncs.count + st.analysis.importedGlobalVariables.count + st.analysis.importedGlobalFuncs.count ) - for decl in st.importedGlobalVariables { + for decl in st.analysis.importedGlobalVariables { decls.append(contentsOf: render(forFunc: decl)) } - for decl in st.importedGlobalFuncs { + for decl in st.analysis.importedGlobalFuncs { decls.append(contentsOf: render(forFunc: decl)) } diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift index 1f9d8610..492168f6 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift @@ -16,8 +16,8 @@ import JavaTypes import SwiftSyntax import SwiftSyntaxBuilder -class FFMSwift2JavaGenerator: Swift2JavaGenerator { - private let log = Logger(label: "ffm-generator", logLevel: .info) +package class FFMSwift2JavaGenerator: Swift2JavaGenerator { + let log = Logger(label: "ffm-generator", logLevel: .info) let analysis: AnalysisResult let swiftModuleName: String @@ -25,6 +25,7 @@ class FFMSwift2JavaGenerator: Swift2JavaGenerator { let swiftOutputDirectory: String let javaOutputDirectory: String let swiftStdlibTypes: SwiftStandardLibraryTypes + let symbolTable: SwiftSymbolTable var javaPackagePath: String { javaPackage.replacingOccurrences(of: ".", with: "/") @@ -32,25 +33,27 @@ class FFMSwift2JavaGenerator: Swift2JavaGenerator { var thunkNameRegistry: ThunkNameRegistry = ThunkNameRegistry() - init( - analysis: AnalysisResult, - swiftModuleName: String, + /// Cached Java translation result. 'nil' indicates failed translation. + var translatedSignatures: [ImportedFunc: TranslatedFunctionSignature?] = [:] + + package init( + translator: Swift2JavaTranslator, javaPackage: String, swiftOutputDirectory: String, - javaOutputDirectory: String + javaOutputDirectory: String, ) { - self.analysis = analysis - self.swiftModuleName = swiftModuleName + self.analysis = translator.result + self.swiftModuleName = translator.swiftModuleName self.javaPackage = javaPackage self.swiftOutputDirectory = swiftOutputDirectory self.javaOutputDirectory = javaOutputDirectory - - var parsedSwiftModule = SwiftParsedModuleSymbolTable(moduleName: "Swift") - self.swiftStdlibTypes = SwiftStandardLibraryTypes(into: &parsedSwiftModule) + self.symbolTable = translator.symbolTable + self.swiftStdlibTypes = translator.swiftStdlibTypes } func generate() throws { try writeExportedJavaSources() + try writeSwiftThunkSources() } } @@ -80,10 +83,13 @@ extension FFMSwift2JavaGenerator { extension FFMSwift2JavaGenerator { + package func writeExportedJavaSources() throws { + var printer = CodePrinter() + try writeExportedJavaSources(printer: &printer) + } /// Every imported public type becomes a public class in its own file in Java. - func writeExportedJavaSources() throws { - var printer = CodePrinter() + package func writeExportedJavaSources(printer: inout CodePrinter) throws { for (_, ty) in analysis.importedTypes.sorted(by: { (lhs, rhs) in lhs.key < rhs.key }) { let filename = "\(ty.swiftNominal.name).java" log.info("Printing contents: \(filename)") diff --git a/Sources/JExtractSwiftLib/GenerationMode.swift b/Sources/JExtractSwiftLib/GenerationMode.swift new file mode 100644 index 00000000..95266e1a --- /dev/null +++ b/Sources/JExtractSwiftLib/GenerationMode.swift @@ -0,0 +1,6 @@ +import ArgumentParser + +public enum GenerationMode: String, ExpressibleByArgument { + /// Foreign Value and Memory API + case ffm +} diff --git a/Sources/JExtractSwiftLib/Swift2Java.swift b/Sources/JExtractSwiftLib/Swift2Java.swift index a793ae25..895dc61f 100644 --- a/Sources/JExtractSwiftLib/Swift2Java.swift +++ b/Sources/JExtractSwiftLib/Swift2Java.swift @@ -89,15 +89,17 @@ public struct SwiftToJava { try translator.analyze() - let generator = FFMSwift2JavaGenerator( - analysis: translator.result, - swiftModuleName: self.swiftModule, - javaPackage: self.packageName, - swiftOutputDirectory: outputDirectorySwift, - javaOutputDirectory: outputDirectoryJava - ) - - try generator.generate() + switch mode { + case .ffm: + let generator = FFMSwift2JavaGenerator( + translator: translator, + javaPackage: self.packageName, + swiftOutputDirectory: outputDirectorySwift, + javaOutputDirectory: outputDirectoryJava + ) + + try generator.generate() + } print("[swift-java] Generated Java sources (\(packageName)) in: \(outputDirectoryJava)/") diff --git a/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift b/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift index f53820bd..ace5f444 100644 --- a/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift +++ b/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift @@ -33,13 +33,6 @@ public final class Swift2JavaTranslator { var inputs: [Input] = [] - // ==== Output configuration - let javaPackage: String - - var javaPackagePath: String { - javaPackage.replacingOccurrences(of: ".", with: "/") - } - // ==== Output state package var importedGlobalVariables: [ImportedFunc] = [] @@ -54,21 +47,14 @@ public final class Swift2JavaTranslator { package let symbolTable: SwiftSymbolTable - package var thunkNameRegistry: ThunkNameRegistry = ThunkNameRegistry() - - /// Cached Java translation result. 'nil' indicates failed translation. - var translatedSignatures: [ImportedFunc: TranslatedFunctionSignature?] = [:] - /// The name of the Swift module being translated. var swiftModuleName: String { symbolTable.moduleName } public init( - javaPackage: String, swiftModuleName: String ) { - self.javaPackage = javaPackage self.symbolTable = SwiftSymbolTable(parsedModuleName: swiftModuleName) // Create a mock of the Swift standard library. @@ -82,18 +68,10 @@ public final class Swift2JavaTranslator { // MARK: Analysis extension Swift2JavaTranslator { - /// The primitive Java type to use for Swift's Int type, which follows the - /// size of a pointer. - /// - /// FIXME: Consider whether to extract this information from the Swift - /// interface file, so that it would be 'int' for 32-bit targets or 'long' for - /// 64-bit targets but make the Java code different for the two, vs. adding - /// a checked truncation operation at the Java/Swift board. - var javaPrimitiveForSwiftInt: JavaType { .long } - var result: AnalysisResult { AnalysisResult( importedTypes: self.importedTypes, + importedGlobalVariables: self.importedGlobalVariables, importedGlobalFuncs: self.importedGlobalFuncs ) } @@ -117,11 +95,7 @@ extension Swift2JavaTranslator { func analyze() throws { prepareForTranslation() - let visitor = Swift2JavaVisitor( - moduleName: self.swiftModuleName, - targetJavaPackage: self.javaPackage, - translator: self - ) + let visitor = Swift2JavaVisitor(translator: self) for input in self.inputs { log.trace("Analyzing \(input.filePath)") diff --git a/Sources/JExtractSwiftLib/Swift2JavaVisitor.swift b/Sources/JExtractSwiftLib/Swift2JavaVisitor.swift index 4bb85a46..0b4d6bbf 100644 --- a/Sources/JExtractSwiftLib/Swift2JavaVisitor.swift +++ b/Sources/JExtractSwiftLib/Swift2JavaVisitor.swift @@ -19,13 +19,6 @@ import SwiftSyntax final class Swift2JavaVisitor: SyntaxVisitor { let translator: Swift2JavaTranslator - /// The Swift module we're visiting declarations in - let moduleName: String - - /// The target java package we are going to generate types into eventually, - /// store this along with type names as we import them. - let targetJavaPackage: String - /// Type context stack associated with the syntax. var typeContext: [(syntaxID: Syntax.ID, type: ImportedNominalType)] = [] @@ -42,9 +35,7 @@ final class Swift2JavaVisitor: SyntaxVisitor { var log: Logger { translator.log } - init(moduleName: String, targetJavaPackage: String, translator: Swift2JavaTranslator) { - self.moduleName = moduleName - self.targetJavaPackage = targetJavaPackage + init(translator: Swift2JavaTranslator) { self.translator = translator super.init(viewMode: .all) diff --git a/Tests/JExtractSwiftTests/Asserts/LoweringAssertions.swift b/Tests/JExtractSwiftTests/Asserts/LoweringAssertions.swift index b306689d..5dd28cc8 100644 --- a/Tests/JExtractSwiftTests/Asserts/LoweringAssertions.swift +++ b/Tests/JExtractSwiftTests/Asserts/LoweringAssertions.swift @@ -32,7 +32,6 @@ func assertLoweredFunction( column: Int = #column ) throws { let translator = Swift2JavaTranslator( - javaPackage: javaPackage, swiftModuleName: swiftModuleName ) @@ -42,18 +41,25 @@ func assertLoweredFunction( translator.prepareForTranslation() + let generator = FFMSwift2JavaGenerator( + translator: translator, + javaPackage: "com.example.swift", + swiftOutputDirectory: "/fake", + javaOutputDirectory: "/fake" + ) + let swiftFunctionName: String let apiKind: SwiftAPIKind let loweredFunction: LoweredFunctionSignature if let inputFunction = inputDecl.as(FunctionDeclSyntax.self) { - loweredFunction = try translator.lowerFunctionSignature( + loweredFunction = try generator.lowerFunctionSignature( inputFunction, enclosingType: enclosingType ) swiftFunctionName = inputFunction.name.text apiKind = .function } else if let inputInitializer = inputDecl.as(InitializerDeclSyntax.self) { - loweredFunction = try translator.lowerFunctionSignature( + loweredFunction = try generator.lowerFunctionSignature( inputInitializer, enclosingType: enclosingType ) @@ -112,7 +118,6 @@ func assertLoweredVariableAccessor( column: Int = #column ) throws { let translator = Swift2JavaTranslator( - javaPackage: javaPackage, swiftModuleName: swiftModuleName ) @@ -122,8 +127,15 @@ func assertLoweredVariableAccessor( translator.prepareForTranslation() + let generator = FFMSwift2JavaGenerator( + translator: translator, + javaPackage: javaPackage, + swiftOutputDirectory: "/fake", + javaOutputDirectory: "/fake" + ) + let swiftVariableName = inputDecl.bindings.first!.pattern.description - let loweredFunction = try translator.lowerFunctionSignature(inputDecl, isSet: isSet, enclosingType: enclosingType) + let loweredFunction = try generator.lowerFunctionSignature(inputDecl, isSet: isSet, enclosingType: enclosingType) let loweredCDecl = loweredFunction?.cdeclThunk( cName: "c_\(swiftVariableName)", diff --git a/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift b/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift index 3923cf3e..3ea03d98 100644 --- a/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift +++ b/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift @@ -35,13 +35,20 @@ func assertOutput( ) throws { try! translator.analyze(file: "/fake/Fake.swiftinterface", text: input) + let generator = FFMSwift2JavaGenerator( + translator: translator, + javaPackage: "com.example.swift", + swiftOutputDirectory: "/fake", + javaOutputDirectory: "/fake" + ) + let output: String var printer: CodePrinter = CodePrinter(mode: .accumulateAll) switch renderKind { case .swift: - try translator.writeSwiftThunkSources(outputDirectory: "/fake", printer: &printer) + try generator.writeSwiftThunkSources(printer: &printer) case .java: - try translator.writeExportedJavaSources(outputDirectory: "/fake", printer: &printer) + try generator.writeExportedJavaSources(printer: &printer) } output = printer.finalize() diff --git a/Tests/JExtractSwiftTests/ClassPrintingTests.swift b/Tests/JExtractSwiftTests/ClassPrintingTests.swift index 1edcdaf0..f0c59456 100644 --- a/Tests/JExtractSwiftTests/ClassPrintingTests.swift +++ b/Tests/JExtractSwiftTests/ClassPrintingTests.swift @@ -42,7 +42,6 @@ struct ClassPrintingTests { @Test("Import: class layout") func class_layout() throws { let st = Swift2JavaTranslator( - javaPackage: "com.example.swift", swiftModuleName: "__FakeModule" ) diff --git a/Tests/JExtractSwiftTests/FuncCallbackImportTests.swift b/Tests/JExtractSwiftTests/FuncCallbackImportTests.swift index 8b401ce3..f1afa7c0 100644 --- a/Tests/JExtractSwiftTests/FuncCallbackImportTests.swift +++ b/Tests/JExtractSwiftTests/FuncCallbackImportTests.swift @@ -35,7 +35,6 @@ final class FuncCallbackImportTests { @Test("Import: public func callMe(callback: () -> ())") func func_callMeFunc_Runnable() throws { let st = Swift2JavaTranslator( - javaPackage: "com.example.swift", swiftModuleName: "__FakeModule" ) st.log.logLevel = .error @@ -44,8 +43,15 @@ final class FuncCallbackImportTests { let funcDecl = st.importedGlobalFuncs.first { $0.name == "callMe" }! + let generator = FFMSwift2JavaGenerator( + translator: st, + javaPackage: "com.example.swift", + swiftOutputDirectory: "/fake", + javaOutputDirectory: "/fake" + ) + let output = CodePrinter.toString { printer in - st.printJavaBindingWrapperMethod(&printer, funcDecl) + generator.printJavaBindingWrapperMethod(&printer, funcDecl) } assertOutput( diff --git a/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift b/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift index 2963ce9e..f3a101aa 100644 --- a/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift +++ b/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift @@ -234,7 +234,6 @@ extension FunctionDescriptorTests { body: (String) throws -> Void ) throws { let st = Swift2JavaTranslator( - javaPackage: javaPackage, swiftModuleName: swiftModuleName ) st.log.logLevel = logLevel @@ -245,8 +244,15 @@ extension FunctionDescriptorTests { $0.name == methodIdentifier }! + let generator = FFMSwift2JavaGenerator( + translator: st, + javaPackage: javaPackage, + swiftOutputDirectory: "/fake", + javaOutputDirectory: "/fake" + ) + let output = CodePrinter.toString { printer in - st.printJavaBindingDescriptorClass(&printer, funcDecl) + generator.printJavaBindingDescriptorClass(&printer, funcDecl) } try body(output) @@ -261,13 +267,19 @@ extension FunctionDescriptorTests { body: (String) throws -> Void ) throws { let st = Swift2JavaTranslator( - javaPackage: javaPackage, swiftModuleName: swiftModuleName ) st.log.logLevel = logLevel try st.analyze(file: "/fake/Sample.swiftinterface", text: interfaceFile) + let generator = FFMSwift2JavaGenerator( + translator: st, + javaPackage: javaPackage, + swiftOutputDirectory: "/fake", + javaOutputDirectory: "/fake" + ) + let accessorDecl: ImportedFunc? = st.importedTypes.values.compactMap { $0.variables.first { @@ -279,7 +291,7 @@ extension FunctionDescriptorTests { } let getOutput = CodePrinter.toString { printer in - st.printJavaBindingDescriptorClass(&printer, accessorDecl) + generator.printJavaBindingDescriptorClass(&printer, accessorDecl) } try body(getOutput) diff --git a/Tests/JExtractSwiftTests/MethodImportTests.swift b/Tests/JExtractSwiftTests/MethodImportTests.swift index 48515ff2..cd2bc150 100644 --- a/Tests/JExtractSwiftTests/MethodImportTests.swift +++ b/Tests/JExtractSwiftTests/MethodImportTests.swift @@ -63,17 +63,23 @@ final class MethodImportTests { @Test("Import: public func helloWorld()") func method_helloWorld() throws { let st = Swift2JavaTranslator( - javaPackage: "com.example.swift", swiftModuleName: "__FakeModule" ) st.log.logLevel = .error try st.analyze(file: "Fake.swift", text: class_interfaceFile) + let generator = FFMSwift2JavaGenerator( + translator: st, + javaPackage: "com.example.swift", + swiftOutputDirectory: "/fake", + javaOutputDirectory: "/fake" + ) + let funcDecl = st.importedGlobalFuncs.first { $0.name == "helloWorld" }! let output = CodePrinter.toString { printer in - st.printJavaBindingWrapperMethod(&printer, funcDecl) + generator.printJavaBindingWrapperMethod(&printer, funcDecl) } assertOutput( @@ -96,7 +102,6 @@ final class MethodImportTests { @Test("Import: public func globalTakeInt(i: Int)") func func_globalTakeInt() throws { let st = Swift2JavaTranslator( - javaPackage: "com.example.swift", swiftModuleName: "__FakeModule" ) st.log.logLevel = .error @@ -107,8 +112,15 @@ final class MethodImportTests { $0.name == "globalTakeInt" }! + let generator = FFMSwift2JavaGenerator( + translator: st, + javaPackage: "com.example.swift", + swiftOutputDirectory: "/fake", + javaOutputDirectory: "/fake" + ) + let output = CodePrinter.toString { printer in - st.printJavaBindingWrapperMethod(&printer, funcDecl) + generator.printJavaBindingWrapperMethod(&printer, funcDecl) } assertOutput( @@ -131,7 +143,6 @@ final class MethodImportTests { @Test("Import: public func globalTakeIntLongString(i32: Int32, l: Int64, s: String)") func func_globalTakeIntLongString() throws { let st = Swift2JavaTranslator( - javaPackage: "com.example.swift", swiftModuleName: "__FakeModule" ) st.log.logLevel = .error @@ -142,8 +153,15 @@ final class MethodImportTests { $0.name == "globalTakeIntLongString" }! + let generator = FFMSwift2JavaGenerator( + translator: st, + javaPackage: "com.example.swift", + swiftOutputDirectory: "/fake", + javaOutputDirectory: "/fake" + ) + let output = CodePrinter.toString { printer in - st.printJavaBindingWrapperMethod(&printer, funcDecl) + generator.printJavaBindingWrapperMethod(&printer, funcDecl) } assertOutput( @@ -169,7 +187,6 @@ final class MethodImportTests { @Test("Import: public func globalReturnClass() -> MySwiftClass") func func_globalReturnClass() throws { let st = Swift2JavaTranslator( - javaPackage: "com.example.swift", swiftModuleName: "__FakeModule" ) st.log.logLevel = .error @@ -180,8 +197,15 @@ final class MethodImportTests { $0.name == "globalReturnClass" }! + let generator = FFMSwift2JavaGenerator( + translator: st, + javaPackage: "com.example.swift", + swiftOutputDirectory: "/fake", + javaOutputDirectory: "/fake" + ) + let output = CodePrinter.toString { printer in - st.printJavaBindingWrapperMethod(&printer, funcDecl) + generator.printJavaBindingWrapperMethod(&printer, funcDecl) } assertOutput( @@ -207,7 +231,6 @@ final class MethodImportTests { @Test func method_class_helloMemberFunction() throws { let st = Swift2JavaTranslator( - javaPackage: "com.example.swift", swiftModuleName: "__FakeModule" ) st.log.logLevel = .error @@ -218,8 +241,15 @@ final class MethodImportTests { $0.name == "helloMemberFunction" }! + let generator = FFMSwift2JavaGenerator( + translator: st, + javaPackage: "com.example.swift", + swiftOutputDirectory: "/fake", + javaOutputDirectory: "/fake" + ) + let output = CodePrinter.toString { printer in - st.printJavaBindingWrapperMethod(&printer, funcDecl) + generator.printJavaBindingWrapperMethod(&printer, funcDecl) } assertOutput( @@ -243,7 +273,6 @@ final class MethodImportTests { @Test func method_class_makeInt() throws { let st = Swift2JavaTranslator( - javaPackage: "com.example.swift", swiftModuleName: "__FakeModule" ) st.log.logLevel = .info @@ -254,8 +283,15 @@ final class MethodImportTests { $0.name == "makeInt" }! + let generator = FFMSwift2JavaGenerator( + translator: st, + javaPackage: "com.example.swift", + swiftOutputDirectory: "/fake", + javaOutputDirectory: "/fake" + ) + let output = CodePrinter.toString { printer in - st.printJavaBindingWrapperMethod(&printer, funcDecl) + generator.printJavaBindingWrapperMethod(&printer, funcDecl) } assertOutput( @@ -279,7 +315,6 @@ final class MethodImportTests { @Test func class_constructor() throws { let st = Swift2JavaTranslator( - javaPackage: "com.example.swift", swiftModuleName: "__FakeModule" ) st.log.logLevel = .info @@ -290,8 +325,15 @@ final class MethodImportTests { $0.name == "init" }! + let generator = FFMSwift2JavaGenerator( + translator: st, + javaPackage: "com.example.swift", + swiftOutputDirectory: "/fake", + javaOutputDirectory: "/fake" + ) + let output = CodePrinter.toString { printer in - st.printJavaBindingWrapperMethod(&printer, initDecl) + generator.printJavaBindingWrapperMethod(&printer, initDecl) } assertOutput( @@ -316,7 +358,6 @@ final class MethodImportTests { @Test func struct_constructor() throws { let st = Swift2JavaTranslator( - javaPackage: "com.example.swift", swiftModuleName: "__FakeModule" ) st.log.logLevel = .info @@ -327,8 +368,15 @@ final class MethodImportTests { $0.name == "init" }! + let generator = FFMSwift2JavaGenerator( + translator: st, + javaPackage: "com.example.swift", + swiftOutputDirectory: "/fake", + javaOutputDirectory: "/fake" + ) + let output = CodePrinter.toString { printer in - st.printJavaBindingWrapperMethod(&printer, initDecl) + generator.printJavaBindingWrapperMethod(&printer, initDecl) } assertOutput( diff --git a/Tests/JExtractSwiftTests/MethodThunkTests.swift b/Tests/JExtractSwiftTests/MethodThunkTests.swift index f6f5ce71..b91c0d8f 100644 --- a/Tests/JExtractSwiftTests/MethodThunkTests.swift +++ b/Tests/JExtractSwiftTests/MethodThunkTests.swift @@ -33,7 +33,6 @@ final class MethodThunkTests { @Test("Thunk overloads: globalFunc(a: Int32, b: Int64) & globalFunc(i32: Int32, l: Int64)") func thunk_overloads() throws { let st = Swift2JavaTranslator( - javaPackage: "com.example.swift", swiftModuleName: "FakeModule" ) st.log.logLevel = .error diff --git a/Tests/JExtractSwiftTests/StringPassingTests.swift b/Tests/JExtractSwiftTests/StringPassingTests.swift index ae131b94..d0ad7784 100644 --- a/Tests/JExtractSwiftTests/StringPassingTests.swift +++ b/Tests/JExtractSwiftTests/StringPassingTests.swift @@ -26,7 +26,6 @@ final class StringPassingTests { @Test("Import: public func writeString(string: String) -> Int") func method_helloWorld() throws { let st = Swift2JavaTranslator( - javaPackage: "com.example.swift", swiftModuleName: "__FakeModule" ) st.log.logLevel = .trace diff --git a/Tests/JExtractSwiftTests/VariableImportTests.swift b/Tests/JExtractSwiftTests/VariableImportTests.swift index 9d8650b4..9d873cc3 100644 --- a/Tests/JExtractSwiftTests/VariableImportTests.swift +++ b/Tests/JExtractSwiftTests/VariableImportTests.swift @@ -36,7 +36,6 @@ final class VariableImportTests { @Test("Import: var counter: Int") func variable_int() throws { let st = Swift2JavaTranslator( - javaPackage: "com.example.swift", swiftModuleName: "FakeModule" ) st.log.logLevel = .error From 1e5419580517946e35f54fe6e76a22fe3756fabc Mon Sep 17 00:00:00 2001 From: Mads Odgaard Date: Sun, 8 Jun 2025 10:17:35 +0200 Subject: [PATCH 272/426] only add .editorconfig for .swift files --- .editorconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.editorconfig b/.editorconfig index 9c71277f..d8f9516f 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,6 +1,6 @@ root = true -[*] +[*.swift] indent_style = space indent_size = 2 insert_final_newline = true From cabbdc045f8b4be2f1c9362ace6fbf373ae9a713 Mon Sep 17 00:00:00 2001 From: Mads Odgaard Date: Sun, 8 Jun 2025 10:20:28 +0200 Subject: [PATCH 273/426] remove trailing comma --- Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift index 492168f6..fa235edf 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift @@ -40,7 +40,7 @@ package class FFMSwift2JavaGenerator: Swift2JavaGenerator { translator: Swift2JavaTranslator, javaPackage: String, swiftOutputDirectory: String, - javaOutputDirectory: String, + javaOutputDirectory: String ) { self.analysis = translator.result self.swiftModuleName = translator.swiftModuleName From a16cecfee447631cafda004de0043431682e0e78 Mon Sep 17 00:00:00 2001 From: Mads Odgaard Date: Mon, 9 Jun 2025 09:19:27 +0200 Subject: [PATCH 274/426] add license headers --- Sources/JExtractSwiftLib/AnalysisResult.swift | 14 ++++++++++++++ Sources/JExtractSwiftLib/GenerationMode.swift | 14 ++++++++++++++ Sources/JExtractSwiftLib/Swift2JavaGenerator.swift | 14 ++++++++++++++ 3 files changed, 42 insertions(+) diff --git a/Sources/JExtractSwiftLib/AnalysisResult.swift b/Sources/JExtractSwiftLib/AnalysisResult.swift index 1e37d5c5..4d33bea1 100644 --- a/Sources/JExtractSwiftLib/AnalysisResult.swift +++ b/Sources/JExtractSwiftLib/AnalysisResult.swift @@ -1,3 +1,17 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + struct AnalysisResult { let importedTypes: [String: ImportedNominalType] let importedGlobalVariables: [ImportedFunc] diff --git a/Sources/JExtractSwiftLib/GenerationMode.swift b/Sources/JExtractSwiftLib/GenerationMode.swift index 95266e1a..e2c4b486 100644 --- a/Sources/JExtractSwiftLib/GenerationMode.swift +++ b/Sources/JExtractSwiftLib/GenerationMode.swift @@ -1,3 +1,17 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + import ArgumentParser public enum GenerationMode: String, ExpressibleByArgument { diff --git a/Sources/JExtractSwiftLib/Swift2JavaGenerator.swift b/Sources/JExtractSwiftLib/Swift2JavaGenerator.swift index e78598e5..f9c32ad5 100644 --- a/Sources/JExtractSwiftLib/Swift2JavaGenerator.swift +++ b/Sources/JExtractSwiftLib/Swift2JavaGenerator.swift @@ -1,3 +1,17 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + protocol Swift2JavaGenerator { func generate() throws } From f85aad238369670f477c1701a78e4a44da3d4a77 Mon Sep 17 00:00:00 2001 From: Mads Odgaard Date: Mon, 9 Jun 2025 09:20:32 +0200 Subject: [PATCH 275/426] bring back old generation order --- Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift index fa235edf..c5faa49a 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift @@ -52,8 +52,8 @@ package class FFMSwift2JavaGenerator: Swift2JavaGenerator { } func generate() throws { - try writeExportedJavaSources() try writeSwiftThunkSources() + try writeExportedJavaSources() } } From 632eb0be7f61841e6e24fbe88c20b3c8dd8eb8a7 Mon Sep 17 00:00:00 2001 From: Mads Odgaard Date: Mon, 9 Jun 2025 14:39:34 +0200 Subject: [PATCH 276/426] use log level from translator --- Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift index c5faa49a..5abd145e 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift @@ -17,8 +17,7 @@ import SwiftSyntax import SwiftSyntaxBuilder package class FFMSwift2JavaGenerator: Swift2JavaGenerator { - let log = Logger(label: "ffm-generator", logLevel: .info) - + let log: Logger let analysis: AnalysisResult let swiftModuleName: String let javaPackage: String @@ -42,6 +41,7 @@ package class FFMSwift2JavaGenerator: Swift2JavaGenerator { swiftOutputDirectory: String, javaOutputDirectory: String ) { + self.log = Logger(label: "ffm-generator", logLevel: translator.log.logLevel) self.analysis = translator.result self.swiftModuleName = translator.swiftModuleName self.javaPackage = javaPackage From 30b0ce0fdfe1e751d13ff5540cdb336ee94b1b37 Mon Sep 17 00:00:00 2001 From: Mads Odgaard Date: Mon, 9 Jun 2025 14:58:53 +0200 Subject: [PATCH 277/426] migrate to shared tool --- .../FFM/FFMSwift2JavaGenerator.swift | 3 +++ .../ForeignValueLayouts.swift | 0 Sources/JExtractSwiftLib/Swift2Java.swift | 20 +++++-------------- .../Configuration.swift | 4 +++- .../GenerationMode.swift | 4 +--- Sources/SwiftJavaTool/SwiftJava.swift | 6 ++++++ 6 files changed, 18 insertions(+), 19 deletions(-) rename Sources/JExtractSwiftLib/{JavaConstants => FFM}/ForeignValueLayouts.swift (100%) rename Sources/{JExtractSwiftLib => JavaKitConfigurationShared}/GenerationMode.swift (86%) diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift index 5abd145e..bd3251b4 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift @@ -53,7 +53,10 @@ package class FFMSwift2JavaGenerator: Swift2JavaGenerator { func generate() throws { try writeSwiftThunkSources() + print("[swift-java] Generated Swift sources (module: '\(self.swiftModuleName)') in: \(swiftOutputDirectory)/") + try writeExportedJavaSources() + print("[swift-java] Generated Java sources (package: '\(javaPackage)') in: \(javaOutputDirectory)/") } } diff --git a/Sources/JExtractSwiftLib/JavaConstants/ForeignValueLayouts.swift b/Sources/JExtractSwiftLib/FFM/ForeignValueLayouts.swift similarity index 100% rename from Sources/JExtractSwiftLib/JavaConstants/ForeignValueLayouts.swift rename to Sources/JExtractSwiftLib/FFM/ForeignValueLayouts.swift diff --git a/Sources/JExtractSwiftLib/Swift2Java.swift b/Sources/JExtractSwiftLib/Swift2Java.swift index 895dc61f..8adb7670 100644 --- a/Sources/JExtractSwiftLib/Swift2Java.swift +++ b/Sources/JExtractSwiftLib/Swift2Java.swift @@ -31,7 +31,6 @@ public struct SwiftToJava { } let translator = Swift2JavaTranslator( - javaPackage: config.javaPackage ?? "", // no package is ok, we'd generate all into top level swiftModuleName: swiftModule ) translator.log.logLevel = config.logLevel ?? .info @@ -89,27 +88,18 @@ public struct SwiftToJava { try translator.analyze() - switch mode { - case .ffm: + switch config.mode { + case .some(.ffm), .none: let generator = FFMSwift2JavaGenerator( translator: translator, - javaPackage: self.packageName, - swiftOutputDirectory: outputDirectorySwift, - javaOutputDirectory: outputDirectoryJava + javaPackage: config.javaPackage ?? "", + swiftOutputDirectory: outputSwiftDirectory, + javaOutputDirectory: outputJavaDirectory ) try generator.generate() } - - print("[swift-java] Generated Java sources (\(packageName)) in: \(outputDirectoryJava)/") - - try translator.writeSwiftThunkSources(outputDirectory: outputSwiftDirectory) - print("[swift-java] Generated Swift sources (module: '\(config.swiftModule ?? "")') in: \(outputSwiftDirectory)/") - - try translator.writeExportedJavaSources(outputDirectory: outputJavaDirectory) - print("[swift-java] Generated Java sources (package: '\(config.javaPackage ?? "")') in: \(outputJavaDirectory)/") - print("[swift-java] Imported Swift module '\(swiftModule)': " + "done.".green) } diff --git a/Sources/JavaKitConfigurationShared/Configuration.swift b/Sources/JavaKitConfigurationShared/Configuration.swift index 1c4fad56..2314a1b8 100644 --- a/Sources/JavaKitConfigurationShared/Configuration.swift +++ b/Sources/JavaKitConfigurationShared/Configuration.swift @@ -38,6 +38,8 @@ public struct Configuration: Codable { public var outputJavaDirectory: String? + public var mode: GenerationMode? + // ==== java 2 swift --------------------------------------------------------- /// The Java class path that should be passed along to the Java2Swift tool. @@ -255,4 +257,4 @@ extension LogLevel { } try container.encode(text) } -} \ No newline at end of file +} diff --git a/Sources/JExtractSwiftLib/GenerationMode.swift b/Sources/JavaKitConfigurationShared/GenerationMode.swift similarity index 86% rename from Sources/JExtractSwiftLib/GenerationMode.swift rename to Sources/JavaKitConfigurationShared/GenerationMode.swift index e2c4b486..ff1d081d 100644 --- a/Sources/JExtractSwiftLib/GenerationMode.swift +++ b/Sources/JavaKitConfigurationShared/GenerationMode.swift @@ -12,9 +12,7 @@ // //===----------------------------------------------------------------------===// -import ArgumentParser - -public enum GenerationMode: String, ExpressibleByArgument { +public enum GenerationMode: String, Codable { /// Foreign Value and Memory API case ffm } diff --git a/Sources/SwiftJavaTool/SwiftJava.swift b/Sources/SwiftJavaTool/SwiftJava.swift index a0ba75dc..cae7a2a4 100644 --- a/Sources/SwiftJavaTool/SwiftJava.swift +++ b/Sources/SwiftJavaTool/SwiftJava.swift @@ -72,6 +72,9 @@ struct SwiftJava: AsyncParsableCommand { @Option(help: "The Java package the generated Java code should be emitted into.") var javaPackage: String? = nil + @Option(help: "The mode of generation to use for the output files. Used with jextract mode.") + var mode: GenerationMode = .ffm + // TODO: clarify this vs outputSwift (history: outputSwift is jextract, and this was java2swift) @Option(name: .shortAndLong, help: "The directory in which to output the generated Swift files or the SwiftJava configuration file.") var outputDirectory: String? = nil @@ -227,6 +230,7 @@ struct SwiftJava: AsyncParsableCommand { config.inputSwiftDirectory = self.inputSwift config.outputSwiftDirectory = self.outputSwift config.outputJavaDirectory = self.outputJava + config.mode = self.mode toolMode = .jextract } else if jar { @@ -512,3 +516,5 @@ extension SwiftJava.ToolMode { } } } + +extension GenerationMode: ExpressibleByArgument {} From 28a7a4c1a90df4807024adcc2a4ad8e1bbf0ae98 Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Mon, 9 Jun 2025 09:05:18 -0700 Subject: [PATCH 278/426] Add .editorconfig to .licenseignore --- .licenseignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.licenseignore b/.licenseignore index bcafb671..df3de377 100644 --- a/.licenseignore +++ b/.licenseignore @@ -1,3 +1,4 @@ +.editorconfig .gitignore .licenseignore .swiftformatignore From a729e7a77cee48a66054906e67314d16222afe5d Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Mon, 9 Jun 2025 12:48:10 -0700 Subject: [PATCH 279/426] Add missing dependencies for JavaKitConfigurationShared JExtractSwiftLib and SwiftJavaTool import JavaKitConfigurationShared --- Package.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Package.swift b/Package.swift index 9f82277d..47312ccd 100644 --- a/Package.swift +++ b/Package.swift @@ -385,6 +385,7 @@ let package = Package( "SwiftJavaLib", "JExtractSwiftLib", "JavaKitShared", + "JavaKitConfigurationShared", ], swiftSettings: [ @@ -403,6 +404,7 @@ let package = Package( .product(name: "ArgumentParser", package: "swift-argument-parser"), "JavaTypes", "JavaKitShared", + "JavaKitConfigurationShared", ], swiftSettings: [ .swiftLanguageMode(.v5), From 7860cb89a66e95604686bce3fb6456ad00c4d65f Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Fri, 6 Jun 2025 16:13:02 -0700 Subject: [PATCH 280/426] [JExtract] Import any C compatible closure Generalized closure parameter import, part 1. Start with C-compatible closures which don't need any conversions. --- .../com/example/swift/MySwiftLibraryTest.java | 4 +- .../MySwiftLibrary/MySwiftStruct.swift | 4 + .../com/example/swift/HelloJava2Swift.java | 3 + .../com/example/swift/MySwiftLibraryTest.java | 4 +- ...Swift2JavaGenerator+FunctionLowering.swift | 52 ++++- ...t2JavaGenerator+JavaBindingsPrinting.swift | 202 +++++++++++++++--- ...MSwift2JavaGenerator+JavaTranslation.swift | 168 ++++++++++++--- ...ift2JavaGenerator+SwiftThunkPrinting.swift | 4 +- .../FFM/FFMSwift2JavaGenerator.swift | 15 +- .../java/org/swift/swiftkit/SwiftKit.java | 33 +-- .../FuncCallbackImportTests.swift | 178 ++++++++++++++- .../FunctionDescriptorImportTests.swift | 30 +-- .../StringPassingTests.swift | 6 +- .../VariableImportTests.swift | 14 +- 14 files changed, 591 insertions(+), 126 deletions(-) diff --git a/Samples/SwiftAndJavaJarSampleLib/src/test/java/com/example/swift/MySwiftLibraryTest.java b/Samples/SwiftAndJavaJarSampleLib/src/test/java/com/example/swift/MySwiftLibraryTest.java index 82472418..74df5da8 100644 --- a/Samples/SwiftAndJavaJarSampleLib/src/test/java/com/example/swift/MySwiftLibraryTest.java +++ b/Samples/SwiftAndJavaJarSampleLib/src/test/java/com/example/swift/MySwiftLibraryTest.java @@ -43,9 +43,9 @@ void call_globalTakeInt() { void call_globalCallMeRunnable() { CountDownLatch countDownLatch = new CountDownLatch(3); - MySwiftLibrary.globalCallMeRunnable(new Runnable() { + MySwiftLibrary.globalCallMeRunnable(new MySwiftLibrary.globalCallMeRunnable.run() { @Override - public void run() { + public void apply() { countDownLatch.countDown(); } }); diff --git a/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftStruct.swift b/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftStruct.swift index 8feb3d2b..363e0683 100644 --- a/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftStruct.swift +++ b/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftStruct.swift @@ -48,6 +48,10 @@ public struct MySwiftStruct { self.len } + public func withCapLen(_ body: (Int, Int) -> Void) { + body(cap, len) + } + public mutating func increaseCap(by value: Int) -> Int { precondition(value > 0) self.cap += value diff --git a/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java b/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java index e20ac378..69dfbdb3 100644 --- a/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java +++ b/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java @@ -67,6 +67,9 @@ static void examples() { MySwiftStruct swiftValue = MySwiftStruct.init(2222, 1111, arena); SwiftKit.trace("swiftValue.capacity = " + swiftValue.getCapacity()); + swiftValue.withCapLen((cap, len) -> { + SwiftKit.trace("withCapLenCallback: cap=" + cap + ", len=" + len); + }); } System.out.println("DONE."); diff --git a/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/MySwiftLibraryTest.java b/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/MySwiftLibraryTest.java index 41d83305..2df53843 100644 --- a/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/MySwiftLibraryTest.java +++ b/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/MySwiftLibraryTest.java @@ -64,9 +64,9 @@ void call_writeString_jni() { void call_globalCallMeRunnable() { CountDownLatch countDownLatch = new CountDownLatch(3); - MySwiftLibrary.globalCallMeRunnable(new Runnable() { + MySwiftLibrary.globalCallMeRunnable(new MySwiftLibrary.globalCallMeRunnable.run() { @Override - public void run() { + public void apply() { countDownLatch.countDown(); } }); diff --git a/Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift b/Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift index cd5ea0a2..02501dc5 100644 --- a/Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift +++ b/Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift @@ -116,7 +116,7 @@ struct CdeclLowering { ) } - /// Lower a Swift function parameter type to cdecl parameters. + /// Lower a Swift function parameter to cdecl parameters. /// /// For example, Swift parameter `arg value: inout Int` can be lowered with /// `lowerParameter(intTy, .inout, "value")`. @@ -276,25 +276,63 @@ struct CdeclLowering { } return LoweredParameter(cdeclParameters: parameters, conversion: .tuplify(conversions)) - case .function(let fn) where fn.parameters.isEmpty && fn.resultType.isVoid: + case .function(let fn): + let (loweredTy, conversion) = try lowerFunctionType(fn) return LoweredParameter( cdeclParameters: [ SwiftParameter( convention: .byValue, parameterName: parameterName, - type: .function(SwiftFunctionType(convention: .c, parameters: [], resultType: fn.resultType)) + type: loweredTy ) ], - // '@convention(c) () -> ()' is compatible with '() -> Void'. - conversion: .placeholder + conversion: conversion ) - case .function, .optional: - // FIXME: Support other function types than '() -> Void'. + case .optional: throw LoweringError.unhandledType(type) } } + /// Lower a Swift function type (i.e. closure) to cdecl function type. + /// + /// - Parameters: + /// - fn: the Swift function type to lower. + func lowerFunctionType( + _ fn: SwiftFunctionType + ) throws -> (type: SwiftType, conversion: ConversionStep) { + var parameters: [SwiftParameter] = [] + var parameterConversions: [ConversionStep] = [] + + for parameter in fn.parameters { + if let _ = try? CType(cdeclType: parameter.type) { + parameters.append(SwiftParameter(convention: .byValue, type: parameter.type)) + parameterConversions.append(.placeholder) + } else { + // Non-trivial types are not yet supported. + throw LoweringError.unhandledType(.function(fn)) + } + } + + let resultType: SwiftType + let resultConversion: ConversionStep + if let _ = try? CType(cdeclType: fn.resultType) { + resultType = fn.resultType + resultConversion = .placeholder + } else { + // Non-trivial types are not yet supported. + throw LoweringError.unhandledType(.function(fn)) + } + + // Ignore the conversions for now, since we don't support non-trivial types yet. + _ = (parameterConversions, resultConversion) + + return ( + type: .function(SwiftFunctionType(convention: .c, parameters: parameters, resultType: resultType)), + conversion: .placeholder + ) + } + /// Lower a Swift result type to cdecl out parameters and return type. /// /// - Parameters: diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift index 77ab9a81..c7c6631a 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift @@ -15,11 +15,11 @@ import JavaTypes extension FFMSwift2JavaGenerator { - func printFunctionDowncallMethods( + package func printFunctionDowncallMethods( _ printer: inout CodePrinter, _ decl: ImportedFunc ) { - guard let _ = translatedSignature(for: decl) else { + guard let _ = translatedDecl(for: decl) else { // Failed to translate. Skip. return } @@ -28,6 +28,8 @@ extension FFMSwift2JavaGenerator { printJavaBindingDescriptorClass(&printer, decl) + printJavaBindingWrapperHelperClass(&printer, decl) + // Render the "make the downcall" functions. printJavaBindingWrapperMethod(&printer, decl) } @@ -38,9 +40,9 @@ extension FFMSwift2JavaGenerator { _ decl: ImportedFunc ) { let thunkName = thunkNameRegistry.functionThunkName(decl: decl) - let translatedSignature = self.translatedSignature(for: decl)! + let translated = self.translatedDecl(for: decl)! // 'try!' because we know 'loweredSignature' can be described with C. - let cFunc = try! translatedSignature.loweredSignature.cFunctionDecl(cName: thunkName) + let cFunc = try! translated.loweredSignature.cFunctionDecl(cName: thunkName) printer.printBraceBlock( """ @@ -52,37 +54,39 @@ extension FFMSwift2JavaGenerator { private static class \(cFunc.name) """ ) { printer in - printFunctionDescriptorValue(&printer, cFunc) + printFunctionDescriptorDefinition(&printer, cFunc.resultType, cFunc.parameters) printer.print( """ - public static final MemorySegment ADDR = + private static final MemorySegment ADDR = \(self.swiftModuleName).findOrThrow("\(cFunc.name)"); - public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); """ ) printJavaBindingDowncallMethod(&printer, cFunc) + printParameterDescriptorClasses(&printer, cFunc) } } /// Print the 'FunctionDescriptor' of the lowered cdecl thunk. - func printFunctionDescriptorValue( + func printFunctionDescriptorDefinition( _ printer: inout CodePrinter, - _ cFunc: CFunction + _ resultType: CType, + _ parameters: [CParameter] ) { - printer.start("public static final FunctionDescriptor DESC = ") + printer.start("private static final FunctionDescriptor DESC = ") - let isEmptyParam = cFunc.parameters.isEmpty - if cFunc.resultType.isVoid { + let isEmptyParam = parameters.isEmpty + if resultType.isVoid { printer.print("FunctionDescriptor.ofVoid(", isEmptyParam ? .continue : .newLine) printer.indent() } else { printer.print("FunctionDescriptor.of(") printer.indent() printer.print("/* -> */", .continue) - printer.print(cFunc.resultType.foreignValueLayout, .parameterNewlineSeparator(isEmptyParam)) + printer.print(resultType.foreignValueLayout, .parameterNewlineSeparator(isEmptyParam)) } - for (param, isLast) in cFunc.parameters.withIsLast { + for (param, isLast) in parameters.withIsLast { printer.print("/* \(param.name ?? "_"): */", .continue) printer.print(param.type.foreignValueLayout, .parameterNewlineSeparator(isLast)) } @@ -124,16 +128,158 @@ extension FFMSwift2JavaGenerator { ) } + /// Print required helper classes/interfaces for describing the CFunction. + /// + /// * function pointer parameter as a functional interface. + /// * Unnamed-struct parameter as a record. (unimplemented) + func printParameterDescriptorClasses( + _ printer: inout CodePrinter, + _ cFunc: CFunction + ) { + for param in cFunc.parameters { + switch param.type { + case .pointer(.function): + let name = "$\(param.name!)" + printFunctionPointerParameterDescriptorClass(&printer, name, param.type) + default: + continue + } + } + } + + /// Print a class describing a function pointer parameter type. + /// + /// ```java + /// class $ { + /// @FunctionalInterface + /// interface Function { + /// apply(); + /// } + /// static final MethodDescriptor DESC = FunctionDescriptor.of(...); + /// static final MethodHandle HANDLE = SwiftKit.upcallHandle(Function.class, "apply", DESC); + /// static MemorySegment toUpcallStub(Function fi, Arena arena) { + /// return Linker.nativeLinker().upcallStub(HANDLE.bindTo(fi), DESC, arena); + /// } + /// } + /// ``` + func printFunctionPointerParameterDescriptorClass( + _ printer: inout CodePrinter, + _ name: String, + _ cType: CType + ) { + guard case .pointer(.function(let cResultType, let cParameterTypes, variadic: false)) = cType else { + preconditionFailure("must be a C function pointer type; name=\(name), cType=\(cType)") + } + + let cParams = cParameterTypes.enumerated().map { i, ty in + CParameter(name: "_\(i)", type: ty) + } + let paramDecls = cParams.map({"\($0.type.javaType) \($0.name!)"}) + + printer.printBraceBlock( + """ + /** + * {snippet lang=c : + * \(cType) + * } + */ + private static class \(name) + """ + ) { printer in + printer.print( + """ + @FunctionalInterface + public interface Function { + \(cResultType.javaType) apply(\(paramDecls.joined(separator: ", "))); + } + """ + ) + printFunctionDescriptorDefinition(&printer, cResultType, cParams) + printer.print( + """ + private static final MethodHandle HANDLE = SwiftKit.upcallHandle(Function.class, "apply", DESC); + private static MemorySegment toUpcallStub(Function fi, Arena arena) { + return Linker.nativeLinker().upcallStub(HANDLE.bindTo(fi), DESC, arena); + } + """ + ) + } + } + + /// Print the helper type container for a user-facing Java API. + /// + /// * User-facing functional interfaces. + func printJavaBindingWrapperHelperClass( + _ printer: inout CodePrinter, + _ decl: ImportedFunc + ) { + let translated = self.translatedDecl(for: decl)! + let bindingDescriptorName = self.thunkNameRegistry.functionThunkName(decl: decl) + if translated.functionTypes.isEmpty { + return + } + + printer.printBraceBlock( + """ + public static class \(translated.name) + """ + ) { printer in + for functionType in translated.functionTypes { + printJavaBindingWrapperFunctionTypeHelper(&printer, functionType, bindingDescriptorName) + } + } + } + + /// Print "wrapper" functional interface representing a Swift closure type. + func printJavaBindingWrapperFunctionTypeHelper( + _ printer: inout CodePrinter, + _ functionType: TranslatedFunctionType, + _ bindingDescriptorName: String + ) { + let cdeclDescriptor = "\(bindingDescriptorName).$\(functionType.name)" + if functionType.isCompatibleWithC { + // If the user-facing functional interface is C ABI compatible, just extend + // the lowered function pointer parameter interface. + printer.print( + """ + @FunctionalInterface + public interface \(functionType.name) extends \(cdeclDescriptor).Function {} + private static MemorySegment $toUpcallStub(\(functionType.name) fi, Arena arena) { + return \(bindingDescriptorName).$\(functionType.name).toUpcallStub(fi, arena); + } + """ + ) + } else { + // Otherwise, the lambda must be wrapped with the lowered function instance. + assertionFailure("should be unreachable at this point") + let apiParams = functionType.parameters.flatMap { + $0.javaParameters.map { param in "\(param.type) \(param.name)" } + } + + printer.print( + """ + @FunctionalInterface + public interface \(functionType.name) { + \(functionType.result.javaResultType) apply(\(apiParams.joined(separator: ", "))); + } + private static MemorySegment $toUpcallStub(\(functionType.name) fi, Arena arena) { + return \(cdeclDescriptor).toUpcallStub(() -> { + fi() + }, arena); + } + """ + ) + } + } + /// Print the calling body that forwards all the parameters to the `methodName`, /// with adding `SwiftArena.ofAuto()` at the end. - public func printJavaBindingWrapperMethod( + package func printJavaBindingWrapperMethod( _ printer: inout CodePrinter, - _ decl: ImportedFunc) { - let methodName: String = switch decl.apiKind { - case .getter: "get\(decl.name.toCamelCase)" - case .setter: "set\(decl.name.toCamelCase)" - case .function, .initializer: decl.name - } + _ decl: ImportedFunc + ) { + let translated = self.translatedDecl(for: decl)! + let methodName = translated.name var modifiers = "public" switch decl.functionSignature.selfParameter { @@ -143,7 +289,7 @@ extension FFMSwift2JavaGenerator { break } - let translatedSignature = self.translatedSignature(for: decl)! + let translatedSignature = translated.translatedSignature let returnTy = translatedSignature.result.javaResultType var paramDecls = translatedSignature.parameters @@ -182,7 +328,7 @@ extension FFMSwift2JavaGenerator { _ decl: ImportedFunc ) { //=== Part 1: prepare temporary arena if needed. - let translatedSignature = self.translatedSignature(for: decl)! + let translatedSignature = self.translatedDecl(for: decl)!.translatedSignature if translatedSignature.requiresTemporaryArena { printer.print("try(var arena$ = Arena.ofConfined()) {") @@ -273,7 +419,7 @@ extension JavaConversionStep { /// Whether the conversion uses SwiftArena. var requiresSwiftArena: Bool { switch self { - case .pass, .swiftValueSelfSegment, .construct, .cast, .call: + case .pass, .swiftValueSelfSegment, .construct, .cast, .call, .method: return false case .constructSwiftValue: return true @@ -285,7 +431,7 @@ extension JavaConversionStep { switch self { case .pass, .swiftValueSelfSegment, .construct, .constructSwiftValue, .cast: return false - case .call(_, let withArena): + case .call(_, let withArena), .method(_, _, let withArena): return withArena } } @@ -297,7 +443,7 @@ extension JavaConversionStep { switch self { case .pass, .swiftValueSelfSegment: return true - case .cast, .construct, .constructSwiftValue, .call: + case .cast, .construct, .constructSwiftValue, .call, .method: return false } } @@ -317,6 +463,10 @@ extension JavaConversionStep { let arenaArg = withArena ? ", arena$" : "" return "\(function)(\(placeholder)\(arenaArg))" + case .method(let methodName, let arguments, let withArena): + let argsStr = (arguments + (withArena ? ["arena$"] : [])).joined(separator: " ,") + return "\(placeholder).\(methodName)(\(argsStr))" + case .constructSwiftValue(let javaType): return "new \(javaType.className!)(\(placeholder), swiftArena$)" diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift index 56eb606d..c7e2338d 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift @@ -15,26 +15,23 @@ import JavaTypes extension FFMSwift2JavaGenerator { - func translatedSignature( + func translatedDecl( for decl: ImportedFunc - ) -> TranslatedFunctionSignature? { - if let cached = translatedSignatures[decl] { + ) -> TranslatedFunctionDecl? { + if let cached = translatedDecls[decl] { return cached } - let translated: TranslatedFunctionSignature? + let translated: TranslatedFunctionDecl? do { - let lowering = CdeclLowering(swiftStdlibTypes: self.swiftStdlibTypes) - let loweredSignature = try lowering.lowerFunctionSignature(decl.functionSignature) - let translation = JavaTranslation(swiftStdlibTypes: self.swiftStdlibTypes) - translated = try translation.translate(loweredFunctionSignature: loweredSignature) + translated = try translation.translate(decl) } catch { self.log.info("Failed to translate: '\(decl.swiftDecl.qualifiedNameForDebug)'; \(error)") translated = nil } - translatedSignatures[decl] = translated + translatedDecls[decl] = translated return translated } } @@ -82,19 +79,47 @@ struct TranslatedResult { var conversion: JavaConversionStep } -/// Translated function signature representing a Swift API. + +/// Translated Java API representing a Swift API. /// /// Since this holds the lowered signature, and the original `SwiftFunctionSignature` /// in it, this contains all the API information (except the name) to generate the /// cdecl thunk, Java binding, and the Java wrapper function. -struct TranslatedFunctionSignature { - var loweredSignature: LoweredFunctionSignature +struct TranslatedFunctionDecl { + /// Java function name. + let name: String + /// Functional interfaces required for the Java method. + let functionTypes: [TranslatedFunctionType] + + /// Function signature. + let translatedSignature: TranslatedFunctionSignature + + /// Cdecl lowerd signature. + let loweredSignature: LoweredFunctionSignature +} + +/// Function signature for a Java API. +struct TranslatedFunctionSignature { var selfParameter: TranslatedParameter? var parameters: [TranslatedParameter] var result: TranslatedResult } +/// Represent a Swift closure type in the user facing Java API. +/// +/// Closures are translated to named functional interfaces in Java. +struct TranslatedFunctionType { + var name: String + var parameters: [TranslatedParameter] + var result: TranslatedResult + + /// Whether or not this functional interface with C ABI compatible. + var isCompatibleWithC: Bool { + result.conversion.isPass && parameters.allSatisfy(\.conversion.isPass) + } +} + extension TranslatedFunctionSignature { /// Whether or not if the down-calling requires temporary "Arena" which is /// only used during the down-calling. @@ -121,12 +146,92 @@ extension TranslatedFunctionSignature { struct JavaTranslation { var swiftStdlibTypes: SwiftStandardLibraryTypes - /// Translate Swift API to user-facing Java API. + func translate( + _ decl: ImportedFunc + ) throws -> TranslatedFunctionDecl { + let lowering = CdeclLowering(swiftStdlibTypes: self.swiftStdlibTypes) + let loweredSignature = try lowering.lowerFunctionSignature(decl.functionSignature) + + // Name. + let javaName = switch decl.apiKind { + case .getter: "get\(decl.name.toCamelCase)" + case .setter: "set\(decl.name.toCamelCase)" + case .function, .initializer: decl.name + } + + // Closures. + var funcTypes: [TranslatedFunctionType] = [] + for (idx, param) in decl.functionSignature.parameters.enumerated() { + switch param.type { + case .function(let funcTy): + let paramName = param.parameterName ?? "_\(idx)" + let translatedClosure = try translateFunctionType(name: paramName, swiftType: funcTy) + funcTypes.append(translatedClosure) + case .tuple: + // TODO: Implement + break + default: + break + } + } + + // Signature. + let translatedSignature = try translate(loweredFunctionSignature: loweredSignature, methodName: javaName) + + return TranslatedFunctionDecl( + name: javaName, + functionTypes: funcTypes, + translatedSignature: translatedSignature, + loweredSignature: loweredSignature + ) + } + + /// Translate Swift closure type to Java functional interface. + func translateFunctionType( + name: String, + swiftType: SwiftFunctionType + ) throws -> TranslatedFunctionType { + var translatedParams: [TranslatedParameter] = [] + + for (i, param) in swiftType.parameters.enumerated() { + let paramName = param.parameterName ?? "_\(i)" + if let cType = try? CType(cdeclType: param.type) { + let translatedParam = TranslatedParameter( + javaParameters: [ + JavaParameter(type: cType.javaType, name: paramName) + ], + conversion: .pass + ) + translatedParams.append(translatedParam) + continue + } + throw JavaTranslationError.unhandledType(.function(swiftType)) + } + + guard let resultCType = try? CType(cdeclType: swiftType.resultType) else { + throw JavaTranslationError.unhandledType(.function(swiftType)) + } + + let transltedResult = TranslatedResult( + javaResultType: resultCType.javaType, + outParameters: [], + conversion: .pass + ) + + return TranslatedFunctionType( + name: name, + parameters: translatedParams, + result: transltedResult + ) + } + + /// Translate a Swift API signature to the user-facing Java API signature. /// /// Note that the result signature is for the high-level Java API, not the /// low-level FFM down-calling interface. func translate( - loweredFunctionSignature: LoweredFunctionSignature + loweredFunctionSignature: LoweredFunctionSignature, + methodName: String ) throws -> TranslatedFunctionSignature { let swiftSignature = loweredFunctionSignature.original @@ -136,6 +241,7 @@ struct JavaTranslation { selfParameter = try self.translate( swiftParam: swiftSelf, loweredParam: loweredFunctionSignature.selfParameter!, + methodName: methodName, parameterName: swiftSelf.parameterName ?? "self" ) } else { @@ -150,6 +256,7 @@ struct JavaTranslation { return try self.translate( swiftParam: swiftParam, loweredParam: loweredParam, + methodName: methodName, parameterName: parameterName ) } @@ -161,17 +268,17 @@ struct JavaTranslation { ) return TranslatedFunctionSignature( - loweredSignature: loweredFunctionSignature, selfParameter: selfParameter, parameters: parameters, result: result ) } - /// Translate + /// Translate a Swift API parameter to the user-facing Java API parameter. func translate( swiftParam: SwiftParameter, loweredParam: LoweredParameter, + methodName: String, parameterName: String ) throws -> TranslatedParameter { let swiftType = swiftParam.type @@ -184,7 +291,7 @@ struct JavaTranslation { javaParameters: [ JavaParameter( type: javaType, - name: loweredParam.cdeclParameters[0].parameterName! + name: parameterName ) ], conversion: .pass @@ -198,7 +305,7 @@ struct JavaTranslation { javaParameters: [ JavaParameter( type: JavaType.class(package: "org.swift.swiftkit", name: "SwiftAnyType"), - name: loweredParam.cdeclParameters[0].parameterName!) + name: parameterName) ], conversion: .swiftValueSelfSegment ) @@ -222,7 +329,7 @@ struct JavaTranslation { javaParameters: [ JavaParameter( type: .javaLangString, - name: loweredParam.cdeclParameters[0].parameterName! + name: parameterName ) ], conversion: .call(function: "SwiftKit.toCString", withArena: true) @@ -242,7 +349,7 @@ struct JavaTranslation { javaParameters: [ JavaParameter( type: try translate(swiftType: swiftType), - name: loweredParam.cdeclParameters[0].parameterName! + name: parameterName ) ], conversion: .swiftValueSelfSegment @@ -252,21 +359,22 @@ struct JavaTranslation { // TODO: Implement. throw JavaTranslationError.unhandledType(swiftType) - case .function(let fn) where fn.parameters.isEmpty && fn.resultType.isVoid: + case .function: return TranslatedParameter( javaParameters: [ JavaParameter( - type: JavaType.class(package: "java.lang", name: "Runnable"), - name: loweredParam.cdeclParameters[0].parameterName!) + type: JavaType.class(package: nil, name: "\(methodName).\(parameterName)"), + name: parameterName) ], - conversion: .call(function: "SwiftKit.toUpcallStub", withArena: true) + conversion: .call(function: "\(methodName).$toUpcallStub", withArena: true) ) - case .optional, .function: + case .optional: throw JavaTranslationError.unhandledType(swiftType) } } + /// Translate a Swift API result to the user-facing Java API result. func translate( swiftResult: SwiftResult, loweredResult: LoweredResult @@ -357,6 +465,10 @@ enum JavaConversionStep { // If `withArena` is true, `arena$` argument is added. case call(function: String, withArena: Bool) + // Apply a method on the placeholder. + // If `withArena` is true, `arena$` argument is added. + case method(methodName: String, arguments: [String] = [], withArena: Bool) + // Call 'new \(Type)(\(placeholder), swiftArena$)'. case constructSwiftValue(JavaType) @@ -365,6 +477,10 @@ enum JavaConversionStep { // Casting the placeholder to the certain type. case cast(JavaType) + + var isPass: Bool { + return if case .pass = self { true } else { false } + } } extension CType { @@ -443,5 +559,5 @@ extension CType { enum JavaTranslationError: Error { case inoutNotSupported(SwiftType) - case unhandledType(SwiftType) + case unhandledType(SwiftType, file: String = #file, line: Int = #line) } diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+SwiftThunkPrinting.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+SwiftThunkPrinting.swift index 416bc851..02d715a0 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+SwiftThunkPrinting.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+SwiftThunkPrinting.swift @@ -175,11 +175,11 @@ struct SwiftThunkTranslator { st.log.trace("Rendering thunks for: \(decl.displayName)") let thunkName = st.thunkNameRegistry.functionThunkName(decl: decl) - guard let translatedSignatures = st.translatedSignature(for: decl) else { + guard let translated = st.translatedDecl(for: decl) else { return [] } - let thunkFunc = translatedSignatures.loweredSignature.cdeclThunk( + let thunkFunc = translated.loweredSignature.cdeclThunk( cName: thunkName, swiftAPIName: decl.name, as: decl.apiKind, diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift index bd3251b4..7cd0075b 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift @@ -33,7 +33,8 @@ package class FFMSwift2JavaGenerator: Swift2JavaGenerator { var thunkNameRegistry: ThunkNameRegistry = ThunkNameRegistry() /// Cached Java translation result. 'nil' indicates failed translation. - var translatedSignatures: [ImportedFunc: TranslatedFunctionSignature?] = [:] + var translatedDecls: [ImportedFunc: TranslatedFunctionDecl?] = [:] + package init( translator: Swift2JavaTranslator, @@ -267,18 +268,6 @@ extension FFMSwift2JavaGenerator { """ ) - printer.print( - """ - static MethodHandle upcallHandle(Class fi, String name, FunctionDescriptor fdesc) { - try { - return MethodHandles.lookup().findVirtual(fi, name, fdesc.toMethodType()); - } catch (ReflectiveOperationException ex) { - throw new AssertionError(ex); - } - } - """ - ) - printer.print( """ static MemoryLayout align(MemoryLayout layout, long align) { diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftKit.java b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftKit.java index 85c491e4..9c04eded 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftKit.java +++ b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftKit.java @@ -77,9 +77,10 @@ public static void traceDowncall(Object... args) { String traceArgs = Arrays.stream(args) .map(Object::toString) .collect(Collectors.joining(", ")); - System.out.printf("[java][%s:%d] Downcall: %s(%s)\n", + System.out.printf("[java][%s:%d] Downcall: %s.%s(%s)\n", ex.getStackTrace()[1].getFileName(), ex.getStackTrace()[1].getLineNumber(), + ex.getStackTrace()[1].getClassName(), ex.getStackTrace()[1].getMethodName(), traceArgs); } @@ -448,26 +449,26 @@ public static long getSwiftInt(MemorySegment memorySegment, VarHandle handle) { } /** - * Convert String to a MemorySegment filled with the C string. + * Get the method handle of a functional interface. + * + * @param fi functional interface. + * @param name name of the single abstraction method. + * @param fdesc function descriptor of the method. + * @return unbound method handle. */ - public static MemorySegment toCString(String str, Arena arena) { - return arena.allocateFrom(str); + public static MethodHandle upcallHandle(Class fi, String name, FunctionDescriptor fdesc) { + try { + return MethodHandles.lookup().findVirtual(fi, name, fdesc.toMethodType()); + } catch (ReflectiveOperationException ex) { + throw new AssertionError(ex); + } } /** - * Convert Runnable to a MemorySegment which is an upcall stub for it. + * Convert String to a MemorySegment filled with the C string. */ - public static MemorySegment toUpcallStub(Runnable callback, Arena arena) { - try { - FunctionDescriptor descriptor = FunctionDescriptor.ofVoid(); - MethodHandle handle = MethodHandles.lookup() - .findVirtual(Runnable.class, "run", descriptor.toMethodType()) - .bindTo(callback); - return Linker.nativeLinker() - .upcallStub(handle, descriptor, arena); - } catch (Exception e) { - throw new AssertionError("should be unreachable"); - } + public static MemorySegment toCString(String str, Arena arena) { + return arena.allocateFrom(str); } private static class swift_getTypeName { diff --git a/Tests/JExtractSwiftTests/FuncCallbackImportTests.swift b/Tests/JExtractSwiftTests/FuncCallbackImportTests.swift index f1afa7c0..457e3a7a 100644 --- a/Tests/JExtractSwiftTests/FuncCallbackImportTests.swift +++ b/Tests/JExtractSwiftTests/FuncCallbackImportTests.swift @@ -29,11 +29,12 @@ final class FuncCallbackImportTests { import _StringProcessing import _SwiftConcurrencyShims - public func callMe(callback: () -> ()) + public func callMe(callback: () -> Void) + public func callMeMore(callback: (UnsafeRawPointer, Float) -> Int, fn: () -> ()) """ - @Test("Import: public func callMe(callback: () -> ())") - func func_callMeFunc_Runnable() throws { + @Test("Import: public func callMe(callback: () -> Void)") + func func_callMeFunc_callback() throws { let st = Swift2JavaTranslator( swiftModuleName: "__FakeModule" ) @@ -51,22 +52,185 @@ final class FuncCallbackImportTests { ) let output = CodePrinter.toString { printer in - generator.printJavaBindingWrapperMethod(&printer, funcDecl) + generator.printFunctionDowncallMethods(&printer, funcDecl) } assertOutput( output, expected: """ + // ==== -------------------------------------------------- + // callMe + /** + * {@snippet lang=c : + * void swiftjava___FakeModule_callMe_callback(void (*callback)(void)) + * } + */ + private static class swiftjava___FakeModule_callMe_callback { + private static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( + /* callback: */SwiftValueLayout.SWIFT_POINTER + ); + private static final MemorySegment ADDR = + __FakeModule.findOrThrow("swiftjava___FakeModule_callMe_callback"); + private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + public static void call(java.lang.foreign.MemorySegment callback) { + try { + if (SwiftKit.TRACE_DOWNCALLS) { + SwiftKit.traceDowncall(callback); + } + HANDLE.invokeExact(callback); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + /** + * {snippet lang=c : + * void (*)(void) + * } + */ + private static class $callback { + @FunctionalInterface + public interface Function { + void apply(); + } + private static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid(); + private static final MethodHandle HANDLE = SwiftKit.upcallHandle(Function.class, "apply", DESC); + private static MemorySegment toUpcallStub(Function fi, Arena arena) { + return Linker.nativeLinker().upcallStub(HANDLE.bindTo(fi), DESC, arena); + } + } + } + public static class callMe { + @FunctionalInterface + public interface callback extends swiftjava___FakeModule_callMe_callback.$callback.Function {} + private static MemorySegment $toUpcallStub(callback fi, Arena arena) { + return swiftjava___FakeModule_callMe_callback.$callback.toUpcallStub(fi, arena); + } + } + /** + * Downcall to Swift: + * {@snippet lang=swift : + * public func callMe(callback: () -> Void) + * } + */ + public static void callMe(callMe.callback callback) { + try(var arena$ = Arena.ofConfined()) { + swiftjava___FakeModule_callMe_callback.call(callMe.$toUpcallStub(callback, arena$)); + } + } + """ + ) + } + + @Test("Import: public func callMeMore(callback: (UnsafeRawPointer, Float) -> Int, fn: () -> ())") + func func_callMeMoreFunc_callback() throws { + let st = Swift2JavaTranslator( + swiftModuleName: "__FakeModule" + ) + st.log.logLevel = .error + + try st.analyze(file: "Fake.swift", text: Self.class_interfaceFile) + + let funcDecl = st.importedGlobalFuncs.first { $0.name == "callMeMore" }! + + let generator = FFMSwift2JavaGenerator( + translator: st, + javaPackage: "com.example.swift", + swiftOutputDirectory: "/fake", + javaOutputDirectory: "/fake" + ) + + let output = CodePrinter.toString { printer in + generator.printFunctionDowncallMethods(&printer, funcDecl) + } + + assertOutput( + output, + expected: + """ + // ==== -------------------------------------------------- + // callMeMore + /** + * {@snippet lang=c : + * void swiftjava___FakeModule_callMeMore_callback_fn(ptrdiff_t (*callback)(const void *, float), void (*fn)(void)) + * } + */ + private static class swiftjava___FakeModule_callMeMore_callback_fn { + private static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( + /* callback: */SwiftValueLayout.SWIFT_POINTER, + /* fn: */SwiftValueLayout.SWIFT_POINTER + ); + private static final MemorySegment ADDR = + __FakeModule.findOrThrow("swiftjava___FakeModule_callMeMore_callback_fn"); + private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + public static void call(java.lang.foreign.MemorySegment callback, java.lang.foreign.MemorySegment fn) { + try { + if (SwiftKit.TRACE_DOWNCALLS) { + SwiftKit.traceDowncall(callback, fn); + } + HANDLE.invokeExact(callback, fn); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + /** + * {snippet lang=c : + * ptrdiff_t (*)(const void *, float) + * } + */ + private static class $callback { + @FunctionalInterface + public interface Function { + long apply(java.lang.foreign.MemorySegment _0, float _1); + } + private static final FunctionDescriptor DESC = FunctionDescriptor.of( + /* -> */SwiftValueLayout.SWIFT_INT, + /* _0: */SwiftValueLayout.SWIFT_POINTER, + /* _1: */SwiftValueLayout.SWIFT_FLOAT + ); + private static final MethodHandle HANDLE = SwiftKit.upcallHandle(Function.class, "apply", DESC); + private static MemorySegment toUpcallStub(Function fi, Arena arena) { + return Linker.nativeLinker().upcallStub(HANDLE.bindTo(fi), DESC, arena); + } + } + /** + * {snippet lang=c : + * void (*)(void) + * } + */ + private static class $fn { + @FunctionalInterface + public interface Function { + void apply(); + } + private static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid(); + private static final MethodHandle HANDLE = SwiftKit.upcallHandle(Function.class, "apply", DESC); + private static MemorySegment toUpcallStub(Function fi, Arena arena) { + return Linker.nativeLinker().upcallStub(HANDLE.bindTo(fi), DESC, arena); + } + } + } + public static class callMeMore { + @FunctionalInterface + public interface callback extends swiftjava___FakeModule_callMeMore_callback_fn.$callback.Function {} + private static MemorySegment $toUpcallStub(callback fi, Arena arena) { + return swiftjava___FakeModule_callMeMore_callback_fn.$callback.toUpcallStub(fi, arena); + } + @FunctionalInterface + public interface fn extends swiftjava___FakeModule_callMeMore_callback_fn.$fn.Function {} + private static MemorySegment $toUpcallStub(fn fi, Arena arena) { + return swiftjava___FakeModule_callMeMore_callback_fn.$fn.toUpcallStub(fi, arena); + } + } /** * Downcall to Swift: * {@snippet lang=swift : - * public func callMe(callback: () -> ()) + * public func callMeMore(callback: (UnsafeRawPointer, Float) -> Int, fn: () -> ()) * } */ - public static void callMe(java.lang.Runnable callback) { + public static void callMeMore(callMeMore.callback callback, callMeMore.fn fn) { try(var arena$ = Arena.ofConfined()) { - swiftjava___FakeModule_callMe_callback.call(SwiftKit.toUpcallStub(callback, arena$)) + swiftjava___FakeModule_callMeMore_callback_fn.call(callMeMore.$toUpcallStub(callback, arena$), callMeMore.$toUpcallStub(fn, arena$)); } } """ diff --git a/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift b/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift index f3a101aa..2cac6218 100644 --- a/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift +++ b/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift @@ -57,12 +57,12 @@ final class FunctionDescriptorTests { * } */ private static class swiftjava_SwiftModule_globalTakeInt_i { - public static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( + private static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( /* i: */SwiftValueLayout.SWIFT_INT ); - public static final MemorySegment ADDR = + private static final MemorySegment ADDR = SwiftModule.findOrThrow("swiftjava_SwiftModule_globalTakeInt_i"); - public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); public static void call(long i) { try { if (SwiftKit.TRACE_DOWNCALLS) { @@ -92,13 +92,13 @@ final class FunctionDescriptorTests { * } */ private static class swiftjava_SwiftModule_globalTakeLongInt_l_i32 { - public static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( + private static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( /* l: */SwiftValueLayout.SWIFT_INT64, /* i32: */SwiftValueLayout.SWIFT_INT32 ); - public static final MemorySegment ADDR = + private static final MemorySegment ADDR = SwiftModule.findOrThrow("swiftjava_SwiftModule_globalTakeLongInt_l_i32"); - public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); public static void call(long l, int i32) { try { if (SwiftKit.TRACE_DOWNCALLS) { @@ -128,13 +128,13 @@ final class FunctionDescriptorTests { * } */ private static class swiftjava_SwiftModule_echoInt_i { - public static final FunctionDescriptor DESC = FunctionDescriptor.of( + private static final FunctionDescriptor DESC = FunctionDescriptor.of( /* -> */SwiftValueLayout.SWIFT_INT, /* i: */SwiftValueLayout.SWIFT_INT ); - public static final MemorySegment ADDR = + private static final MemorySegment ADDR = SwiftModule.findOrThrow("swiftjava_SwiftModule_echoInt_i"); - public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); public static long call(long i) { try { if (SwiftKit.TRACE_DOWNCALLS) { @@ -164,13 +164,13 @@ final class FunctionDescriptorTests { * } */ private static class swiftjava_SwiftModule_MySwiftClass_counter$get { - public static final FunctionDescriptor DESC = FunctionDescriptor.of( + private static final FunctionDescriptor DESC = FunctionDescriptor.of( /* -> */SwiftValueLayout.SWIFT_INT32, /* self: */SwiftValueLayout.SWIFT_POINTER ); - public static final MemorySegment ADDR = + private static final MemorySegment ADDR = SwiftModule.findOrThrow("swiftjava_SwiftModule_MySwiftClass_counter$get"); - public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); public static int call(java.lang.foreign.MemorySegment self) { try { if (SwiftKit.TRACE_DOWNCALLS) { @@ -199,13 +199,13 @@ final class FunctionDescriptorTests { * } */ private static class swiftjava_SwiftModule_MySwiftClass_counter$set { - public static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( + private static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( /* newValue: */SwiftValueLayout.SWIFT_INT32, /* self: */SwiftValueLayout.SWIFT_POINTER ); - public static final MemorySegment ADDR = + private static final MemorySegment ADDR = SwiftModule.findOrThrow("swiftjava_SwiftModule_MySwiftClass_counter$set"); - public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); public static void call(int newValue, java.lang.foreign.MemorySegment self) { try { if (SwiftKit.TRACE_DOWNCALLS) { diff --git a/Tests/JExtractSwiftTests/StringPassingTests.swift b/Tests/JExtractSwiftTests/StringPassingTests.swift index d0ad7784..92ce8ea6 100644 --- a/Tests/JExtractSwiftTests/StringPassingTests.swift +++ b/Tests/JExtractSwiftTests/StringPassingTests.swift @@ -40,13 +40,13 @@ final class StringPassingTests { * } */ private static class swiftjava___FakeModule_writeString_string { - public static final FunctionDescriptor DESC = FunctionDescriptor.of( + private static final FunctionDescriptor DESC = FunctionDescriptor.of( /* -> */SwiftValueLayout.SWIFT_INT, /* string: */SwiftValueLayout.SWIFT_POINTER ); - public static final MemorySegment ADDR = + private static final MemorySegment ADDR = __FakeModule.findOrThrow("swiftjava___FakeModule_writeString_string"); - public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); public static long call(java.lang.foreign.MemorySegment string) { try { if (SwiftKit.TRACE_DOWNCALLS) { diff --git a/Tests/JExtractSwiftTests/VariableImportTests.swift b/Tests/JExtractSwiftTests/VariableImportTests.swift index 9d873cc3..562b92ae 100644 --- a/Tests/JExtractSwiftTests/VariableImportTests.swift +++ b/Tests/JExtractSwiftTests/VariableImportTests.swift @@ -42,17 +42,17 @@ final class VariableImportTests { try assertOutput( st, input: class_interfaceFile, .java, - detectChunkByInitialLines: 7, + detectChunkByInitialLines: 8, expectedChunks: [ """ private static class swiftjava_FakeModule_MySwiftClass_counterInt$get { - public static final FunctionDescriptor DESC = FunctionDescriptor.of( + private static final FunctionDescriptor DESC = FunctionDescriptor.of( /* -> */SwiftValueLayout.SWIFT_INT, /* self: */SwiftValueLayout.SWIFT_POINTER ); - public static final MemorySegment ADDR = + private static final MemorySegment ADDR = FakeModule.findOrThrow("swiftjava_FakeModule_MySwiftClass_counterInt$get"); - public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); public static long call(java.lang.foreign.MemorySegment self) { try { if (SwiftKit.TRACE_DOWNCALLS) { @@ -79,13 +79,13 @@ final class VariableImportTests { """, """ private static class swiftjava_FakeModule_MySwiftClass_counterInt$set { - public static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( + private static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( /* newValue: */SwiftValueLayout.SWIFT_INT, /* self: */SwiftValueLayout.SWIFT_POINTER ); - public static final MemorySegment ADDR = + private static final MemorySegment ADDR = FakeModule.findOrThrow("swiftjava_FakeModule_MySwiftClass_counterInt$set"); - public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); public static void call(long newValue, java.lang.foreign.MemorySegment self) { try { if (SwiftKit.TRACE_DOWNCALLS) { From b7781cb60b203861d420196c1ebbffae89429171 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Wed, 11 Jun 2025 11:13:37 +0900 Subject: [PATCH 281/426] Update README about supported Swift versions Currently we recommend an older version of Swift while we update support for the upcoming 6.2. --- README.md | 30 +++++++----------------------- 1 file changed, 7 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index bbe3c964..b7ad4def 100644 --- a/README.md +++ b/README.md @@ -22,26 +22,9 @@ To build and use this project, currently, you will need to download a custom too **Required toolchain download:** -- Go to https://www.swift.org/download/ -- Find the "latest" `Trunk Development (main)` toolchain for your OS - -If these are too old, you can resort to one of these fallback toolchains: - -Fallback development toolchain on **macOS**: - -- https://ci.swift.org/job/swift-PR-toolchain-macos/1539/artifact/branch-main/swift-PR-76905-1539-osx.tar.gz - -Fallback development toolchain on **Linux (Ubuntu 22.04)**: - -``` -URL=$(curl -s "https://ci.swift.org/job/oss-swift-package-ubuntu-22_04/lastSuccessfulBuild/consoleText" | grep 'Toolchain: ' | sed 's/Toolchain: //g') -wget ${URL} -``` - -or just use the provided docker image (explained below). - -https://www.swift.org/download/ +Currently this project supports Swift `6.0.x` and we are working on supporting later releases. +You can use Swiftly ([macOS](https://www.swift.org/install/macos/swiftly/) / [linux](https://www.swift.org/install/linux/swiftly/)) the Swift toolchain installer to install the necessary Swift versions. ### Required JDK versions @@ -50,16 +33,18 @@ This project consists of different modules which have different Swift and Java r **JavaKit** – the Swift macros allowing the invocation of Java libraries from Swift - **JDK 17+**, any recent JDK installation should be sufficient, as only general reflection and JNI APIs are used by this integration -- **Swift 6.0+**, because the library uses modern Swift macros +- **Swift 6.0.x**, because the library uses modern Swift macros **jextract-swift** – the source generator that ingests .swiftinterface files and makes them available to be called from generated Java sources -- **Swift 6.x development snapshots**, because of dependence on rich swift interface files +- **Swift 6.0.x development snapshots**, because of dependence on rich swift interface files - **JDK 22+** because of dependence on [JEP-454: Foreign Function & Memory API](https://openjdk.org/jeps/454) - We are validating the implementation using the currently supported non-LTE release, which at present means JDK-23. The extract tool may become able to generate legacy compatible sources, which would not require JEP-454 and would instead rely on existing JNI facilities. Currently though, efforts are focused on the forward-looking implementation using modern foreign function and memory APIs. +Support for more recent Swift versions will be provided, for now please stick to 6.0 while evaluating this early version of swift-java. + ## Development and Testing This project contains multiple builds, living side by side together. @@ -89,8 +74,7 @@ To run a simple app showcasing a Swift process calling into a Java library you c ```bash cd Samples/JavaKitSampleApp -swift build -java -cp .build/plugins/outputs/javakitsampleapp/JavaKitExample/destination/JavaCompilerPlugin/Java -Djava.library.path=.build/debug com.example.swift.JavaKitSampleMain +./ci-validate.sh # which is just `swift build` and a `java -cp ...` invocation of the compiled program ``` #### jextract (Java -> Swift) From 673689ee3d4022e21a5be5e08c31fcc30bdca1ec Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Fri, 13 Jun 2025 15:53:06 -0700 Subject: [PATCH 282/426] [JExtract] Introduce SwiftKnownTypes to construct stdlib types easily. Rename `SwiftStandardLibraryTypes` to `SwiftStandardLibraryTypeDecls` Rename `KnownStandardLibraryType` to `SwiftStandardLibraryTypeKind` --- .../FFM/CDeclLowering/CRepresentation.swift | 2 +- ...Swift2JavaGenerator+FunctionLowering.swift | 63 +++++++--------- ...MSwift2JavaGenerator+JavaTranslation.swift | 2 +- .../FFM/FFMSwift2JavaGenerator.swift | 4 +- .../Swift2JavaTranslator.swift | 4 +- .../SwiftTypes/SwiftKnownTypes.swift | 73 +++++++++++++++++++ .../SwiftNominalTypeDeclaration.swift | 6 +- ...ft => SwiftStandardLibraryTypeDecls.swift} | 30 ++++---- .../Asserts/LoweringAssertions.swift | 4 +- 9 files changed, 124 insertions(+), 64 deletions(-) create mode 100644 Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownTypes.swift rename Sources/JExtractSwiftLib/SwiftTypes/{SwiftStandardLibraryTypes.swift => SwiftStandardLibraryTypeDecls.swift} (85%) diff --git a/Sources/JExtractSwiftLib/FFM/CDeclLowering/CRepresentation.swift b/Sources/JExtractSwiftLib/FFM/CDeclLowering/CRepresentation.swift index e1a69d12..c52bf7db 100644 --- a/Sources/JExtractSwiftLib/FFM/CDeclLowering/CRepresentation.swift +++ b/Sources/JExtractSwiftLib/FFM/CDeclLowering/CRepresentation.swift @@ -99,7 +99,7 @@ enum CDeclToCLoweringError: Error { case invalidFunctionConvention(SwiftFunctionType) } -extension KnownStandardLibraryType { +extension SwiftStandardLibraryTypeKind { /// Determine the primitive C type that corresponds to this C standard /// library type, if there is one. var primitiveCType: CType? { diff --git a/Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift b/Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift index 02501dc5..061dc997 100644 --- a/Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift +++ b/Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift @@ -75,7 +75,11 @@ extension FFMSwift2JavaGenerator { /// Responsible for lowering Swift API to C API. struct CdeclLowering { - var swiftStdlibTypes: SwiftStandardLibraryTypes + var knownTypes: SwiftKnownTypes + + init(swiftStdlibTypes: SwiftStandardLibraryTypeDecls) { + self.knownTypes = SwiftKnownTypes(decls: swiftStdlibTypes) + } /// Lower the given Swift function signature to a Swift @_cdecl function signature, /// which is C compatible, and the corresponding Java method signature. @@ -149,11 +153,7 @@ struct CdeclLowering { SwiftParameter( convention: .byValue, parameterName: parameterName, - type: .nominal( - SwiftNominalType( - nominalTypeDecl: swiftStdlibTypes[.unsafeRawPointer] - ) - ) + type: knownTypes.unsafeRawPointer ) ], conversion: .unsafeCastPointer(.placeholder, swiftType: instanceType) @@ -173,10 +173,14 @@ struct CdeclLowering { // Typed pointers are mapped down to their raw forms in cdecl entry // points. These can be passed through directly. let isMutable = knownType == .unsafeMutablePointer - let rawPointerNominal = swiftStdlibTypes[isMutable ? .unsafeMutableRawPointer : .unsafeRawPointer] - let paramType: SwiftType = .nominal(SwiftNominalType(nominalTypeDecl: rawPointerNominal)) return LoweredParameter( - cdeclParameters: [SwiftParameter(convention: .byValue, parameterName: parameterName, type: paramType)], + cdeclParameters: [ + SwiftParameter( + convention: .byValue, + parameterName: parameterName, + type: isMutable ? knownTypes.unsafeMutableRawPointer : knownTypes.unsafeRawPointer + ) + ], conversion: .typedPointer(.placeholder, swiftType: genericArgs[0]) ) @@ -186,17 +190,15 @@ struct CdeclLowering { } // Typed pointers are lowered to (raw-pointer, count) pair. let isMutable = knownType == .unsafeMutableBufferPointer - let rawPointerNominal = swiftStdlibTypes[isMutable ? .unsafeMutableRawPointer : .unsafeRawPointer] - return LoweredParameter( cdeclParameters: [ SwiftParameter( convention: .byValue, parameterName: "\(parameterName)_pointer", - type: .nominal(SwiftNominalType(nominalTypeDecl: rawPointerNominal)) + type: isMutable ? knownTypes.unsafeMutableRawPointer : knownTypes.unsafeRawPointer ), SwiftParameter( convention: .byValue, parameterName: "\(parameterName)_count", - type: .nominal(SwiftNominalType(nominalTypeDecl: swiftStdlibTypes[.int])) + type: knownTypes.int ), ], conversion: .initialize( type, @@ -221,12 +223,7 @@ struct CdeclLowering { SwiftParameter( convention: .byValue, parameterName: parameterName, - type: .nominal(SwiftNominalType( - nominalTypeDecl: swiftStdlibTypes.unsafePointerDecl, - genericArguments: [ - .nominal(SwiftNominalType(nominalTypeDecl: swiftStdlibTypes[.int8])) - ] - )) + type: knownTypes.unsafePointer(knownTypes.int8) ) ], conversion: .initialize(type, arguments: [ @@ -243,15 +240,12 @@ struct CdeclLowering { // Arbitrary nominal types are passed-in as an pointer. let isMutable = (convention == .inout) - let rawPointerNominal = swiftStdlibTypes[isMutable ? .unsafeMutableRawPointer : .unsafeRawPointer] - let parameterType: SwiftType = .nominal(SwiftNominalType(nominalTypeDecl: rawPointerNominal)) - return LoweredParameter( cdeclParameters: [ SwiftParameter( convention: .byValue, parameterName: parameterName, - type: parameterType + type: isMutable ? knownTypes.unsafeMutableRawPointer : knownTypes.unsafeRawPointer ), ], conversion: .pointee(.typedPointer(.placeholder, swiftType: type)) @@ -352,12 +346,10 @@ struct CdeclLowering { switch type { case .metatype: // 'unsafeBitcast(, to: UnsafeRawPointer.self)' as 'UnsafeRawPointer' - - let resultType: SwiftType = .nominal(SwiftNominalType(nominalTypeDecl: swiftStdlibTypes[.unsafeRawPointer])) return LoweredResult( - cdeclResultType: resultType, + cdeclResultType: knownTypes.unsafeRawPointer, cdeclOutParameters: [], - conversion: .unsafeCastPointer(.placeholder, swiftType: resultType) + conversion: .unsafeCastPointer(.placeholder, swiftType: knownTypes.unsafeRawPointer) ) case .nominal(let nominal): @@ -367,8 +359,7 @@ struct CdeclLowering { case .unsafePointer, .unsafeMutablePointer: // Typed pointers are lowered to corresponding raw forms. let isMutable = knownType == .unsafeMutablePointer - let rawPointerNominal = swiftStdlibTypes[isMutable ? .unsafeMutableRawPointer : .unsafeRawPointer] - let resultType: SwiftType = .nominal(SwiftNominalType(nominalTypeDecl: rawPointerNominal)) + let resultType: SwiftType = isMutable ? knownTypes.unsafeMutableRawPointer : knownTypes.unsafeRawPointer return LoweredResult( cdeclResultType: resultType, cdeclOutParameters: [], @@ -378,11 +369,10 @@ struct CdeclLowering { case .unsafeBufferPointer, .unsafeMutableBufferPointer: // Typed pointers are lowered to (raw-pointer, count) pair. let isMutable = knownType == .unsafeMutableBufferPointer - let rawPointerType = swiftStdlibTypes[isMutable ? .unsafeMutableRawPointer : .unsafeRawPointer] return try lowerResult( .tuple([ - .nominal(SwiftNominalType(nominalTypeDecl: rawPointerType)), - .nominal(SwiftNominalType(nominalTypeDecl: swiftStdlibTypes[.int])) + isMutable ? knownTypes.unsafeMutableRawPointer : knownTypes.unsafeRawPointer, + knownTypes.int ]), outParameterName: outParameterName ) @@ -407,7 +397,7 @@ struct CdeclLowering { SwiftParameter( convention: .byValue, parameterName: outParameterName, - type: .nominal(SwiftNominalType(nominalTypeDecl: swiftStdlibTypes[.unsafeMutableRawPointer])) + type: knownTypes.unsafeMutableRawPointer ) ], conversion: .populatePointer(name: outParameterName, assumingType: type, to: .placeholder) @@ -431,10 +421,7 @@ struct CdeclLowering { let parameter = SwiftParameter( convention: .byValue, parameterName: parameterName, - type: .nominal(SwiftNominalType( - nominalTypeDecl: swiftStdlibTypes.unsafeMutablePointerDecl, - genericArguments: [lowered.cdeclResultType] - )) + type: knownTypes.unsafeMutablePointer(lowered.cdeclResultType) ) parameters.append(parameter) conversions.append(.populatePointer( @@ -551,7 +538,7 @@ extension LoweredFunctionSignature { cName: String, swiftAPIName: String, as apiKind: SwiftAPIKind, - stdlibTypes: SwiftStandardLibraryTypes + stdlibTypes: SwiftStandardLibraryTypeDecls ) -> FunctionDeclSyntax { let cdeclParams = allLoweredParameters.map(\.description).joined(separator: ", ") diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift index c7e2338d..47616030 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift @@ -144,7 +144,7 @@ extension TranslatedFunctionSignature { } struct JavaTranslation { - var swiftStdlibTypes: SwiftStandardLibraryTypes + var swiftStdlibTypes: SwiftStandardLibraryTypeDecls func translate( _ decl: ImportedFunc diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift index 7cd0075b..036ee31e 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift @@ -23,7 +23,7 @@ package class FFMSwift2JavaGenerator: Swift2JavaGenerator { let javaPackage: String let swiftOutputDirectory: String let javaOutputDirectory: String - let swiftStdlibTypes: SwiftStandardLibraryTypes + let swiftStdlibTypes: SwiftStandardLibraryTypeDecls let symbolTable: SwiftSymbolTable var javaPackagePath: String { @@ -49,7 +49,7 @@ package class FFMSwift2JavaGenerator: Swift2JavaGenerator { self.swiftOutputDirectory = swiftOutputDirectory self.javaOutputDirectory = javaOutputDirectory self.symbolTable = translator.symbolTable - self.swiftStdlibTypes = translator.swiftStdlibTypes + self.swiftStdlibTypes = translator.swiftStdlibTypeDecls } func generate() throws { diff --git a/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift b/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift index ace5f444..857a053a 100644 --- a/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift +++ b/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift @@ -43,7 +43,7 @@ public final class Swift2JavaTranslator { /// type representation. package var importedTypes: [String: ImportedNominalType] = [:] - package var swiftStdlibTypes: SwiftStandardLibraryTypes + package var swiftStdlibTypeDecls: SwiftStandardLibraryTypeDecls package let symbolTable: SwiftSymbolTable @@ -59,7 +59,7 @@ public final class Swift2JavaTranslator { // Create a mock of the Swift standard library. var parsedSwiftModule = SwiftParsedModuleSymbolTable(moduleName: "Swift") - self.swiftStdlibTypes = SwiftStandardLibraryTypes(into: &parsedSwiftModule) + self.swiftStdlibTypeDecls = SwiftStandardLibraryTypeDecls(into: &parsedSwiftModule) self.symbolTable.importedModules.append(parsedSwiftModule.symbolTable) } } diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownTypes.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownTypes.swift new file mode 100644 index 00000000..eaae18cd --- /dev/null +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownTypes.swift @@ -0,0 +1,73 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +struct SwiftKnownTypes { + private let decls: SwiftStandardLibraryTypeDecls + + init(decls: SwiftStandardLibraryTypeDecls) { + self.decls = decls + } + + var bool: SwiftType { .nominal(SwiftNominalType(nominalTypeDecl: decls[.bool])) } + var int: SwiftType { .nominal(SwiftNominalType(nominalTypeDecl: decls[.int])) } + var uint: SwiftType { .nominal(SwiftNominalType(nominalTypeDecl: decls[.uint])) } + var int8: SwiftType { .nominal(SwiftNominalType(nominalTypeDecl: decls[.int8])) } + var uint8: SwiftType { .nominal(SwiftNominalType(nominalTypeDecl: decls[.uint8])) } + var int16: SwiftType { .nominal(SwiftNominalType(nominalTypeDecl: decls[.int16])) } + var uint16: SwiftType { .nominal(SwiftNominalType(nominalTypeDecl: decls[.uint16])) } + var int32: SwiftType { .nominal(SwiftNominalType(nominalTypeDecl: decls[.int32])) } + var uint32: SwiftType { .nominal(SwiftNominalType(nominalTypeDecl: decls[.uint32])) } + var int64: SwiftType { .nominal(SwiftNominalType(nominalTypeDecl: decls[.int64])) } + var uint64: SwiftType { .nominal(SwiftNominalType(nominalTypeDecl: decls[.uint64])) } + var float: SwiftType { .nominal(SwiftNominalType(nominalTypeDecl: decls[.float])) } + var double: SwiftType { .nominal(SwiftNominalType(nominalTypeDecl: decls[.double])) } + var unsafeRawPointer: SwiftType { .nominal(SwiftNominalType(nominalTypeDecl: decls[.unsafeRawPointer])) } + var unsafeMutableRawPointer: SwiftType { .nominal(SwiftNominalType(nominalTypeDecl: decls[.unsafeMutableRawPointer])) } + + func unsafePointer(_ pointeeType: SwiftType) -> SwiftType { + .nominal( + SwiftNominalType( + nominalTypeDecl: decls.unsafePointerDecl, + genericArguments: [pointeeType] + ) + ) + } + + func unsafeMutablePointer(_ pointeeType: SwiftType) -> SwiftType { + .nominal( + SwiftNominalType( + nominalTypeDecl: decls.unsafeMutablePointerDecl, + genericArguments: [pointeeType] + ) + ) + } + + func unsafeBufferPointer(_ elementType: SwiftType) -> SwiftType { + .nominal( + SwiftNominalType( + nominalTypeDecl: decls.unsafeBufferPointerDecl, + genericArguments: [elementType] + ) + ) + } + + func unsafeMutableBufferPointer(_ elementType: SwiftType) -> SwiftType { + .nominal( + SwiftNominalType( + nominalTypeDecl: decls.unsafeMutableBufferPointerDecl, + genericArguments: [elementType] + ) + ) + } +} diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftNominalTypeDeclaration.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftNominalTypeDeclaration.swift index c8330126..29a287fe 100644 --- a/Sources/JExtractSwiftLib/SwiftTypes/SwiftNominalTypeDeclaration.swift +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftNominalTypeDeclaration.swift @@ -52,7 +52,7 @@ package class SwiftNominalTypeDeclaration { /// Identify this nominal declaration as one of the known standard library /// types, like 'Swift.Int[. - lazy var knownStandardLibraryType: KnownStandardLibraryType? = { + lazy var knownStandardLibraryType: SwiftStandardLibraryTypeKind? = { self.computeKnownStandardLibraryType() }() @@ -80,12 +80,12 @@ package class SwiftNominalTypeDeclaration { /// Determine the known standard library type for this nominal type /// declaration. - private func computeKnownStandardLibraryType() -> KnownStandardLibraryType? { + private func computeKnownStandardLibraryType() -> SwiftStandardLibraryTypeKind? { if parent != nil || moduleName != "Swift" { return nil } - return KnownStandardLibraryType(typeNameInSwiftModule: name) + return SwiftStandardLibraryTypeKind(typeNameInSwiftModule: name) } package var qualifiedName: String { diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftStandardLibraryTypes.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftStandardLibraryTypeDecls.swift similarity index 85% rename from Sources/JExtractSwiftLib/SwiftTypes/SwiftStandardLibraryTypes.swift rename to Sources/JExtractSwiftLib/SwiftTypes/SwiftStandardLibraryTypeDecls.swift index 4b07c575..51e1adcf 100644 --- a/Sources/JExtractSwiftLib/SwiftTypes/SwiftStandardLibraryTypes.swift +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftStandardLibraryTypeDecls.swift @@ -14,7 +14,7 @@ import SwiftSyntax -enum KnownStandardLibraryType: String, Hashable, CaseIterable { +enum SwiftStandardLibraryTypeKind: String, Hashable, CaseIterable { case bool = "Bool" case int = "Int" case uint = "UInt" @@ -60,7 +60,7 @@ enum KnownStandardLibraryType: String, Hashable, CaseIterable { /// Captures many types from the Swift standard library in their most basic /// forms, so that the translator can reason about them in source code. -public struct SwiftStandardLibraryTypes { +public struct SwiftStandardLibraryTypeDecls { // Swift.UnsafePointer let unsafePointerDecl: SwiftNominalTypeDeclaration @@ -74,16 +74,16 @@ public struct SwiftStandardLibraryTypes { let unsafeMutableBufferPointerDecl: SwiftNominalTypeDeclaration /// Mapping from known standard library types to their nominal type declaration. - let knownTypeToNominal: [KnownStandardLibraryType: SwiftNominalTypeDeclaration] + let knownTypeToNominal: [SwiftStandardLibraryTypeKind: SwiftNominalTypeDeclaration] /// Mapping from nominal type declarations to known types. - let nominalTypeDeclToKnownType: [SwiftNominalTypeDeclaration: KnownStandardLibraryType] + let nominalTypeDeclToKnownType: [SwiftNominalTypeDeclaration: SwiftStandardLibraryTypeKind] private static func recordKnownType( - _ type: KnownStandardLibraryType, + _ type: SwiftStandardLibraryTypeKind, _ syntax: NominalTypeDeclSyntaxNode, - knownTypeToNominal: inout [KnownStandardLibraryType: SwiftNominalTypeDeclaration], - nominalTypeDeclToKnownType: inout [SwiftNominalTypeDeclaration: KnownStandardLibraryType], + knownTypeToNominal: inout [SwiftStandardLibraryTypeKind: SwiftNominalTypeDeclaration], + nominalTypeDeclToKnownType: inout [SwiftNominalTypeDeclaration: SwiftStandardLibraryTypeKind], parsedModule: inout SwiftParsedModuleSymbolTable ) { let nominalDecl = parsedModule.addNominalTypeDeclaration(syntax, parent: nil) @@ -92,9 +92,9 @@ public struct SwiftStandardLibraryTypes { } private static func recordKnownNonGenericStruct( - _ type: KnownStandardLibraryType, - knownTypeToNominal: inout [KnownStandardLibraryType: SwiftNominalTypeDeclaration], - nominalTypeDeclToKnownType: inout [SwiftNominalTypeDeclaration: KnownStandardLibraryType], + _ type: SwiftStandardLibraryTypeKind, + knownTypeToNominal: inout [SwiftStandardLibraryTypeKind: SwiftNominalTypeDeclaration], + nominalTypeDeclToKnownType: inout [SwiftNominalTypeDeclaration: SwiftStandardLibraryTypeKind], parsedModule: inout SwiftParsedModuleSymbolTable ) { recordKnownType( @@ -155,11 +155,11 @@ public struct SwiftStandardLibraryTypes { parent: nil ) - var knownTypeToNominal: [KnownStandardLibraryType: SwiftNominalTypeDeclaration] = [:] - var nominalTypeDeclToKnownType: [SwiftNominalTypeDeclaration: KnownStandardLibraryType] = [:] + var knownTypeToNominal: [SwiftStandardLibraryTypeKind: SwiftNominalTypeDeclaration] = [:] + var nominalTypeDeclToKnownType: [SwiftNominalTypeDeclaration: SwiftStandardLibraryTypeKind] = [:] // Handle all of the non-generic types at once. - for knownType in KnownStandardLibraryType.allCases { + for knownType in SwiftStandardLibraryTypeKind.allCases { guard !knownType.isGeneric else { continue } @@ -176,11 +176,11 @@ public struct SwiftStandardLibraryTypes { self.nominalTypeDeclToKnownType = nominalTypeDeclToKnownType } - subscript(knownType: KnownStandardLibraryType) -> SwiftNominalTypeDeclaration { + subscript(knownType: SwiftStandardLibraryTypeKind) -> SwiftNominalTypeDeclaration { knownTypeToNominal[knownType]! } - subscript(nominalType: SwiftNominalTypeDeclaration) -> KnownStandardLibraryType? { + subscript(nominalType: SwiftNominalTypeDeclaration) -> SwiftStandardLibraryTypeKind? { nominalTypeDeclToKnownType[nominalType] } } diff --git a/Tests/JExtractSwiftTests/Asserts/LoweringAssertions.swift b/Tests/JExtractSwiftTests/Asserts/LoweringAssertions.swift index 5dd28cc8..f017bc49 100644 --- a/Tests/JExtractSwiftTests/Asserts/LoweringAssertions.swift +++ b/Tests/JExtractSwiftTests/Asserts/LoweringAssertions.swift @@ -73,7 +73,7 @@ func assertLoweredFunction( cName: "c_\(swiftFunctionName)", swiftAPIName: swiftFunctionName, as: apiKind, - stdlibTypes: translator.swiftStdlibTypes + stdlibTypes: translator.swiftStdlibTypeDecls ) #expect( @@ -141,7 +141,7 @@ func assertLoweredVariableAccessor( cName: "c_\(swiftVariableName)", swiftAPIName: swiftVariableName, as: isSet ? .setter : .getter, - stdlibTypes: translator.swiftStdlibTypes + stdlibTypes: translator.swiftStdlibTypeDecls ) #expect( From 660acb7c145b850036d9d7181b4e81eed156eb7f Mon Sep 17 00:00:00 2001 From: Mads Odgaard Date: Sun, 15 Jun 2025 16:10:12 +0200 Subject: [PATCH 283/426] [jextract] Generate code for free functions with primitive types in JNI mode (#269) * generate java code for primitive types and global functions * output swift thunk for JNI * add tests * remove unsigned integer support for now --- Sources/JExtractSwiftLib/ImportedDecls.swift | 1 - .../JNI/JNISwift2JavaGenerator.swift | 253 ++++++++++++++++++ Sources/JExtractSwiftLib/Swift2Java.swift | 10 + .../GenerationMode.swift | 3 + Sources/JavaTypes/JavaType+JNI.swift | 2 +- .../Asserts/TextAssertions.swift | 48 +++- .../ClassPrintingTests.swift | 6 +- .../JNI/JNIModuleTests.swift | 110 ++++++++ .../JExtractSwiftTests/MethodThunkTests.swift | 8 +- .../StringPassingTests.swift | 8 +- .../VariableImportTests.swift | 8 +- 11 files changed, 419 insertions(+), 38 deletions(-) create mode 100644 Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator.swift create mode 100644 Tests/JExtractSwiftTests/JNI/JNIModuleTests.swift diff --git a/Sources/JExtractSwiftLib/ImportedDecls.swift b/Sources/JExtractSwiftLib/ImportedDecls.swift index e98d29b3..3619890b 100644 --- a/Sources/JExtractSwiftLib/ImportedDecls.swift +++ b/Sources/JExtractSwiftLib/ImportedDecls.swift @@ -60,7 +60,6 @@ public final class ImportedFunc: ImportedDecl, CustomStringConvertible { self.swiftDecl.signatureString } - var parentType: SwiftType? { guard let selfParameter = functionSignature.selfParameter else { return nil diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator.swift new file mode 100644 index 00000000..56d75218 --- /dev/null +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator.swift @@ -0,0 +1,253 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import JavaTypes + +package class JNISwift2JavaGenerator: Swift2JavaGenerator { + let analysis: AnalysisResult + let swiftModuleName: String + let javaPackage: String + let logger: Logger + let swiftOutputDirectory: String + let javaOutputDirectory: String + + var javaPackagePath: String { + javaPackage.replacingOccurrences(of: ".", with: "/") + } + + var thunkNameRegistry = ThunkNameRegistry() + + package init( + translator: Swift2JavaTranslator, + javaPackage: String, + swiftOutputDirectory: String, + javaOutputDirectory: String + ) { + self.logger = Logger(label: "jni-generator", logLevel: translator.log.logLevel) + self.analysis = translator.result + self.swiftModuleName = translator.swiftModuleName + self.javaPackage = javaPackage + self.swiftOutputDirectory = swiftOutputDirectory + self.javaOutputDirectory = javaOutputDirectory + } + + func generate() throws { + try writeSwiftThunkSources() + try writeExportedJavaSources() + } +} + +extension JNISwift2JavaGenerator { + func writeExportedJavaSources() throws { + var printer = CodePrinter() + try writeExportedJavaSources(&printer) + } + + package func writeExportedJavaSources(_ printer: inout CodePrinter) throws { + let filename = "\(self.swiftModuleName).java" + logger.trace("Printing module class: \(filename)") + printModule(&printer) + + if let outputFile = try printer.writeContents( + outputDirectory: javaOutputDirectory, + javaPackagePath: javaPackagePath, + filename: filename + ) { + logger.info("[swift-java] Generated: \(self.swiftModuleName).java (at \(outputFile))") + } + } + + func writeSwiftThunkSources() throws { + var printer = CodePrinter() + try writeSwiftThunkSources(&printer) + } + + package func writeSwiftThunkSources(_ printer: inout CodePrinter) throws { + let moduleFilenameBase = "\(self.swiftModuleName)Module+SwiftJava" + let moduleFilename = "\(moduleFilenameBase).swift" + + do { + logger.trace("Printing swift module class: \(moduleFilename)") + + try printGlobalSwiftThunkSources(&printer) + + if let outputFile = try printer.writeContents( + outputDirectory: self.swiftOutputDirectory, + javaPackagePath: javaPackagePath, + filename: moduleFilename + ) { + print("[swift-java] Generated: \(moduleFilenameBase.bold).swift (at \(outputFile)") + } + } catch { + logger.warning("Failed to write to Swift thunks: \(moduleFilename)") + } + } +} + +extension JNISwift2JavaGenerator { + private func printGlobalSwiftThunkSources(_ printer: inout CodePrinter) throws { + printer.print( + """ + // Generated by swift-java + + import JavaKit + + """) + + for decl in analysis.importedGlobalFuncs { + printSwiftFunctionThunk(&printer, decl) + printer.println() + } + } + + private func printSwiftFunctionThunk(_ printer: inout CodePrinter, _ decl: ImportedFunc) { + // TODO: Replace swiftModuleName with class name if non-global + let cName = "Java_" + self.javaPackage.replacingOccurrences(of: ".", with: "_") + "_\(swiftModuleName)_" + decl.name + let thunkName = thunkNameRegistry.functionThunkName(decl: decl) + let translatedParameters = decl.functionSignature.parameters.enumerated().map { idx, param in + (param.parameterName ?? "arg\(idx)", param.type.javaType) + } + + let thunkParameters = [ + "environment: UnsafeMutablePointer!", + "thisClass: jclass" + ] + translatedParameters.map { "\($0.0): \($0.1.jniTypeName)"} + let swiftReturnType = decl.functionSignature.result.type + + let thunkReturnType = !swiftReturnType.isVoid ? " -> \(swiftReturnType.javaType.jniTypeName)" : "" + + printer.printBraceBlock( + """ + @_cdecl("\(cName)") + func \(thunkName)(\(thunkParameters.joined(separator: ", ")))\(thunkReturnType) + """ + ) { printer in + let downcallParameters = zip(decl.functionSignature.parameters, translatedParameters).map { originalParam, translatedParam in + let label = originalParam.argumentLabel ?? originalParam.parameterName ?? "" + return "\(label)\(!label.isEmpty ? ": " : "")\(originalParam.type)(fromJNI: \(translatedParam.0), in: environment!)" + } + let functionDowncall = "\(swiftModuleName).\(decl.name)(\(downcallParameters.joined(separator: ", ")))" + + if swiftReturnType.isVoid { + printer.print(functionDowncall) + } else { + printer.print( + """ + let result = \(functionDowncall) + return result.getJNIValue(in: environment)") + """ + ) + } + } + } +} + +extension JNISwift2JavaGenerator { + private func printModule(_ printer: inout CodePrinter) { + printHeader(&printer) + printPackage(&printer) + + printModuleClass(&printer) { printer in + for decl in analysis.importedGlobalFuncs { + self.logger.trace("Print global function: \(decl)") + printFunctionBinding(&printer, decl) + printer.println() + } + } + } + + private func printHeader(_ printer: inout CodePrinter) { + printer.print( + """ + // Generated by jextract-swift + // Swift module: \(swiftModuleName) + + """ + ) + } + + private func printPackage(_ printer: inout CodePrinter) { + printer.print( + """ + package \(javaPackage); + + """ + ) + } + + private func printModuleClass(_ printer: inout CodePrinter, body: (inout CodePrinter) -> Void) { + printer.printBraceBlock("public final class \(swiftModuleName)") { printer in + body(&printer) + } + } + + private func printFunctionBinding(_ printer: inout CodePrinter, _ decl: ImportedFunc) { + let returnType = decl.functionSignature.result.type.javaType + let params = decl.functionSignature.parameters.enumerated().map { idx, param in + "\(param.type.javaType) \(param.parameterName ?? "arg\(idx))")" + } + + printer.print( + """ + /** + * Downcall to Swift: + * {@snippet lang=swift : + * \(decl.signatureString) + * } + */ + """ + ) + printer.print("public static native \(returnType) \(decl.name)(\(params.joined(separator: ", ")));") + } +} + +extension SwiftType { + var javaType: JavaType { + switch self { + case .nominal(let nominalType): + if let knownType = nominalType.nominalTypeDecl.knownStandardLibraryType { + guard let javaType = knownType.javaType else { + fatalError("unsupported known type: \(knownType)") + } + return javaType + } + + fatalError("unsupported nominal type: \(nominalType)") + + case .tuple([]): + return .void + + case .metatype, .optional, .tuple, .function: + fatalError("unsupported type: \(self)") + } + } +} + +extension SwiftStandardLibraryTypeKind { + var javaType: JavaType? { + switch self { + case .bool: .boolean + case .int: .long // TODO: Handle 32-bit or 64-bit + case .int8: .byte + case .uint16: .char + case .int16: .short + case .int32: .int + case .int64: .long + case .float: .float + case .double: .double + case .void: .void + case .uint, .uint8, .uint32, .uint64, .unsafeRawPointer, .unsafeMutableRawPointer, .unsafePointer, .unsafeMutablePointer, .unsafeBufferPointer, .unsafeMutableBufferPointer, .string: nil + } + } +} diff --git a/Sources/JExtractSwiftLib/Swift2Java.swift b/Sources/JExtractSwiftLib/Swift2Java.swift index 8adb7670..9b1b06bc 100644 --- a/Sources/JExtractSwiftLib/Swift2Java.swift +++ b/Sources/JExtractSwiftLib/Swift2Java.swift @@ -97,6 +97,16 @@ public struct SwiftToJava { javaOutputDirectory: outputJavaDirectory ) + try generator.generate() + + case .jni: + let generator = JNISwift2JavaGenerator( + translator: translator, + javaPackage: config.javaPackage ?? "", + swiftOutputDirectory: outputSwiftDirectory, + javaOutputDirectory: outputJavaDirectory + ) + try generator.generate() } diff --git a/Sources/JavaKitConfigurationShared/GenerationMode.swift b/Sources/JavaKitConfigurationShared/GenerationMode.swift index ff1d081d..ea30a436 100644 --- a/Sources/JavaKitConfigurationShared/GenerationMode.swift +++ b/Sources/JavaKitConfigurationShared/GenerationMode.swift @@ -15,4 +15,7 @@ public enum GenerationMode: String, Codable { /// Foreign Value and Memory API case ffm + + /// Java Native Interface + case jni } diff --git a/Sources/JavaTypes/JavaType+JNI.swift b/Sources/JavaTypes/JavaType+JNI.swift index 41a93d25..08361bac 100644 --- a/Sources/JavaTypes/JavaType+JNI.swift +++ b/Sources/JavaTypes/JavaType+JNI.swift @@ -14,7 +14,7 @@ extension JavaType { /// Map this Java type to the appropriate JNI type name. - var jniTypeName: String { + package var jniTypeName: String { switch self { case .boolean: "jboolean" case .float: "jfloat" diff --git a/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift b/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift index 3ea03d98..b3a09a22 100644 --- a/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift +++ b/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift @@ -14,6 +14,7 @@ import JExtractSwiftLib import Testing +import JavaKitConfigurationShared import struct Foundation.CharacterSet enum RenderKind { @@ -23,9 +24,10 @@ enum RenderKind { func assertOutput( dump: Bool = false, - _ translator: Swift2JavaTranslator, input: String, + _ mode: GenerationMode, _ renderKind: RenderKind, + swiftModuleName: String = "SwiftModule", detectChunkByInitialLines: Int = 4, expectedChunks: [String], fileID: String = #fileID, @@ -33,22 +35,42 @@ func assertOutput( line: Int = #line, column: Int = #column ) throws { - try! translator.analyze(file: "/fake/Fake.swiftinterface", text: input) + let translator = Swift2JavaTranslator(swiftModuleName: swiftModuleName) - let generator = FFMSwift2JavaGenerator( - translator: translator, - javaPackage: "com.example.swift", - swiftOutputDirectory: "/fake", - javaOutputDirectory: "/fake" - ) + try! translator.analyze(file: "/fake/Fake.swiftinterface", text: input) let output: String var printer: CodePrinter = CodePrinter(mode: .accumulateAll) - switch renderKind { - case .swift: - try generator.writeSwiftThunkSources(printer: &printer) - case .java: - try generator.writeExportedJavaSources(printer: &printer) + switch mode { + case .ffm: + let generator = FFMSwift2JavaGenerator( + translator: translator, + javaPackage: "com.example.swift", + swiftOutputDirectory: "/fake", + javaOutputDirectory: "/fake" + ) + + switch renderKind { + case .swift: + try generator.writeSwiftThunkSources(printer: &printer) + case .java: + try generator.writeExportedJavaSources(printer: &printer) + } + + case .jni: + let generator = JNISwift2JavaGenerator( + translator: translator, + javaPackage: "com.example.swift", + swiftOutputDirectory: "/fake", + javaOutputDirectory: "/fake" + ) + + switch renderKind { + case .swift: + try generator.writeSwiftThunkSources(&printer) + case .java: + try generator.writeExportedJavaSources(&printer) + } } output = printer.finalize() diff --git a/Tests/JExtractSwiftTests/ClassPrintingTests.swift b/Tests/JExtractSwiftTests/ClassPrintingTests.swift index f0c59456..6c0d8d0a 100644 --- a/Tests/JExtractSwiftTests/ClassPrintingTests.swift +++ b/Tests/JExtractSwiftTests/ClassPrintingTests.swift @@ -41,11 +41,7 @@ struct ClassPrintingTests { @Test("Import: class layout") func class_layout() throws { - let st = Swift2JavaTranslator( - swiftModuleName: "__FakeModule" - ) - - try assertOutput(st, input: class_interfaceFile, .java, expectedChunks: [ + try assertOutput(input: class_interfaceFile, .ffm, .java, swiftModuleName: "__FakeModule", expectedChunks: [ """ public static final SwiftAnyType TYPE_METADATA = new SwiftAnyType(SwiftKit.swiftjava.getType("__FakeModule", "MySwiftClass")); diff --git a/Tests/JExtractSwiftTests/JNI/JNIModuleTests.swift b/Tests/JExtractSwiftTests/JNI/JNIModuleTests.swift new file mode 100644 index 00000000..c5df98a1 --- /dev/null +++ b/Tests/JExtractSwiftTests/JNI/JNIModuleTests.swift @@ -0,0 +1,110 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import JExtractSwiftLib +import Testing + +@Suite +struct JNIModuleTests { + let globalMethodWithPrimitives = """ + public func helloWorld() + public func takeIntegers(i1: Int8, i2: Int16, i3: Int32, i4: Int) -> UInt16 + public func otherPrimitives(b: Bool, f: Float, d: Double) + """ + + @Test + func generatesModuleJavaClass() throws { + let input = "public func helloWorld()" + + try assertOutput(input: input, .jni, .java, expectedChunks: [ + """ + // Generated by jextract-swift + // Swift module: SwiftModule + + package com.example.swift; + + public final class SwiftModule { + """ + ]) + } + + @Test + func globalMethodWithPrimitives_javaBindings() throws { + try assertOutput( + input: globalMethodWithPrimitives, + .jni, + .java, + expectedChunks: [ + """ + /** + * Downcall to Swift: + * {@snippet lang=swift : + * public func helloWorld() + * } + */ + public static native void helloWorld(); + """, + """ + /** + * Downcall to Swift: + * {@snippet lang=swift : + * public func takeIntegers(i1: Int8, i2: Int16, i3: Int32, i4: Int) -> UInt16 + * } + */ + public static native char takeIntegers(byte i1, short i2, int i3, long i4); + """, + """ + /** + * Downcall to Swift: + * {@snippet lang=swift : + * public func otherPrimitives(b: Bool, f: Float, d: Double) + * } + */ + public static native void otherPrimitives(boolean b, float f, double d); + """ + ] + ) + } + + @Test + func globalMethodWithPrimitives_swiftThunks() throws { + try assertOutput( + input: globalMethodWithPrimitives, + .jni, + .swift, + detectChunkByInitialLines: 1, + expectedChunks: [ + """ + @_cdecl("Java_com_example_swift_SwiftModule_helloWorld") + func swiftjava_SwiftModule_helloWorld(environment: UnsafeMutablePointer!, thisClass: jclass) { + SwiftModule.helloWorld() + } + """, + """ + @_cdecl("Java_com_example_swift_SwiftModule_takeIntegers") + func swiftjava_SwiftModule_takeIntegers_i1_i2_i3_i4(environment: UnsafeMutablePointer!, thisClass: jclass, i1: jbyte, i2: jshort, i3: jint, i4: jlong) -> jchar { + let result = SwiftModule.takeIntegers(i1: Int8(fromJNI: i1, in: environment!), i2: Int16(fromJNI: i2, in: environment!), i3: Int32(fromJNI: i3, in: environment!), i4: Int(fromJNI: i4, in: environment!)) + return result.getJNIValue(in: environment)") + } + """, + """ + @_cdecl("Java_com_example_swift_SwiftModule_otherPrimitives") + func swiftjava_SwiftModule_otherPrimitives_b_f_d(environment: UnsafeMutablePointer!, thisClass: jclass, b: jboolean, f: jfloat, d: jdouble) { + SwiftModule.otherPrimitives(b: Bool(fromJNI: b, in: environment!), f: Float(fromJNI: f, in: environment!), d: Double(fromJNI: d, in: environment!)) + } + """ + ] + ) + } +} diff --git a/Tests/JExtractSwiftTests/MethodThunkTests.swift b/Tests/JExtractSwiftTests/MethodThunkTests.swift index b91c0d8f..dab550b3 100644 --- a/Tests/JExtractSwiftTests/MethodThunkTests.swift +++ b/Tests/JExtractSwiftTests/MethodThunkTests.swift @@ -32,13 +32,9 @@ final class MethodThunkTests { @Test("Thunk overloads: globalFunc(a: Int32, b: Int64) & globalFunc(i32: Int32, l: Int64)") func thunk_overloads() throws { - let st = Swift2JavaTranslator( - swiftModuleName: "FakeModule" - ) - st.log.logLevel = .error - try assertOutput( - st, input: input, .swift, + input: input, .ffm, .swift, + swiftModuleName: "FakeModule", detectChunkByInitialLines: 1, expectedChunks: [ diff --git a/Tests/JExtractSwiftTests/StringPassingTests.swift b/Tests/JExtractSwiftTests/StringPassingTests.swift index 92ce8ea6..99dfab5c 100644 --- a/Tests/JExtractSwiftTests/StringPassingTests.swift +++ b/Tests/JExtractSwiftTests/StringPassingTests.swift @@ -25,13 +25,9 @@ final class StringPassingTests { @Test("Import: public func writeString(string: String) -> Int") func method_helloWorld() throws { - let st = Swift2JavaTranslator( - swiftModuleName: "__FakeModule" - ) - st.log.logLevel = .trace - try assertOutput( - st, input: class_interfaceFile, .java, + input: class_interfaceFile, .ffm, .java, + swiftModuleName: "__FakeModule", expectedChunks: [ """ /** diff --git a/Tests/JExtractSwiftTests/VariableImportTests.swift b/Tests/JExtractSwiftTests/VariableImportTests.swift index 562b92ae..33f41e20 100644 --- a/Tests/JExtractSwiftTests/VariableImportTests.swift +++ b/Tests/JExtractSwiftTests/VariableImportTests.swift @@ -35,13 +35,9 @@ final class VariableImportTests { @Test("Import: var counter: Int") func variable_int() throws { - let st = Swift2JavaTranslator( - swiftModuleName: "FakeModule" - ) - st.log.logLevel = .error - try assertOutput( - st, input: class_interfaceFile, .java, + input: class_interfaceFile, .ffm, .java, + swiftModuleName: "FakeModule", detectChunkByInitialLines: 8, expectedChunks: [ """ From ccc87db5e3c63f861fb2fa1d433843cef4fcba73 Mon Sep 17 00:00:00 2001 From: Mads Odgaard Date: Mon, 16 Jun 2025 04:03:05 +0200 Subject: [PATCH 284/426] add support for strings (#273) --- .../JNI/JNISwift2JavaGenerator.swift | 7 +-- .../JNI/JNIModuleTests.swift | 43 +++++++++++++++++++ 2 files changed, 47 insertions(+), 3 deletions(-) diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator.swift index 56d75218..946223ae 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator.swift @@ -134,8 +134,8 @@ extension JNISwift2JavaGenerator { """ ) { printer in let downcallParameters = zip(decl.functionSignature.parameters, translatedParameters).map { originalParam, translatedParam in - let label = originalParam.argumentLabel ?? originalParam.parameterName ?? "" - return "\(label)\(!label.isEmpty ? ": " : "")\(originalParam.type)(fromJNI: \(translatedParam.0), in: environment!)" + let label = originalParam.argumentLabel.map { "\($0): "} ?? "" + return "\(label)\(originalParam.type)(fromJNI: \(translatedParam.0), in: environment!)" } let functionDowncall = "\(swiftModuleName).\(decl.name)(\(downcallParameters.joined(separator: ", ")))" @@ -247,7 +247,8 @@ extension SwiftStandardLibraryTypeKind { case .float: .float case .double: .double case .void: .void - case .uint, .uint8, .uint32, .uint64, .unsafeRawPointer, .unsafeMutableRawPointer, .unsafePointer, .unsafeMutablePointer, .unsafeBufferPointer, .unsafeMutableBufferPointer, .string: nil + case .string: .javaLangString + case .uint, .uint8, .uint32, .uint64, .unsafeRawPointer, .unsafeMutableRawPointer, .unsafePointer, .unsafeMutablePointer, .unsafeBufferPointer, .unsafeMutableBufferPointer: nil } } } diff --git a/Tests/JExtractSwiftTests/JNI/JNIModuleTests.swift b/Tests/JExtractSwiftTests/JNI/JNIModuleTests.swift index c5df98a1..ba6258a1 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIModuleTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIModuleTests.swift @@ -23,6 +23,10 @@ struct JNIModuleTests { public func otherPrimitives(b: Bool, f: Float, d: Double) """ + let globalMethodWithString = """ + public func copy(_ string: String) -> String + """ + @Test func generatesModuleJavaClass() throws { let input = "public func helloWorld()" @@ -107,4 +111,43 @@ struct JNIModuleTests { ] ) } + + @Test + func globalMethodWithString_javaBindings() throws { + try assertOutput( + input: globalMethodWithString, + .jni, + .java, + expectedChunks: [ + """ + /** + * Downcall to Swift: + * {@snippet lang=swift : + * public func copy(_ string: String) -> String + * } + */ + public static native java.lang.String copy(java.lang.String string); + """, + ] + ) + } + + @Test + func globalMethodWithString_swiftThunks() throws { + try assertOutput( + input: globalMethodWithString, + .jni, + .swift, + detectChunkByInitialLines: 1, + expectedChunks: [ + """ + @_cdecl("Java_com_example_swift_SwiftModule_copy") + func swiftjava_SwiftModule_copy__(environment: UnsafeMutablePointer!, thisClass: jclass, string: jstring?) -> jstring? { + let result = SwiftModule.copy(String(fromJNI: string, in: environment!)) + return result.getJNIValue(in: environment) + } + """, + ] + ) + } } From 2fb33d8fa376865c81cab17d812ff0fd26d9b15a Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Mon, 16 Jun 2025 11:13:25 +0900 Subject: [PATCH 285/426] Extract `configure` into its own subcommand (first of such extractions) (#268) --- .../JExtractSwiftCommandPlugin.swift | 2 +- .../JExtractSwiftPlugin.swift | 2 +- Plugins/PluginsShared/PluginUtils.swift | 4 +- Plugins/SwiftJavaPlugin/SwiftJavaPlugin.swift | 15 +- .../Sources/Test/swift-java.config | 429 ++++++++++++++ Samples/JavaSieve/Package.swift | 2 + .../JavaSieve/Sources/JavaSieve/main.swift | 7 +- .../Sources/JavaSieve/swift-java.config | 1 + .../Configuration.swift | 4 +- .../Commands/ConfigureCommand.swift | 238 ++++++++ .../ResolveCommand.swift} | 40 +- .../SwiftJava+GenerateWrappers.swift | 7 +- .../{ => Commands}/SwiftJava+JExtract.swift | 0 Sources/SwiftJavaTool/CommonOptions.swift | 59 ++ .../SwiftJavaTool/Java/JavaClassLoader.swift | 29 + .../SwiftJava+EmitConfiguration.swift | 120 ---- Sources/SwiftJavaTool/SwiftJava.swift | 525 ++++++------------ .../SwiftJavaBaseAsyncParsableCommand.swift | 181 ++++++ USER_GUIDE.md | 97 ++-- 19 files changed, 1213 insertions(+), 549 deletions(-) create mode 100644 Samples/JavaDependencySampleApp/Sources/Test/swift-java.config create mode 100644 Sources/SwiftJavaTool/Commands/ConfigureCommand.swift rename Sources/SwiftJavaTool/{SwiftJava+FetchDependencies.swift => Commands/ResolveCommand.swift} (86%) rename Sources/SwiftJavaTool/{ => Commands}/SwiftJava+GenerateWrappers.swift (95%) rename Sources/SwiftJavaTool/{ => Commands}/SwiftJava+JExtract.swift (100%) create mode 100644 Sources/SwiftJavaTool/CommonOptions.swift create mode 100644 Sources/SwiftJavaTool/Java/JavaClassLoader.swift delete mode 100644 Sources/SwiftJavaTool/SwiftJava+EmitConfiguration.swift create mode 100644 Sources/SwiftJavaTool/SwiftJavaBaseAsyncParsableCommand.swift diff --git a/Plugins/JExtractSwiftCommandPlugin/JExtractSwiftCommandPlugin.swift b/Plugins/JExtractSwiftCommandPlugin/JExtractSwiftCommandPlugin.swift index 3ea89886..f97feab6 100644 --- a/Plugins/JExtractSwiftCommandPlugin/JExtractSwiftCommandPlugin.swift +++ b/Plugins/JExtractSwiftCommandPlugin/JExtractSwiftCommandPlugin.swift @@ -72,7 +72,7 @@ final class JExtractSwiftCommandPlugin: SwiftJavaPluginProtocol, BuildToolPlugin var arguments: [String] = [ "--input-swift", sourceDir, - "--module-name", sourceModule.name, + "--swift-module", sourceModule.name, "--output-java", context.outputJavaDirectory.path(percentEncoded: false), "--output-swift", context.outputSwiftDirectory.path(percentEncoded: false), // TODO: "--build-cache-directory", ... diff --git a/Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift b/Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift index a2cda352..4b52df26 100644 --- a/Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift +++ b/Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift @@ -55,7 +55,7 @@ struct JExtractSwiftBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin { var arguments: [String] = [ "--input-swift", sourceDir, - "--module-name", sourceModule.name, + "--swift-module", sourceModule.name, "--output-java", outputJavaDirectory.path(percentEncoded: false), "--output-swift", outputSwiftDirectory.path(percentEncoded: false), // TODO: "--build-cache-directory", ... diff --git a/Plugins/PluginsShared/PluginUtils.swift b/Plugins/PluginsShared/PluginUtils.swift index 691d3375..863cf99c 100644 --- a/Plugins/PluginsShared/PluginUtils.swift +++ b/Plugins/PluginsShared/PluginUtils.swift @@ -72,8 +72,8 @@ extension PluginContext { .appending(path: "Sources") } - func cachedClasspathFile(moduleName: String) -> URL { + func cachedClasspathFile(swiftModule: String) -> URL { self.pluginWorkDirectoryURL - .appending(path: "\(moduleName)", directoryHint: .notDirectory) + .appending(path: "\(swiftModule)", directoryHint: .notDirectory) } } diff --git a/Plugins/SwiftJavaPlugin/SwiftJavaPlugin.swift b/Plugins/SwiftJavaPlugin/SwiftJavaPlugin.swift index 77d7058d..effdcc53 100644 --- a/Plugins/SwiftJavaPlugin/SwiftJavaPlugin.swift +++ b/Plugins/SwiftJavaPlugin/SwiftJavaPlugin.swift @@ -166,8 +166,9 @@ struct SwiftJavaBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin { displayName: displayName, executable: executable, arguments: [ + // FIXME: change to 'resolve' subcommand "--fetch", configFile.path(percentEncoded: false), - "--module-name", sourceModule.name, + "--swift-module", sourceModule.name, "--output-directory", outputDirectory(context: context, generated: false).path(percentEncoded: false) ], environment: [:], @@ -180,21 +181,21 @@ struct SwiftJavaBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin { } if !outputSwiftFiles.isEmpty { + let displayName = "Wrapping \(classes.count) Java classes in Swift target '\(sourceModule.name)'" + log("Prepared: \(displayName)") commands += [ .buildCommand( - displayName: "Wrapping \(classes.count) Java classes in Swift target '\(sourceModule.name)'", + displayName: displayName, executable: executable, arguments: arguments, - inputFiles: compiledClassFiles + fetchDependenciesOutputFiles + [ - configFile - ], + inputFiles: compiledClassFiles + fetchDependenciesOutputFiles + [ configFile ], outputFiles: outputSwiftFiles ) ] } else { log("No Swift output files, skip wrapping") } - + return commands } } @@ -202,7 +203,7 @@ struct SwiftJavaBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin { extension SwiftJavaBuildToolPlugin { func argumentsModuleName(sourceModule: Target) -> [String] { return [ - "--module-name", sourceModule.name + "--swift-module", sourceModule.name ] } diff --git a/Samples/JavaDependencySampleApp/Sources/Test/swift-java.config b/Samples/JavaDependencySampleApp/Sources/Test/swift-java.config new file mode 100644 index 00000000..50fd7337 --- /dev/null +++ b/Samples/JavaDependencySampleApp/Sources/Test/swift-java.config @@ -0,0 +1,429 @@ +{ + "classes" : { + "org.apache.commons.codec.BinaryDecoder" : "BinaryDecoder", + "org.apache.commons.codec.BinaryEncoder" : "BinaryEncoder", + "org.apache.commons.codec.CharEncoding" : "CharEncoding", + "org.apache.commons.codec.Charsets" : "Charsets", + "org.apache.commons.codec.CodecPolicy" : "CodecPolicy", + "org.apache.commons.codec.Decoder" : "Decoder", + "org.apache.commons.codec.DecoderException" : "DecoderException", + "org.apache.commons.codec.Encoder" : "Encoder", + "org.apache.commons.codec.EncoderException" : "EncoderException", + "org.apache.commons.codec.Resources" : "Resources", + "org.apache.commons.codec.StringDecoder" : "StringDecoder", + "org.apache.commons.codec.StringEncoder" : "StringEncoder", + "org.apache.commons.codec.StringEncoderComparator" : "StringEncoderComparator", + "org.apache.commons.codec.binary.Base16" : "Base16", + "org.apache.commons.codec.binary.Base16InputStream" : "Base16InputStream", + "org.apache.commons.codec.binary.Base16OutputStream" : "Base16OutputStream", + "org.apache.commons.codec.binary.Base32" : "Base32", + "org.apache.commons.codec.binary.Base32$Builder" : "Base32.Builder", + "org.apache.commons.codec.binary.Base32InputStream" : "Base32InputStream", + "org.apache.commons.codec.binary.Base32OutputStream" : "Base32OutputStream", + "org.apache.commons.codec.binary.Base64" : "Base64", + "org.apache.commons.codec.binary.Base64$Builder" : "Base64.Builder", + "org.apache.commons.codec.binary.Base64InputStream" : "Base64InputStream", + "org.apache.commons.codec.binary.Base64OutputStream" : "Base64OutputStream", + "org.apache.commons.codec.binary.BaseNCodec" : "BaseNCodec", + "org.apache.commons.codec.binary.BaseNCodec$AbstractBuilder" : "BaseNCodec.AbstractBuilder", + "org.apache.commons.codec.binary.BaseNCodec$Context" : "BaseNCodec.Context", + "org.apache.commons.codec.binary.BaseNCodecInputStream" : "BaseNCodecInputStream", + "org.apache.commons.codec.binary.BaseNCodecOutputStream" : "BaseNCodecOutputStream", + "org.apache.commons.codec.binary.BinaryCodec" : "BinaryCodec", + "org.apache.commons.codec.binary.CharSequenceUtils" : "CharSequenceUtils", + "org.apache.commons.codec.binary.Hex" : "Hex", + "org.apache.commons.codec.binary.StringUtils" : "StringUtils", + "org.apache.commons.codec.cli.Digest" : "Digest", + "org.apache.commons.codec.digest.B64" : "B64", + "org.apache.commons.codec.digest.Blake3" : "Blake3", + "org.apache.commons.codec.digest.Blake3$ChunkState" : "Blake3.ChunkState", + "org.apache.commons.codec.digest.Blake3$EngineState" : "Blake3.EngineState", + "org.apache.commons.codec.digest.Blake3$Output" : "Blake3.Output", + "org.apache.commons.codec.digest.Crypt" : "Crypt", + "org.apache.commons.codec.digest.DigestUtils" : "DigestUtils", + "org.apache.commons.codec.digest.HmacAlgorithms" : "HmacAlgorithms", + "org.apache.commons.codec.digest.HmacUtils" : "HmacUtils", + "org.apache.commons.codec.digest.Md5Crypt" : "Md5Crypt", + "org.apache.commons.codec.digest.MessageDigestAlgorithms" : "MessageDigestAlgorithms", + "org.apache.commons.codec.digest.MurmurHash2" : "MurmurHash2", + "org.apache.commons.codec.digest.MurmurHash3" : "MurmurHash3", + "org.apache.commons.codec.digest.MurmurHash3$IncrementalHash32" : "MurmurHash3.IncrementalHash32", + "org.apache.commons.codec.digest.MurmurHash3$IncrementalHash32x86" : "MurmurHash3.IncrementalHash32x86", + "org.apache.commons.codec.digest.PureJavaCrc32" : "PureJavaCrc32", + "org.apache.commons.codec.digest.PureJavaCrc32C" : "PureJavaCrc32C", + "org.apache.commons.codec.digest.Sha2Crypt" : "Sha2Crypt", + "org.apache.commons.codec.digest.UnixCrypt" : "UnixCrypt", + "org.apache.commons.codec.digest.XXHash32" : "XXHash32", + "org.apache.commons.codec.language.AbstractCaverphone" : "AbstractCaverphone", + "org.apache.commons.codec.language.Caverphone" : "Caverphone", + "org.apache.commons.codec.language.Caverphone1" : "Caverphone1", + "org.apache.commons.codec.language.Caverphone2" : "Caverphone2", + "org.apache.commons.codec.language.ColognePhonetic" : "ColognePhonetic", + "org.apache.commons.codec.language.ColognePhonetic$CologneBuffer" : "ColognePhonetic.CologneBuffer", + "org.apache.commons.codec.language.ColognePhonetic$CologneInputBuffer" : "ColognePhonetic.CologneInputBuffer", + "org.apache.commons.codec.language.ColognePhonetic$CologneOutputBuffer" : "ColognePhonetic.CologneOutputBuffer", + "org.apache.commons.codec.language.DaitchMokotoffSoundex" : "DaitchMokotoffSoundex", + "org.apache.commons.codec.language.DaitchMokotoffSoundex$Branch" : "DaitchMokotoffSoundex.Branch", + "org.apache.commons.codec.language.DaitchMokotoffSoundex$Rule" : "DaitchMokotoffSoundex.Rule", + "org.apache.commons.codec.language.DoubleMetaphone" : "DoubleMetaphone", + "org.apache.commons.codec.language.DoubleMetaphone$DoubleMetaphoneResult" : "DoubleMetaphone.DoubleMetaphoneResult", + "org.apache.commons.codec.language.MatchRatingApproachEncoder" : "MatchRatingApproachEncoder", + "org.apache.commons.codec.language.Metaphone" : "Metaphone", + "org.apache.commons.codec.language.Nysiis" : "Nysiis", + "org.apache.commons.codec.language.RefinedSoundex" : "RefinedSoundex", + "org.apache.commons.codec.language.Soundex" : "Soundex", + "org.apache.commons.codec.language.SoundexUtils" : "SoundexUtils", + "org.apache.commons.codec.language.bm.BeiderMorseEncoder" : "BeiderMorseEncoder", + "org.apache.commons.codec.language.bm.Lang" : "Lang", + "org.apache.commons.codec.language.bm.Lang$LangRule" : "Lang.LangRule", + "org.apache.commons.codec.language.bm.Languages" : "Languages", + "org.apache.commons.codec.language.bm.Languages$LanguageSet" : "Languages.LanguageSet", + "org.apache.commons.codec.language.bm.Languages$SomeLanguages" : "Languages.SomeLanguages", + "org.apache.commons.codec.language.bm.NameType" : "NameType", + "org.apache.commons.codec.language.bm.PhoneticEngine" : "PhoneticEngine", + "org.apache.commons.codec.language.bm.PhoneticEngine$PhonemeBuilder" : "PhoneticEngine.PhonemeBuilder", + "org.apache.commons.codec.language.bm.PhoneticEngine$RulesApplication" : "PhoneticEngine.RulesApplication", + "org.apache.commons.codec.language.bm.ResourceConstants" : "ResourceConstants", + "org.apache.commons.codec.language.bm.Rule" : "Rule", + "org.apache.commons.codec.language.bm.Rule$Phoneme" : "Rule.Phoneme", + "org.apache.commons.codec.language.bm.Rule$PhonemeExpr" : "Rule.PhonemeExpr", + "org.apache.commons.codec.language.bm.Rule$PhonemeList" : "Rule.PhonemeList", + "org.apache.commons.codec.language.bm.Rule$RPattern" : "Rule.RPattern", + "org.apache.commons.codec.language.bm.RuleType" : "RuleType", + "org.apache.commons.codec.net.BCodec" : "BCodec", + "org.apache.commons.codec.net.PercentCodec" : "PercentCodec", + "org.apache.commons.codec.net.QCodec" : "QCodec", + "org.apache.commons.codec.net.QuotedPrintableCodec" : "QuotedPrintableCodec", + "org.apache.commons.codec.net.RFC1522Codec" : "RFC1522Codec", + "org.apache.commons.codec.net.URLCodec" : "URLCodec", + "org.apache.commons.codec.net.Utils" : "Utils", + "org.apache.commons.csv.CSVException" : "CSVException", + "org.apache.commons.csv.CSVFormat" : "CSVFormat", + "org.apache.commons.csv.CSVFormat$Builder" : "CSVFormat.Builder", + "org.apache.commons.csv.CSVFormat$Predefined" : "CSVFormat.Predefined", + "org.apache.commons.csv.CSVParser" : "CSVParser", + "org.apache.commons.csv.CSVParser$CSVRecordIterator" : "CSVParser.CSVRecordIterator", + "org.apache.commons.csv.CSVParser$Headers" : "CSVParser.Headers", + "org.apache.commons.csv.CSVPrinter" : "CSVPrinter", + "org.apache.commons.csv.CSVRecord" : "CSVRecord", + "org.apache.commons.csv.Constants" : "Constants", + "org.apache.commons.csv.DuplicateHeaderMode" : "DuplicateHeaderMode", + "org.apache.commons.csv.ExtendedBufferedReader" : "ExtendedBufferedReader", + "org.apache.commons.csv.Lexer" : "Lexer", + "org.apache.commons.csv.QuoteMode" : "QuoteMode", + "org.apache.commons.csv.Token" : "Token", + "org.apache.commons.csv.Token$Type" : "Token.Type", + "org.apache.commons.io.ByteOrderMark" : "ByteOrderMark", + "org.apache.commons.io.ByteOrderParser" : "ByteOrderParser", + "org.apache.commons.io.Charsets" : "Charsets", + "org.apache.commons.io.CloseableURLConnection" : "CloseableURLConnection", + "org.apache.commons.io.CopyUtils" : "CopyUtils", + "org.apache.commons.io.DirectoryWalker" : "DirectoryWalker", + "org.apache.commons.io.DirectoryWalker$CancelException" : "DirectoryWalker.CancelException", + "org.apache.commons.io.EndianUtils" : "EndianUtils", + "org.apache.commons.io.FileCleaner" : "FileCleaner", + "org.apache.commons.io.FileCleaningTracker" : "FileCleaningTracker", + "org.apache.commons.io.FileCleaningTracker$Reaper" : "FileCleaningTracker.Reaper", + "org.apache.commons.io.FileCleaningTracker$Tracker" : "FileCleaningTracker.Tracker", + "org.apache.commons.io.FileDeleteStrategy" : "FileDeleteStrategy", + "org.apache.commons.io.FileDeleteStrategy$ForceFileDeleteStrategy" : "FileDeleteStrategy.ForceFileDeleteStrategy", + "org.apache.commons.io.FileExistsException" : "FileExistsException", + "org.apache.commons.io.FileSystem" : "FileSystem", + "org.apache.commons.io.FileSystemUtils" : "FileSystemUtils", + "org.apache.commons.io.FileUtils" : "FileUtils", + "org.apache.commons.io.FilenameUtils" : "FilenameUtils", + "org.apache.commons.io.HexDump" : "HexDump", + "org.apache.commons.io.IO" : "IO", + "org.apache.commons.io.IOCase" : "IOCase", + "org.apache.commons.io.IOExceptionList" : "IOExceptionList", + "org.apache.commons.io.IOExceptionWithCause" : "IOExceptionWithCause", + "org.apache.commons.io.IOIndexedException" : "IOIndexedException", + "org.apache.commons.io.IOUtils" : "IOUtils", + "org.apache.commons.io.LineIterator" : "LineIterator", + "org.apache.commons.io.RandomAccessFileMode" : "RandomAccessFileMode", + "org.apache.commons.io.RandomAccessFiles" : "RandomAccessFiles", + "org.apache.commons.io.StandardLineSeparator" : "StandardLineSeparator", + "org.apache.commons.io.StreamIterator" : "StreamIterator", + "org.apache.commons.io.TaggedIOException" : "TaggedIOException", + "org.apache.commons.io.ThreadMonitor" : "ThreadMonitor", + "org.apache.commons.io.ThreadUtils" : "ThreadUtils", + "org.apache.commons.io.UncheckedIOExceptions" : "UncheckedIOExceptions", + "org.apache.commons.io.build.AbstractOrigin" : "AbstractOrigin", + "org.apache.commons.io.build.AbstractOrigin$ByteArrayOrigin" : "AbstractOrigin.ByteArrayOrigin", + "org.apache.commons.io.build.AbstractOrigin$CharSequenceOrigin" : "AbstractOrigin.CharSequenceOrigin", + "org.apache.commons.io.build.AbstractOrigin$FileOrigin" : "AbstractOrigin.FileOrigin", + "org.apache.commons.io.build.AbstractOrigin$InputStreamOrigin" : "AbstractOrigin.InputStreamOrigin", + "org.apache.commons.io.build.AbstractOrigin$OutputStreamOrigin" : "AbstractOrigin.OutputStreamOrigin", + "org.apache.commons.io.build.AbstractOrigin$PathOrigin" : "AbstractOrigin.PathOrigin", + "org.apache.commons.io.build.AbstractOrigin$ReaderOrigin" : "AbstractOrigin.ReaderOrigin", + "org.apache.commons.io.build.AbstractOrigin$URIOrigin" : "AbstractOrigin.URIOrigin", + "org.apache.commons.io.build.AbstractOrigin$WriterOrigin" : "AbstractOrigin.WriterOrigin", + "org.apache.commons.io.build.AbstractOriginSupplier" : "AbstractOriginSupplier", + "org.apache.commons.io.build.AbstractStreamBuilder" : "AbstractStreamBuilder", + "org.apache.commons.io.build.AbstractSupplier" : "AbstractSupplier", + "org.apache.commons.io.channels.FileChannels" : "FileChannels", + "org.apache.commons.io.charset.CharsetDecoders" : "CharsetDecoders", + "org.apache.commons.io.charset.CharsetEncoders" : "CharsetEncoders", + "org.apache.commons.io.comparator.AbstractFileComparator" : "AbstractFileComparator", + "org.apache.commons.io.comparator.CompositeFileComparator" : "CompositeFileComparator", + "org.apache.commons.io.comparator.DefaultFileComparator" : "DefaultFileComparator", + "org.apache.commons.io.comparator.DirectoryFileComparator" : "DirectoryFileComparator", + "org.apache.commons.io.comparator.ExtensionFileComparator" : "ExtensionFileComparator", + "org.apache.commons.io.comparator.LastModifiedFileComparator" : "LastModifiedFileComparator", + "org.apache.commons.io.comparator.NameFileComparator" : "NameFileComparator", + "org.apache.commons.io.comparator.PathFileComparator" : "PathFileComparator", + "org.apache.commons.io.comparator.ReverseFileComparator" : "ReverseFileComparator", + "org.apache.commons.io.comparator.SizeFileComparator" : "SizeFileComparator", + "org.apache.commons.io.file.AccumulatorPathVisitor" : "AccumulatorPathVisitor", + "org.apache.commons.io.file.CleaningPathVisitor" : "CleaningPathVisitor", + "org.apache.commons.io.file.CopyDirectoryVisitor" : "CopyDirectoryVisitor", + "org.apache.commons.io.file.Counters" : "Counters", + "org.apache.commons.io.file.Counters$AbstractPathCounters" : "Counters.AbstractPathCounters", + "org.apache.commons.io.file.Counters$BigIntegerCounter" : "Counters.BigIntegerCounter", + "org.apache.commons.io.file.Counters$BigIntegerPathCounters" : "Counters.BigIntegerPathCounters", + "org.apache.commons.io.file.Counters$Counter" : "Counters.Counter", + "org.apache.commons.io.file.Counters$LongCounter" : "Counters.LongCounter", + "org.apache.commons.io.file.Counters$LongPathCounters" : "Counters.LongPathCounters", + "org.apache.commons.io.file.Counters$NoopCounter" : "Counters.NoopCounter", + "org.apache.commons.io.file.Counters$NoopPathCounters" : "Counters.NoopPathCounters", + "org.apache.commons.io.file.Counters$PathCounters" : "Counters.PathCounters", + "org.apache.commons.io.file.CountingPathVisitor" : "CountingPathVisitor", + "org.apache.commons.io.file.DeleteOption" : "DeleteOption", + "org.apache.commons.io.file.DeletingPathVisitor" : "DeletingPathVisitor", + "org.apache.commons.io.file.DirectoryStreamFilter" : "DirectoryStreamFilter", + "org.apache.commons.io.file.FilesUncheck" : "FilesUncheck", + "org.apache.commons.io.file.NoopPathVisitor" : "NoopPathVisitor", + "org.apache.commons.io.file.PathFilter" : "PathFilter", + "org.apache.commons.io.file.PathUtils" : "PathUtils", + "org.apache.commons.io.file.PathUtils$RelativeSortedPaths" : "PathUtils.RelativeSortedPaths", + "org.apache.commons.io.file.PathVisitor" : "PathVisitor", + "org.apache.commons.io.file.SimplePathVisitor" : "SimplePathVisitor", + "org.apache.commons.io.file.StandardDeleteOption" : "StandardDeleteOption", + "org.apache.commons.io.file.attribute.FileTimes" : "FileTimes", + "org.apache.commons.io.file.spi.FileSystemProviders" : "FileSystemProviders", + "org.apache.commons.io.filefilter.AbstractFileFilter" : "AbstractFileFilter", + "org.apache.commons.io.filefilter.AgeFileFilter" : "AgeFileFilter", + "org.apache.commons.io.filefilter.AndFileFilter" : "AndFileFilter", + "org.apache.commons.io.filefilter.CanExecuteFileFilter" : "CanExecuteFileFilter", + "org.apache.commons.io.filefilter.CanReadFileFilter" : "CanReadFileFilter", + "org.apache.commons.io.filefilter.CanWriteFileFilter" : "CanWriteFileFilter", + "org.apache.commons.io.filefilter.ConditionalFileFilter" : "ConditionalFileFilter", + "org.apache.commons.io.filefilter.DelegateFileFilter" : "DelegateFileFilter", + "org.apache.commons.io.filefilter.DirectoryFileFilter" : "DirectoryFileFilter", + "org.apache.commons.io.filefilter.EmptyFileFilter" : "EmptyFileFilter", + "org.apache.commons.io.filefilter.FalseFileFilter" : "FalseFileFilter", + "org.apache.commons.io.filefilter.FileEqualsFileFilter" : "FileEqualsFileFilter", + "org.apache.commons.io.filefilter.FileFileFilter" : "FileFileFilter", + "org.apache.commons.io.filefilter.FileFilterUtils" : "FileFilterUtils", + "org.apache.commons.io.filefilter.HiddenFileFilter" : "HiddenFileFilter", + "org.apache.commons.io.filefilter.IOFileFilter" : "IOFileFilter", + "org.apache.commons.io.filefilter.MagicNumberFileFilter" : "MagicNumberFileFilter", + "org.apache.commons.io.filefilter.NameFileFilter" : "NameFileFilter", + "org.apache.commons.io.filefilter.NotFileFilter" : "NotFileFilter", + "org.apache.commons.io.filefilter.OrFileFilter" : "OrFileFilter", + "org.apache.commons.io.filefilter.PathEqualsFileFilter" : "PathEqualsFileFilter", + "org.apache.commons.io.filefilter.PathMatcherFileFilter" : "PathMatcherFileFilter", + "org.apache.commons.io.filefilter.PathVisitorFileFilter" : "PathVisitorFileFilter", + "org.apache.commons.io.filefilter.PrefixFileFilter" : "PrefixFileFilter", + "org.apache.commons.io.filefilter.RegexFileFilter" : "RegexFileFilter", + "org.apache.commons.io.filefilter.SizeFileFilter" : "SizeFileFilter", + "org.apache.commons.io.filefilter.SuffixFileFilter" : "SuffixFileFilter", + "org.apache.commons.io.filefilter.SymbolicLinkFileFilter" : "SymbolicLinkFileFilter", + "org.apache.commons.io.filefilter.TrueFileFilter" : "TrueFileFilter", + "org.apache.commons.io.filefilter.WildcardFileFilter" : "WildcardFileFilter", + "org.apache.commons.io.filefilter.WildcardFileFilter$Builder" : "WildcardFileFilter.Builder", + "org.apache.commons.io.filefilter.WildcardFilter" : "WildcardFilter", + "org.apache.commons.io.function.Constants" : "Constants", + "org.apache.commons.io.function.Erase" : "Erase", + "org.apache.commons.io.function.IOBaseStream" : "IOBaseStream", + "org.apache.commons.io.function.IOBaseStreamAdapter" : "IOBaseStreamAdapter", + "org.apache.commons.io.function.IOBiConsumer" : "IOBiConsumer", + "org.apache.commons.io.function.IOBiFunction" : "IOBiFunction", + "org.apache.commons.io.function.IOBinaryOperator" : "IOBinaryOperator", + "org.apache.commons.io.function.IOComparator" : "IOComparator", + "org.apache.commons.io.function.IOConsumer" : "IOConsumer", + "org.apache.commons.io.function.IOFunction" : "IOFunction", + "org.apache.commons.io.function.IOIntSupplier" : "IOIntSupplier", + "org.apache.commons.io.function.IOIterator" : "IOIterator", + "org.apache.commons.io.function.IOIteratorAdapter" : "IOIteratorAdapter", + "org.apache.commons.io.function.IOLongSupplier" : "IOLongSupplier", + "org.apache.commons.io.function.IOPredicate" : "IOPredicate", + "org.apache.commons.io.function.IOQuadFunction" : "IOQuadFunction", + "org.apache.commons.io.function.IORunnable" : "IORunnable", + "org.apache.commons.io.function.IOSpliterator" : "IOSpliterator", + "org.apache.commons.io.function.IOSpliteratorAdapter" : "IOSpliteratorAdapter", + "org.apache.commons.io.function.IOStream" : "IOStream", + "org.apache.commons.io.function.IOStreamAdapter" : "IOStreamAdapter", + "org.apache.commons.io.function.IOStreams" : "IOStreams", + "org.apache.commons.io.function.IOSupplier" : "IOSupplier", + "org.apache.commons.io.function.IOTriConsumer" : "IOTriConsumer", + "org.apache.commons.io.function.IOTriFunction" : "IOTriFunction", + "org.apache.commons.io.function.IOUnaryOperator" : "IOUnaryOperator", + "org.apache.commons.io.function.Uncheck" : "Uncheck", + "org.apache.commons.io.function.UncheckedIOBaseStream" : "UncheckedIOBaseStream", + "org.apache.commons.io.function.UncheckedIOIterator" : "UncheckedIOIterator", + "org.apache.commons.io.function.UncheckedIOSpliterator" : "UncheckedIOSpliterator", + "org.apache.commons.io.input.AbstractCharacterFilterReader" : "AbstractCharacterFilterReader", + "org.apache.commons.io.input.AbstractInputStream" : "AbstractInputStream", + "org.apache.commons.io.input.AutoCloseInputStream" : "AutoCloseInputStream", + "org.apache.commons.io.input.AutoCloseInputStream$Builder" : "AutoCloseInputStream.Builder", + "org.apache.commons.io.input.BOMInputStream" : "BOMInputStream", + "org.apache.commons.io.input.BOMInputStream$Builder" : "BOMInputStream.Builder", + "org.apache.commons.io.input.BoundedInputStream" : "BoundedInputStream", + "org.apache.commons.io.input.BoundedInputStream$AbstractBuilder" : "BoundedInputStream.AbstractBuilder", + "org.apache.commons.io.input.BoundedInputStream$Builder" : "BoundedInputStream.Builder", + "org.apache.commons.io.input.BoundedReader" : "BoundedReader", + "org.apache.commons.io.input.BrokenInputStream" : "BrokenInputStream", + "org.apache.commons.io.input.BrokenReader" : "BrokenReader", + "org.apache.commons.io.input.BufferedFileChannelInputStream" : "BufferedFileChannelInputStream", + "org.apache.commons.io.input.BufferedFileChannelInputStream$Builder" : "BufferedFileChannelInputStream.Builder", + "org.apache.commons.io.input.ByteBufferCleaner" : "ByteBufferCleaner", + "org.apache.commons.io.input.ByteBufferCleaner$Cleaner" : "ByteBufferCleaner.Cleaner", + "org.apache.commons.io.input.ByteBufferCleaner$Java8Cleaner" : "ByteBufferCleaner.Java8Cleaner", + "org.apache.commons.io.input.ByteBufferCleaner$Java9Cleaner" : "ByteBufferCleaner.Java9Cleaner", + "org.apache.commons.io.input.CharSequenceInputStream" : "CharSequenceInputStream", + "org.apache.commons.io.input.CharSequenceInputStream$Builder" : "CharSequenceInputStream.Builder", + "org.apache.commons.io.input.CharSequenceReader" : "CharSequenceReader", + "org.apache.commons.io.input.CharacterFilterReader" : "CharacterFilterReader", + "org.apache.commons.io.input.CharacterSetFilterReader" : "CharacterSetFilterReader", + "org.apache.commons.io.input.ChecksumInputStream" : "ChecksumInputStream", + "org.apache.commons.io.input.ChecksumInputStream$Builder" : "ChecksumInputStream.Builder", + "org.apache.commons.io.input.CircularInputStream" : "CircularInputStream", + "org.apache.commons.io.input.ClassLoaderObjectInputStream" : "ClassLoaderObjectInputStream", + "org.apache.commons.io.input.CloseShieldInputStream" : "CloseShieldInputStream", + "org.apache.commons.io.input.CloseShieldReader" : "CloseShieldReader", + "org.apache.commons.io.input.ClosedInputStream" : "ClosedInputStream", + "org.apache.commons.io.input.ClosedReader" : "ClosedReader", + "org.apache.commons.io.input.CountingInputStream" : "CountingInputStream", + "org.apache.commons.io.input.DemuxInputStream" : "DemuxInputStream", + "org.apache.commons.io.input.InfiniteCircularInputStream" : "InfiniteCircularInputStream", + "org.apache.commons.io.input.Input" : "Input", + "org.apache.commons.io.input.MarkShieldInputStream" : "MarkShieldInputStream", + "org.apache.commons.io.input.MemoryMappedFileInputStream" : "MemoryMappedFileInputStream", + "org.apache.commons.io.input.MemoryMappedFileInputStream$Builder" : "MemoryMappedFileInputStream.Builder", + "org.apache.commons.io.input.MessageDigestCalculatingInputStream" : "MessageDigestCalculatingInputStream", + "org.apache.commons.io.input.MessageDigestCalculatingInputStream$Builder" : "MessageDigestCalculatingInputStream.Builder", + "org.apache.commons.io.input.MessageDigestCalculatingInputStream$MessageDigestMaintainingObserver" : "MessageDigestCalculatingInputStream.MessageDigestMaintainingObserver", + "org.apache.commons.io.input.MessageDigestInputStream" : "MessageDigestInputStream", + "org.apache.commons.io.input.MessageDigestInputStream$Builder" : "MessageDigestInputStream.Builder", + "org.apache.commons.io.input.MessageDigestInputStream$MessageDigestMaintainingObserver" : "MessageDigestInputStream.MessageDigestMaintainingObserver", + "org.apache.commons.io.input.NullInputStream" : "NullInputStream", + "org.apache.commons.io.input.NullReader" : "NullReader", + "org.apache.commons.io.input.ObservableInputStream" : "ObservableInputStream", + "org.apache.commons.io.input.ObservableInputStream$Observer" : "ObservableInputStream.Observer", + "org.apache.commons.io.input.ProxyInputStream" : "ProxyInputStream", + "org.apache.commons.io.input.ProxyReader" : "ProxyReader", + "org.apache.commons.io.input.QueueInputStream" : "QueueInputStream", + "org.apache.commons.io.input.QueueInputStream$Builder" : "QueueInputStream.Builder", + "org.apache.commons.io.input.RandomAccessFileInputStream" : "RandomAccessFileInputStream", + "org.apache.commons.io.input.RandomAccessFileInputStream$Builder" : "RandomAccessFileInputStream.Builder", + "org.apache.commons.io.input.ReadAheadInputStream" : "ReadAheadInputStream", + "org.apache.commons.io.input.ReadAheadInputStream$Builder" : "ReadAheadInputStream.Builder", + "org.apache.commons.io.input.ReaderInputStream" : "ReaderInputStream", + "org.apache.commons.io.input.ReaderInputStream$Builder" : "ReaderInputStream.Builder", + "org.apache.commons.io.input.ReversedLinesFileReader" : "ReversedLinesFileReader", + "org.apache.commons.io.input.ReversedLinesFileReader$Builder" : "ReversedLinesFileReader.Builder", + "org.apache.commons.io.input.ReversedLinesFileReader$FilePart" : "ReversedLinesFileReader.FilePart", + "org.apache.commons.io.input.SequenceReader" : "SequenceReader", + "org.apache.commons.io.input.SwappedDataInputStream" : "SwappedDataInputStream", + "org.apache.commons.io.input.TaggedInputStream" : "TaggedInputStream", + "org.apache.commons.io.input.TaggedReader" : "TaggedReader", + "org.apache.commons.io.input.Tailer" : "Tailer", + "org.apache.commons.io.input.Tailer$Builder" : "Tailer.Builder", + "org.apache.commons.io.input.Tailer$RandomAccessFileBridge" : "Tailer.RandomAccessFileBridge", + "org.apache.commons.io.input.Tailer$RandomAccessResourceBridge" : "Tailer.RandomAccessResourceBridge", + "org.apache.commons.io.input.Tailer$Tailable" : "Tailer.Tailable", + "org.apache.commons.io.input.Tailer$TailablePath" : "Tailer.TailablePath", + "org.apache.commons.io.input.TailerListener" : "TailerListener", + "org.apache.commons.io.input.TailerListenerAdapter" : "TailerListenerAdapter", + "org.apache.commons.io.input.TeeInputStream" : "TeeInputStream", + "org.apache.commons.io.input.TeeReader" : "TeeReader", + "org.apache.commons.io.input.ThrottledInputStream" : "ThrottledInputStream", + "org.apache.commons.io.input.ThrottledInputStream$Builder" : "ThrottledInputStream.Builder", + "org.apache.commons.io.input.TimestampedObserver" : "TimestampedObserver", + "org.apache.commons.io.input.UncheckedBufferedReader" : "UncheckedBufferedReader", + "org.apache.commons.io.input.UncheckedBufferedReader$Builder" : "UncheckedBufferedReader.Builder", + "org.apache.commons.io.input.UncheckedFilterInputStream" : "UncheckedFilterInputStream", + "org.apache.commons.io.input.UncheckedFilterInputStream$Builder" : "UncheckedFilterInputStream.Builder", + "org.apache.commons.io.input.UncheckedFilterReader" : "UncheckedFilterReader", + "org.apache.commons.io.input.UncheckedFilterReader$Builder" : "UncheckedFilterReader.Builder", + "org.apache.commons.io.input.UnixLineEndingInputStream" : "UnixLineEndingInputStream", + "org.apache.commons.io.input.UnsupportedOperationExceptions" : "UnsupportedOperationExceptions", + "org.apache.commons.io.input.UnsynchronizedBufferedInputStream" : "UnsynchronizedBufferedInputStream", + "org.apache.commons.io.input.UnsynchronizedBufferedInputStream$Builder" : "UnsynchronizedBufferedInputStream.Builder", + "org.apache.commons.io.input.UnsynchronizedBufferedReader" : "UnsynchronizedBufferedReader", + "org.apache.commons.io.input.UnsynchronizedByteArrayInputStream" : "UnsynchronizedByteArrayInputStream", + "org.apache.commons.io.input.UnsynchronizedByteArrayInputStream$Builder" : "UnsynchronizedByteArrayInputStream.Builder", + "org.apache.commons.io.input.UnsynchronizedFilterInputStream" : "UnsynchronizedFilterInputStream", + "org.apache.commons.io.input.UnsynchronizedFilterInputStream$Builder" : "UnsynchronizedFilterInputStream.Builder", + "org.apache.commons.io.input.UnsynchronizedReader" : "UnsynchronizedReader", + "org.apache.commons.io.input.WindowsLineEndingInputStream" : "WindowsLineEndingInputStream", + "org.apache.commons.io.input.XmlStreamReader" : "XmlStreamReader", + "org.apache.commons.io.input.XmlStreamReader$Builder" : "XmlStreamReader.Builder", + "org.apache.commons.io.input.XmlStreamReaderException" : "XmlStreamReaderException", + "org.apache.commons.io.input.buffer.CircularBufferInputStream" : "CircularBufferInputStream", + "org.apache.commons.io.input.buffer.CircularByteBuffer" : "CircularByteBuffer", + "org.apache.commons.io.input.buffer.PeekableInputStream" : "PeekableInputStream", + "org.apache.commons.io.monitor.FileAlterationListener" : "FileAlterationListener", + "org.apache.commons.io.monitor.FileAlterationListenerAdaptor" : "FileAlterationListenerAdaptor", + "org.apache.commons.io.monitor.FileAlterationMonitor" : "FileAlterationMonitor", + "org.apache.commons.io.monitor.FileAlterationObserver" : "FileAlterationObserver", + "org.apache.commons.io.monitor.FileEntry" : "FileEntry", + "org.apache.commons.io.monitor.SerializableFileTime" : "SerializableFileTime", + "org.apache.commons.io.output.AbstractByteArrayOutputStream" : "AbstractByteArrayOutputStream", + "org.apache.commons.io.output.AbstractByteArrayOutputStream$InputStreamConstructor" : "AbstractByteArrayOutputStream.InputStreamConstructor", + "org.apache.commons.io.output.AppendableOutputStream" : "AppendableOutputStream", + "org.apache.commons.io.output.AppendableWriter" : "AppendableWriter", + "org.apache.commons.io.output.BrokenOutputStream" : "BrokenOutputStream", + "org.apache.commons.io.output.BrokenWriter" : "BrokenWriter", + "org.apache.commons.io.output.ByteArrayOutputStream" : "ByteArrayOutputStream", + "org.apache.commons.io.output.ChunkedOutputStream" : "ChunkedOutputStream", + "org.apache.commons.io.output.ChunkedOutputStream$Builder" : "ChunkedOutputStream.Builder", + "org.apache.commons.io.output.ChunkedWriter" : "ChunkedWriter", + "org.apache.commons.io.output.CloseShieldOutputStream" : "CloseShieldOutputStream", + "org.apache.commons.io.output.CloseShieldWriter" : "CloseShieldWriter", + "org.apache.commons.io.output.ClosedOutputStream" : "ClosedOutputStream", + "org.apache.commons.io.output.ClosedWriter" : "ClosedWriter", + "org.apache.commons.io.output.CountingOutputStream" : "CountingOutputStream", + "org.apache.commons.io.output.DeferredFileOutputStream" : "DeferredFileOutputStream", + "org.apache.commons.io.output.DeferredFileOutputStream$Builder" : "DeferredFileOutputStream.Builder", + "org.apache.commons.io.output.DemuxOutputStream" : "DemuxOutputStream", + "org.apache.commons.io.output.FileWriterWithEncoding" : "FileWriterWithEncoding", + "org.apache.commons.io.output.FileWriterWithEncoding$Builder" : "FileWriterWithEncoding.Builder", + "org.apache.commons.io.output.FilterCollectionWriter" : "FilterCollectionWriter", + "org.apache.commons.io.output.LockableFileWriter" : "LockableFileWriter", + "org.apache.commons.io.output.LockableFileWriter$Builder" : "LockableFileWriter.Builder", + "org.apache.commons.io.output.NullAppendable" : "NullAppendable", + "org.apache.commons.io.output.NullOutputStream" : "NullOutputStream", + "org.apache.commons.io.output.NullPrintStream" : "NullPrintStream", + "org.apache.commons.io.output.NullWriter" : "NullWriter", + "org.apache.commons.io.output.ProxyCollectionWriter" : "ProxyCollectionWriter", + "org.apache.commons.io.output.ProxyOutputStream" : "ProxyOutputStream", + "org.apache.commons.io.output.ProxyWriter" : "ProxyWriter", + "org.apache.commons.io.output.QueueOutputStream" : "QueueOutputStream", + "org.apache.commons.io.output.StringBuilderWriter" : "StringBuilderWriter", + "org.apache.commons.io.output.TaggedOutputStream" : "TaggedOutputStream", + "org.apache.commons.io.output.TaggedWriter" : "TaggedWriter", + "org.apache.commons.io.output.TeeOutputStream" : "TeeOutputStream", + "org.apache.commons.io.output.TeeWriter" : "TeeWriter", + "org.apache.commons.io.output.ThresholdingOutputStream" : "ThresholdingOutputStream", + "org.apache.commons.io.output.UncheckedAppendable" : "UncheckedAppendable", + "org.apache.commons.io.output.UncheckedAppendableImpl" : "UncheckedAppendableImpl", + "org.apache.commons.io.output.UncheckedFilterOutputStream" : "UncheckedFilterOutputStream", + "org.apache.commons.io.output.UncheckedFilterOutputStream$Builder" : "UncheckedFilterOutputStream.Builder", + "org.apache.commons.io.output.UncheckedFilterWriter" : "UncheckedFilterWriter", + "org.apache.commons.io.output.UncheckedFilterWriter$Builder" : "UncheckedFilterWriter.Builder", + "org.apache.commons.io.output.UnsynchronizedByteArrayOutputStream" : "UnsynchronizedByteArrayOutputStream", + "org.apache.commons.io.output.UnsynchronizedByteArrayOutputStream$Builder" : "UnsynchronizedByteArrayOutputStream.Builder", + "org.apache.commons.io.output.WriterOutputStream" : "WriterOutputStream", + "org.apache.commons.io.output.WriterOutputStream$Builder" : "WriterOutputStream.Builder", + "org.apache.commons.io.output.XmlStreamWriter" : "XmlStreamWriter", + "org.apache.commons.io.output.XmlStreamWriter$Builder" : "XmlStreamWriter.Builder", + "org.apache.commons.io.serialization.ClassNameMatcher" : "ClassNameMatcher", + "org.apache.commons.io.serialization.FullClassNameMatcher" : "FullClassNameMatcher", + "org.apache.commons.io.serialization.RegexpClassNameMatcher" : "RegexpClassNameMatcher", + "org.apache.commons.io.serialization.ValidatingObjectInputStream" : "ValidatingObjectInputStream", + "org.apache.commons.io.serialization.WildcardClassNameMatcher" : "WildcardClassNameMatcher" + }, + "classpath" : "\/Users\/ktoso\/code\/swift-java\/Samples\/JavaDependencySampleApp\/.build\/swift-java-dependencies-C358EF3D-93BF-4D44-9523-80865DF0B59D\/build\/classes\/java\/main:\/Users\/ktoso\/code\/swift-java\/Samples\/JavaDependencySampleApp\/.build\/swift-java-dependencies-C358EF3D-93BF-4D44-9523-80865DF0B59D\/build\/resources\/main:\/Users\/ktoso\/.gradle\/caches\/modules-2\/files-2.1\/org.apache.commons\/commons-csv\/1.12.0\/c77e053d7189bc0857f8d323ab61cb949965fbd1\/commons-csv-1.12.0.jar:\/Users\/ktoso\/.gradle\/caches\/modules-2\/files-2.1\/commons-io\/commons-io\/2.17.0\/ddcc8433eb019fb48fe25207c0278143f3e1d7e2\/commons-io-2.17.0.jar:\/Users\/ktoso\/.gradle\/caches\/modules-2\/files-2.1\/commons-codec\/commons-codec\/1.17.1\/973638b7149d333563584137ebf13a691bb60579\/commons-codec-1.17.1.jar:\/Users\/ktoso\/code\/swift-java\/Samples\/JavaDependencySampleApp\/.build\/swift-java-dependencies-C358EF3D-93BF-4D44-9523-80865DF0B59D\/build\/classes\/java\/main:\/Users\/ktoso\/code\/swift-java\/Samples\/JavaDependencySampleApp\/.build\/swift-java-dependencies-C358EF3D-93BF-4D44-9523-80865DF0B59D\/build\/resources\/main:\/Users\/ktoso\/.gradle\/caches\/modules-2\/files-2.1\/org.apache.commons\/commons-csv\/1.12.0\/c77e053d7189bc0857f8d323ab61cb949965fbd1\/commons-csv-1.12.0.jar:\/Users\/ktoso\/.gradle\/caches\/modules-2\/files-2.1\/commons-io\/commons-io\/2.17.0\/ddcc8433eb019fb48fe25207c0278143f3e1d7e2\/commons-io-2.17.0.jar:\/Users\/ktoso\/.gradle\/caches\/modules-2\/files-2.1\/commons-codec\/commons-codec\/1.17.1\/973638b7149d333563584137ebf13a691bb60579\/commons-codec-1.17.1.jar:test.jar:\/Users\/ktoso\/code\/swift-java\/Samples\/JavaDependencySampleApp\/.build\/swift-java-dependencies-C358EF3D-93BF-4D44-9523-80865DF0B59D\/build\/classes\/java\/main:\/Users\/ktoso\/code\/swift-java\/Samples\/JavaDependencySampleApp\/.build\/swift-java-dependencies-C358EF3D-93BF-4D44-9523-80865DF0B59D\/build\/resources\/main:\/Users\/ktoso\/.gradle\/caches\/modules-2\/files-2.1\/org.apache.commons\/commons-csv\/1.12.0\/c77e053d7189bc0857f8d323ab61cb949965fbd1\/commons-csv-1.12.0.jar:\/Users\/ktoso\/.gradle\/caches\/modules-2\/files-2.1\/commons-io\/commons-io\/2.17.0\/ddcc8433eb019fb48fe25207c0278143f3e1d7e2\/commons-io-2.17.0.jar:\/Users\/ktoso\/.gradle\/caches\/modules-2\/files-2.1\/commons-codec\/commons-codec\/1.17.1\/973638b7149d333563584137ebf13a691bb60579\/commons-codec-1.17.1.jar:\/Users\/ktoso\/code\/swift-java\/Samples\/JavaDependencySampleApp\/.build\/swift-java-dependencies-C358EF3D-93BF-4D44-9523-80865DF0B59D\/build\/classes\/java\/main:\/Users\/ktoso\/code\/swift-java\/Samples\/JavaDependencySampleApp\/.build\/swift-java-dependencies-C358EF3D-93BF-4D44-9523-80865DF0B59D\/build\/resources\/main:\/Users\/ktoso\/.gradle\/caches\/modules-2\/files-2.1\/org.apache.commons\/commons-csv\/1.12.0\/c77e053d7189bc0857f8d323ab61cb949965fbd1\/commons-csv-1.12.0.jar:\/Users\/ktoso\/.gradle\/caches\/modules-2\/files-2.1\/commons-io\/commons-io\/2.17.0\/ddcc8433eb019fb48fe25207c0278143f3e1d7e2\/commons-io-2.17.0.jar:\/Users\/ktoso\/.gradle\/caches\/modules-2\/files-2.1\/commons-codec\/commons-codec\/1.17.1\/973638b7149d333563584137ebf13a691bb60579\/commons-codec-1.17.1.jar:test.jar:\/Users\/ktoso\/code\/swift-java\/Samples\/JavaDependencySampleApp\/.build\/swift-java-dependencies-C358EF3D-93BF-4D44-9523-80865DF0B59D\/build\/classes\/java\/main:\/Users\/ktoso\/code\/swift-java\/Samples\/JavaDependencySampleApp\/.build\/swift-java-dependencies-C358EF3D-93BF-4D44-9523-80865DF0B59D\/build\/resources\/main:\/Users\/ktoso\/.gradle\/caches\/modules-2\/files-2.1\/org.apache.commons\/commons-csv\/1.12.0\/c77e053d7189bc0857f8d323ab61cb949965fbd1\/commons-csv-1.12.0.jar:\/Users\/ktoso\/.gradle\/caches\/modules-2\/files-2.1\/commons-io\/commons-io\/2.17.0\/ddcc8433eb019fb48fe25207c0278143f3e1d7e2\/commons-io-2.17.0.jar:\/Users\/ktoso\/.gradle\/caches\/modules-2\/files-2.1\/commons-codec\/commons-codec\/1.17.1\/973638b7149d333563584137ebf13a691bb60579\/commons-codec-1.17.1.jar:\/Users\/ktoso\/code\/swift-java\/Samples\/JavaDependencySampleApp\/.build\/swift-java-dependencies-C358EF3D-93BF-4D44-9523-80865DF0B59D\/build\/classes\/java\/main:\/Users\/ktoso\/code\/swift-java\/Samples\/JavaDependencySampleApp\/.build\/swift-java-dependencies-C358EF3D-93BF-4D44-9523-80865DF0B59D\/build\/resources\/main:\/Users\/ktoso\/.gradle\/caches\/modules-2\/files-2.1\/org.apache.commons\/commons-csv\/1.12.0\/c77e053d7189bc0857f8d323ab61cb949965fbd1\/commons-csv-1.12.0.jar:\/Users\/ktoso\/.gradle\/caches\/modules-2\/files-2.1\/commons-io\/commons-io\/2.17.0\/ddcc8433eb019fb48fe25207c0278143f3e1d7e2\/commons-io-2.17.0.jar:\/Users\/ktoso\/.gradle\/caches\/modules-2\/files-2.1\/commons-codec\/commons-codec\/1.17.1\/973638b7149d333563584137ebf13a691bb60579\/commons-codec-1.17.1.jar:test.jar:\/Users\/ktoso\/code\/swift-java\/Samples\/JavaDependencySampleApp\/.build\/swift-java-dependencies-C358EF3D-93BF-4D44-9523-80865DF0B59D\/build\/classes\/java\/main:\/Users\/ktoso\/code\/swift-java\/Samples\/JavaDependencySampleApp\/.build\/swift-java-dependencies-C358EF3D-93BF-4D44-9523-80865DF0B59D\/build\/resources\/main:\/Users\/ktoso\/.gradle\/caches\/modules-2\/files-2.1\/org.apache.commons\/commons-csv\/1.12.0\/c77e053d7189bc0857f8d323ab61cb949965fbd1\/commons-csv-1.12.0.jar:\/Users\/ktoso\/.gradle\/caches\/modules-2\/files-2.1\/commons-io\/commons-io\/2.17.0\/ddcc8433eb019fb48fe25207c0278143f3e1d7e2\/commons-io-2.17.0.jar:\/Users\/ktoso\/.gradle\/caches\/modules-2\/files-2.1\/commons-codec\/commons-codec\/1.17.1\/973638b7149d333563584137ebf13a691bb60579\/commons-codec-1.17.1.jar:\/Users\/ktoso\/code\/swift-java\/Samples\/JavaDependencySampleApp\/.build\/swift-java-dependencies-C358EF3D-93BF-4D44-9523-80865DF0B59D\/build\/classes\/java\/main:\/Users\/ktoso\/code\/swift-java\/Samples\/JavaDependencySampleApp\/.build\/swift-java-dependencies-C358EF3D-93BF-4D44-9523-80865DF0B59D\/build\/resources\/main:\/Users\/ktoso\/.gradle\/caches\/modules-2\/files-2.1\/org.apache.commons\/commons-csv\/1.12.0\/c77e053d7189bc0857f8d323ab61cb949965fbd1\/commons-csv-1.12.0.jar:\/Users\/ktoso\/.gradle\/caches\/modules-2\/files-2.1\/commons-io\/commons-io\/2.17.0\/ddcc8433eb019fb48fe25207c0278143f3e1d7e2\/commons-io-2.17.0.jar:\/Users\/ktoso\/.gradle\/caches\/modules-2\/files-2.1\/commons-codec\/commons-codec\/1.17.1\/973638b7149d333563584137ebf13a691bb60579\/commons-codec-1.17.1.jar:test.jar:\/Users\/ktoso\/code\/swift-java\/Samples\/JavaDependencySampleApp\/.build\/swift-java-dependencies-C358EF3D-93BF-4D44-9523-80865DF0B59D\/build\/classes\/java\/main:\/Users\/ktoso\/code\/swift-java\/Samples\/JavaDependencySampleApp\/.build\/swift-java-dependencies-C358EF3D-93BF-4D44-9523-80865DF0B59D\/build\/resources\/main:\/Users\/ktoso\/.gradle\/caches\/modules-2\/files-2.1\/org.apache.commons\/commons-csv\/1.12.0\/c77e053d7189bc0857f8d323ab61cb949965fbd1\/commons-csv-1.12.0.jar:\/Users\/ktoso\/.gradle\/caches\/modules-2\/files-2.1\/commons-io\/commons-io\/2.17.0\/ddcc8433eb019fb48fe25207c0278143f3e1d7e2\/commons-io-2.17.0.jar:\/Users\/ktoso\/.gradle\/caches\/modules-2\/files-2.1\/commons-codec\/commons-codec\/1.17.1\/973638b7149d333563584137ebf13a691bb60579\/commons-codec-1.17.1.jar:\/Users\/ktoso\/code\/swift-java\/Samples\/JavaDependencySampleApp\/.build\/swift-java-dependencies-C358EF3D-93BF-4D44-9523-80865DF0B59D\/build\/classes\/java\/main:\/Users\/ktoso\/code\/swift-java\/Samples\/JavaDependencySampleApp\/.build\/swift-java-dependencies-C358EF3D-93BF-4D44-9523-80865DF0B59D\/build\/resources\/main:\/Users\/ktoso\/.gradle\/caches\/modules-2\/files-2.1\/org.apache.commons\/commons-csv\/1.12.0\/c77e053d7189bc0857f8d323ab61cb949965fbd1\/commons-csv-1.12.0.jar:\/Users\/ktoso\/.gradle\/caches\/modules-2\/files-2.1\/commons-io\/commons-io\/2.17.0\/ddcc8433eb019fb48fe25207c0278143f3e1d7e2\/commons-io-2.17.0.jar:\/Users\/ktoso\/.gradle\/caches\/modules-2\/files-2.1\/commons-codec\/commons-codec\/1.17.1\/973638b7149d333563584137ebf13a691bb60579\/commons-codec-1.17.1.jar:test.jar:test.jar:test.jar:test.jar:test.jar:test.jar:configure:test.jar:configure" +} diff --git a/Samples/JavaSieve/Package.swift b/Samples/JavaSieve/Package.swift index cd65f82e..65c10481 100644 --- a/Samples/JavaSieve/Package.swift +++ b/Samples/JavaSieve/Package.swift @@ -54,6 +54,7 @@ let package = Package( .product(name: "JavaKit", package: "swift-java"), .product(name: "JavaKitJar", package: "swift-java"), ], + exclude: ["swift-java.config"], swiftSettings: [ .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) ], @@ -71,6 +72,7 @@ let package = Package( .product(name: "JavaKit", package: "swift-java"), .product(name: "JavaKitCollection", package: "swift-java"), ], + exclude: ["swift-java.config"], swiftSettings: [ .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) ], diff --git a/Samples/JavaSieve/Sources/JavaSieve/main.swift b/Samples/JavaSieve/Sources/JavaSieve/main.swift index e2047713..feec792d 100644 --- a/Samples/JavaSieve/Sources/JavaSieve/main.swift +++ b/Samples/JavaSieve/Sources/JavaSieve/main.swift @@ -15,10 +15,7 @@ import JavaKit import JavaMath -let jvm = try JavaVirtualMachine.shared(classpath: [ - "quadratic-sieve-Java/build/libs/QuadraticSieve-1.0.jar", - ".", -]) +let jvm = try JavaVirtualMachine.shared() do { let sieveClass = try JavaClass(environment: jvm.environment()) @@ -26,7 +23,7 @@ do { print("Found prime: \(prime.intValue())") } - try JavaClass().HALF_UP + _ = try JavaClass().HALF_UP // can import a Java enum value } catch { print("Failure: \(error)") } diff --git a/Samples/JavaSieve/Sources/JavaSieve/swift-java.config b/Samples/JavaSieve/Sources/JavaSieve/swift-java.config index 7e055d1c..40d01d4b 100644 --- a/Samples/JavaSieve/Sources/JavaSieve/swift-java.config +++ b/Samples/JavaSieve/Sources/JavaSieve/swift-java.config @@ -29,3 +29,4 @@ "com.gazman.quadratic_sieve.wheel.Wheel" : "Wheel" } } + diff --git a/Sources/JavaKitConfigurationShared/Configuration.swift b/Sources/JavaKitConfigurationShared/Configuration.swift index 2314a1b8..2298b9fa 100644 --- a/Sources/JavaKitConfigurationShared/Configuration.swift +++ b/Sources/JavaKitConfigurationShared/Configuration.swift @@ -137,13 +137,13 @@ public func readConfiguration(configPath: URL, file: String = #fileID, line: UIn } } -public func findSwiftJavaClasspaths(moduleName: String) -> [String] { +public func findSwiftJavaClasspaths(swiftModule: String) -> [String] { let basePath: String = FileManager.default.currentDirectoryPath let pluginOutputsDir = URL(fileURLWithPath: basePath) .appendingPathComponent(".build", isDirectory: true) .appendingPathComponent("plugins", isDirectory: true) .appendingPathComponent("outputs", isDirectory: true) - .appendingPathComponent(moduleName, isDirectory: true) + .appendingPathComponent(swiftModule, isDirectory: true) return findSwiftJavaClasspaths(in: pluginOutputsDir.path) } diff --git a/Sources/SwiftJavaTool/Commands/ConfigureCommand.swift b/Sources/SwiftJavaTool/Commands/ConfigureCommand.swift new file mode 100644 index 00000000..8574888d --- /dev/null +++ b/Sources/SwiftJavaTool/Commands/ConfigureCommand.swift @@ -0,0 +1,238 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import ArgumentParser +import Foundation +import SwiftJavaLib +import JExtractSwiftLib +import JavaKit +import JavaKitJar +import JavaKitNetwork +import JavaKitReflection +import SwiftSyntax +import SwiftSyntaxBuilder +import JavaKitConfigurationShared +import JavaKitShared + +extension SwiftJava { + struct ConfigureCommand: SwiftJavaBaseAsyncParsableCommand, HasCommonOptions, HasCommonJVMOptions { + static let configuration = CommandConfiguration( + commandName: "configure", + abstract: "Configure and emit a swift-java.config file based on an input dependency or jar file") + + @OptionGroup var commonOptions: SwiftJava.CommonOptions + @OptionGroup var commonJVMOptions: SwiftJava.CommonJVMOptions + + // TODO: This should be a "make wrappers" option that just detects when we give it a jar + @Flag( + help: "Specifies that the input is a *.jar file whose public classes will be loaded. The output of swift-java will be a configuration file (swift-java.config) that can be used as input to a subsequent swift-java invocation to generate wrappers for those public classes." + ) + var jar: Bool = false + + @Option( + name: .long, + help: "How to handle an existing swift-java.config; by default 'overwrite' by can be changed to amending a configuration" + ) + var existingConfigFile: ExistingConfigFileMode = .overwrite + enum ExistingConfigFileMode: String, ExpressibleByArgument, Codable { + case overwrite + case amend + } + + @Option(help: "The name of the Swift module into which the resulting Swift types will be generated.") + var swiftModule: String + + var effectiveSwiftModule: String { + swiftModule + } + + @Argument( + help: "The input file, which is either a swift-java configuration file or (if '-jar' was specified) a Jar file." + ) + var input: String? + } +} + +extension SwiftJava.ConfigureCommand { + mutating func runSwiftJavaCommand(config: inout Configuration) async throws { + // Form a class path from all of our input sources: + // * Command-line option --classpath + let classpathOptionEntries: [String] = self.commonJVMOptions.classpath.flatMap { $0.split(separator: ":").map(String.init) } + let classpathFromEnv = ProcessInfo.processInfo.environment["CLASSPATH"]?.split(separator: ":").map(String.init) ?? [] + let classpathFromConfig: [String] = config.classpath?.split(separator: ":").map(String.init) ?? [] + print("[debug][swift-java] Base classpath from config: \(classpathFromConfig)") + + var classpathEntries: [String] = classpathFromConfig + + let swiftJavaCachedModuleClasspath = findSwiftJavaClasspaths(in: + // self.effectiveCacheDirectory ?? + FileManager.default.currentDirectoryPath) + print("[debug][swift-java] Classpath from *.swift-java.classpath files: \(swiftJavaCachedModuleClasspath)") + classpathEntries += swiftJavaCachedModuleClasspath + + if !classpathOptionEntries.isEmpty { + print("[debug][swift-java] Classpath from options: \(classpathOptionEntries)") + classpathEntries += classpathOptionEntries + } else { + // * Base classpath from CLASSPATH env variable + print("[debug][swift-java] Classpath from environment: \(classpathFromEnv)") + classpathEntries += classpathFromEnv + } + + let extraClasspath = input ?? "" // FIXME: just use the -cp as usual + let extraClasspathEntries = extraClasspath.split(separator: ":").map(String.init) + print("[debug][swift-java] Extra classpath: \(extraClasspathEntries)") + classpathEntries += extraClasspathEntries + + // Bring up the Java VM when necessary + + if logLevel >= .debug { + let classpathString = classpathEntries.joined(separator: ":") + print("[debug][swift-java] Initialize JVM with classpath: \(classpathString)") + } + let jvm = try JavaVirtualMachine.shared(classpath: classpathEntries) + + try emitConfiguration(classpath: self.commonJVMOptions.classpath, environment: jvm.environment()) + } + + /// Get base configuration, depending on if we are to 'amend' or 'overwrite' the existing configuration. + func getBaseConfigurationForWrite() throws -> (Bool, Configuration) { + guard let actualOutputDirectory = self.actualOutputDirectory else { + // If output has no path there's nothing to amend + return (false, .init()) + } + + switch self.existingConfigFile { + case .overwrite: + // always make up a fresh instance if we're overwriting + return (false, .init()) + case .amend: + let configPath = actualOutputDirectory + guard let config = try readConfiguration(sourceDir: configPath.path) else { + return (false, .init()) + } + return (true, config) + } + } + + // TODO: make this perhaps "emit type mappings" + mutating func emitConfiguration( + classpath: [String], + environment: JNIEnvironment + ) throws { + if let filterJavaPackage = self.commonJVMOptions.filterJavaPackage { + print("[java-swift][debug] Generate Java->Swift type mappings. Active filter: \(filterJavaPackage)") + } + print("[java-swift][debug] Classpath: \(classpath)") + + if classpath.isEmpty { + print("[java-swift][warning] Classpath is empty!") + } + + // Get a fresh or existing configuration we'll amend + var (amendExistingConfig, configuration) = try getBaseConfigurationForWrite() + if amendExistingConfig { + print("[swift-java] Amend existing swift-java.config file...") + } + configuration.classpath = classpath.joined(separator: ":") // TODO: is this correct? + + // Import types from all the classpath entries; + // Note that we use the package level filtering, so users have some control over what gets imported. + let classpathEntries = classpath.split(separator: ":").map(String.init) + for entry in classpathEntries { + guard fileOrDirectoryExists(at: entry) else { + // We only log specific jars missing, as paths may be empty directories that won't hurt not existing. + print("[debug][swift-java] Classpath entry does not exist: \(entry)") + continue + } + + print("[debug][swift-java] Importing classpath entry: \(entry)") + if entry.hasSuffix(".jar") { + let jarFile = try JarFile(entry, false, environment: environment) + try addJavaToSwiftMappings( + to: &configuration, + forJar: jarFile, + environment: environment + ) + } else if FileManager.default.fileExists(atPath: entry) { + print("[warning][swift-java] Currently unable handle directory classpath entries for config generation! Skipping: \(entry)") + } else { + print("[warning][swift-java] Classpath entry does not exist, skipping: \(entry)") + } + } + + // Encode the configuration. + let contents = try configuration.renderJSON() + + // Write the file. + try writeContents( + contents, + to: "swift-java.config", + description: "swift-java configuration file" + ) + } + + mutating func addJavaToSwiftMappings( + to configuration: inout Configuration, + forJar jarFile: JarFile, + environment: JNIEnvironment + ) throws { + for entry in jarFile.entries()! { + // We only look at class files in the Jar file. + guard entry.getName().hasSuffix(".class") else { + continue + } + + // Skip some "common" files we know that would be duplicated in every jar + guard !entry.getName().hasPrefix("META-INF") else { + continue + } + guard !entry.getName().hasSuffix("package-info") else { + continue + } + guard !entry.getName().hasSuffix("package-info.class") else { + continue + } + + // If this is a local class, it cannot be mapped into Swift. + if entry.getName().isLocalJavaClass { + continue + } + + let javaCanonicalName = String(entry.getName().replacing("/", with: ".") + .dropLast(".class".count)) + + if let filterJavaPackage = self.commonJVMOptions.filterJavaPackage, + !javaCanonicalName.hasPrefix(filterJavaPackage) { + // Skip classes which don't match our expected prefix + continue + } + + if configuration.classes?[javaCanonicalName] != nil { + // We never overwrite an existing class mapping configuration. + // E.g. the user may have configured a custom name for a type. + continue + } + + configuration.classes?[javaCanonicalName] = + javaCanonicalName.defaultSwiftNameForJavaClass + } + } + +} + +package func fileOrDirectoryExists(at path: String) -> Bool { + var isDirectory: ObjCBool = false + return FileManager.default.fileExists(atPath: path, isDirectory: &isDirectory) +} \ No newline at end of file diff --git a/Sources/SwiftJavaTool/SwiftJava+FetchDependencies.swift b/Sources/SwiftJavaTool/Commands/ResolveCommand.swift similarity index 86% rename from Sources/SwiftJavaTool/SwiftJava+FetchDependencies.swift rename to Sources/SwiftJavaTool/Commands/ResolveCommand.swift index 47570b19..eb96e490 100644 --- a/Sources/SwiftJavaTool/SwiftJava+FetchDependencies.swift +++ b/Sources/SwiftJavaTool/Commands/ResolveCommand.swift @@ -2,7 +2,7 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Copyright (c) 2024-2025 Apple Inc. and the Swift.org project authors // Licensed under Apache License v2.0 // // See LICENSE.txt for license information @@ -12,6 +12,7 @@ // //===----------------------------------------------------------------------===// +import ArgumentParser import Foundation import SwiftJavaLib import JavaKit @@ -23,12 +24,37 @@ import JavaKitShared import _Subprocess extension SwiftJava { + struct ResolveCommand: SwiftJavaBaseAsyncParsableCommand { + static let configuration = CommandConfiguration( + commandName: "resolve", + abstract: "Resolve dependencies and write the resulting swift-java.classpath file") + @OptionGroup var commonOptions: SwiftJava.CommonOptions + + @Option(help: "The name of the Swift module into which the resulting Swift types will be generated.") + var swiftModule: String + + var effectiveSwiftModule: String { + swiftModule + } + + } +} + +extension SwiftJava.ResolveCommand { + mutating func runSwiftJavaCommand(config: inout Configuration) async throws { + fatalError("NOT IMPLEMENTED: resolve") + } +} + + + +extension SwiftJava { var SwiftJavaClasspathPrefix: String { "SWIFT_JAVA_CLASSPATH:" } var printRuntimeClasspathTaskName: String { "printRuntimeClasspath" } - func fetchDependencies(moduleName: String, + func fetchDependencies(swiftModule: String, dependencies: [JavaDependencyDescriptor]) async throws -> ResolvedDependencyClasspath { let deps = dependencies.map { $0.descriptionGradleStyle } print("[debug][swift-java] Resolve and fetch dependencies for: \(deps)") @@ -37,7 +63,7 @@ extension SwiftJava { let classpathEntries = dependenciesClasspath.split(separator: ":") - print("[info][swift-java] Resolved classpath for \(deps.count) dependencies of '\(moduleName)', classpath entries: \(classpathEntries.count), ", terminator: "") + print("[info][swift-java] Resolved classpath for \(deps.count) dependencies of '\(swiftModule)', classpath entries: \(classpathEntries.count), ", terminator: "") print("done.".green) for entry in classpathEntries { @@ -128,7 +154,7 @@ extension SwiftJava { } mutating func writeFetchedDependenciesClasspath( - moduleName: String, + swiftModule: String, cacheDir: String, resolvedClasspath: ResolvedDependencyClasspath) throws { // Convert the artifact name to a module name @@ -137,14 +163,14 @@ extension SwiftJava { // The file contents are just plain let contents = resolvedClasspath.classpath - print("[debug][swift-java] Resolved dependency: \(classpath)") + print("[debug][swift-java] Resolved dependency: \(commonJVMOptions.classpath)") // Write the file try writeContents( contents, outputDirectoryOverride: URL(fileURLWithPath: cacheDir), - to: "\(moduleName).swift-java.classpath", - description: "swift-java.classpath file for module \(moduleName)" + to: "\(swiftModule).swift-java.classpath", + description: "swift-java.classpath file for module \(swiftModule)" ) } diff --git a/Sources/SwiftJavaTool/SwiftJava+GenerateWrappers.swift b/Sources/SwiftJavaTool/Commands/SwiftJava+GenerateWrappers.swift similarity index 95% rename from Sources/SwiftJavaTool/SwiftJava+GenerateWrappers.swift rename to Sources/SwiftJavaTool/Commands/SwiftJava+GenerateWrappers.swift index a57644de..676b278d 100644 --- a/Sources/SwiftJavaTool/SwiftJava+GenerateWrappers.swift +++ b/Sources/SwiftJavaTool/Commands/SwiftJava+GenerateWrappers.swift @@ -27,11 +27,8 @@ extension SwiftJava { dependentConfigs: [(String, Configuration)], environment: JNIEnvironment ) throws { - guard let moduleName else { - fatalError("--module-name must be set in 'generate wrappers' mode!") - } let translator = JavaTranslator( - swiftModuleName: moduleName, + swiftModuleName: effectiveSwiftModule, environment: environment, translateAsClass: true ) @@ -49,7 +46,7 @@ extension SwiftJava { } // Add the configuration for this module. - translator.addConfiguration(config, forSwiftModule: moduleName) + translator.addConfiguration(config, forSwiftModule: effectiveSwiftModule) // Load all of the explicitly-requested classes. let classLoader = try JavaClass(environment: environment) diff --git a/Sources/SwiftJavaTool/SwiftJava+JExtract.swift b/Sources/SwiftJavaTool/Commands/SwiftJava+JExtract.swift similarity index 100% rename from Sources/SwiftJavaTool/SwiftJava+JExtract.swift rename to Sources/SwiftJavaTool/Commands/SwiftJava+JExtract.swift diff --git a/Sources/SwiftJavaTool/CommonOptions.swift b/Sources/SwiftJavaTool/CommonOptions.swift new file mode 100644 index 00000000..43a35a5d --- /dev/null +++ b/Sources/SwiftJavaTool/CommonOptions.swift @@ -0,0 +1,59 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import ArgumentParser +import Foundation +import SwiftJavaLib +import JExtractSwiftLib +import JavaKit +import JavaKitJar +import JavaKitNetwork +import JavaKitReflection +import SwiftSyntax +import SwiftSyntaxBuilder +import JavaKitConfigurationShared +import JavaKitShared + +protocol HasCommonOptions { + var commonOptions: SwiftJava.CommonOptions { get set } +} + +protocol HasCommonJVMOptions { + var commonJVMOptions: SwiftJava.CommonJVMOptions { get set } +} + +extension SwiftJava { + struct CommonOptions: ParsableArguments { + // TODO: clarify this vs outputSwift (history: outputSwift is jextract, and this was java2swift) + @Option(name: .shortAndLong, help: "The directory in which to output the generated Swift files or the SwiftJava configuration file.") + var outputDirectory: String? = nil + + @Option(help: "Directory containing Swift files which should be extracted into Java bindings. Also known as 'jextract' mode. Must be paired with --output-java and --output-swift.") + var inputSwift: String? = nil + + @Option(name: .shortAndLong, help: "Configure the level of logs that should be printed") + var logLevel: Logger.Level = .info + } + + struct CommonJVMOptions: ParsableArguments { + @Option( + name: [.customLong("cp"), .customLong("classpath")], + help: "Class search path of directories and zip/jar files from which Java classes can be loaded." + ) + var classpath: [String] = [] + + @Option(name: .shortAndLong, help: "While scanning a classpath, inspect only types included in this package") + var filterJavaPackage: String? = nil + } +} \ No newline at end of file diff --git a/Sources/SwiftJavaTool/Java/JavaClassLoader.swift b/Sources/SwiftJavaTool/Java/JavaClassLoader.swift new file mode 100644 index 00000000..41492d53 --- /dev/null +++ b/Sources/SwiftJavaTool/Java/JavaClassLoader.swift @@ -0,0 +1,29 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import SwiftJavaLib +import JavaKitShared +import JavaRuntime +import JavaKit + +@JavaClass("java.lang.ClassLoader") +public struct ClassLoader { + @JavaMethod + public func loadClass(_ arg0: String) throws -> JavaClass? +} + +extension JavaClass { + @JavaStaticMethod + public func getSystemClassLoader() -> ClassLoader? +} \ No newline at end of file diff --git a/Sources/SwiftJavaTool/SwiftJava+EmitConfiguration.swift b/Sources/SwiftJavaTool/SwiftJava+EmitConfiguration.swift deleted file mode 100644 index e029d2db..00000000 --- a/Sources/SwiftJavaTool/SwiftJava+EmitConfiguration.swift +++ /dev/null @@ -1,120 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of Swift.org project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -import Foundation -import ArgumentParser -import SwiftJavaLib -import JavaKit -import JavaKitJar -import JavaKitConfigurationShared - -extension SwiftJava { - - // TODO: make this perhaps "emit type mappings" - mutating func emitConfiguration( - classpath: String, - environment: JNIEnvironment - ) throws { - print("[java-swift] Generate Java->Swift type mappings. Active filter: \(javaPackageFilter)") - print("[java-swift] Classpath: \(classpath)") - - if classpath.isEmpty { - print("[warning][java-swift] Classpath is empty!") - } - - // Get a fresh or existing configuration we'll amend - var (amendExistingConfig, configuration) = try getBaseConfigurationForWrite() - if amendExistingConfig { - print("[swift-java] Amend existing swift-java.config file...") - } - configuration.classpath = classpath // TODO: is this correct? - - // Import types from all the classpath entries; - // Note that we use the package level filtering, so users have some control over what gets imported. - for entry in classpath.split(separator: ":").map(String.init) { - print("[debug][swift-java] Importing classpath entry: \(entry)") - if entry.hasSuffix(".jar") { - let jarFile = try JarFile(entry, false, environment: environment) - try addJavaToSwiftMappings( - to: &configuration, - forJar: jarFile, - environment: environment - ) - } else if FileManager.default.fileExists(atPath: entry) { - print("[warning][swift-java] Currently unable handle directory classpath entries for config generation! Skipping: \(entry)") - } else { - print("[warning][swift-java] Classpath entry does not exist, skipping: \(entry)") - } - } - - // Encode the configuration. - let contents = try configuration.renderJSON() - - // Write the file. - try writeContents( - contents, - to: "swift-java.config", - description: "swift-java configuration file" - ) - } - - mutating func addJavaToSwiftMappings( - to configuration: inout Configuration, - forJar jarFile: JarFile, - environment: JNIEnvironment - ) throws { - for entry in jarFile.entries()! { - // We only look at class files in the Jar file. - guard entry.getName().hasSuffix(".class") else { - continue - } - - // Skip some "common" files we know that would be duplicated in every jar - guard !entry.getName().hasPrefix("META-INF") else { - continue - } - guard !entry.getName().hasSuffix("package-info") else { - continue - } - guard !entry.getName().hasSuffix("package-info.class") else { - continue - } - - // If this is a local class, it cannot be mapped into Swift. - if entry.getName().isLocalJavaClass { - continue - } - - let javaCanonicalName = String(entry.getName().replacing("/", with: ".") - .dropLast(".class".count)) - - if let javaPackageFilter { - if !javaCanonicalName.hasPrefix(javaPackageFilter) { - // Skip classes which don't match our expected prefix - continue - } - } - - if configuration.classes?[javaCanonicalName] != nil { - // We never overwrite an existing class mapping configuration. - // E.g. the user may have configured a custom name for a type. - continue - } - - configuration.classes?[javaCanonicalName] = - javaCanonicalName.defaultSwiftNameForJavaClass - } - } - -} \ No newline at end of file diff --git a/Sources/SwiftJavaTool/SwiftJava.swift b/Sources/SwiftJavaTool/SwiftJava.swift index cae7a2a4..0e6e64ae 100644 --- a/Sources/SwiftJavaTool/SwiftJava.swift +++ b/Sources/SwiftJavaTool/SwiftJava.swift @@ -27,11 +27,22 @@ import JavaKitShared /// Command-line utility to drive the export of Java classes into Swift types. @main -struct SwiftJava: AsyncParsableCommand { +struct SwiftJava: SwiftJavaBaseAsyncParsableCommand { // FIXME: this is just a normal async command, no parsing happening here static var _commandName: String { "swift-java" } + static let configuration = CommandConfiguration( + abstract: "Generate sources and configuration for Swift and Java interoperability.", + subcommands: [ + ConfigureCommand.self, + ResolveCommand.self, + ]) + @Option(help: "The name of the Swift module into which the resulting Swift types will be generated.") - var moduleName: String? // TODO: rename to --swift-module? + var swiftModule: String? + + var effectiveSwiftModule: String { + swiftModule ?? "UnknownSwiftModule" + } @Option( help: @@ -39,30 +50,14 @@ struct SwiftJava: AsyncParsableCommand { ) var dependsOn: [String] = [] - // TODO: This should be a "make wrappers" option that just detects when we give it a jar - @Flag( - help: - "Specifies that the input is a Jar file whose public classes will be loaded. The output of Java2Swift will be a configuration file (Java2Swift.config) that can be used as input to a subsequent Java2Swift invocation to generate wrappers for those public classes." - ) - var jar: Bool = false - @Flag(help: "Fetch dependencies from given target (containing swift-java configuration) or dependency string") var fetch: Bool = false - @Option( - name: [.customLong("cp"), .customLong("classpath")], - help: "Class search path of directories and zip/jar files from which Java classes can be loaded." - ) - var classpath: [String] = [] - @Option( help: "The names of Java classes whose declared native methods will be implemented in Swift." ) var swiftNativeImplementation: [String] = [] - @Option(help: "Directory containing Swift files which should be extracted into Java bindings. Also known as 'jextract' mode. Must be paired with --output-java and --output-swift.") - var inputSwift: String? = nil - @Option(help: "The directory where generated Swift files should be written. Generally used with jextract mode.") var outputSwift: String? = nil @@ -75,107 +70,36 @@ struct SwiftJava: AsyncParsableCommand { @Option(help: "The mode of generation to use for the output files. Used with jextract mode.") var mode: GenerationMode = .ffm - // TODO: clarify this vs outputSwift (history: outputSwift is jextract, and this was java2swift) - @Option(name: .shortAndLong, help: "The directory in which to output the generated Swift files or the SwiftJava configuration file.") - var outputDirectory: String? = nil +// // TODO: clarify this vs outputSwift (history: outputSwift is jextract, and this was java2swift) +// @Option(name: .shortAndLong, help: "The directory in which to output the generated Swift files or the SwiftJava configuration file.") +// var outputDirectory: String? = nil @Option(name: .shortAndLong, help: "Directory where to write cached values (e.g. swift-java.classpath files)") var cacheDirectory: String? = nil - @Option(name: .shortAndLong, help: "Configure the level of logs that should be printed") - var logLevel: Logger.Level = .info + @OptionGroup var commonOptions: SwiftJava.CommonOptions + @OptionGroup var commonJVMOptions: SwiftJava.CommonJVMOptions var effectiveCacheDirectory: String? { if let cacheDirectory { return cacheDirectory - } else if let outputDirectory { + } else if let outputDirectory = commonOptions.outputDirectory { return outputDirectory } else { return nil } } - - @Option(name: .shortAndLong, help: "How to handle an existing swift-java.config; by default 'overwrite' by can be changed to amending a configuration") - var existingConfig: ExistingConfigFileMode = .overwrite - public enum ExistingConfigFileMode: String, ExpressibleByArgument, Codable { - case overwrite - case amend - } - - @Option(name: .shortAndLong, help: "While scanning a classpath, inspect only types included in this package") - var javaPackageFilter: String? = nil @Argument( help: "The input file, which is either a Java2Swift configuration file or (if '-jar' was specified) a Jar file." ) - var input: String? - - /// Whether we have ensured that the output directory exists. - var createdOutputDirectory: Bool = false - - var moduleBaseDir: Foundation.URL? { - if let outputDirectory { - if outputDirectory == "-" { - return nil - } - - print("[debug][swift-java] Module base directory based on outputDirectory!") - return URL(fileURLWithPath: outputDirectory) - } - - guard let moduleName else { - return nil - } - - // Put the result into Sources/\(moduleName). - let baseDir = URL(fileURLWithPath: ".") - .appendingPathComponent("Sources", isDirectory: true) - .appendingPathComponent(moduleName, isDirectory: true) - - return baseDir - } - - /// The output directory in which to place the generated files, which will - /// be the specified directory (--output-directory or -o option) if given, - /// or a default directory derived from the other command-line arguments. - /// - /// Returns `nil` only when we should emit the files to standard output. - var actualOutputDirectory: Foundation.URL? { - if let outputDirectory { - if outputDirectory == "-" { - return nil - } - - return URL(fileURLWithPath: outputDirectory) - } - - guard let moduleName else { - fatalError("--module-name must be set!") - } - - // Put the result into Sources/\(moduleName). - let baseDir = URL(fileURLWithPath: ".") - .appendingPathComponent("Sources", isDirectory: true) - .appendingPathComponent(moduleName, isDirectory: true) - - // For generated Swift sources, put them into a "generated" subdirectory. - // The configuration file goes at the top level. - let outputDir: Foundation.URL - if jar { - precondition(self.input != nil, "-jar mode requires path to jar to be specified as input path") - outputDir = baseDir - } else { - outputDir = baseDir - .appendingPathComponent("generated", isDirectory: true) - } - - return outputDir - } + var input: String? // FIXME: top level command cannot have input argument like this + // FIXME: this is subcommands /// Describes what kind of generation action is being performed by swift-java. enum ToolMode { - /// Generate a configuration file given a Jar file. - case configuration(extraClasspath: String) // FIXME: this is more like "extract" configuration from classpath + // /// Generate a configuration file given a Jar file. + // case configuration(extraClasspath: String) // FIXME: this is more like "extract" configuration from classpath /// Generate Swift wrappers for Java classes based on the given /// configuration. @@ -188,216 +112,180 @@ struct SwiftJava: AsyncParsableCommand { case jextract // TODO: carry jextract specific config here? } - mutating func run() async { - guard CommandLine.arguments.count > 1 else { + mutating func runSwiftJavaCommand(config: inout Configuration) async throws { + guard CommandLine.arguments.count > 2 else { // there's no "default" command, print USAGE when no arguments/parameters are passed. - print("Must specify run mode.\n\(Self.helpMessage())") + print("error: Must specify mode subcommand (e.g. configure, resolve, jextract, ...).\n\n\(Self.helpMessage())") return } - print("[info][swift-java] Run: \(CommandLine.arguments.joined(separator: " "))") - print("[info][swift-java] Current work directory: \(URL(fileURLWithPath: "."))") - print("[info][swift-java] Module base directory: \(moduleBaseDir)") - do { - var earlyConfig: Configuration? - if let moduleBaseDir { - print("[debug][swift-java] Load config from module base directory: \(moduleBaseDir.path)") - earlyConfig = try readConfiguration(sourceDir: moduleBaseDir.path) - } else if let inputSwift { - print("[debug][swift-java] Load config from module swift input directory: \(inputSwift)") - earlyConfig = try readConfiguration(sourceDir: inputSwift) - } - var config = earlyConfig ?? Configuration() + if let javaPackage { + config.javaPackage = javaPackage + } - config.logLevel = self.logLevel - if let javaPackage { - config.javaPackage = javaPackage + // Determine the mode in which we'll execute. + let toolMode: ToolMode + // TODO: some options are exclusive to each other so we should detect that + if let inputSwift = commonOptions.inputSwift { + guard let inputSwift = commonOptions.inputSwift else { + print("[swift-java] --input-swift enabled 'jextract' mode, however no --output-swift directory was provided!\n\(Self.helpMessage())") + return + } + guard let outputSwift else { + print("[swift-java] --output-swift enabled 'jextract' mode, however no --output-swift directory was provided!\n\(Self.helpMessage())") + return + } + guard let outputJava else { + print("[swift-java] --output-java enabled 'jextract' mode, however no --output-java directory was provided!\n\(Self.helpMessage())") + return + } + config.swiftModule = self.swiftModule ?? "UnknownModule" + config.inputSwiftDirectory = inputSwift + config.outputSwiftDirectory = outputSwift + config.outputJavaDirectory = outputJava + + toolMode = .jextract +// } else if jar { +// guard let input else { +// fatalError("Mode -jar requires path\n\(Self.helpMessage())") +// } +// toolMode = .configuration(extraClasspath: input) + } else if fetch { + guard let input else { + fatalError("Mode 'fetch' requires path\n\(Self.helpMessage())") } + config = try JavaTranslator.readConfiguration(from: URL(fileURLWithPath: input)) + guard let dependencies = config.dependencies else { + print("[swift-java] Running in 'fetch dependencies' mode but dependencies list was empty!") + print("[swift-java] Nothing to do: done.") + return + } + toolMode = .fetchDependencies + } else { + guard let input else { + fatalError("Mode -jar requires path\n\(Self.helpMessage())") + } + config = try JavaTranslator.readConfiguration(from: URL(fileURLWithPath: input)) + toolMode = .classWrappers + } - // Determine the mode in which we'll execute. - let toolMode: ToolMode - // TODO: some options are exclusive to each other so we should detect that - if let inputSwift { - guard let outputSwift else { - print("[swift-java] --input-swift enabled 'jextract' mode, however no --output-swift directory was provided!\n\(Self.helpMessage())") - return - } - guard let outputJava else { - print("[swift-java] --input-swift enabled 'jextract' mode, however no --output-java directory was provided!\n\(Self.helpMessage())") - return - } - config.swiftModule = self.moduleName // FIXME: rename the moduleName - config.inputSwiftDirectory = self.inputSwift - config.outputSwiftDirectory = self.outputSwift - config.outputJavaDirectory = self.outputJava - config.mode = self.mode - - toolMode = .jextract - } else if jar { - guard let input else { - fatalError("Mode -jar requires path\n\(Self.helpMessage())") - } - toolMode = .configuration(extraClasspath: input) - } else if fetch { - guard let input else { - fatalError("Mode 'fetch' requires path\n\(Self.helpMessage())") - } - config = try JavaTranslator.readConfiguration(from: URL(fileURLWithPath: input)) - guard let dependencies = config.dependencies else { - print("[swift-java] Running in 'fetch dependencies' mode but dependencies list was empty!") - print("[swift-java] Nothing to do: done.") - return - } - toolMode = .fetchDependencies - } else { - guard let input else { - fatalError("Mode -jar requires path\n\(Self.helpMessage())") - } - config = try JavaTranslator.readConfiguration(from: URL(fileURLWithPath: input)) - toolMode = .classWrappers + print("[debug][swift-java] Running swift-java in mode: " + "\(toolMode.prettyName)".bold) + + let swiftModule: String = + self.swiftModule ?? + self.effectiveSwiftModule.split(separator: "/").dropLast().last.map(String.init) ?? "__UnknownModule" + + // Load all of the dependent configurations and associate them with Swift + // modules. + let dependentConfigs = try dependsOn.map { dependentConfig in + guard let equalLoc = dependentConfig.firstIndex(of: "=") else { + throw JavaToSwiftError.badConfigOption(dependentConfig) } - print("[debug][swift-java] Running swift-java in mode: " + "\(toolMode.prettyName)".bold) + let afterEqual = dependentConfig.index(after: equalLoc) + let swiftModuleName = String(dependentConfig[.. (javaClassName: String, swiftName: String) { @@ -421,65 +309,6 @@ struct SwiftJava: AsyncParsableCommand { return (javaClassName, swiftName.javaClassNameToCanonicalName) } - mutating func writeContents( - _ contents: String, - to filename: String, description: String) throws { - try writeContents( - contents, - outputDirectoryOverride: self.actualOutputDirectory, - to: filename, - description: description) - } - - mutating func writeContents( - _ contents: String, - outputDirectoryOverride: Foundation.URL?, - to filename: String, - description: String) throws { - guard let outputDir = (outputDirectoryOverride ?? actualOutputDirectory) else { - print("// \(filename) - \(description)") - print(contents) - return - } - - // If we haven't tried to create the output directory yet, do so now before - // we write any files to it. - if !createdOutputDirectory { - try FileManager.default.createDirectory( - at: outputDir, - withIntermediateDirectories: true - ) - createdOutputDirectory = true - } - - // Write the file: - let file = outputDir.appendingPathComponent(filename) - print("[debug][swift-java] Writing \(description) to '\(file.path)'... ", terminator: "") - try contents.write(to: file, atomically: true, encoding: .utf8) - print("done.".green) - } -} - -extension SwiftJava { - /// Get base configuration, depending on if we are to 'amend' or 'overwrite' the existing configuration. - package func getBaseConfigurationForWrite() throws -> (Bool, Configuration) { - guard let actualOutputDirectory = self.actualOutputDirectory else { - // If output has no path there's nothing to amend - return (false, .init()) - } - - switch self.existingConfig { - case .overwrite: - // always make up a fresh instance if we're overwriting - return (false, .init()) - case .amend: - let configPath = actualOutputDirectory - guard let config = try readConfiguration(sourceDir: configPath.path) else { - return (false, .init()) - } - return (true, config) - } - } } enum JavaToSwiftError: Error { @@ -495,21 +324,9 @@ extension JavaToSwiftError: CustomStringConvertible { } } -@JavaClass("java.lang.ClassLoader") -public struct ClassLoader { - @JavaMethod - public func loadClass(_ arg0: String) throws -> JavaClass? -} - -extension JavaClass { - @JavaStaticMethod - public func getSystemClassLoader() -> ClassLoader? -} - extension SwiftJava.ToolMode { var prettyName: String { switch self { - case .configuration: "Configuration" case .fetchDependencies: "Fetch dependencies" case .classWrappers: "Wrap Java classes" case .jextract: "JExtract Swift for Java" diff --git a/Sources/SwiftJavaTool/SwiftJavaBaseAsyncParsableCommand.swift b/Sources/SwiftJavaTool/SwiftJavaBaseAsyncParsableCommand.swift new file mode 100644 index 00000000..afe4f80c --- /dev/null +++ b/Sources/SwiftJavaTool/SwiftJavaBaseAsyncParsableCommand.swift @@ -0,0 +1,181 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import ArgumentParser +import Foundation +import SwiftJavaLib +import JExtractSwiftLib +import JavaKit +import JavaKitJar +import JavaKitNetwork +import JavaKitReflection +import SwiftSyntax +import SwiftSyntaxBuilder +import JavaKitConfigurationShared +import JavaKitShared + +protocol SwiftJavaBaseAsyncParsableCommand: AsyncParsableCommand { + var logLevel: Logger.Level { get set } + + var commonOptions: SwiftJava.CommonOptions { get set } + + var effectiveSwiftModule: String { get } + + mutating func runSwiftJavaCommand(config: inout Configuration) async throws + +} + +extension SwiftJavaBaseAsyncParsableCommand { + public mutating func run() async { + print("[info][swift-java] Run: \(CommandLine.arguments.joined(separator: " "))") + print("[info][swift-java] Current work directory: \(URL(fileURLWithPath: "."))") + + do { + var config = try readInitialConfiguration(command: self) + try await runSwiftJavaCommand(config: &config) + } catch { + // We fail like this since throwing out of the run often ends up hiding the failure reason when it is executed as SwiftPM plugin (!) + let message = "Failed with error: \(error)" + print("[error][java-swift] \(message)") + fatalError(message) + } + + // Just for debugging so it is clear which command has finished + print("[debug][swift-java] " + "Done: ".green + CommandLine.arguments.joined(separator: " ").green) + } +} + +extension SwiftJavaBaseAsyncParsableCommand { + mutating func writeContents( + _ contents: String, + to filename: String, description: String) throws { + try writeContents( + contents, + outputDirectoryOverride: self.actualOutputDirectory, + to: filename, + description: description) + } + + mutating func writeContents( + _ contents: String, + outputDirectoryOverride: Foundation.URL?, + to filename: String, + description: String) throws { + guard let outputDir = (outputDirectoryOverride ?? actualOutputDirectory) else { + print("// \(filename) - \(description)") + print(contents) + return + } + + // If we haven't tried to create the output directory yet, do so now before + // we write any files to it. + // if !createdOutputDirectory { + try FileManager.default.createDirectory( + at: outputDir, + withIntermediateDirectories: true + ) + // createdOutputDirectory = true + //} + + // Write the file: + let file = outputDir.appendingPathComponent(filename) + print("[debug][swift-java] Writing \(description) to '\(file.path)'... ", terminator: "") + try contents.write(to: file, atomically: true, encoding: .utf8) + print("done.".green) + } +} + + +extension SwiftJavaBaseAsyncParsableCommand { + var logLevel: Logger.Level { + get { + self.commonOptions.logLevel + } + set { + self.commonOptions.logLevel = newValue + } + } +} +extension SwiftJavaBaseAsyncParsableCommand { + + var moduleBaseDir: Foundation.URL? { +// if let outputDirectory = commonOptions.outputDirectory { +// if outputDirectory == "-" { +// return nil +// } +// +// print("[debug][swift-java] Module base directory based on outputDirectory!") +// return URL(fileURLWithPath: outputDirectory) +// } + +// guard let swiftModule else { +// return nil +// } + + // Put the result into Sources/\(swiftModule). + let baseDir = URL(fileURLWithPath: ".") + .appendingPathComponent("Sources", isDirectory: true) + .appendingPathComponent(self.effectiveSwiftModule, isDirectory: true) + + return baseDir + } + + /// The output directory in which to place the generated files, which will + /// be the specified directory (--output-directory or -o option) if given, + /// or a default directory derived from the other command-line arguments. + /// + /// Returns `nil` only when we should emit the files to standard output. + var actualOutputDirectory: Foundation.URL? { + if let outputDirectory = commonOptions.outputDirectory { + if outputDirectory == "-" { + return nil + } + + return URL(fileURLWithPath: outputDirectory) + } + + // Put the result into Sources/\(swiftModule). + let baseDir = URL(fileURLWithPath: ".") + .appendingPathComponent("Sources", isDirectory: true) + .appendingPathComponent(effectiveSwiftModule, isDirectory: true) + + // For generated Swift sources, put them into a "generated" subdirectory. + // The configuration file goes at the top level. + let outputDir: Foundation.URL + // if jar { + // precondition(self.input != nil, "-jar mode requires path to jar to be specified as input path") + outputDir = baseDir + // } else { + // outputDir = baseDir + // .appendingPathComponent("generated", isDirectory: true) + // } + + return outputDir + } + + func readInitialConfiguration(command: some SwiftJavaBaseAsyncParsableCommand) throws -> Configuration { + var earlyConfig: Configuration? + if let moduleBaseDir { + print("[debug][swift-java] Load config from module base directory: \(moduleBaseDir.path)") + earlyConfig = try readConfiguration(sourceDir: moduleBaseDir.path) + } else if let inputSwift = commonOptions.inputSwift { + print("[debug][swift-java] Load config from module swift input directory: \(inputSwift)") + earlyConfig = try readConfiguration(sourceDir: inputSwift) + } + var config = earlyConfig ?? Configuration() + // override configuration with options from command line + config.logLevel = command.logLevel + return config + } +} \ No newline at end of file diff --git a/USER_GUIDE.md b/USER_GUIDE.md index 2abe8ea0..d7d796fd 100644 --- a/USER_GUIDE.md +++ b/USER_GUIDE.md @@ -8,8 +8,8 @@ Before using this package, set the `JAVA_HOME` environment variable to point at ### Using Java libraries from Swift -Existing Java libraries can be wrapped for use in Swift with the `Java2Swift` -tool. In a Swift program, the most direct way to access a Java API is to use the SwiftPM plugin to provide Swift wrappers for the Java classes. To do so, add a configuration file `Java2Swift.config` into the source directory for the Swift target. This is a JSON file that specifies Java classes and the Swift type name that should be generated to wrap them. For example, the following file maps `java.math.BigInteger` to a Swift type named `BigInteger`: +Existing Java libraries can be wrapped for use in Swift with the `swift-java` +tool. In a Swift program, the most direct way to access a Java API is to use the SwiftPM plugin to provide Swift wrappers for the Java classes. To do so, add a configuration file `swift-java.config` into the source directory for the Swift target. This is a JSON file that specifies Java classes and the Swift type name that should be generated to wrap them. For example, the following file maps `java.math.BigInteger` to a Swift type named `BigInteger`: ```json { @@ -31,11 +31,11 @@ or, equivalently, adding the following to the package dependencies: .package(url: "https://github.com/swiftlang/swift-java", branch: "main"), ``` -Finally, update `Package.swift` so that the `Java2SwiftPlugin` plugin runs on the target in which you want to generate Swift wrappers. The plugin looks like this: +Finally, update `Package.swift` so that the `SwiftJavaPlugin` plugin runs on the target in which you want to generate Swift wrappers. The plugin looks like this: ```swift plugins: [ - .plugin(name: "Java2SwiftPlugin", package: "swift-java"), + .plugin(name: "SwiftJavaPlugin", package: "swift-java"), ] ``` @@ -101,10 +101,10 @@ let bigInt = BigInteger(veryBigNumber, environment: jniEnvironment) ### Importing a Jar file into Swift -Java libraries are often distributed as Jar files. The `Java2Swift` tool can inspect a Jar file to create a `Java2Swift.config` file that will wrap all of the public classes for use in Swift. Following the example in `swift-java/Samples/JavaSieve`, we will wrap a small [Java library for computing prime numbers](https://github.com/gazman-sdk/quadratic-sieve-Java) for use in Swift. Assuming we have a Jar file `QuadraticSieve-1.0.jar` in the package directory, run the following command: +Java libraries are often distributed as Jar files. The `swift-java` tool can inspect a Jar file to create a `swift-java.config` file that will wrap all of the public classes for use in Swift. Following the example in `swift-java/Samples/JavaSieve`, we will wrap a small [Java library for computing prime numbers](https://github.com/gazman-sdk/quadratic-sieve-Java) for use in Swift. Assuming we have a Jar file `QuadraticSieve-1.0.jar` in the package directory, run the following command: ```swift -swift run Java2Swift --module-name JavaSieve --jar QuadraticSieve-1.0.jar +swift-java generate --module-name JavaSieve --jar QuadraticSieve-1.0.jar ``` The resulting configuration file will look something like this: @@ -142,7 +142,7 @@ The resulting configuration file will look something like this: } ``` -As with the previous `JavaProbablyPrime` sample, the `JavaSieve` target in `Package.swift` should depend on the `swift-java` package modules (`JavaKit`) and apply the `Java2Swift` plugin. This makes all of the Java classes found in the Jar file available to Swift within the `JavaSieve` target. +As with the previous `JavaProbablyPrime` sample, the `JavaSieve` target in `Package.swift` should depend on the `swift-java` package modules (`JavaKit`) and apply the `swift-java` plugin. This makes all of the Java classes found in the Jar file available to Swift within the `JavaSieve` target. If you inspect the build output, there are a number of warnings that look like this: @@ -159,12 +159,12 @@ These warnings mean that some of the APIs in the Java library aren't available i .product(name: "JavaKit", package: "swift-java"), ], plugins: [ - .plugin(name: "Java2SwiftPlugin", package: "swift-java"), + .plugin(name: "SwiftJavaPlugin", package: "swift-java"), ] ), ``` -Then define a a Java2Swift configuration file in `Sources/JavaMath/Java2Swift.config` to bring in the types we need: +Then define a a swift-java configuration file in `Sources/JavaMath/swift-java.config` to bring in the types we need: ```json { @@ -255,7 +255,7 @@ public class HelloSwift { } ``` -On the Swift side, the Java class needs to be exposed to Swift through `Java2Swift.config`, e.g.,: +On the Swift side, the Java class needs to be exposed to Swift through `swift-java.config`, e.g.,: ```swift { @@ -393,7 +393,7 @@ A number of JavaKit modules provide Swift projections of Java classes and interf | `java.lang.Throwable` | `Throwable` | `JavaKit` | | `java.net.URL` | `URL` | `JavaKitNetwork` | -The `Java2Swift` tool can translate any other Java classes into Swift projections. The easiest way to use `Java2Swift` is with the SwiftPM plugin described above. More information about using this tool directly are provided later in this document +The `swift-java` tool can translate any other Java classes into Swift projections. The easiest way to use `swift-java` is with the SwiftPM plugin described above. More information about using this tool directly are provided later in this document #### Improve parameter names of imported Java methods When building Java libraries you can pass the `-parameters` option to javac @@ -438,65 +438,71 @@ public struct Enumeration { } ``` -## Translating Java classes with `Java2Swift` +## Translating Java classes with `swift-java` -The `Java2Swift` is a Swift program that uses Java's runtime reflection facilities to translate the requested Java classes into their Swift projections. The output is a number of Swift source files, each of which corresponds to a -single Java class. The `Java2Swift` can be executed like this: +The `swift-java` is a Swift program that uses Java's runtime reflection facilities to translate the requested Java classes into their Swift projections. The output is a number of Swift source files, each of which corresponds to a +single Java class. The `swift-java` can be executed like this: ``` -swift run Java2Swift +swift-java ``` to produce help output like the following: ``` -USAGE: Java2Swift --module-name [--depends-on ...] [--jar] [--cp ...] [--output-directory ] +OVERVIEW: Generate sources and configuration for Swift and Java interoperability. -ARGUMENTS: - The input file, which is either a Java2Swift - configuration file or (if '-jar' was specified) - a Jar file. +USAGE: swift-java OPTIONS: - --module-name - The name of the Swift module into which the resulting - Swift types will be generated. --depends-on - A Java2Swift configuration file for a given Swift - module name on which this module depends, e.g., - JavaKitJar=Sources/JavaKitJar/Java2Swift.config. - There should be one of these options for each Swift - module that this module depends on (transitively) - that contains wrapped Java sources. - --jar Specifies that the input is a Jar file whose public - classes will be loaded. The output of Java2Swift will - be a configuration file (Java2Swift.config) that can - be used as input to a subsequent Java2Swift - invocation to generate wrappers for those public - classes. - --cp, --classpath Class search path of directories and zip/jar files - from which Java classes can be loaded. + A Java2Swift configuration file for a given Swift module name on which this module depends, e.g., JavaKitJar=Sources/JavaKitJar/Java2Swift.config. There should be one of these options for each Swift module that this + module depends on (transitively) that contains wrapped Java sources. + --jar Specifies that the input is a Jar file whose public classes will be loaded. The output of Java2Swift will be a configuration file (Java2Swift.config) that can be used as input to a subsequent Java2Swift invocation to + generate wrappers for those public classes. + --fetch Fetch dependencies from given target (containing swift-java configuration) or dependency string + --swift-native-implementation + The names of Java classes whose declared native methods will be implemented in Swift. + --output-swift + The directory where generated Swift files should be written. Generally used with jextract mode. + --output-java + The directory where generated Java files should be written. Generally used with jextract mode. + --java-package + The Java package the generated Java code should be emitted into. + -c, --cache-directory + Directory where to write cached values (e.g. swift-java.classpath files) -o, --output-directory - The directory in which to output the generated Swift - files or the Java2Swift configuration file. (default: - .) + The directory in which to output the generated Swift files or the SwiftJava configuration file. + --input-swift + Directory containing Swift files which should be extracted into Java bindings. Also known as 'jextract' mode. Must be paired with --output-java and --output-swift. + -l, --log-level + Configure the level of logs that should be printed (values: trace, debug, info, notice, warning, error, critical; default: log level) + --cp, --classpath Class search path of directories and zip/jar files from which Java classes can be loaded. + -f, --filter-java-package + While scanning a classpath, inspect only types included in this package -h, --help Show help information. + +SUBCOMMANDS: + configure Configure and emit a swift-java.config file based on an input dependency or jar file + resolve Resolve dependencies and write the resulting swift-java.classpath file + + See 'swift-java help ' for detailed help. ``` For example, the `JavaKitJar` library is generated with this command line: ```swift -swift run Java2Swift --module-name JavaKitJar --depends-on JavaKit=Sources/JavaKit/Java2Swift.config -o Sources/JavaKitJar/generated Sources/JavaKitJar/Java2Swift.config +swift run swift-java --module-name JavaKitJar --depends-on JavaKit=Sources/JavaKit/swift-java.config -o Sources/JavaKitJar/generated Sources/JavaKitJar/swift-java.config ``` -The `--module-name JavaKitJar` parameter describes the name of the Swift module in which the code will be generated. +The `--swift-module JavaKitJar` parameter describes the name of the Swift module in which the code will be generated. -The `--depends-on` option is followed by the Java2Swift configuration files for any library on which this Swift library depends. Each `--depends-on` option is of the form `=`, and tells Java2Swift which other Java classes have already been translated to Swift. For example, if your Java class uses `java.net.URL`, then you should include +The `--depends-on` option is followed by the swift-java configuration files for any library on which this Swift library depends. Each `--depends-on` option is of the form `=`, and tells swift-java which other Java classes have already been translated to Swift. For example, if your Java class uses `java.net.URL`, then you should include `JavaKitNetwork`'s configuration file as a dependency here. The `-o` option specifies the output directory. Typically, this will be `Sources//generated` or similar to keep the generated Swift files separate from any hand-written ones. To see the output on the terminal rather than writing files to disk, pass `-` for this option. -Finally, the command line should contain the `Java2Swift.config` file containing the list of classes that should be translated into Swift and their corresponding Swift type names. The tool will output a single `.swift` file for each class, along with warnings for any public API that cannot be translated into Swift. The most common warnings are due to missing Swift projections for Java classes. For example, here we have not translated (or provided the translation manifests for) the Java classes +Finally, the command line should contain the `swift-java.config` file containing the list of classes that should be translated into Swift and their corresponding Swift type names. The tool will output a single `.swift` file for each class, along with warnings for any public API that cannot be translated into Swift. The most common warnings are due to missing Swift projections for Java classes. For example, here we have not translated (or provided the translation manifests for) the Java classes `java.util.zip.ZipOutputStream` and `java.io.OutputStream`: ``` @@ -507,7 +513,7 @@ warning: Unable to translate 'java.util.jar.JarInputStream' method 'transferTo': The result of such warnings is that certain information won't be statically available in Swift, e.g., the superclass won't be known (so we will assume it is `JavaObject`), or the specified constructors or methods won't be translated. If you don't need these APIs, the warnings can be safely ignored. The APIs can still be called dynamically via JNI. -The `--jar` option changes the operation of `Java2Swift`. Instead of wrapping Java classes in Swift, it scans the given input Jar file to find all public classes and outputs a configuration file `Java2Swift.config` mapping all of the Java classes in the Jar file to Swift types. The `--jar` mode is expected to be used to help import a Java library into Swift wholesale, after which Java2Swift should invoked again given the generated configuration file. +The `--jar` option changes the operation of `swift-java`. Instead of wrapping Java classes in Swift, it scans the given input Jar file to find all public classes and outputs a configuration file `swift-java.config` mapping all of the Java classes in the Jar file to Swift types. The `--jar` mode is expected to be used to help import a Java library into Swift wholesale, after which swift-java should invoked again given the generated configuration file. ### Under construction: Create a Java class to wrap the Swift library @@ -651,6 +657,7 @@ A Swift function may accept a closure which is used as a callback: func callMe(maybe: () -> ()) {} ``` +Minimal support for c-compatible closures is implemented, more documentation soon. ## `jextract-swift` importer behavior From d0eeaccd407d29f0503268ae3d5f881f326f82ff Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Mon, 16 Jun 2025 17:42:23 -0700 Subject: [PATCH 286/426] Bump swift-syntax version to 601.0.1 (#275) --- Package.swift | 2 +- .../JExtractSwiftLib/SwiftTypes/SwiftType.swift | 14 ++++++++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/Package.swift b/Package.swift index 47312ccd..55102874 100644 --- a/Package.swift +++ b/Package.swift @@ -191,7 +191,7 @@ let package = Package( ], dependencies: [ - .package(url: "https://github.com/swiftlang/swift-syntax", from: "600.0.1"), + .package(url: "https://github.com/swiftlang/swift-syntax", from: "601.0.1"), .package(url: "https://github.com/apple/swift-argument-parser", from: "1.5.0"), .package(url: "https://github.com/apple/swift-system", from: "1.4.0"), diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftType.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftType.swift index 5b0d8961..353b9b31 100644 --- a/Sources/JExtractSwiftLib/SwiftTypes/SwiftType.swift +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftType.swift @@ -180,7 +180,12 @@ extension SwiftType { // Translate the generic arguments. let genericArgs = try identifierType.genericArgumentClause.map { genericArgumentClause in try genericArgumentClause.arguments.map { argument in - try SwiftType(argument.argument, symbolTable: symbolTable) + switch argument.argument { + case .type(let argumentTy): + try SwiftType(argumentTy, symbolTable: symbolTable) + default: + throw TypeTranslationError.unimplementedType(type) + } } } @@ -210,7 +215,12 @@ extension SwiftType { // Translate the generic arguments. let genericArgs = try memberType.genericArgumentClause.map { genericArgumentClause in try genericArgumentClause.arguments.map { argument in - try SwiftType(argument.argument, symbolTable: symbolTable) + switch argument.argument { + case .type(let argumentTy): + try SwiftType(argumentTy, symbolTable: symbolTable) + default: + throw TypeTranslationError.unimplementedType(type) + } } } From 5c697668e93c8802ecd5230bf6473a878beed1aa Mon Sep 17 00:00:00 2001 From: Mads Odgaard Date: Tue, 17 Jun 2025 13:08:42 +0200 Subject: [PATCH 287/426] [jextract] add support for throwing functions in JNI mode (#277) --- ...Swift2JavaGenerator+FunctionLowering.swift | 3 +- Sources/JExtractSwiftLib/ImportedDecls.swift | 4 ++ .../JNI/JNISwift2JavaGenerator.swift | 29 ++++++-- .../SwiftTypes/SwiftEffectSpecifier.swift | 17 +++++ .../SwiftTypes/SwiftFunctionSignature.swift | 64 +++++++++++++---- .../JNI/JNIModuleTests.swift | 68 +++++++++++++++++++ 6 files changed, 163 insertions(+), 22 deletions(-) create mode 100644 Sources/JExtractSwiftLib/SwiftTypes/SwiftEffectSpecifier.swift diff --git a/Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift b/Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift index 061dc997..6938dc58 100644 --- a/Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift +++ b/Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift @@ -526,7 +526,8 @@ public struct LoweredFunctionSignature: Equatable { SwiftFunctionSignature( selfParameter: nil, parameters: allLoweredParameters, - result: SwiftResult(convention: .direct, type: result.cdeclResultType) + result: SwiftResult(convention: .direct, type: result.cdeclResultType), + effectSpecifiers: [] ) } } diff --git a/Sources/JExtractSwiftLib/ImportedDecls.swift b/Sources/JExtractSwiftLib/ImportedDecls.swift index 3619890b..ee86fc98 100644 --- a/Sources/JExtractSwiftLib/ImportedDecls.swift +++ b/Sources/JExtractSwiftLib/ImportedDecls.swift @@ -98,6 +98,10 @@ public final class ImportedFunc: ImportedDecl, CustomStringConvertible { return prefix + context + self.name } + var isThrowing: Bool { + self.functionSignature.effectSpecifiers.contains(.throws) + } + init( module: String, swiftDecl: any DeclSyntaxProtocol, diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator.swift index 946223ae..bab4c67f 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator.swift @@ -124,7 +124,6 @@ extension JNISwift2JavaGenerator { "thisClass: jclass" ] + translatedParameters.map { "\($0.0): \($0.1.jniTypeName)"} let swiftReturnType = decl.functionSignature.result.type - let thunkReturnType = !swiftReturnType.isVoid ? " -> \(swiftReturnType.javaType.jniTypeName)" : "" printer.printBraceBlock( @@ -137,17 +136,32 @@ extension JNISwift2JavaGenerator { let label = originalParam.argumentLabel.map { "\($0): "} ?? "" return "\(label)\(originalParam.type)(fromJNI: \(translatedParam.0), in: environment!)" } - let functionDowncall = "\(swiftModuleName).\(decl.name)(\(downcallParameters.joined(separator: ", ")))" + let tryClause: String = decl.isThrowing ? "try " : "" + let functionDowncall = "\(tryClause)\(swiftModuleName).\(decl.name)(\(downcallParameters.joined(separator: ", ")))" - if swiftReturnType.isVoid { - printer.print(functionDowncall) + let innerBody = if swiftReturnType.isVoid { + functionDowncall } else { + """ + let result = \(functionDowncall) + return result.getJNIValue(in: environment)") + """ + } + + if decl.isThrowing { + let dummyReturn = !swiftReturnType.isVoid ? "return \(swiftReturnType).jniPlaceholderValue" : "" printer.print( """ - let result = \(functionDowncall) - return result.getJNIValue(in: environment)") + do { + \(innerBody) + } catch { + environment.throwAsException(error) + \(dummyReturn) + } """ ) + } else { + printer.print(innerBody) } } } @@ -197,6 +211,7 @@ extension JNISwift2JavaGenerator { let params = decl.functionSignature.parameters.enumerated().map { idx, param in "\(param.type.javaType) \(param.parameterName ?? "arg\(idx))")" } + let throwsClause = decl.isThrowing ? " throws Exception" : "" printer.print( """ @@ -208,7 +223,7 @@ extension JNISwift2JavaGenerator { */ """ ) - printer.print("public static native \(returnType) \(decl.name)(\(params.joined(separator: ", ")));") + printer.print("public static native \(returnType) \(decl.name)(\(params.joined(separator: ", ")))\(throwsClause);") } } diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftEffectSpecifier.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftEffectSpecifier.swift new file mode 100644 index 00000000..9ba4d7ad --- /dev/null +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftEffectSpecifier.swift @@ -0,0 +1,17 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +enum SwiftEffectSpecifier: Equatable { + case `throws` +} diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftFunctionSignature.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftFunctionSignature.swift index cd4dbf7a..8f0b3128 100644 --- a/Sources/JExtractSwiftLib/SwiftTypes/SwiftFunctionSignature.swift +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftFunctionSignature.swift @@ -21,11 +21,18 @@ public struct SwiftFunctionSignature: Equatable { var selfParameter: SwiftSelfParameter? var parameters: [SwiftParameter] var result: SwiftResult + var effectSpecifiers: [SwiftEffectSpecifier] - init(selfParameter: SwiftSelfParameter? = nil, parameters: [SwiftParameter], result: SwiftResult) { + init( + selfParameter: SwiftSelfParameter? = nil, + parameters: [SwiftParameter], + result: SwiftResult, + effectSpecifiers: [SwiftEffectSpecifier] + ) { self.selfParameter = selfParameter self.parameters = parameters self.result = result + self.effectSpecifiers = effectSpecifiers } } @@ -68,13 +75,16 @@ extension SwiftFunctionSignature { throw SwiftFunctionTranslationError.generic(generics) } + let (parameters, effectSpecifiers) = try Self.translateFunctionSignature( + node.signature, + symbolTable: symbolTable + ) + self.init( selfParameter: .initializer(enclosingType), - parameters: try Self.translateFunctionSignature( - node.signature, - symbolTable: symbolTable - ), - result: SwiftResult(convention: .direct, type: enclosingType) + parameters: parameters, + result: SwiftResult(convention: .direct, type: enclosingType), + effectSpecifiers: effectSpecifiers ) } @@ -120,7 +130,7 @@ extension SwiftFunctionSignature { } // Translate the parameters. - let parameters = try Self.translateFunctionSignature( + let (parameters, effectSpecifiers) = try Self.translateFunctionSignature( node.signature, symbolTable: symbolTable ) @@ -136,26 +146,28 @@ extension SwiftFunctionSignature { result = .void } - self.init(selfParameter: selfParameter, parameters: parameters, result: result) + self.init(selfParameter: selfParameter, parameters: parameters, result: result, effectSpecifiers: effectSpecifiers) } /// Translate the function signature, returning the list of translated - /// parameters. + /// parameters and effect specifiers. static func translateFunctionSignature( _ signature: FunctionSignatureSyntax, symbolTable: SwiftSymbolTable - ) throws -> [SwiftParameter] { - // FIXME: Prohibit effects for now. - if let throwsClause = signature.effectSpecifiers?.throwsClause { - throw SwiftFunctionTranslationError.throws(throwsClause) + ) throws -> ([SwiftParameter], [SwiftEffectSpecifier]) { + var effectSpecifiers = [SwiftEffectSpecifier]() + if signature.effectSpecifiers?.throwsClause != nil { + effectSpecifiers.append(.throws) } if let asyncSpecifier = signature.effectSpecifiers?.asyncSpecifier { throw SwiftFunctionTranslationError.async(asyncSpecifier) } - return try signature.parameterClause.parameters.map { param in + let parameters = try signature.parameterClause.parameters.map { param in try SwiftParameter(param, symbolTable: symbolTable) } + + return (parameters, effectSpecifiers) } init(_ varNode: VariableDeclSyntax, isSet: Bool, enclosingType: SwiftType?, symbolTable: SwiftSymbolTable) throws { @@ -195,6 +207,22 @@ extension SwiftFunctionSignature { } let valueType = try SwiftType(varTypeNode, symbolTable: symbolTable) + var effectSpecifiers: [SwiftEffectSpecifier]? = nil + switch binding.accessorBlock?.accessors { + case .getter(let getter): + if let getter = getter.as(AccessorDeclSyntax.self) { + effectSpecifiers = Self.effectSpecifiers(from: getter) + } + case .accessors(let accessors): + if let getter = accessors.first(where: { $0.accessorSpecifier.tokenKind == .keyword(.get) }) { + effectSpecifiers = Self.effectSpecifiers(from: getter) + } + default: + break + } + + self.effectSpecifiers = effectSpecifiers ?? [] + if isSet { self.parameters = [SwiftParameter(convention: .byValue, parameterName: "newValue", type: valueType)] self.result = .void @@ -203,6 +231,14 @@ extension SwiftFunctionSignature { self.result = .init(convention: .direct, type: valueType) } } + + private static func effectSpecifiers(from decl: AccessorDeclSyntax) -> [SwiftEffectSpecifier] { + var effectSpecifiers = [SwiftEffectSpecifier]() + if decl.effectSpecifiers?.throwsClause != nil { + effectSpecifiers.append(.throws) + } + return effectSpecifiers + } } extension VariableDeclSyntax { diff --git a/Tests/JExtractSwiftTests/JNI/JNIModuleTests.swift b/Tests/JExtractSwiftTests/JNI/JNIModuleTests.swift index ba6258a1..2f73cca4 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIModuleTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIModuleTests.swift @@ -27,6 +27,11 @@ struct JNIModuleTests { public func copy(_ string: String) -> String """ + let globalMethodThrowing = """ + public func methodA() throws + public func methodB() throws -> Int64 + """ + @Test func generatesModuleJavaClass() throws { let input = "public func helloWorld()" @@ -150,4 +155,67 @@ struct JNIModuleTests { ] ) } + + @Test + func globalMethodThrowing_javaBindings() throws { + try assertOutput( + input: globalMethodThrowing, + .jni, + .java, + expectedChunks: [ + """ + /** + * Downcall to Swift: + * {@snippet lang=swift : + * public func methodA() throws + * } + */ + public static native void methodA() throws Exception; + """, + """ + /** + * Downcall to Swift: + * {@snippet lang=swift : + * public func methodB() throws -> Int64 + * } + */ + public static native long methodB() throws Exception; + """, + ] + ) + } + + @Test + func globalMethodThrowing_swiftThunks() throws { + try assertOutput( + input: globalMethodThrowing, + .jni, + .swift, + detectChunkByInitialLines: 1, + expectedChunks: [ + """ + @_cdecl("Java_com_example_swift_SwiftModule_methodA") + func swiftjava_SwiftModule_methodA(environment: UnsafeMutablePointer!, thisClass: jclass) { + do { + try SwiftModule.methodA() + } catch { + environment.throwAsException(error) + } + } + """, + """ + @_cdecl("Java_com_example_swift_SwiftModule_methodB") + func swiftjava_SwiftModule_methodB(environment: UnsafeMutablePointer!, thisClass: jclass) -> jlong { + do { + let result = try SwiftModule.methodB() + return result.getJNIValue(in: environment) + } catch { + environment.throwAsException(error) + return Int64.jniPlaceholderValue + } + } + """, + ] + ) + } } From d78fee1367fb98e786046bc0267db1b0f19cbd9f Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Tue, 17 Jun 2025 13:05:02 -0700 Subject: [PATCH 288/426] [JExtract] Prohibit 'throws' in FFM generator It's just not supported yet. --- .../FFMSwift2JavaGenerator+FunctionLowering.swift | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift b/Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift index 6938dc58..7609937d 100644 --- a/Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift +++ b/Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift @@ -109,6 +109,11 @@ struct CdeclLowering { ) } + for effect in signature.effectSpecifiers { + // Prohibit any effects for now. + throw LoweringError.effectNotSupported(effect) + } + // Lower the result. let loweredResult = try lowerResult(signature.result.type) @@ -642,4 +647,5 @@ extension LoweredFunctionSignature { enum LoweringError: Error { case inoutNotSupported(SwiftType) case unhandledType(SwiftType) + case effectNotSupported(SwiftEffectSpecifier) } From c9dc9b693db57301ba6e9b45164fc50337c21be1 Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Tue, 17 Jun 2025 14:51:20 -0700 Subject: [PATCH 289/426] [JExtract] Bridge UnsafeRawBufferPointer (#279) --- .../MySwiftLibrary/MySwiftLibrary.swift | 6 ++ .../com/example/swift/HelloJava2Swift.java | 2 + .../ExampleSwiftLibrary/MySwiftLibrary.swift | 4 + .../FFM/CDeclLowering/CRepresentation.swift | 5 +- ...Swift2JavaGenerator+FunctionLowering.swift | 60 +++++++++++++++ .../JExtractSwiftLib/FFM/ConversionStep.swift | 31 +++++++- ...t2JavaGenerator+JavaBindingsPrinting.swift | 74 +++++++++++------- ...MSwift2JavaGenerator+JavaTranslation.swift | 77 ++++++++++++++----- .../FFM/FFMSwift2JavaGenerator.swift | 7 +- .../FFM/ForeignValueLayouts.swift | 1 + .../JNI/JNISwift2JavaGenerator.swift | 7 +- .../SwiftStandardLibraryTypeDecls.swift | 14 +++- .../SwiftTypes/SwiftType.swift | 16 +++- .../FunctionLoweringTests.swift | 18 +++++ .../MethodImportTests.swift | 49 ++++++++++++ 15 files changed, 314 insertions(+), 57 deletions(-) diff --git a/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift b/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift index 2bd1905c..8b6066cf 100644 --- a/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift +++ b/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift @@ -47,6 +47,12 @@ public func globalCallMeRunnable(run: () -> ()) { run() } +public func globalReceiveRawBuffer(buf: UnsafeRawBufferPointer) -> Int { + return buf.count +} + +public var globalBuffer: UnsafeRawBufferPointer = UnsafeRawBufferPointer(UnsafeMutableRawBufferPointer.allocate(byteCount: 124, alignment: 1)) + // ==== Internal helpers func p(_ msg: String, file: String = #fileID, line: UInt = #line, function: String = #function) { diff --git a/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java b/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java index 69dfbdb3..f3073201 100644 --- a/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java +++ b/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java @@ -45,6 +45,8 @@ static void examples() { SwiftKit.trace("running runnable"); }); + SwiftKit.trace("getGlobalBuffer().byteSize()=" + MySwiftLibrary.getGlobalBuffer().byteSize()); + // Example of using an arena; MyClass.deinit is run at end of scope try (var arena = SwiftArena.ofConfined()) { MySwiftClass obj = MySwiftClass.init(2222, 7777, arena); diff --git a/Sources/ExampleSwiftLibrary/MySwiftLibrary.swift b/Sources/ExampleSwiftLibrary/MySwiftLibrary.swift index 96afd331..1c9477f1 100644 --- a/Sources/ExampleSwiftLibrary/MySwiftLibrary.swift +++ b/Sources/ExampleSwiftLibrary/MySwiftLibrary.swift @@ -41,6 +41,10 @@ public func globalCallMeRunnable(run: () -> ()) { run() } +public func globalReceiveRawBuffer(buf: UnsafeRawBufferPointer) -> Int { + return buf.count +} + public class MySwiftClass { public var len: Int diff --git a/Sources/JExtractSwiftLib/FFM/CDeclLowering/CRepresentation.swift b/Sources/JExtractSwiftLib/FFM/CDeclLowering/CRepresentation.swift index c52bf7db..eb27e5f6 100644 --- a/Sources/JExtractSwiftLib/FFM/CDeclLowering/CRepresentation.swift +++ b/Sources/JExtractSwiftLib/FFM/CDeclLowering/CRepresentation.swift @@ -65,6 +65,9 @@ extension CType { case .tuple([]): self = .void + case .optional(let wrapped) where wrapped.isPointer: + try self.init(cdeclType: wrapped) + case .metatype, .optional, .tuple: throw CDeclToCLoweringError.invalidCDeclType(cdeclType) } @@ -122,7 +125,7 @@ extension SwiftStandardLibraryTypeKind { .qualified(const: true, volatile: false, type: .void) ) case .void: .void - case .unsafePointer, .unsafeMutablePointer, .unsafeBufferPointer, .unsafeMutableBufferPointer, .string: + case .unsafePointer, .unsafeMutablePointer, .unsafeRawBufferPointer, .unsafeMutableRawBufferPointer, .unsafeBufferPointer, .unsafeMutableBufferPointer, .string: nil } } diff --git a/Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift b/Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift index 7609937d..2c7520dd 100644 --- a/Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift +++ b/Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift @@ -220,6 +220,35 @@ struct CdeclLowering { ) ) + case .unsafeRawBufferPointer, .unsafeMutableRawBufferPointer: + // pointer buffers are lowered to (raw-pointer, count) pair. + let isMutable = knownType == .unsafeMutableRawBufferPointer + return LoweredParameter( + cdeclParameters: [ + SwiftParameter( + convention: .byValue, + parameterName: "\(parameterName)_pointer", + type: .optional(isMutable ? knownTypes.unsafeMutableRawPointer : knownTypes.unsafeRawPointer) + ), + SwiftParameter( + convention: .byValue, parameterName: "\(parameterName)_count", + type: knownTypes.int + ) + ], + conversion: .initialize( + type, + arguments: [ + LabeledArgument( + label: "start", + argument: .explodedComponent(.placeholder, component: "pointer") + ), + LabeledArgument( + label: "count", + argument: .explodedComponent(.placeholder, component: "count") + ) + ] + )) + case .string: // 'String' is passed in by C string. i.e. 'UnsafePointer' ('const uint8_t *') if knownType == .string { @@ -382,6 +411,37 @@ struct CdeclLowering { outParameterName: outParameterName ) + case .unsafeRawBufferPointer, .unsafeMutableRawBufferPointer: + // pointer buffers are lowered to (raw-pointer, count) pair. + let isMutable = knownType == .unsafeMutableRawBufferPointer + return LoweredResult( + cdeclResultType: .void, + cdeclOutParameters: [ + SwiftParameter( + convention: .byValue, + parameterName: "\(outParameterName)_pointer", + type: knownTypes.unsafeMutablePointer( + .optional(isMutable ? knownTypes.unsafeMutableRawPointer : knownTypes.unsafeRawPointer) + ) + ), + SwiftParameter( + convention: .byValue, + parameterName: "\(outParameterName)_count", + type: knownTypes.unsafeMutablePointer(knownTypes.int) + ), + ], + conversion: .aggregate([ + .populatePointer( + name: "\(outParameterName)_pointer", + to: .member(.placeholder, member: "baseAddress") + ), + .populatePointer( + name: "\(outParameterName)_count", + to: .member(.placeholder, member: "count") + ) + ], name: outParameterName) + ) + case .void: return LoweredResult(cdeclResultType: .void, cdeclOutParameters: [], conversion: .placeholder) diff --git a/Sources/JExtractSwiftLib/FFM/ConversionStep.swift b/Sources/JExtractSwiftLib/FFM/ConversionStep.swift index 31d731bc..315acc60 100644 --- a/Sources/JExtractSwiftLib/FFM/ConversionStep.swift +++ b/Sources/JExtractSwiftLib/FFM/ConversionStep.swift @@ -52,9 +52,14 @@ enum ConversionStep: Equatable { /// Initialize mutable raw pointer with a typed value. indirect case populatePointer(name: String, assumingType: SwiftType? = nil, to: ConversionStep) - /// Perform multiple conversions, but discard the result. + /// Perform multiple conversions for each tuple input elements, but discard the result. case tupleExplode([ConversionStep], name: String?) + /// Perform multiple conversions using the same input. + case aggregate([ConversionStep], name: String?) + + indirect case member(ConversionStep, member: String) + /// Count the number of times that the placeholder occurs within this /// conversion step. var placeholderCount: Int { @@ -63,13 +68,14 @@ enum ConversionStep: Equatable { .pointee(let inner), .typedPointer(let inner, swiftType: _), .unsafeCastPointer(let inner, swiftType: _), - .populatePointer(name: _, assumingType: _, to: let inner): + .populatePointer(name: _, assumingType: _, to: let inner), + .member(let inner, member: _): inner.placeholderCount case .initialize(_, arguments: let arguments): arguments.reduce(0) { $0 + $1.argument.placeholderCount } case .placeholder, .tupleExplode: 1 - case .tuplify(let elements): + case .tuplify(let elements), .aggregate(let elements, _): elements.reduce(0) { $0 + $1.placeholderCount } } } @@ -140,6 +146,25 @@ enum ConversionStep: Equatable { } } return nil + + case .member(let step, let member): + let inner = step.asExprSyntax(placeholder: placeholder, bodyItems: &bodyItems) + return "\(inner).\(raw: member)" + + case .aggregate(let steps, let name): + let toExplode: String + if let name { + bodyItems.append("let \(raw: name) = \(raw: placeholder)") + toExplode = name + } else { + toExplode = placeholder + } + for step in steps { + if let result = step.asExprSyntax(placeholder: toExplode, bodyItems: &bodyItems) { + bodyItems.append(CodeBlockItemSyntax(item: .expr(result))) + } + } + return nil } } } diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift index c7c6631a..ba88869d 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift @@ -365,7 +365,7 @@ extension FFMSwift2JavaGenerator { "arena$" } - let varName = "_result" + outParameter.name + let varName = outParameter.name.isEmpty ? "_result" : "_result_" + outParameter.name printer.print( "MemorySegment \(varName) = \(arena).allocate(\(memoryLayout));" @@ -419,32 +419,35 @@ extension JavaConversionStep { /// Whether the conversion uses SwiftArena. var requiresSwiftArena: Bool { switch self { - case .pass, .swiftValueSelfSegment, .construct, .cast, .call, .method: + case .placeholder, .constant, .readOutParameter: return false case .constructSwiftValue: return true + + case .call(let inner, _, _), .cast(let inner, _), .construct(let inner, _), + .method(let inner, _, _, _), .swiftValueSelfSegment(let inner): + return inner.requiresSwiftArena + + case .commaSeparated(let list): + return list.contains(where: { $0.requiresSwiftArena }) } } /// Whether the conversion uses temporary Arena. var requiresTemporaryArena: Bool { switch self { - case .pass, .swiftValueSelfSegment, .construct, .constructSwiftValue, .cast: + case .placeholder, .constant: return false - case .call(_, let withArena), .method(_, _, let withArena): - return withArena - } - } - - /// Whether if the result evaluation is trivial. - /// - /// If this is false, it's advised to store it to a variable if it's used multiple times - var isTrivial: Bool { - switch self { - case .pass, .swiftValueSelfSegment: + case .readOutParameter: return true - case .cast, .construct, .constructSwiftValue, .call, .method: - return false + case .cast(let inner, _), .construct(let inner, _), .constructSwiftValue(let inner, _), .swiftValueSelfSegment(let inner): + return inner.requiresSwiftArena + case .call(let inner, _, let withArena): + return withArena || inner.requiresTemporaryArena + case .method(let inner, _, let args, let withArena): + return withArena || inner.requiresTemporaryArena || args.contains(where: { $0.requiresTemporaryArena }) + case .commaSeparated(let list): + return list.contains(where: { $0.requiresTemporaryArena }) } } @@ -453,28 +456,43 @@ extension JavaConversionStep { // NOTE: 'printer' is used if the conversion wants to cause side-effects. // E.g. storing a temporary values into a variable. switch self { - case .pass: + case .placeholder: return placeholder case .swiftValueSelfSegment: return "\(placeholder).$memorySegment()" - case .call(let function, let withArena): + case .call(let inner, let function, let withArena): + let inner = inner.render(&printer, placeholder) let arenaArg = withArena ? ", arena$" : "" - return "\(function)(\(placeholder)\(arenaArg))" + return "\(function)(\(inner)\(arenaArg))" + + case .method(let inner, let methodName, let arguments, let withArena): + let inner = inner.render(&printer, placeholder) + let args = arguments.map { $0.render(&printer, placeholder) } + let argsStr = (args + (withArena ? ["arena$"] : [])).joined(separator: " ,") + return "\(inner).\(methodName)(\(argsStr))" + + case .constructSwiftValue(let inner, let javaType): + let inner = inner.render(&printer, placeholder) + return "new \(javaType.className!)(\(inner), swiftArena$)" + + case .construct(let inner, let javaType): + let inner = inner.render(&printer, placeholder) + return "new \(javaType)(\(inner))" - case .method(let methodName, let arguments, let withArena): - let argsStr = (arguments + (withArena ? ["arena$"] : [])).joined(separator: " ,") - return "\(placeholder).\(methodName)(\(argsStr))" + case .cast(let inner, let javaType): + let inner = inner.render(&printer, placeholder) + return "(\(javaType)) \(inner)" - case .constructSwiftValue(let javaType): - return "new \(javaType.className!)(\(placeholder), swiftArena$)" + case .commaSeparated(let list): + return list.map({ $0.render(&printer, placeholder)}).joined(separator: ", ") - case .construct(let javaType): - return "new \(javaType)(\(placeholder))" + case .constant(let value): + return value - case .cast(let javaType): - return "(\(javaType)) \(placeholder)" + case .readOutParameter(let javaType, let name): + return "\(placeholder)_\(name).get(\(ForeignValueLayout(javaType: javaType)!), 0)" } } } diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift index 47616030..6f17158b 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift @@ -116,7 +116,7 @@ struct TranslatedFunctionType { /// Whether or not this functional interface with C ABI compatible. var isCompatibleWithC: Bool { - result.conversion.isPass && parameters.allSatisfy(\.conversion.isPass) + result.conversion.isPlaceholder && parameters.allSatisfy(\.conversion.isPlaceholder) } } @@ -200,7 +200,7 @@ struct JavaTranslation { javaParameters: [ JavaParameter(type: cType.javaType, name: paramName) ], - conversion: .pass + conversion: .placeholder ) translatedParams.append(translatedParam) continue @@ -215,7 +215,7 @@ struct JavaTranslation { let transltedResult = TranslatedResult( javaResultType: resultCType.javaType, outParameters: [], - conversion: .pass + conversion: .placeholder ) return TranslatedFunctionType( @@ -294,7 +294,7 @@ struct JavaTranslation { name: parameterName ) ], - conversion: .pass + conversion: .placeholder ) } @@ -307,7 +307,7 @@ struct JavaTranslation { type: JavaType.class(package: "org.swift.swiftkit", name: "SwiftAnyType"), name: parameterName) ], - conversion: .swiftValueSelfSegment + conversion: .swiftValueSelfSegment(.placeholder) ) case .nominal(let swiftNominalType): @@ -324,6 +324,17 @@ struct JavaTranslation { // FIXME: Implement throw JavaTranslationError.unhandledType(swiftType) + case .unsafeRawBufferPointer, .unsafeMutableRawBufferPointer: + return TranslatedParameter( + javaParameters: [ + JavaParameter(type: .javaForeignMemorySegment, name: parameterName), + ], + conversion: .commaSeparated([ + .placeholder, + .method(.placeholder, methodName: "byteSize", arguments: [], withArena: false) + ]) + ) + case .string: return TranslatedParameter( javaParameters: [ @@ -332,7 +343,7 @@ struct JavaTranslation { name: parameterName ) ], - conversion: .call(function: "SwiftKit.toCString", withArena: true) + conversion: .call(.placeholder, function: "SwiftKit.toCString", withArena: true) ) default: @@ -352,7 +363,7 @@ struct JavaTranslation { name: parameterName ) ], - conversion: .swiftValueSelfSegment + conversion: .swiftValueSelfSegment(.placeholder) ) case .tuple: @@ -366,7 +377,7 @@ struct JavaTranslation { type: JavaType.class(package: nil, name: "\(methodName).\(parameterName)"), name: parameterName) ], - conversion: .call(function: "\(methodName).$toUpcallStub", withArena: true) + conversion: .call(.placeholder, function: "\(methodName).$toUpcallStub", withArena: true) ) case .optional: @@ -388,7 +399,7 @@ struct JavaTranslation { return TranslatedResult( javaResultType: javaType, outParameters: [], - conversion: .pass + conversion: .placeholder ) } @@ -399,12 +410,29 @@ struct JavaTranslation { return TranslatedResult( javaResultType: javaType, outParameters: [], - conversion: .construct(javaType) + conversion: .construct(.placeholder, javaType) ) case .nominal(let swiftNominalType): if let knownType = swiftNominalType.nominalTypeDecl.knownStandardLibraryType { switch knownType { + case .unsafeRawBufferPointer, .unsafeMutableRawBufferPointer: + return TranslatedResult( + javaResultType: .javaForeignMemorySegment, + outParameters: [ + JavaParameter(type: .javaForeignMemorySegment, name: "pointer"), + JavaParameter(type: .long, name: "count"), + ], + conversion: .method( + .readOutParameter(.javaForeignMemorySegment, component: "pointer"), + methodName: "reinterpret", + arguments: [ + .readOutParameter(.long, component: "count") + ], + withArena: false + ) + ) + case .unsafePointer, .unsafeMutablePointer: // FIXME: Implement throw JavaTranslationError.unhandledType(swiftType) @@ -430,7 +458,7 @@ struct JavaTranslation { outParameters: [ JavaParameter(type: javaType, name: "") ], - conversion: .constructSwiftValue(javaType) + conversion: .constructSwiftValue(.placeholder, javaType) ) case .tuple: @@ -456,30 +484,39 @@ struct JavaTranslation { /// Describes how to convert values between Java types and FFM types. enum JavaConversionStep { // Pass through. - case pass + case placeholder + + // A fixed value + case constant(String) // 'value.$memorySegment()' - case swiftValueSelfSegment + indirect case swiftValueSelfSegment(JavaConversionStep) // call specified function using the placeholder as arguments. // If `withArena` is true, `arena$` argument is added. - case call(function: String, withArena: Bool) + indirect case call(JavaConversionStep, function: String, withArena: Bool) // Apply a method on the placeholder. // If `withArena` is true, `arena$` argument is added. - case method(methodName: String, arguments: [String] = [], withArena: Bool) + indirect case method(JavaConversionStep, methodName: String, arguments: [JavaConversionStep] = [], withArena: Bool) // Call 'new \(Type)(\(placeholder), swiftArena$)'. - case constructSwiftValue(JavaType) + indirect case constructSwiftValue(JavaConversionStep, JavaType) // Construct the type using the placeholder as arguments. - case construct(JavaType) + indirect case construct(JavaConversionStep, JavaType) // Casting the placeholder to the certain type. - case cast(JavaType) + indirect case cast(JavaConversionStep, JavaType) + + // Convert the results of the inner steps to a comma separated list. + indirect case commaSeparated([JavaConversionStep]) + + // Refer an exploded argument suffixed with `_\(name)`. + indirect case readOutParameter(JavaType, component: String) - var isPass: Bool { - return if case .pass = self { true } else { false } + var isPlaceholder: Bool { + return if case .placeholder = self { true } else { false } } } diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift index 036ee31e..4a65f7cc 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift @@ -138,7 +138,12 @@ extension FFMSwift2JavaGenerator { printImports(&printer) printModuleClass(&printer) { printer in - // TODO: print all "static" methods + + for decl in analysis.importedGlobalVariables { + self.log.trace("Print imported decl: \(decl)") + printFunctionDowncallMethods(&printer, decl) + } + for decl in analysis.importedGlobalFuncs { self.log.trace("Print imported decl: \(decl)") printFunctionDowncallMethods(&printer, decl) diff --git a/Sources/JExtractSwiftLib/FFM/ForeignValueLayouts.swift b/Sources/JExtractSwiftLib/FFM/ForeignValueLayouts.swift index 7cf1d4df..3784a75a 100644 --- a/Sources/JExtractSwiftLib/FFM/ForeignValueLayouts.swift +++ b/Sources/JExtractSwiftLib/FFM/ForeignValueLayouts.swift @@ -43,6 +43,7 @@ public struct ForeignValueLayout: CustomStringConvertible, Equatable { case .long: self = .SwiftInt64 case .float: self = .SwiftFloat case .double: self = .SwiftDouble + case .javaForeignMemorySegment: self = .SwiftPointer case .array, .class, .void: return nil } } diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator.swift index bab4c67f..b15688dc 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator.swift @@ -263,7 +263,12 @@ extension SwiftStandardLibraryTypeKind { case .double: .double case .void: .void case .string: .javaLangString - case .uint, .uint8, .uint32, .uint64, .unsafeRawPointer, .unsafeMutableRawPointer, .unsafePointer, .unsafeMutablePointer, .unsafeBufferPointer, .unsafeMutableBufferPointer: nil + case .uint, .uint8, .uint32, .uint64, + .unsafeRawPointer, .unsafeMutableRawPointer, + .unsafePointer, .unsafeMutablePointer, + .unsafeRawBufferPointer, .unsafeMutableRawBufferPointer, + .unsafeBufferPointer, .unsafeMutableBufferPointer: + nil } } } diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftStandardLibraryTypeDecls.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftStandardLibraryTypeDecls.swift index 51e1adcf..5678b2bb 100644 --- a/Sources/JExtractSwiftLib/SwiftTypes/SwiftStandardLibraryTypeDecls.swift +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftStandardLibraryTypeDecls.swift @@ -30,6 +30,8 @@ enum SwiftStandardLibraryTypeKind: String, Hashable, CaseIterable { case double = "Double" case unsafeRawPointer = "UnsafeRawPointer" case unsafeMutableRawPointer = "UnsafeMutableRawPointer" + case unsafeRawBufferPointer = "UnsafeRawBufferPointer" + case unsafeMutableRawBufferPointer = "UnsafeMutableRawBufferPointer" case unsafePointer = "UnsafePointer" case unsafeMutablePointer = "UnsafeMutablePointer" case unsafeBufferPointer = "UnsafeBufferPointer" @@ -48,7 +50,8 @@ enum SwiftStandardLibraryTypeKind: String, Hashable, CaseIterable { switch self { case .bool, .double, .float, .int, .int8, .int16, .int32, .int64, .uint, .uint8, .uint16, .uint32, .uint64, .unsafeRawPointer, - .unsafeMutableRawPointer, .string, .void: + .unsafeMutableRawPointer, .unsafeRawBufferPointer, .unsafeMutableRawBufferPointer, + .string, .void: false case .unsafePointer, .unsafeMutablePointer, .unsafeBufferPointer, @@ -56,6 +59,15 @@ enum SwiftStandardLibraryTypeKind: String, Hashable, CaseIterable { true } } + + var isPointer: Bool { + switch self { + case .unsafePointer, .unsafeMutablePointer, .unsafeRawPointer, .unsafeMutableRawPointer: + return true + default: + return false + } + } } /// Captures many types from the Swift standard library in their most basic diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftType.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftType.swift index 353b9b31..c2ddd2a5 100644 --- a/Sources/JExtractSwiftLib/SwiftTypes/SwiftType.swift +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftType.swift @@ -38,8 +38,7 @@ enum SwiftType: Equatable { asNominalType?.nominalTypeDecl } - /// Whether this is the "Void" type, which is actually an empty - /// tuple. + /// Whether this is the "Void" type, which is actually an empty tuple. var isVoid: Bool { switch self { case .tuple([]): @@ -51,6 +50,19 @@ enum SwiftType: Equatable { } } + /// Whether this is a pointer type. I.e 'Unsafe[Mutable][Raw]Pointer' + var isPointer: Bool { + switch self { + case .nominal(let nominal): + if let knownType = nominal.nominalTypeDecl.knownStandardLibraryType { + return knownType.isPointer + } + default: + break + } + return false; + } + /// Reference type /// /// * Mutations don't require 'inout' convention. diff --git a/Tests/JExtractSwiftTests/FunctionLoweringTests.swift b/Tests/JExtractSwiftTests/FunctionLoweringTests.swift index b7855e43..c707732e 100644 --- a/Tests/JExtractSwiftTests/FunctionLoweringTests.swift +++ b/Tests/JExtractSwiftTests/FunctionLoweringTests.swift @@ -315,6 +315,24 @@ final class FunctionLoweringTests { ) } + @Test("Lowering UnsafeRawBufferPointer") + func lowerRawBufferPointer() throws { + try assertLoweredFunction( + """ + func swapRawBufferPointer(buffer: UnsafeRawBufferPointer) -> UnsafeMutableRawBufferPointer {} + """, + expectedCDecl: """ + @_cdecl("c_swapRawBufferPointer") + public func c_swapRawBufferPointer(_ buffer_pointer: UnsafeRawPointer?, _ buffer_count: Int, _ _result_pointer: UnsafeMutablePointer, _ _result_count: UnsafeMutablePointer) { + let _result = swapRawBufferPointer(buffer: UnsafeRawBufferPointer(start: buffer_pointer, count: buffer_count)) + _result_pointer.initialize(to: _result.baseAddress) + _result_count.initialize(to: _result.count) + } + """, + expectedCFunction: "void c_swapRawBufferPointer(const void *buffer_pointer, ptrdiff_t buffer_count, void **_result_pointer, ptrdiff_t *_result_count)" + ) + } + @Test("Lowering () -> Void type") func lowerSimpleClosureTypes() throws { try assertLoweredFunction(""" diff --git a/Tests/JExtractSwiftTests/MethodImportTests.swift b/Tests/JExtractSwiftTests/MethodImportTests.swift index cd2bc150..2405e0ac 100644 --- a/Tests/JExtractSwiftTests/MethodImportTests.swift +++ b/Tests/JExtractSwiftTests/MethodImportTests.swift @@ -40,6 +40,8 @@ final class MethodImportTests { ) public func globalReturnClass() -> MySwiftClass + + public func swapRawBufferPointer(buffer: UnsafeRawBufferPointer) -> UnsafeMutableRawBufferPointer extension MySwiftClass { public func helloMemberInExtension() @@ -228,6 +230,53 @@ final class MethodImportTests { ) } + @Test("Import: func swapRawBufferPointer(buffer: _)") + func func_globalSwapRawBufferPointer() throws { + let st = Swift2JavaTranslator( + swiftModuleName: "__FakeModule" + ) + st.log.logLevel = .error + + try st.analyze(file: "Fake.swift", text: class_interfaceFile) + + let funcDecl = st.importedGlobalFuncs.first { + $0.name == "swapRawBufferPointer" + }! + + let generator = FFMSwift2JavaGenerator( + translator: st, + javaPackage: "com.example.swift", + swiftOutputDirectory: "/fake", + javaOutputDirectory: "/fake" + ) + + let output = CodePrinter.toString { printer in + generator.printJavaBindingWrapperMethod(&printer, funcDecl) + } + + assertOutput( + dump: true, + output, + expected: + """ + /** + * Downcall to Swift: + * {@snippet lang=swift : + * public func swapRawBufferPointer(buffer: UnsafeRawBufferPointer) -> UnsafeMutableRawBufferPointer + * } + */ + public static java.lang.foreign.MemorySegment swapRawBufferPointer(java.lang.foreign.MemorySegment buffer) { + try(var arena$ = Arena.ofConfined()) { + MemorySegment _result_pointer = arena$.allocate(SwiftValueLayout.SWIFT_POINTER); + MemorySegment _result_count = arena$.allocate(SwiftValueLayout.SWIFT_INT64); + swiftjava___FakeModule_swapRawBufferPointer_buffer.call(buffer, buffer.byteSize(), _result_pointer, _result_count); + return _result_pointer.get(SwiftValueLayout.SWIFT_POINTER, 0).reinterpret(_result_count.get(SwiftValueLayout.SWIFT_INT64, 0)); + } + } + """ + ) + } + @Test func method_class_helloMemberFunction() throws { let st = Swift2JavaTranslator( From 5a209c93f036ceb2c2cdc9f5bb58c8053d9da309 Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Mon, 23 Jun 2025 16:42:45 -0700 Subject: [PATCH 290/426] [JExtract] Bridge closures with UnsafeRawBufferPointer parameter First step to bridging closures with conversions. --- .../MySwiftLibrary/MySwiftLibrary.swift | 4 + .../com/example/swift/HelloJava2Swift.java | 3 + ...Swift2JavaGenerator+FunctionLowering.swift | 82 +++++++++++++--- .../JExtractSwiftLib/FFM/ConversionStep.swift | 53 +++++++++- ...t2JavaGenerator+JavaBindingsPrinting.swift | 50 +++++++--- ...MSwift2JavaGenerator+JavaTranslation.swift | 88 +++++++++++++---- .../FuncCallbackImportTests.swift | 97 +++++++++++++++++++ .../FunctionLoweringTests.swift | 18 ++++ 8 files changed, 351 insertions(+), 44 deletions(-) diff --git a/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift b/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift index 8b6066cf..18b6546d 100644 --- a/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift +++ b/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift @@ -53,6 +53,10 @@ public func globalReceiveRawBuffer(buf: UnsafeRawBufferPointer) -> Int { public var globalBuffer: UnsafeRawBufferPointer = UnsafeRawBufferPointer(UnsafeMutableRawBufferPointer.allocate(byteCount: 124, alignment: 1)) +public func withBuffer(body: (UnsafeRawBufferPointer) -> Void) { + body(globalBuffer) +} + // ==== Internal helpers func p(_ msg: String, file: String = #fileID, line: UInt = #line, function: String = #function) { diff --git a/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java b/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java index f3073201..c12d82dd 100644 --- a/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java +++ b/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java @@ -47,6 +47,9 @@ static void examples() { SwiftKit.trace("getGlobalBuffer().byteSize()=" + MySwiftLibrary.getGlobalBuffer().byteSize()); + MySwiftLibrary.withBuffer((buf) -> { + SwiftKit.trace("withBuffer{$0.byteSize()}=" + buf.byteSize()); + }); // Example of using an arena; MyClass.deinit is run at end of scope try (var arena = SwiftArena.ofConfined()) { MySwiftClass obj = MySwiftClass.init(2222, 7777, arena); diff --git a/Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift b/Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift index 2c7520dd..db764e2e 100644 --- a/Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift +++ b/Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift @@ -332,14 +332,15 @@ struct CdeclLowering { var parameters: [SwiftParameter] = [] var parameterConversions: [ConversionStep] = [] - for parameter in fn.parameters { - if let _ = try? CType(cdeclType: parameter.type) { - parameters.append(SwiftParameter(convention: .byValue, type: parameter.type)) - parameterConversions.append(.placeholder) - } else { - // Non-trivial types are not yet supported. - throw LoweringError.unhandledType(.function(fn)) - } + for (i, parameter) in fn.parameters.enumerated() { + let parameterName = parameter.parameterName ?? "_\(i)" + let loweredParam = try lowerClosureParameter( + parameter.type, + convention: parameter.convention, + parameterName: parameterName + ) + parameters.append(contentsOf: loweredParam.cdeclParameters) + parameterConversions.append(loweredParam.conversion) } let resultType: SwiftType @@ -352,15 +353,74 @@ struct CdeclLowering { throw LoweringError.unhandledType(.function(fn)) } - // Ignore the conversions for now, since we don't support non-trivial types yet. - _ = (parameterConversions, resultConversion) + let isCompatibleWithC = parameterConversions.allSatisfy(\.isPlaceholder) && resultConversion.isPlaceholder return ( type: .function(SwiftFunctionType(convention: .c, parameters: parameters, resultType: resultType)), - conversion: .placeholder + conversion: isCompatibleWithC ? .placeholder : .closureLowering(parameters: parameterConversions, result: resultConversion) ) } + func lowerClosureParameter( + _ type: SwiftType, + convention: SwiftParameterConvention, + parameterName: String + ) throws -> LoweredParameter { + // If there is a 1:1 mapping between this Swift type and a C type, we just + // return it. + if let _ = try? CType(cdeclType: type) { + return LoweredParameter( + cdeclParameters: [ + SwiftParameter( + convention: .byValue, + parameterName: parameterName, + type: type + ), + ], + conversion: .placeholder + ) + } + + switch type { + case .nominal(let nominal): + if let knownType = nominal.nominalTypeDecl.knownStandardLibraryType { + switch knownType { + case .unsafeRawBufferPointer, .unsafeMutableRawBufferPointer: + // pointer buffers are lowered to (raw-pointer, count) pair. + let isMutable = knownType == .unsafeMutableRawBufferPointer + return LoweredParameter( + cdeclParameters: [ + SwiftParameter( + convention: .byValue, + parameterName: "\(parameterName)_pointer", + type: .optional(isMutable ? knownTypes.unsafeMutableRawPointer : knownTypes.unsafeRawPointer) + ), + SwiftParameter( + convention: .byValue, + parameterName: "\(parameterName)_count", + type: knownTypes.int + ), + ], + conversion: .tuplify([ + .member(.placeholder, member: "baseAddress"), + .member(.placeholder, member: "count") + ]) + ) + + default: + throw LoweringError.unhandledType(type) + } + } + + // Custom types are not supported yet. + throw LoweringError.unhandledType(type) + + case .function, .metatype, .optional, .tuple: + // TODO: Implement + throw LoweringError.unhandledType(type) + } + } + /// Lower a Swift result type to cdecl out parameters and return type. /// /// - Parameters: diff --git a/Sources/JExtractSwiftLib/FFM/ConversionStep.swift b/Sources/JExtractSwiftLib/FFM/ConversionStep.swift index 315acc60..c7fa53e3 100644 --- a/Sources/JExtractSwiftLib/FFM/ConversionStep.swift +++ b/Sources/JExtractSwiftLib/FFM/ConversionStep.swift @@ -58,6 +58,8 @@ enum ConversionStep: Equatable { /// Perform multiple conversions using the same input. case aggregate([ConversionStep], name: String?) + indirect case closureLowering(parameters: [ConversionStep], result: ConversionStep) + indirect case member(ConversionStep, member: String) /// Count the number of times that the placeholder occurs within this @@ -73,13 +75,20 @@ enum ConversionStep: Equatable { inner.placeholderCount case .initialize(_, arguments: let arguments): arguments.reduce(0) { $0 + $1.argument.placeholderCount } - case .placeholder, .tupleExplode: + case .placeholder, .tupleExplode, .closureLowering: 1 case .tuplify(let elements), .aggregate(let elements, _): elements.reduce(0) { $0 + $1.placeholderCount } } } + var isPlaceholder: Bool { + if case .placeholder = self { + return true + } + return false + } + /// Convert the conversion step into an expression with the given /// value as the placeholder value in the expression. func asExprSyntax(placeholder: String, bodyItems: inout [CodeBlockItemSyntax]) -> ExprSyntax? { @@ -165,6 +174,48 @@ enum ConversionStep: Equatable { } } return nil + + case .closureLowering(let parameterSteps, let resultStep): + var body: [CodeBlockItemSyntax] = [] + + // Lower parameters. + var params: [String] = [] + var args: [ExprSyntax] = [] + for (i, parameterStep) in parameterSteps.enumerated() { + let paramName = "_\(i)" + params.append(paramName) + if case .tuplify(let elemSteps) = parameterStep { + for elemStep in elemSteps { + if let elemExpr = elemStep.asExprSyntax(placeholder: paramName, bodyItems: &body) { + args.append(elemExpr) + } + } + } else if let paramExpr = parameterStep.asExprSyntax(placeholder: paramName, bodyItems: &body) { + args.append(paramExpr) + } + } + + // Call the lowered closure with lowered parameters. + let loweredResult = "\(placeholder)(\(args.map(\.description).joined(separator: ", ")))" + + // Raise the lowered result. + let result = resultStep.asExprSyntax(placeholder: loweredResult.description, bodyItems: &body) + body.append("return \(result)") + + // Construct the closure expression. + var closure = ExprSyntax( + """ + { (\(raw: params.joined(separator: ", "))) in + } + """ + ).cast(ClosureExprSyntax.self) + + closure.statements = CodeBlockItemListSyntax { + body.map { + $0.with(\.leadingTrivia, [.newlines(1), .spaces(4)]) + } + } + return ExprSyntax(closure) } } } diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift index ba88869d..a6cc6b26 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift @@ -251,7 +251,6 @@ extension FFMSwift2JavaGenerator { ) } else { // Otherwise, the lambda must be wrapped with the lowered function instance. - assertionFailure("should be unreachable at this point") let apiParams = functionType.parameters.flatMap { $0.javaParameters.map { param in "\(param.type) \(param.name)" } } @@ -262,13 +261,38 @@ extension FFMSwift2JavaGenerator { public interface \(functionType.name) { \(functionType.result.javaResultType) apply(\(apiParams.joined(separator: ", "))); } - private static MemorySegment $toUpcallStub(\(functionType.name) fi, Arena arena) { - return \(cdeclDescriptor).toUpcallStub(() -> { - fi() - }, arena); - } """ ) + + let cdeclParams = functionType.cdeclType.parameters.map( { "\($0.parameterName!)" }) + + printer.printBraceBlock( + """ + private static MemorySegment $toUpcallStub(\(functionType.name) fi, Arena arena) + """ + ) { printer in + printer.print( + """ + return \(cdeclDescriptor).toUpcallStub((\(cdeclParams.joined(separator: ", "))) -> { + """ + ) + printer.indent() + var convertedArgs: [String] = [] + for param in functionType.parameters { + let arg = param.conversion.render(&printer, param.javaParameters[0].name) + convertedArgs.append(arg) + } + + let call = "fi.apply(\(convertedArgs.joined(separator: ", ")))" + let result = functionType.result.conversion.render(&printer, call) + if functionType.result.javaResultType == .void { + printer.print("\(result);") + } else { + printer.print("return \(result);") + } + printer.outdent() + printer.print("}, arena);") + } } } @@ -419,7 +443,7 @@ extension JavaConversionStep { /// Whether the conversion uses SwiftArena. var requiresSwiftArena: Bool { switch self { - case .placeholder, .constant, .readOutParameter: + case .placeholder, .explodedName, .constant, .readMemorySegment: return false case .constructSwiftValue: return true @@ -436,9 +460,9 @@ extension JavaConversionStep { /// Whether the conversion uses temporary Arena. var requiresTemporaryArena: Bool { switch self { - case .placeholder, .constant: + case .placeholder, .explodedName, .constant: return false - case .readOutParameter: + case .readMemorySegment: return true case .cast(let inner, _), .construct(let inner, _), .constructSwiftValue(let inner, _), .swiftValueSelfSegment(let inner): return inner.requiresSwiftArena @@ -459,6 +483,9 @@ extension JavaConversionStep { case .placeholder: return placeholder + case .explodedName(let component): + return "\(placeholder)_\(component)" + case .swiftValueSelfSegment: return "\(placeholder).$memorySegment()" @@ -491,8 +518,9 @@ extension JavaConversionStep { case .constant(let value): return value - case .readOutParameter(let javaType, let name): - return "\(placeholder)_\(name).get(\(ForeignValueLayout(javaType: javaType)!), 0)" + case .readMemorySegment(let inner, let javaType): + let inner = inner.render(&printer, placeholder) + return "\(inner).get(\(ForeignValueLayout(javaType: javaType)!), 0)" } } } diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift index 6f17158b..af1ddd09 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift @@ -113,6 +113,8 @@ struct TranslatedFunctionType { var name: String var parameters: [TranslatedParameter] var result: TranslatedResult + var swiftType: SwiftFunctionType + var cdeclType: SwiftFunctionType /// Whether or not this functional interface with C ABI compatible. var isCompatibleWithC: Bool { @@ -159,13 +161,19 @@ struct JavaTranslation { case .function, .initializer: decl.name } + // Signature. + let translatedSignature = try translate(loweredFunctionSignature: loweredSignature, methodName: javaName) + // Closures. var funcTypes: [TranslatedFunctionType] = [] for (idx, param) in decl.functionSignature.parameters.enumerated() { switch param.type { case .function(let funcTy): let paramName = param.parameterName ?? "_\(idx)" - let translatedClosure = try translateFunctionType(name: paramName, swiftType: funcTy) + guard case .function( let cdeclTy) = loweredSignature.parameters[idx].cdeclParameters[0].type else { + preconditionFailure("closure parameter wasn't lowered to a function type; \(funcTy)") + } + let translatedClosure = try translateFunctionType(name: paramName, swiftType: funcTy, cdeclType: cdeclTy) funcTypes.append(translatedClosure) case .tuple: // TODO: Implement @@ -175,9 +183,6 @@ struct JavaTranslation { } } - // Signature. - let translatedSignature = try translate(loweredFunctionSignature: loweredSignature, methodName: javaName) - return TranslatedFunctionDecl( name: javaName, functionTypes: funcTypes, @@ -189,23 +194,16 @@ struct JavaTranslation { /// Translate Swift closure type to Java functional interface. func translateFunctionType( name: String, - swiftType: SwiftFunctionType + swiftType: SwiftFunctionType, + cdeclType: SwiftFunctionType ) throws -> TranslatedFunctionType { var translatedParams: [TranslatedParameter] = [] for (i, param) in swiftType.parameters.enumerated() { let paramName = param.parameterName ?? "_\(i)" - if let cType = try? CType(cdeclType: param.type) { - let translatedParam = TranslatedParameter( - javaParameters: [ - JavaParameter(type: cType.javaType, name: paramName) - ], - conversion: .placeholder - ) - translatedParams.append(translatedParam) - continue - } - throw JavaTranslationError.unhandledType(.function(swiftType)) + translatedParams.append( + try translateClosureParameter(param.type, convention: param.convention, parameterName: paramName) + ) } guard let resultCType = try? CType(cdeclType: swiftType.resultType) else { @@ -221,10 +219,55 @@ struct JavaTranslation { return TranslatedFunctionType( name: name, parameters: translatedParams, - result: transltedResult + result: transltedResult, + swiftType: swiftType, + cdeclType: cdeclType ) } + func translateClosureParameter( + _ type: SwiftType, + convention: SwiftParameterConvention, + parameterName: String + ) throws -> TranslatedParameter { + if let cType = try? CType(cdeclType: type) { + return TranslatedParameter( + javaParameters: [ + JavaParameter(type: cType.javaType, name: parameterName) + ], + conversion: .placeholder + ) + } + + switch type { + case .nominal(let nominal): + if let knownType = nominal.nominalTypeDecl.knownStandardLibraryType { + switch knownType { + case .unsafeRawBufferPointer, .unsafeMutableRawBufferPointer: + return TranslatedParameter( + javaParameters: [ + JavaParameter(type: .javaForeignMemorySegment, name: parameterName) + ], + conversion: .method( + .explodedName(component: "pointer"), + methodName: "reinterpret", + arguments: [ + .explodedName(component: "count") + ], + withArena: false + ) + ) + default: + break + } + } + default: + break + } + throw JavaTranslationError.unhandledType(type) + } + + /// Translate a Swift API signature to the user-facing Java API signature. /// /// Note that the result signature is for the high-level Java API, not the @@ -424,10 +467,10 @@ struct JavaTranslation { JavaParameter(type: .long, name: "count"), ], conversion: .method( - .readOutParameter(.javaForeignMemorySegment, component: "pointer"), + .readMemorySegment(.explodedName(component: "pointer"), as: .javaForeignMemorySegment), methodName: "reinterpret", arguments: [ - .readOutParameter(.long, component: "count") + .readMemorySegment(.explodedName(component: "count"), as: .long), ], withArena: false ) @@ -483,9 +526,12 @@ struct JavaTranslation { /// Describes how to convert values between Java types and FFM types. enum JavaConversionStep { - // Pass through. + // The input case placeholder + // The input exploded into components. + case explodedName(component: String) + // A fixed value case constant(String) @@ -513,7 +559,7 @@ enum JavaConversionStep { indirect case commaSeparated([JavaConversionStep]) // Refer an exploded argument suffixed with `_\(name)`. - indirect case readOutParameter(JavaType, component: String) + indirect case readMemorySegment(JavaConversionStep, as: JavaType) var isPlaceholder: Bool { return if case .placeholder = self { true } else { false } diff --git a/Tests/JExtractSwiftTests/FuncCallbackImportTests.swift b/Tests/JExtractSwiftTests/FuncCallbackImportTests.swift index 457e3a7a..c738914a 100644 --- a/Tests/JExtractSwiftTests/FuncCallbackImportTests.swift +++ b/Tests/JExtractSwiftTests/FuncCallbackImportTests.swift @@ -31,6 +31,7 @@ final class FuncCallbackImportTests { public func callMe(callback: () -> Void) public func callMeMore(callback: (UnsafeRawPointer, Float) -> Int, fn: () -> ()) + public func withBuffer(body: (UnsafeRawBufferPointer) -> Int) """ @Test("Import: public func callMe(callback: () -> Void)") @@ -237,4 +238,100 @@ final class FuncCallbackImportTests { ) } + @Test("Import: public func withBuffer(body: (UnsafeRawBufferPointer) -> Int)") + func func_withBuffer_body() throws { + let st = Swift2JavaTranslator( + swiftModuleName: "__FakeModule" + ) + st.log.logLevel = .error + + try st.analyze(file: "Fake.swift", text: Self.class_interfaceFile) + + let funcDecl = st.importedGlobalFuncs.first { $0.name == "withBuffer" }! + + let generator = FFMSwift2JavaGenerator( + translator: st, + javaPackage: "com.example.swift", + swiftOutputDirectory: "/fake", + javaOutputDirectory: "/fake" + ) + + let output = CodePrinter.toString { printer in + generator.printFunctionDowncallMethods(&printer, funcDecl) + } + + assertOutput( + output, + expected: + """ + // ==== -------------------------------------------------- + // withBuffer + /** + * {@snippet lang=c : + * void swiftjava___FakeModule_withBuffer_body(ptrdiff_t (*body)(const void *, ptrdiff_t)) + * } + */ + private static class swiftjava___FakeModule_withBuffer_body { + private static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( + /* body: */SwiftValueLayout.SWIFT_POINTER + ); + private static final MemorySegment ADDR = + __FakeModule.findOrThrow("swiftjava___FakeModule_withBuffer_body"); + private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + public static void call(java.lang.foreign.MemorySegment body) { + try { + if (SwiftKit.TRACE_DOWNCALLS) { + SwiftKit.traceDowncall(body); + } + HANDLE.invokeExact(body); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + /** + * {snippet lang=c : + * ptrdiff_t (*)(const void *, ptrdiff_t) + * } + */ + private static class $body { + @FunctionalInterface + public interface Function { + long apply(java.lang.foreign.MemorySegment _0, long _1); + } + private static final FunctionDescriptor DESC = FunctionDescriptor.of( + /* -> */SwiftValueLayout.SWIFT_INT, + /* _0: */SwiftValueLayout.SWIFT_POINTER, + /* _1: */SwiftValueLayout.SWIFT_INT + ); + private static final MethodHandle HANDLE = SwiftKit.upcallHandle(Function.class, "apply", DESC); + private static MemorySegment toUpcallStub(Function fi, Arena arena) { + return Linker.nativeLinker().upcallStub(HANDLE.bindTo(fi), DESC, arena); + } + } + } + public static class withBuffer { + @FunctionalInterface + public interface body { + long apply(java.lang.foreign.MemorySegment _0); + } + private static MemorySegment $toUpcallStub(body fi, Arena arena) { + return swiftjava___FakeModule_withBuffer_body.$body.toUpcallStub((_0_pointer, _0_count) -> { + return fi.apply(_0_pointer.reinterpret(_0_count)); + }, arena); + } + } + /** + * Downcall to Swift: + * {@snippet lang=swift : + * public func withBuffer(body: (UnsafeRawBufferPointer) -> Int) + * } + */ + public static void withBuffer(withBuffer.body body) { + try(var arena$ = Arena.ofConfined()) { + swiftjava___FakeModule_withBuffer_body.call(withBuffer.$toUpcallStub(body, arena$)); + } + } + """ + ) + } } diff --git a/Tests/JExtractSwiftTests/FunctionLoweringTests.swift b/Tests/JExtractSwiftTests/FunctionLoweringTests.swift index c707732e..9422bbdb 100644 --- a/Tests/JExtractSwiftTests/FunctionLoweringTests.swift +++ b/Tests/JExtractSwiftTests/FunctionLoweringTests.swift @@ -333,6 +333,24 @@ final class FunctionLoweringTests { ) } + @Test("Lowering non-C-compatible closures") + func lowerComplexClosureParameter() throws { + try assertLoweredFunction( + """ + func withBuffer(body: (UnsafeRawBufferPointer) -> Int) {} + """, + expectedCDecl: """ + @_cdecl("c_withBuffer") + public func c_withBuffer(_ body: @convention(c) (UnsafeRawPointer?, Int) -> Int) { + withBuffer(body: { (_0) in + return body(_0.baseAddress, _0.count) + }) + } + """, + expectedCFunction: "void c_withBuffer(ptrdiff_t (*body)(const void *, ptrdiff_t))" + ) + } + @Test("Lowering () -> Void type") func lowerSimpleClosureTypes() throws { try assertLoweredFunction(""" From 23055cde668d0d64fb921addf506887e0db5c795 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Tue, 24 Jun 2025 17:07:07 +0900 Subject: [PATCH 291/426] Resolve & jextract subcommands and further dis-entangle commands (#276) --- .github/actions/prepare_env/action.yml | 6 +- .github/workflows/pull_request.yml | 26 +- .gitignore | 3 + .licenseignore | 3 +- .unacceptablelanguageignore | 13 +- ...d-logic.java-common-conventions.gradle.kts | 2 +- Package.swift | 51 +- .../JExtractSwiftCommandPlugin.swift | 159 --- .../JExtractSwiftCommandPlugin/_PluginsShared | 1 - .../JExtractSwiftPlugin.swift | 45 +- .../JavaCompilerPlugin.swift | 21 +- .../SwiftJavaPluginProtocol.swift | 4 +- Plugins/SwiftJavaPlugin/SwiftJavaPlugin.swift | 67 +- Samples/JavaDependencySampleApp/Package.swift | 6 +- .../JavaDependencySampleApp/ci-validate.sh | 8 + Samples/SwiftAndJavaJarSampleLib/LICENSE.txt | 202 +++ .../SwiftAndJavaJarSampleLib/Package.swift | 2 +- .../Sources/MySwiftLibrary/MySwiftClass.swift | 69 ++ .../MySwiftLibrary/MySwiftLibrary.swift | 55 +- Samples/SwiftAndJavaJarSampleLib/build.gradle | 72 +- .../SwiftAndJavaJarSampleLib/ci-validate.sh | 56 + Samples/SwiftKitSampleApp/Package.swift | 2 +- .../MySwiftLibrary/_RuntimeWorkarounds.swift | 22 - Samples/SwiftKitSampleApp/build.gradle | 70 +- ...ift2JavaGenerator+SwiftThunkPrinting.swift | 26 +- .../FFM/FFMSwift2JavaGenerator.swift | 24 + .../JNI/JNISwift2JavaGenerator.swift | 2 +- Sources/JExtractSwiftLib/Swift2Java.swift | 7 +- .../Swift2JavaTranslator.swift | 11 +- .../Configuration.swift | 24 +- .../GenerationMode.swift | 2 +- .../GradleDependencyParsing.swift | 48 + .../JavaTranslator+Configuration.swift | 10 +- .../Commands/ConfigureCommand.swift | 40 +- .../Commands/JExtractCommand.swift | 98 ++ .../Commands/ResolveCommand.swift | 126 +- .../Commands/SwiftJava+JExtract.swift | 40 - ...teWrappers.swift => WrapJavaCommand.swift} | 105 +- Sources/SwiftJavaTool/CommonOptions.swift | 83 +- Sources/SwiftJavaTool/SwiftJava.swift | 271 +--- .../SwiftJavaBaseAsyncParsableCommand.swift | 59 +- Sources/_CShims/process_shims.c | 340 ------ Sources/_Subprocess/API.swift | 370 ++++++ Sources/_Subprocess/AsyncBufferSequence.swift | 99 ++ Sources/_Subprocess/Buffer.swift | 104 ++ Sources/_Subprocess/Configuration.swift | 851 +++++++++++++ Sources/_Subprocess/Error.swift | 141 +++ Sources/_Subprocess/Execution.swift | 192 +++ Sources/_Subprocess/IO/Input.swift | 315 +++++ Sources/_Subprocess/IO/Output.swift | 298 +++++ Sources/_Subprocess/LockedState.swift | 160 --- .../Platforms/Subprocess+Darwin.swift | 625 +++++----- .../Platforms/Subprocess+Linux.swift | 398 +++--- .../Platforms/Subprocess+Unix.swift | 522 ++++---- .../Platforms/Subprocess+Windows.swift | 1088 +++++++++-------- Sources/_Subprocess/Result.swift | 123 ++ Sources/_Subprocess/Subprocess+API.swift | 465 ------- .../Subprocess+AsyncDataSequence.swift | 86 -- .../Subprocess+Configuration.swift | 769 ------------ Sources/_Subprocess/Subprocess+IO.swift | 437 ------- Sources/_Subprocess/Subprocess+Teardown.swift | 125 -- Sources/_Subprocess/Subprocess.swift | 315 ----- .../Input+Foundation.swift | 179 +++ .../Output+Foundation.swift | 53 + .../Span+SubprocessFoundation.swift | 76 ++ Sources/_Subprocess/Teardown.swift | 217 ++++ Sources/_Subprocess/_nio_locks.swift | 526 -------- .../include/process_shims.h | 30 +- .../include/target_conditionals.h} | 10 +- Sources/_SubprocessCShims/process_shims.c | 682 +++++++++++ SwiftKit/build.gradle | 2 +- .../org/swift/swiftkit/SwiftValueLayout.java | 4 +- .../swiftkit/SwiftValueWitnessTable.java | 1 - .../swiftkit/SwiftRuntimeMetadataTest.java | 74 +- .../Asserts/LoweringAssertions.swift | 13 +- .../Asserts/TextAssertions.swift | 6 +- .../FuncCallbackImportTests.swift | 19 +- .../FunctionDescriptorImportTests.swift | 13 +- .../MethodImportTests.swift | 56 +- .../GradleDependencyParsingTests.swift | 45 + docker/Dockerfile | 10 +- docker/install_jdk.sh | 133 +- docker/install_untested_nightly_swift.sh | 43 - 83 files changed, 6462 insertions(+), 5494 deletions(-) delete mode 100644 Plugins/JExtractSwiftCommandPlugin/JExtractSwiftCommandPlugin.swift delete mode 120000 Plugins/JExtractSwiftCommandPlugin/_PluginsShared create mode 100644 Samples/SwiftAndJavaJarSampleLib/LICENSE.txt create mode 100644 Samples/SwiftAndJavaJarSampleLib/Sources/MySwiftLibrary/MySwiftClass.swift create mode 100755 Samples/SwiftAndJavaJarSampleLib/ci-validate.sh delete mode 100644 Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/_RuntimeWorkarounds.swift create mode 100644 Sources/JavaKitConfigurationShared/GradleDependencyParsing.swift create mode 100644 Sources/SwiftJavaTool/Commands/JExtractCommand.swift delete mode 100644 Sources/SwiftJavaTool/Commands/SwiftJava+JExtract.swift rename Sources/SwiftJavaTool/Commands/{SwiftJava+GenerateWrappers.swift => WrapJavaCommand.swift} (53%) delete mode 100644 Sources/_CShims/process_shims.c create mode 100644 Sources/_Subprocess/API.swift create mode 100644 Sources/_Subprocess/AsyncBufferSequence.swift create mode 100644 Sources/_Subprocess/Buffer.swift create mode 100644 Sources/_Subprocess/Configuration.swift create mode 100644 Sources/_Subprocess/Error.swift create mode 100644 Sources/_Subprocess/Execution.swift create mode 100644 Sources/_Subprocess/IO/Input.swift create mode 100644 Sources/_Subprocess/IO/Output.swift delete mode 100644 Sources/_Subprocess/LockedState.swift create mode 100644 Sources/_Subprocess/Result.swift delete mode 100644 Sources/_Subprocess/Subprocess+API.swift delete mode 100644 Sources/_Subprocess/Subprocess+AsyncDataSequence.swift delete mode 100644 Sources/_Subprocess/Subprocess+Configuration.swift delete mode 100644 Sources/_Subprocess/Subprocess+IO.swift delete mode 100644 Sources/_Subprocess/Subprocess+Teardown.swift delete mode 100644 Sources/_Subprocess/Subprocess.swift create mode 100644 Sources/_Subprocess/SubprocessFoundation/Input+Foundation.swift create mode 100644 Sources/_Subprocess/SubprocessFoundation/Output+Foundation.swift create mode 100644 Sources/_Subprocess/SubprocessFoundation/Span+SubprocessFoundation.swift create mode 100644 Sources/_Subprocess/Teardown.swift delete mode 100644 Sources/_Subprocess/_nio_locks.swift rename Sources/{_CShims => _SubprocessCShims}/include/process_shims.h (74%) rename Sources/{_CShims/include/_CShimsTargetConditionals.h => _SubprocessCShims/include/target_conditionals.h} (76%) create mode 100644 Sources/_SubprocessCShims/process_shims.c create mode 100644 Tests/JavaKitConfigurationSharedTests/GradleDependencyParsingTests.swift delete mode 100755 docker/install_untested_nightly_swift.sh diff --git a/.github/actions/prepare_env/action.yml b/.github/actions/prepare_env/action.yml index ebcc8aed..dfd0a435 100644 --- a/.github/actions/prepare_env/action.yml +++ b/.github/actions/prepare_env/action.yml @@ -7,13 +7,13 @@ runs: - name: Install System Dependencies run: apt-get -qq update && apt-get -qq install -y make curl wget libjemalloc2 libjemalloc-dev shell: bash - - name: Cache JDK + - name: Cache JDKs id: cache-jdk uses: actions/cache@v4 continue-on-error: true with: - path: /usr/lib/jvm/default-jdk/ - key: ${{ runner.os }}-jdk-${{ matrix.jdk_vendor }}-${{ hashFiles('/usr/lib/jvm/default-jdk/*') }} + path: /usr/lib/jvm/ + key: ${{ runner.os }}-jdk-${{ matrix.jdk_vendor }}-${{ hashFiles('/usr/lib/jvm/*') }} restore-keys: | ${{ runner.os }}-jdk- - name: Install JDK diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 8fa774bd..39fa7ee6 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -20,8 +20,7 @@ jobs: strategy: fail-fast: true matrix: - # swift_version: ['nightly-main'] - swift_version: ['6.0.2'] + swift_version: ['6.1.2'] os_version: ['jammy'] jdk_vendor: ['Corretto'] container: @@ -36,7 +35,7 @@ jobs: - name: Gradle :SwiftKit:build run: ./gradlew build -x test - name: Gradle :SwiftKit:check - run: ./gradlew :SwiftKit:check --info + run: ./gradlew :SwiftKit:check --debug - name: Gradle compile JMH benchmarks run: ./gradlew compileJmh --info @@ -46,8 +45,7 @@ jobs: strategy: fail-fast: false matrix: - # swift_version: ['nightly-main'] - swift_version: ['6.0.2'] + swift_version: ['6.1.2'] os_version: ['jammy'] jdk_vendor: ['Corretto'] container: @@ -70,8 +68,7 @@ jobs: strategy: fail-fast: false matrix: - # swift_version: ['nightly-main'] - swift_version: ['6.0.2'] + swift_version: ['6.1.2'] os_version: ['jammy'] jdk_vendor: ['Corretto'] container: @@ -90,8 +87,7 @@ jobs: strategy: fail-fast: false matrix: - # swift_version: ['nightly-main'] - swift_version: ['6.0.2'] + swift_version: ['6.1.2'] os_version: ['jammy'] jdk_vendor: ['Corretto'] container: @@ -110,8 +106,7 @@ jobs: strategy: fail-fast: false matrix: - # swift_version: ['nightly-main'] - swift_version: ['6.0.2'] + swift_version: ['6.1.2'] os_version: ['jammy'] jdk_vendor: ['Corretto'] container: @@ -130,8 +125,7 @@ jobs: strategy: fail-fast: false matrix: - # swift_version: ['nightly-main'] - swift_version: ['6.0.2'] + swift_version: ['6.1.2'] os_version: ['jammy'] jdk_vendor: ['Corretto'] container: @@ -150,8 +144,7 @@ jobs: strategy: fail-fast: false matrix: - # swift_version: ['nightly-main'] - swift_version: ['6.0.2'] + swift_version: ['6.1.2'] os_version: ['jammy'] jdk_vendor: ['Corretto'] container: @@ -170,8 +163,7 @@ jobs: strategy: fail-fast: false matrix: - # swift_version: ['nightly-main'] - swift_version: ['6.0.2'] + swift_version: ['6.1.2'] os_version: ['jammy'] jdk_vendor: ['Corretto'] container: diff --git a/.gitignore b/.gitignore index 6712182f..f77390a7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ +.swift-version +.sdkmanrc + .DS_Store .build .idea diff --git a/.licenseignore b/.licenseignore index df3de377..003cac25 100644 --- a/.licenseignore +++ b/.licenseignore @@ -47,5 +47,6 @@ Plugins/**/_PluginsShared Plugins/**/0_PLEASE_SYMLINK* Plugins/PluginsShared/JavaKitConfigurationShared Samples/JavaDependencySampleApp/gradle -Sources/_Subprocess/_nio_locks.swift +Sources/_Subprocess/** +Sources/_SubprocessCShims/** Samples/gradle diff --git a/.unacceptablelanguageignore b/.unacceptablelanguageignore index 0310d1c3..92a1d726 100644 --- a/.unacceptablelanguageignore +++ b/.unacceptablelanguageignore @@ -2,16 +2,5 @@ Sources/SwiftJavaBootstrapJavaTool/SwiftJavaBootstrapJavaTool.swift Sources/_Subprocess/Platforms/Subprocess+Darwin.swift Sources/_Subprocess/Platforms/Subprocess+Linux.swift Sources/_Subprocess/Platforms/Subprocess+Unix.swift -Sources/_Subprocess/Platforms/Subprocess+Unix.swift -Sources/_Subprocess/Platforms/Subprocess+Unix.swift -Sources/_Subprocess/Platforms/Subprocess+Unix.swift -Sources/_Subprocess/Platforms/Subprocess+Unix.swift -Sources/_Subprocess/Platforms/Subprocess+Unix.swift -Sources/_Subprocess/Subprocess+Teardown.swift -Sources/_Subprocess/Subprocess+Teardown.swift -Sources/_Subprocess/Subprocess+Teardown.swift -Sources/_Subprocess/Subprocess+Teardown.swift -Sources/_Subprocess/Subprocess+Teardown.swift -Sources/_Subprocess/Subprocess+Teardown.swift -Sources/_Subprocess/Subprocess+Teardown.swift +Sources/_Subprocess/Teardown.swift Sources/_Subprocess/Subprocess.swift \ No newline at end of file diff --git a/BuildLogic/src/main/kotlin/build-logic.java-common-conventions.gradle.kts b/BuildLogic/src/main/kotlin/build-logic.java-common-conventions.gradle.kts index ef88ce15..fb10bee0 100644 --- a/BuildLogic/src/main/kotlin/build-logic.java-common-conventions.gradle.kts +++ b/BuildLogic/src/main/kotlin/build-logic.java-common-conventions.gradle.kts @@ -23,7 +23,7 @@ plugins { java { toolchain { - languageVersion = JavaLanguageVersion.of(22) + languageVersion = JavaLanguageVersion.of(24) } } diff --git a/Package.swift b/Package.swift index 55102874..58ee1840 100644 --- a/Package.swift +++ b/Package.swift @@ -11,6 +11,7 @@ import Foundation // Library/Java/JavaVirtualMachines/openjdk-21.jdk/Contents/Home. func findJavaHome() -> String { if let home = ProcessInfo.processInfo.environment["JAVA_HOME"] { + print("JAVA_HOME = \(home)") return home } @@ -85,7 +86,7 @@ let javaIncludePath = "\(javaHome)/include" let package = Package( name: "SwiftJava", platforms: [ - .macOS(.v10_15) + .macOS(.v15) ], products: [ // ==== JavaKit (i.e. calling Java directly Swift utilities) @@ -174,12 +175,6 @@ let package = Package( "JExtractSwiftPlugin" ] ), - .plugin( - name: "JExtractSwiftCommandPlugin", - targets: [ - "JExtractSwiftCommandPlugin" - ] - ), // ==== Examples @@ -195,6 +190,10 @@ let package = Package( .package(url: "https://github.com/apple/swift-argument-parser", from: "1.5.0"), .package(url: "https://github.com/apple/swift-system", from: "1.4.0"), +// // FIXME: swift-subprocess stopped supporting 6.0 when it moved into a package; +// // we'll need to drop 6.0 as well, but currently blocked on doing so by swiftpm plugin pending design questions +// .package(url: "https://github.com/swiftlang/swift-subprocess.git", revision: "de15b67f7871c8a039ef7f4813eb39a8878f61a6"), + // Benchmarking .package(url: "https://github.com/ordo-one/package-benchmark", .upToNextMajor(from: "1.4.0")), ], @@ -363,7 +362,8 @@ let package = Package( "JavaTypes", "JavaKitShared", "JavaKitConfigurationShared", - "_Subprocess", // using process spawning + // .product(name: "Subprocess", package: "swift-subprocess") + "_Subprocess", ], swiftSettings: [ .swiftLanguageMode(.v5), @@ -379,6 +379,7 @@ let package = Package( .product(name: "SwiftSyntax", package: "swift-syntax"), .product(name: "SwiftSyntaxBuilder", package: "swift-syntax"), .product(name: "ArgumentParser", package: "swift-argument-parser"), + .product(name: "SystemPackage", package: "swift-system"), "JavaKit", "JavaKitJar", "JavaKitNetwork", @@ -387,11 +388,14 @@ let package = Package( "JavaKitShared", "JavaKitConfigurationShared", ], - swiftSettings: [ .swiftLanguageMode(.v5), .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]), .enableUpcomingFeature("BareSlashRegexLiterals"), + .define( + "SYSTEM_PACKAGE_DARWIN", + .when(platforms: [.macOS, .macCatalyst, .iOS, .watchOS, .tvOS, .visionOS])), + .define("SYSTEM_PACKAGE"), ] ), @@ -419,16 +423,6 @@ let package = Package( "SwiftJavaTool" ] ), - .plugin( - name: "JExtractSwiftCommandPlugin", - capability: .command( - intent: .custom(verb: "jextract", description: "Extract Java accessors from Swift module"), - permissions: [ - ]), - dependencies: [ - "SwiftJavaTool" - ] - ), .testTarget( name: "JavaKitTests", @@ -467,6 +461,15 @@ let package = Package( ] ), + .testTarget( + name: "JavaKitConfigurationSharedTests", + dependencies: ["JavaKitConfigurationShared"], + swiftSettings: [ + .swiftLanguageMode(.v5), + .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) + ] + ), + .testTarget( name: "JExtractSwiftTests", dependencies: [ @@ -480,7 +483,7 @@ let package = Package( // Experimental Foundation Subprocess Copy .target( - name: "_CShims", + name: "_SubprocessCShims", swiftSettings: [ .swiftLanguageMode(.v5) ] @@ -488,11 +491,15 @@ let package = Package( .target( name: "_Subprocess", dependencies: [ - "_CShims", + "_SubprocessCShims", .product(name: "SystemPackage", package: "swift-system"), ], swiftSettings: [ - .swiftLanguageMode(.v5) + .swiftLanguageMode(.v5), + .define( + "SYSTEM_PACKAGE_DARWIN", + .when(platforms: [.macOS, .macCatalyst, .iOS, .watchOS, .tvOS, .visionOS])), + .define("SYSTEM_PACKAGE"), ] ), ] diff --git a/Plugins/JExtractSwiftCommandPlugin/JExtractSwiftCommandPlugin.swift b/Plugins/JExtractSwiftCommandPlugin/JExtractSwiftCommandPlugin.swift deleted file mode 100644 index f97feab6..00000000 --- a/Plugins/JExtractSwiftCommandPlugin/JExtractSwiftCommandPlugin.swift +++ /dev/null @@ -1,159 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of Swift.org project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -import Foundation -import PackagePlugin - -@main -final class JExtractSwiftCommandPlugin: SwiftJavaPluginProtocol, BuildToolPlugin, CommandPlugin { - - var pluginName: String = "swift-java-command" - var verbose: Bool = getEnvironmentBool("SWIFT_JAVA_VERBOSE") - - /// Build the target before attempting to extract from it. - /// This avoids trying to extract from broken sources. - /// - /// You may disable this if confident that input targets sources are correct and there's no need to kick off a pre-build for some reason. - var buildInputs: Bool = true - - /// Build the target once swift-java sources have been generated. - /// This helps verify that the generated output is correct, and won't miscompile on the next build. - var buildOutputs: Bool = true - - func createBuildCommands(context: PluginContext, target: any Target) async throws -> [Command] { - // FIXME: This is not a build plugin but SwiftPM forces us to impleme the protocol anyway? rdar://139556637 - return [] - } - - func performCommand(context: PluginContext, arguments: [String]) throws { - // Plugin can't have dependencies, so we have some naive argument parsing instead: - self.verbose = arguments.contains("-v") || arguments.contains("--verbose") - - for target in context.package.targets { - guard getSwiftJavaConfigPath(target: target) != nil else { - log("[swift-java-command] Skipping jextract step: Missing swift-java.config for target '\(target.name)'") - continue - } - - do { - let extraArguments = arguments.filter { arg in - arg != "-v" && arg != "--verbose" - } - print("[swift-java-command] Extracting Java wrappers from target: '\(target.name)'...") - try performCommand(context: context, target: target, extraArguments: extraArguments) - } catch { - print("[swift-java-command] error: Failed to extract from target '\(target.name)': \(error)") - } - - print("[swift-java-command] Done.") - } - print("[swift-java-command] Generating sources: " + "done".green + ".") - } - - func prepareJExtractArguments(context: PluginContext, target: Target) throws -> [String] { - guard let sourceModule = target.sourceModule else { return [] } - - // Note: Target doesn't have a directoryURL counterpart to directory, - // so we cannot eliminate this deprecation warning. - let sourceDir = target.directory.string - - let configuration = try readConfiguration(sourceDir: "\(sourceDir)") - - var arguments: [String] = [ - "--input-swift", sourceDir, - "--swift-module", sourceModule.name, - "--output-java", context.outputJavaDirectory.path(percentEncoded: false), - "--output-swift", context.outputSwiftDirectory.path(percentEncoded: false), - // TODO: "--build-cache-directory", ... - // Since plugins cannot depend on libraries we cannot detect what the output files will be, - // as it depends on the contents of the input files. Therefore we have to implement this as a prebuild plugin. - // We'll have to make up some caching inside the tool so we don't re-parse files which have not changed etc. - ] - // arguments.append(sourceDir) // TODO: we could do this shape maybe? to have the dirs last? - if let package = configuration?.javaPackage, !package.isEmpty { - ["--java-package", package] - } - - return arguments - } - - /// Perform the command on a specific target. - func performCommand(context: PluginContext, target: Target, extraArguments: [String]) throws { - guard let sourceModule = target.sourceModule else { return } - - if self.buildInputs { - // Make sure the target can builds properly - log("Pre-building target '\(target.name)' before extracting sources...") - let targetBuildResult = try self.packageManager.build(.target(target.name), parameters: .init()) - - guard targetBuildResult.succeeded else { - print("[swift-java-command] Build of '\(target.name)' failed: \(targetBuildResult.logText)") - return - } - } - - let arguments = try prepareJExtractArguments(context: context, target: target) - - try runExtract(context: context, target: target, arguments: arguments + extraArguments) - - if self.buildOutputs { - // Building the *products* since we need to build the dylib that contains our newly generated sources, - // so just building the target again would not be enough. We build all products which we affected using - // our source generation, which usually would be just a product dylib with our library. - // - // In practice, we'll always want to build after generating; either here, - // or via some other task before we run any Java code, calling into Swift. - log("Post-extract building products with target '\(target.name)'...") - for product in context.package.products where product.targets.contains(where: { $0.id == target.id }) { - log("Post-extract building product '\(product.name)'...") - let buildResult = try self.packageManager.build(.product(product.name), parameters: .init()) - - if buildResult.succeeded { - log("Post-extract build: " + "done".green + ".") - } else { - log("Post-extract build: " + "done".red + "!") - } - } - } - } - - func runExtract(context: PluginContext, target: Target, arguments: [String]) throws { - let process = Process() - process.executableURL = try context.tool(named: "SwiftJavaTool").url - process.arguments = arguments - - do { - log("Execute: \(process.executableURL!.absoluteURL.relativePath) \(arguments.joined(separator: " "))") - - try process.run() - process.waitUntilExit() - - assert(process.terminationStatus == 0, "Process failed with exit code: \(process.terminationStatus)") - } catch { - print("[swift-java-command] Failed to extract Java sources for target: '\(target.name); Error: \(error)") - } - } - -} - -// Mini coloring helper, since we cannot have dependencies we keep it minimal here -extension String { - var red: String { - "\u{001B}[0;31m" + "\(self)" + "\u{001B}[0;0m" - } - var green: String { - "\u{001B}[0;32m" + "\(self)" + "\u{001B}[0;0m" - } -} - diff --git a/Plugins/JExtractSwiftCommandPlugin/_PluginsShared b/Plugins/JExtractSwiftCommandPlugin/_PluginsShared deleted file mode 120000 index de623a5e..00000000 --- a/Plugins/JExtractSwiftCommandPlugin/_PluginsShared +++ /dev/null @@ -1 +0,0 @@ -../PluginsShared \ No newline at end of file diff --git a/Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift b/Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift index 4b52df26..7bfb51cf 100644 --- a/Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift +++ b/Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift @@ -40,6 +40,10 @@ struct JExtractSwiftBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin { } let sourceDir = target.directory.string + + // The name of the configuration file JavaKit.config from the target for + // which we are generating Swift wrappers for Java classes. + let configFile = URL(filePath: sourceDir).appending(path: "swift-java.config") let configuration = try readConfiguration(sourceDir: "\(sourceDir)") guard let javaPackage = configuration?.javaPackage else { @@ -54,28 +58,55 @@ struct JExtractSwiftBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin { let outputSwiftDirectory = context.outputSwiftDirectory var arguments: [String] = [ - "--input-swift", sourceDir, + /*subcommand=*/"jextract", "--swift-module", sourceModule.name, + "--input-swift", sourceDir, "--output-java", outputJavaDirectory.path(percentEncoded: false), "--output-swift", outputSwiftDirectory.path(percentEncoded: false), + // since SwiftPM requires all "expected" files do end up being written + // and we don't know which files will have actual thunks generated... we force jextract to write even empty files. + "--write-empty-files", // TODO: "--build-cache-directory", ... // Since plugins cannot depend on libraries we cannot detect what the output files will be, // as it depends on the contents of the input files. Therefore we have to implement this as a prebuild plugin. // We'll have to make up some caching inside the tool so we don't re-parse files which have not changed etc. ] - // arguments.append(sourceDir) if !javaPackage.isEmpty { - arguments.append(contentsOf: ["--java-package", javaPackage]) + arguments += ["--java-package", javaPackage] } + let swiftFiles = sourceModule.sourceFiles.map { $0.url }.filter { + $0.pathExtension == "swift" + } + + var outputSwiftFiles: [URL] = swiftFiles.compactMap { sourceFileURL in + guard sourceFileURL.isFileURL else { + return nil as URL? + } + + let sourceFilePath = sourceFileURL.path + guard sourceFilePath.starts(with: sourceDir) else { + fatalError("Could not get relative path for source file \(sourceFilePath)") + } + var outputURL = outputSwiftDirectory + .appending(path: String(sourceFilePath.dropFirst(sourceDir.count).dropLast(sourceFileURL.lastPathComponent.count + 1))) + + let inputFileName = sourceFileURL.deletingPathExtension().lastPathComponent + return outputURL.appending(path: "\(inputFileName)+SwiftJava.swift") + } + + // Append the "module file" that contains any thunks for global func definitions + outputSwiftFiles += [ + outputSwiftDirectory.appending(path: "\(sourceModule.name)Module+SwiftJava.swift") + ] + return [ - .prebuildCommand( + .buildCommand( displayName: "Generate Java wrappers for Swift types", executable: toolURL, arguments: arguments, - // inputFiles: [ configFile ] + swiftFiles, - // outputFiles: outputJavaFiles - outputFilesDirectory: outputSwiftDirectory + inputFiles: [ configFile ] + swiftFiles, + outputFiles: outputSwiftFiles ) ] } diff --git a/Plugins/JavaCompilerPlugin/JavaCompilerPlugin.swift b/Plugins/JavaCompilerPlugin/JavaCompilerPlugin.swift index b93fe403..55955180 100644 --- a/Plugins/JavaCompilerPlugin/JavaCompilerPlugin.swift +++ b/Plugins/JavaCompilerPlugin/JavaCompilerPlugin.swift @@ -34,7 +34,7 @@ struct JavaCompilerBuildToolPlugin: BuildToolPlugin { // The name of the configuration file JavaKit.config from the target for // which we are generating Swift wrappers for Java classes. - let configFile = URL(filePath: sourceDir).appending(path: "Java2Swift.config") + let configFile = URL(filePath: sourceDir).appending(path: "swift-java.config") let config: Configuration? if let configData = try? Data(contentsOf: configFile) { @@ -45,18 +45,21 @@ struct JavaCompilerBuildToolPlugin: BuildToolPlugin { // The class files themselves will be generated into the build directory // for this target. - let classFiles = javaFiles.map { sourceFileURL in + let classFiles = javaFiles.compactMap { sourceFileURL in + guard sourceFileURL.isFileURL else { + return nil as URL? + } + let sourceFilePath = sourceFileURL.path guard sourceFilePath.starts(with: sourceDir) else { fatalError("Could not get relative path for source file \(sourceFilePath)") } - return URL( - filePath: context.pluginWorkDirectoryURL.path - ).appending(path: "Java") - .appending(path: String(sourceFilePath.dropFirst(sourceDir.count))) - .deletingPathExtension() - .appendingPathExtension("class") + return URL(filePath: context.pluginWorkDirectoryURL.path) + .appending(path: "Java") + .appending(path: String(sourceFilePath.dropFirst(sourceDir.count))) + .deletingPathExtension() + .appendingPathExtension("class") } let javaHome = URL(filePath: findJavaHome()) @@ -73,7 +76,7 @@ struct JavaCompilerBuildToolPlugin: BuildToolPlugin { "-parameters", // keep parameter names, which allows us to emit them in generated Swift decls ] + (config?.compilerVersionArgs ?? []), inputFiles: javaFiles, - outputFiles: classFiles + outputFiles: classFiles // FIXME: this is not quite enough, javac may generate more files for closures etc, which we don't know about unless we compile first ) ] } diff --git a/Plugins/PluginsShared/SwiftJavaPluginProtocol.swift b/Plugins/PluginsShared/SwiftJavaPluginProtocol.swift index 68f8964e..57e38ef7 100644 --- a/Plugins/PluginsShared/SwiftJavaPluginProtocol.swift +++ b/Plugins/PluginsShared/SwiftJavaPluginProtocol.swift @@ -21,8 +21,6 @@ protocol SwiftJavaPluginProtocol { extension SwiftJavaPluginProtocol { func log(_ message: @autoclosure () -> String, terminator: String = "\n") { -// if self.verbose { - print("[\(pluginName)] \(message())", terminator: terminator) -// } + print("[\(pluginName)] \(message())", terminator: terminator) } } diff --git a/Plugins/SwiftJavaPlugin/SwiftJavaPlugin.swift b/Plugins/SwiftJavaPlugin/SwiftJavaPlugin.swift index effdcc53..cbbbe425 100644 --- a/Plugins/SwiftJavaPlugin/SwiftJavaPlugin.swift +++ b/Plugins/SwiftJavaPlugin/SwiftJavaPlugin.swift @@ -44,7 +44,7 @@ struct SwiftJavaBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin { log("Config was: \(config)") var javaDependencies = config.dependencies ?? [] - /// Find the manifest files from other Java2Swift executions in any targets + /// Find the manifest files from other swift-java executions in any targets /// this target depends on. var dependentConfigFiles: [(String, URL)] = [] func searchForConfigFiles(in target: any Target) { @@ -88,26 +88,14 @@ struct SwiftJavaBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin { } var arguments: [String] = [] - arguments += argumentsModuleName(sourceModule: sourceModule) + arguments += argumentsSwiftModule(sourceModule: sourceModule) arguments += argumentsOutputDirectory(context: context) - - arguments += dependentConfigFiles.flatMap { moduleAndConfigFile in - let (moduleName, configFile) = moduleAndConfigFile - return [ - "--depends-on", - "\(moduleName)=\(configFile.path(percentEncoded: false))" - ] - } - arguments.append(configFile.path(percentEncoded: false)) + arguments += argumentsDependedOnConfigs(dependentConfigFiles) -// guard let classes = config.classes else { -// log("Config at \(configFile) did not have 'classes' configured, skipping java2swift step.") -// return [] -// } let classes = config.classes ?? [:] - print("Classes to wrap: \(classes.map(\.key))") + print("[swift-java-plugin] Classes to wrap (\(classes.count)): \(classes.map(\.key))") - /// Determine the set of Swift files that will be emitted by the Java2Swift tool. + /// Determine the set of Swift files that will be emitted by the swift-java tool. // TODO: this is not precise and won't work with more advanced Java files, e.g. lambdas etc. let outputDirectoryGenerated = self.outputDirectory(context: context, generated: true) let outputSwiftFiles = classes.map { (javaClassName, swiftName) in @@ -165,12 +153,9 @@ struct SwiftJavaBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin { .buildCommand( displayName: displayName, executable: executable, - arguments: [ - // FIXME: change to 'resolve' subcommand - "--fetch", configFile.path(percentEncoded: false), - "--swift-module", sourceModule.name, - "--output-directory", outputDirectory(context: context, generated: false).path(percentEncoded: false) - ], + arguments: ["resolve"] + + argumentsOutputDirectory(context: context, generated: false) + + argumentsSwiftModule(sourceModule: sourceModule), environment: [:], inputFiles: [configFile], outputFiles: fetchDependenciesOutputFiles @@ -181,19 +166,24 @@ struct SwiftJavaBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin { } if !outputSwiftFiles.isEmpty { + arguments += [ configFile.path(percentEncoded: false) ] + let displayName = "Wrapping \(classes.count) Java classes in Swift target '\(sourceModule.name)'" log("Prepared: \(displayName)") commands += [ .buildCommand( displayName: displayName, executable: executable, - arguments: arguments, + arguments: ["wrap-java"] + + arguments, inputFiles: compiledClassFiles + fetchDependenciesOutputFiles + [ configFile ], outputFiles: outputSwiftFiles ) ] - } else { - log("No Swift output files, skip wrapping") + } + + if commands.isEmpty { + log("No swift-java commands for module '\(sourceModule.name)'") } return commands @@ -201,19 +191,38 @@ struct SwiftJavaBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin { } extension SwiftJavaBuildToolPlugin { - func argumentsModuleName(sourceModule: Target) -> [String] { + func argumentsSwiftModule(sourceModule: Target) -> [String] { return [ "--swift-module", sourceModule.name ] } - + + // FIXME: remove this and the deprecated property inside SwiftJava, this is a workaround + // since we cannot have the same option in common options and in the top level + // command from which we get into sub commands. The top command will NOT have this option. + func argumentsSwiftModuleDeprecated(sourceModule: Target) -> [String] { + return [ + "--swift-module-deprecated", sourceModule.name + ] + } + func argumentsOutputDirectory(context: PluginContext, generated: Bool = true) -> [String] { return [ "--output-directory", outputDirectory(context: context, generated: generated).path(percentEncoded: false) ] } - + + func argumentsDependedOnConfigs(_ dependentConfigFiles: [(String, URL)]) -> [String] { + dependentConfigFiles.flatMap { moduleAndConfigFile in + let (moduleName, configFile) = moduleAndConfigFile + return [ + "--depends-on", + "\(moduleName)=\(configFile.path(percentEncoded: false))" + ] + } + } + func outputDirectory(context: PluginContext, generated: Bool = true) -> URL { let dir = context.pluginWorkDirectoryURL if generated { diff --git a/Samples/JavaDependencySampleApp/Package.swift b/Samples/JavaDependencySampleApp/Package.swift index b39e7b81..4fa33116 100644 --- a/Samples/JavaDependencySampleApp/Package.swift +++ b/Samples/JavaDependencySampleApp/Package.swift @@ -43,11 +43,7 @@ let javaIncludePath = "\(javaHome)/include" let package = Package( name: "JavaDependencySampleApp", platforms: [ - .macOS(.v13), - .iOS(.v13), - .tvOS(.v13), - .watchOS(.v6), - .macCatalyst(.v13), + .macOS(.v15), ], products: [ diff --git a/Samples/JavaDependencySampleApp/ci-validate.sh b/Samples/JavaDependencySampleApp/ci-validate.sh index 7012b841..2758e6aa 100755 --- a/Samples/JavaDependencySampleApp/ci-validate.sh +++ b/Samples/JavaDependencySampleApp/ci-validate.sh @@ -3,4 +3,12 @@ set -e set -x +# invoke resolve as part of a build run swift run --disable-sandbox + +# explicitly invoke resolve without explicit path or dependency +# the dependencies should be uses from the --swift-module +swift run swift-java resolve \ + Sources/JavaCommonsCSV/swift-java.config \ + --swift-module JavaCommonsCSV \ + --output-directory .build/plugins/outputs/javadependencysampleapp/JavaCommonsCSV/destination/SwiftJavaPlugin/ diff --git a/Samples/SwiftAndJavaJarSampleLib/LICENSE.txt b/Samples/SwiftAndJavaJarSampleLib/LICENSE.txt new file mode 100644 index 00000000..d6456956 --- /dev/null +++ b/Samples/SwiftAndJavaJarSampleLib/LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/Samples/SwiftAndJavaJarSampleLib/Package.swift b/Samples/SwiftAndJavaJarSampleLib/Package.swift index 5f132239..c4c604ee 100644 --- a/Samples/SwiftAndJavaJarSampleLib/Package.swift +++ b/Samples/SwiftAndJavaJarSampleLib/Package.swift @@ -43,7 +43,7 @@ let javaIncludePath = "\(javaHome)/include" let package = Package( name: "SwiftAndJavaJarSampleLib", platforms: [ - .macOS(.v10_15) + .macOS(.v15) ], products: [ .library( diff --git a/Samples/SwiftAndJavaJarSampleLib/Sources/MySwiftLibrary/MySwiftClass.swift b/Samples/SwiftAndJavaJarSampleLib/Sources/MySwiftLibrary/MySwiftClass.swift new file mode 100644 index 00000000..c842715c --- /dev/null +++ b/Samples/SwiftAndJavaJarSampleLib/Sources/MySwiftLibrary/MySwiftClass.swift @@ -0,0 +1,69 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +// This is a "plain Swift" file containing various types of declarations, +// that is exported to Java by using the `jextract-swift` tool. +// +// No annotations are necessary on the Swift side to perform the export. + +#if os(Linux) +import Glibc +#else +import Darwin.C +#endif + +public class MySwiftClass { + + public var len: Int + public var cap: Int + + public init(len: Int, cap: Int) { + self.len = len + self.cap = cap + + p("\(MySwiftClass.self).len = \(self.len)") + p("\(MySwiftClass.self).cap = \(self.cap)") + let addr = unsafeBitCast(self, to: UInt64.self) + p("initializer done, self = 0x\(String(addr, radix: 16, uppercase: true))") + } + + deinit { + let addr = unsafeBitCast(self, to: UInt64.self) + p("Deinit, self = 0x\(String(addr, radix: 16, uppercase: true))") + } + + public var counter: Int32 = 0 + + public func voidMethod() { + p("") + } + + public func takeIntMethod(i: Int) { + p("i:\(i)") + } + + public func echoIntMethod(i: Int) -> Int { + p("i:\(i)") + return i + } + + public func makeIntMethod() -> Int { + p("make int -> 12") + return 12 + } + + public func makeRandomIntMethod() -> Int { + return Int.random(in: 1..<256) + } +} \ No newline at end of file diff --git a/Samples/SwiftAndJavaJarSampleLib/Sources/MySwiftLibrary/MySwiftLibrary.swift b/Samples/SwiftAndJavaJarSampleLib/Sources/MySwiftLibrary/MySwiftLibrary.swift index 84e4618f..e900fdd0 100644 --- a/Samples/SwiftAndJavaJarSampleLib/Sources/MySwiftLibrary/MySwiftLibrary.swift +++ b/Samples/SwiftAndJavaJarSampleLib/Sources/MySwiftLibrary/MySwiftLibrary.swift @@ -39,63 +39,10 @@ public func globalCallMeRunnable(run: () -> ()) { run() } -public class MySwiftClass { - - public var len: Int - public var cap: Int - - public init(len: Int, cap: Int) { - self.len = len - self.cap = cap - - p("\(MySwiftClass.self).len = \(self.len)") - p("\(MySwiftClass.self).cap = \(self.cap)") - let addr = unsafeBitCast(self, to: UInt64.self) - p("initializer done, self = 0x\(String(addr, radix: 16, uppercase: true))") - } - - deinit { - let addr = unsafeBitCast(self, to: UInt64.self) - p("Deinit, self = 0x\(String(addr, radix: 16, uppercase: true))") - } - - public var counter: Int32 = 0 - - public func voidMethod() { - p("") - } - - public func takeIntMethod(i: Int) { - p("i:\(i)") - } - - public func echoIntMethod(i: Int) -> Int { - p("i:\(i)") - return i - } - - public func makeIntMethod() -> Int { - p("make int -> 12") - return 12 - } - - public func makeRandomIntMethod() -> Int { - return Int.random(in: 1..<256) - } -} - // ==== Internal helpers -private func p(_ msg: String, file: String = #fileID, line: UInt = #line, function: String = #function) { +func p(_ msg: String, file: String = #fileID, line: UInt = #line, function: String = #function) { print("[swift][\(file):\(line)](\(function)) \(msg)") fflush(stdout) } -#if os(Linux) -// FIXME: why do we need this workaround? -@_silgen_name("_objc_autoreleaseReturnValue") -public func _objc_autoreleaseReturnValue(a: Any) {} - -@_silgen_name("objc_autoreleaseReturnValue") -public func objc_autoreleaseReturnValue(a: Any) {} -#endif diff --git a/Samples/SwiftAndJavaJarSampleLib/build.gradle b/Samples/SwiftAndJavaJarSampleLib/build.gradle index 2125011d..cc4c79d4 100644 --- a/Samples/SwiftAndJavaJarSampleLib/build.gradle +++ b/Samples/SwiftAndJavaJarSampleLib/build.gradle @@ -38,7 +38,7 @@ repositories { java { toolchain { - languageVersion.set(JavaLanguageVersion.of(22)) + languageVersion.set(JavaLanguageVersion.of(24)) } } @@ -49,38 +49,56 @@ dependencies { testImplementation("org.junit.jupiter:junit-jupiter") } -// This is for development, when we edit the Swift swift-java project, the outputs of the generated sources may change. -// Thus, we also need to watch and re-build the top level project. -def compileSwiftJExtractPlugin = tasks.register("compileSwiftJExtractPlugin", Exec) { - description = "Rebuild the swift-java root project" +def swiftProductsWithJExtractPlugin() { + def stdout = new ByteArrayOutputStream() + def stderr = new ByteArrayOutputStream() - inputs.file(new File(rootDir, "Package.swift")) - inputs.dir(new File(rootDir, "Sources")) - outputs.dir(new File(rootDir, ".build")) + def result = exec { + commandLine 'swift', 'package', 'describe', '--type', 'json' + standardOutput = stdout + errorOutput = stderr + ignoreExitValue = true + } + + def jsonOutput = stdout.toString() + + if (result.exitValue == 0) { + def json = new JsonSlurper().parseText(jsonOutput) + def products = json.targets + .findAll { target -> + target.product_dependencies?.contains("JExtractSwiftPlugin") + } + .collectMany { target -> + target.product_memberships ?: [] + } + return products + } else { + logger.warn("Command failed: ${stderr.toString()}") + return [] + } +} - workingDir = rootDir +def swiftCheckValid = tasks.register("swift-check-valid", Exec) { commandLine "swift" - args("build", - "-c", swiftBuildConfiguration(), - "--product", "SwiftKitSwift", - "--product", "JExtractSwiftPlugin", - "--product", "JExtractSwiftCommandPlugin") + args("-version") } def jextract = tasks.register("jextract", Exec) { - description = "Builds swift sources, including swift-java source generation" - dependsOn compileSwiftJExtractPlugin + description = "Generate Java wrappers for swift target" + dependsOn swiftCheckValid // only because we depend on "live developing" the plugin while using this project to test it inputs.file(new File(rootDir, "Package.swift")) inputs.dir(new File(rootDir, "Sources")) + // If the package description changes, we should execute jextract again, maybe we added jextract to new targets inputs.file(new File(projectDir, "Package.swift")) - inputs.dir(new File(projectDir, "Sources")) - // TODO: we can use package describe --type json to figure out which targets depend on JExtractSwiftPlugin and will produce outputs - // Avoid adding this directory, but create the expected one specifically for all targets - // which WILL produce sources because they have the plugin + // monitor all targets/products which depend on the JExtract plugin + swiftProductsWithJExtractPlugin().each { + logger.info("[swift-java:jextract (Gradle)] Swift input target: ${it}") + inputs.dir(new File(layout.projectDirectory.asFile, "Sources/${it}".toString())) + } outputs.dir(layout.buildDirectory.dir("../.build/plugins/outputs/${layout.projectDirectory.asFile.getName().toLowerCase()}")) File baseSwiftPluginOutputsDir = layout.buildDirectory.dir("../.build/plugins/outputs/").get().asFile @@ -96,7 +114,16 @@ def jextract = tasks.register("jextract", Exec) { workingDir = layout.projectDirectory commandLine "swift" - args("package", "jextract", "-v", "--log-level", "info") // TODO: pass log level from Gradle build + args("build") // since Swift targets which need to be jextract-ed have the jextract build plugin, we just need to build + // If we wanted to execute a specific subcommand, we can like this: + // args("run",/* + // "swift-java", "jextract", + // "--swift-module", "MySwiftLibrary", + // // java.package is obtained from the swift-java.config in the swift module + // "--output-java", "${layout.buildDirectory.dir(".build/plugins/outputs/${layout.projectDirectory.asFile.getName().toLowerCase()}/JExtractSwiftPlugin/src/generated/java").get()}", + // "--output-swift", "${layout.buildDirectory.dir(".build/plugins/outputs/${layout.projectDirectory.asFile.getName().toLowerCase()}/JExtractSwiftPlugin/Sources").get()}", + // "--log-level", (logging.level <= LogLevel.INFO ? "debug" : */"info") + // ) } @@ -126,7 +153,6 @@ tasks.named('test', Test) { // ==== Jar publishing List swiftProductDylibPaths() { - def process = ['swift', 'package', 'describe', '--type', 'json'].execute() process.waitFor() @@ -143,8 +169,6 @@ List swiftProductDylibPaths() { target.product_memberships }.flatten() - - def productDylibPaths = products.collect { logger.info("[swift-java] Include Swift product: '${it}' in product resource paths.") "${layout.projectDirectory}/.build/${swiftBuildConfiguration()}/lib${it}.dylib" diff --git a/Samples/SwiftAndJavaJarSampleLib/ci-validate.sh b/Samples/SwiftAndJavaJarSampleLib/ci-validate.sh new file mode 100755 index 00000000..1b4769e8 --- /dev/null +++ b/Samples/SwiftAndJavaJarSampleLib/ci-validate.sh @@ -0,0 +1,56 @@ +#!/bin/sh + +set -e +set -x + +./gradlew jar + +SWIFT_VERSION="$(swift -version | awk '/Swift version/ { print $3 }')" + +# we make sure to build and run with JDK 24 because the runtime needs latest JDK, unlike Gradle which needed 21. +if [ "$(uname -s)" = 'Darwin' ] +then + export OS='osx' +elif [ "$(uname -s)" = 'Linux' ] +then + export OS='linux' + export PATH="${PATH}:/usr/lib/jvm/jdk-24/bin" # we need to make sure to use the latest JDK to actually compile/run the executable +fi + +# check if we can compile a plain Example file that uses the generated Java bindings that should be in the generated jar +# The classpath MUST end with a * if it contains jar files, and must not if it directly contains class files. +SWIFTKIT_CLASSPATH="$(pwd)/../../SwiftKit/build/libs/*" +MYLIB_CLASSPATH="$(pwd)/build/libs/*" +CLASSPATH="$(pwd)/:${SWIFTKIT_CLASSPATH}:${MYLIB_CLASSPATH}" +echo "CLASSPATH = ${CLASSPATH}" + +javac -cp "${CLASSPATH}" Example.java + +if [ "$(uname -s)" = 'Linux' ] +then + SWIFT_LIB_PATHS=/usr/lib/swift/linux + SWIFT_LIB_PATHS="${SWIFT_LIB_PATHS}:$(find . | grep libMySwiftLibrary.so$ | sort | head -n1 | xargs dirname)" + + # if we are on linux, find the Swiftly or System-wide installed libraries dir + SWIFT_CORE_LIB=$(find "$HOME"/.local -name "libswiftCore.so" 2>/dev/null | grep "$SWIFT_VERSION" | head -n1) + if [ -n "$SWIFT_CORE_LIB" ]; then + SWIFT_LIB_PATHS="${SWIFT_LIB_PATHS}:$(dirname "$SWIFT_CORE_LIB")" + else + # maybe there is one installed system-wide in /usr/lib? + SWIFT_CORE_LIB2=$(find /usr/lib -name "libswiftCore.so" 2>/dev/null | grep "$SWIFT_VERSION" | head -n1) + if [ -n "$SWIFT_CORE_LIB2" ]; then + SWIFT_LIB_PATHS="${SWIFT_LIB_PATHS}:$(dirname "$SWIFT_CORE_LIB2")" + fi + fi +elif [ "$(uname -s)" = 'Darwin' ] +then + SWIFT_LIB_PATHS=$(find "$(swiftly use --print-location)" | grep dylib$ | grep libswiftCore | grep macos | xargs dirname) + SWIFT_LIB_PATHS="${SWIFT_LIB_PATHS}:$(pwd)/$(find . | grep libMySwiftLibrary.dylib$ | sort | head -n1 | xargs dirname)" +fi +echo "SWIFT_LIB_PATHS = ${SWIFT_LIB_PATHS}" + +# Can we run the example? +java --enable-native-access=ALL-UNNAMED \ + -Djava.library.path="${SWIFT_LIB_PATHS}" \ + -cp "${CLASSPATH}" \ + Example diff --git a/Samples/SwiftKitSampleApp/Package.swift b/Samples/SwiftKitSampleApp/Package.swift index 65de7d3a..34d8fcd3 100644 --- a/Samples/SwiftKitSampleApp/Package.swift +++ b/Samples/SwiftKitSampleApp/Package.swift @@ -43,7 +43,7 @@ let javaIncludePath = "\(javaHome)/include" let package = Package( name: "SwiftKitSampleApp", platforms: [ - .macOS(.v10_15) + .macOS(.v15) ], products: [ .library( diff --git a/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/_RuntimeWorkarounds.swift b/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/_RuntimeWorkarounds.swift deleted file mode 100644 index f3056973..00000000 --- a/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/_RuntimeWorkarounds.swift +++ /dev/null @@ -1,22 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of Swift.org project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -#if os(Linux) -// FIXME: why do we need this workaround? -@_silgen_name("_objc_autoreleaseReturnValue") -public func _objc_autoreleaseReturnValue(a: Any) {} - -@_silgen_name("objc_autoreleaseReturnValue") -public func objc_autoreleaseReturnValue(a: Any) {} -#endif diff --git a/Samples/SwiftKitSampleApp/build.gradle b/Samples/SwiftKitSampleApp/build.gradle index 18a55f44..647eaba9 100644 --- a/Samples/SwiftKitSampleApp/build.gradle +++ b/Samples/SwiftKitSampleApp/build.gradle @@ -12,9 +12,11 @@ // //===----------------------------------------------------------------------===// +import groovy.json.JsonSlurper import org.swift.swiftkit.gradle.BuildUtils import java.nio.file.* +import kotlinx.serialization.json.* plugins { id("build-logic.java-application-conventions") @@ -30,42 +32,61 @@ repositories { java { toolchain { - languageVersion.set(JavaLanguageVersion.of(22)) + languageVersion.set(JavaLanguageVersion.of(24)) } } +def swiftProductsWithJExtractPlugin() { + def stdout = new ByteArrayOutputStream() + def stderr = new ByteArrayOutputStream() -// This is for development, when we edit the Swift swift-java project, the outputs of the generated sources may change. -// Thus, we also need to watch and re-build the top level project. -def compileSwiftJExtractPlugin = tasks.register("compileSwiftJExtractPlugin", Exec) { - description = "Rebuild the swift-java root project" + def result = exec { + commandLine 'swift', 'package', 'describe', '--type', 'json' + standardOutput = stdout + errorOutput = stderr + ignoreExitValue = true + } + + def jsonOutput = stdout.toString() + + if (result.exitValue == 0) { + def json = new JsonSlurper().parseText(jsonOutput) + def products = json.targets + .findAll { target -> + target.product_dependencies?.contains("JExtractSwiftPlugin") + } + .collectMany { target -> + target.product_memberships ?: [] + } + return products + } else { + logger.warn("Command failed: ${stderr.toString()}") + return [] + } +} - inputs.file(new File(rootDir, "Package.swift")) - inputs.dir(new File(rootDir, "Sources")) - outputs.dir(new File(rootDir, ".build")) - workingDir = rootDir +def swiftCheckValid = tasks.register("swift-check-valid", Exec) { commandLine "swift" - args("build", - "--product", "SwiftKitSwift", - "--product", "JExtractSwiftPlugin", - "--product", "JExtractSwiftCommandPlugin") + args("-version") } def jextract = tasks.register("jextract", Exec) { - description = "Builds swift sources, including swift-java source generation" - dependsOn compileSwiftJExtractPlugin + description = "Generate Java wrappers for swift target" + dependsOn swiftCheckValid // only because we depend on "live developing" the plugin while using this project to test it inputs.file(new File(rootDir, "Package.swift")) inputs.dir(new File(rootDir, "Sources")) + // If the package description changes, we should execute jextract again, maybe we added jextract to new targets inputs.file(new File(projectDir, "Package.swift")) - inputs.dir(new File(projectDir, "Sources")) - // TODO: we can use package describe --type json to figure out which targets depend on JExtractSwiftPlugin and will produce outputs - // Avoid adding this directory, but create the expected one specifically for all targets - // which WILL produce sources because they have the plugin + // monitor all targets/products which depend on the JExtract plugin + swiftProductsWithJExtractPlugin().each { + logger.info("[swift-java:jextract (Gradle)] Swift input target: ${it}") + inputs.dir(new File(layout.projectDirectory.asFile, "Sources/${it}".toString())) + } outputs.dir(layout.buildDirectory.dir("../.build/plugins/outputs/${layout.projectDirectory.asFile.getName().toLowerCase()}")) File baseSwiftPluginOutputsDir = layout.buildDirectory.dir("../.build/plugins/outputs/").get().asFile @@ -81,7 +102,16 @@ def jextract = tasks.register("jextract", Exec) { workingDir = layout.projectDirectory commandLine "swift" - args("package", "jextract", "-v", "--log-level", "debug") // TODO: pass log level from Gradle build + args("build") // since Swift targets which need to be jextract-ed have the jextract build plugin, we just need to build + // If we wanted to execute a specific subcommand, we can like this: + // args("run",/* + // "swift-java", "jextract", + // "--swift-module", "MySwiftLibrary", + // // java.package is obtained from the swift-java.config in the swift module + // "--output-java", "${layout.buildDirectory.dir(".build/plugins/outputs/${layout.projectDirectory.asFile.getName().toLowerCase()}/JExtractSwiftPlugin/src/generated/java").get()}", + // "--output-swift", "${layout.buildDirectory.dir(".build/plugins/outputs/${layout.projectDirectory.asFile.getName().toLowerCase()}/JExtractSwiftPlugin/Sources").get()}", + // "--log-level", (logging.level <= LogLevel.INFO ? "debug" : */"info") + // ) } // Add the java-swift generated Java sources diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+SwiftThunkPrinting.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+SwiftThunkPrinting.swift index 02d715a0..54ce0d72 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+SwiftThunkPrinting.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+SwiftThunkPrinting.swift @@ -21,6 +21,19 @@ extension FFMSwift2JavaGenerator { try writeSwiftThunkSources(printer: &printer) } + package func writeSwiftExpectedEmptySources() throws { + for expectedFileName in self.expectedOutputSwiftFiles { + log.trace("Write empty file: \(expectedFileName) ...") + + var printer = CodePrinter() + printer.print("// Empty file generated on purpose") + try printer.writeContents( + outputDirectory: self.swiftOutputDirectory, + javaPackagePath: nil, + filename: expectedFileName) + } + } + package func writeSwiftThunkSources(printer: inout CodePrinter) throws { let moduleFilenameBase = "\(self.swiftModuleName)Module+SwiftJava" let moduleFilename = "\(moduleFilenameBase).swift" @@ -32,15 +45,16 @@ extension FFMSwift2JavaGenerator { if let outputFile = try printer.writeContents( outputDirectory: self.swiftOutputDirectory, javaPackagePath: nil, - filename: moduleFilename) - { - print("[swift-java] Generated: \(moduleFilenameBase.bold).swift (at \(outputFile)") + filename: moduleFilename) { + print("[swift-java] Generated: \(moduleFilenameBase.bold).swift (at \(outputFile))") + self.expectedOutputSwiftFiles.remove(moduleFilename) } } catch { log.warning("Failed to write to Swift thunks: \(moduleFilename)") } // === All types + // FIXME: write them all into the same file they were declared from +SwiftJava for (_, ty) in self.analysis.importedTypes.sorted(by: { (lhs, rhs) in lhs.key < rhs.key }) { let fileNameBase = "\(ty.swiftNominal.qualifiedName)+SwiftJava" let filename = "\(fileNameBase).swift" @@ -52,9 +66,9 @@ extension FFMSwift2JavaGenerator { if let outputFile = try printer.writeContents( outputDirectory: self.swiftOutputDirectory, javaPackagePath: nil, - filename: filename) - { - print("[swift-java] Generated: \(fileNameBase.bold).swift (at \(outputFile)") + filename: filename) { + print("[swift-java] Generated: \(fileNameBase.bold).swift (at \(outputFile))") + self.expectedOutputSwiftFiles.remove(filename) } } catch { log.warning("Failed to write to Swift thunks: \(filename)") diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift index 4a65f7cc..09fcf858 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift @@ -15,6 +15,7 @@ import JavaTypes import SwiftSyntax import SwiftSyntaxBuilder +import struct Foundation.URL package class FFMSwift2JavaGenerator: Swift2JavaGenerator { let log: Logger @@ -35,6 +36,9 @@ package class FFMSwift2JavaGenerator: Swift2JavaGenerator { /// Cached Java translation result. 'nil' indicates failed translation. var translatedDecls: [ImportedFunc: TranslatedFunctionDecl?] = [:] + /// Because we need to write empty files for SwiftPM, keep track which files we didn't write yet, + /// and write an empty file for those. + var expectedOutputSwiftFiles: Set package init( translator: Swift2JavaTranslator, @@ -50,6 +54,20 @@ package class FFMSwift2JavaGenerator: Swift2JavaGenerator { self.javaOutputDirectory = javaOutputDirectory self.symbolTable = translator.symbolTable self.swiftStdlibTypes = translator.swiftStdlibTypeDecls + + // If we are forced to write empty files, construct the expected outputs + if translator.config.writeEmptyFiles ?? false { + self.expectedOutputSwiftFiles = Set(translator.inputs.compactMap { (input) -> String? in + guard let filePathPart = input.filePath.split(separator: "/\(translator.swiftModuleName)/").last else { + return nil + } + + return String(filePathPart.replacing(".swift", with: "+SwiftJava.swift")) + }) + self.expectedOutputSwiftFiles.insert("\(translator.swiftModuleName)Module+SwiftJava.swift") + } else { + self.expectedOutputSwiftFiles = [] + } } func generate() throws { @@ -58,6 +76,12 @@ package class FFMSwift2JavaGenerator: Swift2JavaGenerator { try writeExportedJavaSources() print("[swift-java] Generated Java sources (package: '\(javaPackage)') in: \(javaOutputDirectory)/") + + let pendingFileCount = self.expectedOutputSwiftFiles.count + if pendingFileCount > 0 { + print("[swift-java] Write empty [\(pendingFileCount)] 'expected' files in: \(swiftOutputDirectory)/") + try writeSwiftExpectedEmptySources() + } } } diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator.swift index b15688dc..8ec4b437 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator.swift @@ -87,7 +87,7 @@ extension JNISwift2JavaGenerator { javaPackagePath: javaPackagePath, filename: moduleFilename ) { - print("[swift-java] Generated: \(moduleFilenameBase.bold).swift (at \(outputFile)") + print("[swift-java] Generated: \(moduleFilenameBase.bold).swift (at \(outputFile))") } } catch { logger.warning("Failed to write to Swift thunks: \(moduleFilename)") diff --git a/Sources/JExtractSwiftLib/Swift2Java.swift b/Sources/JExtractSwiftLib/Swift2Java.swift index 9b1b06bc..dad25299 100644 --- a/Sources/JExtractSwiftLib/Swift2Java.swift +++ b/Sources/JExtractSwiftLib/Swift2Java.swift @@ -30,21 +30,18 @@ public struct SwiftToJava { fatalError("Missing '--swift-module' name.") } - let translator = Swift2JavaTranslator( - swiftModuleName: swiftModule - ) + let translator = Swift2JavaTranslator(config: config) translator.log.logLevel = config.logLevel ?? .info if config.javaPackage == nil || config.javaPackage!.isEmpty { translator.log.warning("Configured java package is '', consider specifying concrete package for generated sources.") } - print("===== CONFIG ==== \(config)") - guard let inputSwift = config.inputSwiftDirectory else { fatalError("Missing '--swift-input' directory!") } + translator.log.info("Input swift = \(inputSwift)") let inputPaths = inputSwift.split(separator: ",").map { URL(string: String($0))! } translator.log.info("Input paths = \(inputPaths)") diff --git a/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift b/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift index 857a053a..07d8cafb 100644 --- a/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift +++ b/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift @@ -16,6 +16,7 @@ import Foundation import JavaTypes import SwiftBasicFormat import SwiftParser +import JavaKitConfigurationShared import SwiftSyntax /// Takes swift interfaces and translates them into Java used to access those. @@ -24,6 +25,8 @@ public final class Swift2JavaTranslator { package var log = Logger(label: "translator", logLevel: .info) + let config: Configuration + // ==== Input struct Input { @@ -53,9 +56,13 @@ public final class Swift2JavaTranslator { } public init( - swiftModuleName: String + config: Configuration ) { - self.symbolTable = SwiftSymbolTable(parsedModuleName: swiftModuleName) + guard let swiftModule = config.swiftModule else { + fatalError("Missing 'swiftModule' name.") // FIXME: can we make it required in config? but we shared config for many cases + } + self.config = config + self.symbolTable = SwiftSymbolTable(parsedModuleName: swiftModule) // Create a mock of the Swift standard library. var parsedSwiftModule = SwiftParsedModuleSymbolTable(moduleName: "Swift") diff --git a/Sources/JavaKitConfigurationShared/Configuration.swift b/Sources/JavaKitConfigurationShared/Configuration.swift index 2298b9fa..876b577b 100644 --- a/Sources/JavaKitConfigurationShared/Configuration.swift +++ b/Sources/JavaKitConfigurationShared/Configuration.swift @@ -2,7 +2,7 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Copyright (c) 2024-2025 Apple Inc. and the Swift.org project authors // Licensed under Apache License v2.0 // // See LICENSE.txt for license information @@ -38,19 +38,17 @@ public struct Configuration: Codable { public var outputJavaDirectory: String? - public var mode: GenerationMode? + public var mode: JExtractGenerationMode? + + public var writeEmptyFiles: Bool? // FIXME: default it to false, but that plays not nice with Codable // ==== java 2 swift --------------------------------------------------------- - /// The Java class path that should be passed along to the Java2Swift tool. + /// The Java class path that should be passed along to the swift-java tool. public var classpath: String? = nil public var classpathEntries: [String] { - guard let classpath else { - return [] - } - - return classpath.split(separator: ":").map(String.init) + return classpath?.split(separator: ":").map(String.init) ?? [] } /// The Java classes that should be translated to Swift. The keys are @@ -80,6 +78,12 @@ public struct JavaDependencyDescriptor: Hashable, Codable { public var artifactID: String public var version: String + public init(groupID: String, artifactID: String, version: String) { + self.groupID = groupID + self.artifactID = artifactID + self.version = version + } + public init(from decoder: any Decoder) throws { let container = try decoder.singleValueContainer() let string = try container.decode(String.self) @@ -154,7 +158,7 @@ public func findSwiftJavaClasspaths(in basePath: String = FileManager.default.cu let baseURL = URL(fileURLWithPath: basePath) var classpathEntries: [String] = [] - print("[debug][swift-java] Searching for *.swift-java.classpath files in: \(baseURL)") + print("[debug][swift-java] Searching for *.swift-java.classpath files in: \(baseURL.absoluteString)") guard let enumerator = fileManager.enumerator(at: baseURL, includingPropertiesForKeys: []) else { print("[warning][swift-java] Failed to get enumerator for \(baseURL)") return [] @@ -162,7 +166,7 @@ public func findSwiftJavaClasspaths(in basePath: String = FileManager.default.cu for case let fileURL as URL in enumerator { if fileURL.lastPathComponent.hasSuffix(".swift-java.classpath") { - print("[debug][swift-java] Constructing classpath with entries from: \(fileURL.relativePath)") + print("[debug][swift-java] Constructing classpath with entries from: \(fileURL.path)") if let contents = try? String(contentsOf: fileURL) { let entries = contents.split(separator: ":").map(String.init) for entry in entries { diff --git a/Sources/JavaKitConfigurationShared/GenerationMode.swift b/Sources/JavaKitConfigurationShared/GenerationMode.swift index ea30a436..b4a96476 100644 --- a/Sources/JavaKitConfigurationShared/GenerationMode.swift +++ b/Sources/JavaKitConfigurationShared/GenerationMode.swift @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -public enum GenerationMode: String, Codable { +public enum JExtractGenerationMode: String, Codable { /// Foreign Value and Memory API case ffm diff --git a/Sources/JavaKitConfigurationShared/GradleDependencyParsing.swift b/Sources/JavaKitConfigurationShared/GradleDependencyParsing.swift new file mode 100644 index 00000000..bd4aada3 --- /dev/null +++ b/Sources/JavaKitConfigurationShared/GradleDependencyParsing.swift @@ -0,0 +1,48 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import Foundation + +// Regex is not sendable yet so we can't cache it in a let +fileprivate var GradleDependencyDescriptorRegex: Regex<(Substring, Substring, Substring, Substring)> { + try! Regex(#"^([^:]+):([^:]+):(\d[^:]+)$"#) // TODO: improve the regex to be more precise +} + +// note: can't use `package` access level since it would break in usage in plugins in `_PluginsShared`. +public func parseDependencyDescriptor(_ descriptor: String) -> JavaDependencyDescriptor? { + guard let match = try? GradleDependencyDescriptorRegex.firstMatch(in: descriptor) else { + return nil + } + + let groupID = String(match.1) + let artifactID = String(match.2) + let version = String(match.3) + + return JavaDependencyDescriptor(groupID: groupID, artifactID: artifactID, version: version) +} + +// note: can't use `package` access level since it would break in usage in plugins in `_PluginsShared`. +public func parseDependencyDescriptors(_ string: String) -> [JavaDependencyDescriptor] { + let descriptors = string.components(separatedBy: ",") + var parsedDependencies: [JavaDependencyDescriptor] = [] + parsedDependencies.reserveCapacity(descriptors.count) + + for descriptor in descriptors { + if let dependency = parseDependencyDescriptor(descriptor) { + parsedDependencies.append(dependency) + } + } + + return parsedDependencies +} \ No newline at end of file diff --git a/Sources/SwiftJavaLib/JavaTranslator+Configuration.swift b/Sources/SwiftJavaLib/JavaTranslator+Configuration.swift index e0f6d0cb..0f764633 100644 --- a/Sources/SwiftJavaLib/JavaTranslator+Configuration.swift +++ b/Sources/SwiftJavaLib/JavaTranslator+Configuration.swift @@ -16,11 +16,11 @@ import Foundation import JavaKitConfigurationShared extension JavaTranslator { - /// Read a configuration file from the given URL. - package static func readConfiguration(from url: URL) throws -> Configuration { - let contents = try Data(contentsOf: url) - return try JSONDecoder().decode(Configuration.self, from: contents) - } +// /// Read a configuration file from the given URL. +// package static func readConfiguration(from url: URL) throws -> Configuration { +// let contents = try Data(contentsOf: url) +// return try JSONDecoder().decode(Configuration.self, from: contents) +// } /// Load the configuration file with the given name to populate the known set of /// translated Java classes. diff --git a/Sources/SwiftJavaTool/Commands/ConfigureCommand.swift b/Sources/SwiftJavaTool/Commands/ConfigureCommand.swift index 8574888d..2355ea81 100644 --- a/Sources/SwiftJavaTool/Commands/ConfigureCommand.swift +++ b/Sources/SwiftJavaTool/Commands/ConfigureCommand.swift @@ -66,42 +66,11 @@ extension SwiftJava { extension SwiftJava.ConfigureCommand { mutating func runSwiftJavaCommand(config: inout Configuration) async throws { - // Form a class path from all of our input sources: - // * Command-line option --classpath - let classpathOptionEntries: [String] = self.commonJVMOptions.classpath.flatMap { $0.split(separator: ":").map(String.init) } - let classpathFromEnv = ProcessInfo.processInfo.environment["CLASSPATH"]?.split(separator: ":").map(String.init) ?? [] - let classpathFromConfig: [String] = config.classpath?.split(separator: ":").map(String.init) ?? [] - print("[debug][swift-java] Base classpath from config: \(classpathFromConfig)") - - var classpathEntries: [String] = classpathFromConfig - - let swiftJavaCachedModuleClasspath = findSwiftJavaClasspaths(in: - // self.effectiveCacheDirectory ?? - FileManager.default.currentDirectoryPath) - print("[debug][swift-java] Classpath from *.swift-java.classpath files: \(swiftJavaCachedModuleClasspath)") - classpathEntries += swiftJavaCachedModuleClasspath - - if !classpathOptionEntries.isEmpty { - print("[debug][swift-java] Classpath from options: \(classpathOptionEntries)") - classpathEntries += classpathOptionEntries - } else { - // * Base classpath from CLASSPATH env variable - print("[debug][swift-java] Classpath from environment: \(classpathFromEnv)") - classpathEntries += classpathFromEnv - } - - let extraClasspath = input ?? "" // FIXME: just use the -cp as usual - let extraClasspathEntries = extraClasspath.split(separator: ":").map(String.init) - print("[debug][swift-java] Extra classpath: \(extraClasspathEntries)") - classpathEntries += extraClasspathEntries + let classpathEntries = self.configureCommandJVMClasspath( + searchDirs: [self.effectiveSwiftModuleURL], config: config) - // Bring up the Java VM when necessary - - if logLevel >= .debug { - let classpathString = classpathEntries.joined(separator: ":") - print("[debug][swift-java] Initialize JVM with classpath: \(classpathString)") - } - let jvm = try JavaVirtualMachine.shared(classpath: classpathEntries) + let jvm = + try self.makeJVM(classpathEntries: classpathEntries) try emitConfiguration(classpath: self.commonJVMOptions.classpath, environment: jvm.environment()) } @@ -178,6 +147,7 @@ extension SwiftJava.ConfigureCommand { // Write the file. try writeContents( contents, + outputDirectory: self.actualOutputDirectory, to: "swift-java.config", description: "swift-java configuration file" ) diff --git a/Sources/SwiftJavaTool/Commands/JExtractCommand.swift b/Sources/SwiftJavaTool/Commands/JExtractCommand.swift new file mode 100644 index 00000000..c7fe51a8 --- /dev/null +++ b/Sources/SwiftJavaTool/Commands/JExtractCommand.swift @@ -0,0 +1,98 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import Foundation +import ArgumentParser +import SwiftJavaLib +import JavaKit +import JavaKitJar +import SwiftJavaLib +import JExtractSwiftLib +import JavaKitConfigurationShared + +/// Extract Java bindings from Swift sources or interface files. +/// +/// Example usage: +/// ``` +/// > swift-java jextract +// --input-swift Sources/SwiftyBusiness \ +/// --output-swift .build/.../outputs/SwiftyBusiness \ +/// --output-Java .build/.../outputs/Java +/// ``` +extension SwiftJava { + + struct JExtractCommand: SwiftJavaBaseAsyncParsableCommand, HasCommonOptions { + static let configuration = CommandConfiguration( + commandName: "jextract", // TODO: wrap-swift? + abstract: "Wrap Swift functions and types with Java bindings, making them available to be called from Java") + + @OptionGroup var commonOptions: SwiftJava.CommonOptions + + @Option(help: "The mode of generation to use for the output files. Used with jextract mode.") + var mode: JExtractGenerationMode = .ffm + + @Option(help: "The name of the Swift module into which the resulting Swift types will be generated.") + var swiftModule: String + + var effectiveSwiftModule: String { + swiftModule + } + + @Option(help: "The Java package the generated Java code should be emitted into.") + var javaPackage: String? = nil + + @Option(help: "The directory where generated Swift files should be written. Generally used with jextract mode.") + var outputSwift: String + + @Option(help: "The directory where generated Java files should be written. Generally used with jextract mode.") + var outputJava: String + + @Flag(help: "Some build systems require an output to be present when it was 'expected', even if empty. This is used by the JExtractSwiftPlugin build plugin, but otherwise should not be necessary.") + var writeEmptyFiles: Bool = false + } +} + +extension SwiftJava.JExtractCommand { + func runSwiftJavaCommand(config: inout Configuration) async throws { + if let javaPackage { + config.javaPackage = javaPackage + } + config.swiftModule = self.effectiveSwiftModule + config.outputJavaDirectory = outputJava + config.outputSwiftDirectory = outputSwift + config.writeEmptyFiles = writeEmptyFiles + + if let inputSwift = commonOptions.inputSwift { + config.inputSwiftDirectory = inputSwift + } else if let swiftModule = config.swiftModule { + // This is a "good guess" technically a target can be somewhere else, but then you can use --input-swift + config.inputSwiftDirectory = "\(FileManager.default.currentDirectoryPath)/Sources/\(swiftModule)" + } + + print("[debug][swift-java] Running 'swift-java jextract' in mode: " + "\(self.mode)".bold) + + try jextractSwift(config: config) + } +} + +extension SwiftJava.JExtractCommand { + func jextractSwift( + config: Configuration + ) throws { + try SwiftToJava(config: config).run() + } + +} + +extension JExtractGenerationMode: ExpressibleByArgument {} diff --git a/Sources/SwiftJavaTool/Commands/ResolveCommand.swift b/Sources/SwiftJavaTool/Commands/ResolveCommand.swift index eb96e490..4f022d71 100644 --- a/Sources/SwiftJavaTool/Commands/ResolveCommand.swift +++ b/Sources/SwiftJavaTool/Commands/ResolveCommand.swift @@ -22,14 +22,22 @@ import SwiftJavaLib import JavaKitConfigurationShared import JavaKitShared import _Subprocess +#if canImport(System) +import System +#else +@preconcurrency import SystemPackage +#endif + +typealias Configuration = JavaKitConfigurationShared.Configuration extension SwiftJava { - struct ResolveCommand: SwiftJavaBaseAsyncParsableCommand { + struct ResolveCommand: SwiftJavaBaseAsyncParsableCommand, HasCommonOptions, HasCommonJVMOptions { static let configuration = CommandConfiguration( commandName: "resolve", abstract: "Resolve dependencies and write the resulting swift-java.classpath file") @OptionGroup var commonOptions: SwiftJava.CommonOptions + @OptionGroup var commonJVMOptions: SwiftJava.CommonJVMOptions @Option(help: "The name of the Swift module into which the resulting Swift types will be generated.") var swiftModule: String @@ -38,31 +46,58 @@ extension SwiftJava { swiftModule } + @Argument( + help: """ + Additional configuration paths (swift-java.config) files, with defined 'dependencies', \ + or dependency descriptors formatted as 'groupID:artifactID:version' separated by ','. \ + May be empty, in which case the target Swift module's configuration's 'dependencies' will be used. + """ + ) + var input: String? } } extension SwiftJava.ResolveCommand { + var SwiftJavaClasspathPrefix: String { "SWIFT_JAVA_CLASSPATH:" } + var printRuntimeClasspathTaskName: String { "printRuntimeClasspath" } + mutating func runSwiftJavaCommand(config: inout Configuration) async throws { - fatalError("NOT IMPLEMENTED: resolve") - } -} + var dependenciesToResolve: [JavaDependencyDescriptor] = [] + if let input, let inputDependencies = parseDependencyDescriptor(input) { + dependenciesToResolve.append(inputDependencies) + } + if let dependencies = config.dependencies { + dependenciesToResolve += dependencies + } + if dependenciesToResolve.isEmpty { + print("[warn][swift-java] Attempted to 'resolve' dependencies but no dependencies specified in swift-java.config or command input!") + return + } + let dependenciesClasspath = + try await resolveDependencies(swiftModule: swiftModule, dependencies: dependenciesToResolve) -extension SwiftJava { - var SwiftJavaClasspathPrefix: String { "SWIFT_JAVA_CLASSPATH:" } + // FIXME: disentangle the output directory from SwiftJava and then make it a required option in this Command + guard let outputDirectory = self.commonOptions.outputDirectory else { + fatalError("error: Must specify --output-directory in 'resolve' mode! This option will become explicitly required") + } - var printRuntimeClasspathTaskName: String { "printRuntimeClasspath" } + try writeSwiftJavaClasspathFile( + swiftModule: swiftModule, + outputDirectory: outputDirectory, + resolvedClasspath: dependenciesClasspath) + } - func fetchDependencies(swiftModule: String, - dependencies: [JavaDependencyDescriptor]) async throws -> ResolvedDependencyClasspath { + func resolveDependencies( + swiftModule: String, dependencies: [JavaDependencyDescriptor] + ) async throws -> ResolvedDependencyClasspath { let deps = dependencies.map { $0.descriptionGradleStyle } print("[debug][swift-java] Resolve and fetch dependencies for: \(deps)") let dependenciesClasspath = await resolveDependencies(dependencies: dependencies) let classpathEntries = dependenciesClasspath.split(separator: ":") - print("[info][swift-java] Resolved classpath for \(deps.count) dependencies of '\(swiftModule)', classpath entries: \(classpathEntries.count), ", terminator: "") print("done.".green) @@ -88,37 +123,39 @@ extension SwiftJava { try! printGradleProject(directory: resolverDir, dependencies: dependencies) - let process = try! await Subprocess.run( - .at(.init(resolverDir.appendingPathComponent("gradlew").path)), - arguments: [ - "--no-daemon", - "--rerun-tasks", - "\(printRuntimeClasspathTaskName)", - ], - workingDirectory: .init(platformString: resolverDir.path) - ) - - let outString = String( - data: process.standardOutput, - encoding: .utf8 - ) - let errString = String( - data: process.standardError, - encoding: .utf8 - ) + if #available(macOS 15, *) { + let process = try! await _Subprocess.run( + .path(FilePath(resolverDir.appendingPathComponent("gradlew").path)), + arguments: [ + "--no-daemon", + "--rerun-tasks", + "\(printRuntimeClasspathTaskName)", + ], + workingDirectory: Optional(FilePath(resolverDir.path)), + // TODO: we could move to stream processing the outputs + output: .string(limit: Int.max, encoding: UTF8.self), // Don't limit output, we know it will be reasonable size + error: .string(limit: Int.max, encoding: UTF8.self) // Don't limit output, we know it will be reasonable size + ) + + let outString = process.standardOutput ?? "" + let errString = process.standardError ?? "" + + let classpathOutput: String + if let found = outString.split(separator: "\n").first(where: { $0.hasPrefix(self.SwiftJavaClasspathPrefix) }) { + classpathOutput = String(found) + } else if let found = errString.split(separator: "\n").first(where: { $0.hasPrefix(self.SwiftJavaClasspathPrefix) }) { + classpathOutput = String(found) + } else { + let suggestDisablingSandbox = "It may be that the Sandbox has prevented dependency fetching, please re-run with '--disable-sandbox'." + fatalError("Gradle output had no SWIFT_JAVA_CLASSPATH! \(suggestDisablingSandbox). \n" + + "Output was:<<<\(outString ?? "")>>>; Err was:<<<\(errString ?? "")>>>") + } - let classpathOutput: String - if let found = outString?.split(separator: "\n").first(where: { $0.hasPrefix(self.SwiftJavaClasspathPrefix) }) { - classpathOutput = String(found) - } else if let found = errString?.split(separator: "\n").first(where: { $0.hasPrefix(self.SwiftJavaClasspathPrefix) }) { - classpathOutput = String(found) + return String(classpathOutput.dropFirst(SwiftJavaClasspathPrefix.count)) } else { - let suggestDisablingSandbox = "It may be that the Sandbox has prevented dependency fetching, please re-run with '--disable-sandbox'." - fatalError("Gradle output had no SWIFT_JAVA_CLASSPATH! \(suggestDisablingSandbox). \n" + - "Output was:<<<\(outString ?? "")>>>; Err was:<<<\(errString ?? "")>>>") + // Subprocess is unavailable + fatalError("Subprocess is unavailable yet required to execute `gradlew` subprocess. Please update to macOS 15+") } - - return String(classpathOutput.dropFirst(SwiftJavaClasspathPrefix.count)) } func printGradleProject(directory: URL, dependencies: [JavaDependencyDescriptor]) throws { @@ -153,9 +190,9 @@ extension SwiftJava { try settingsGradleText.write(to: settingsGradle, atomically: true, encoding: .utf8) } - mutating func writeFetchedDependenciesClasspath( + mutating func writeSwiftJavaClasspathFile( swiftModule: String, - cacheDir: String, + outputDirectory: String, resolvedClasspath: ResolvedDependencyClasspath) throws { // Convert the artifact name to a module name // e.g. reactive-streams -> ReactiveStreams @@ -163,13 +200,14 @@ extension SwiftJava { // The file contents are just plain let contents = resolvedClasspath.classpath - print("[debug][swift-java] Resolved dependency: \(commonJVMOptions.classpath)") + let filename = "\(swiftModule).swift-java.classpath" + print("[debug][swift-java] Write resolved dependencies to: \(outputDirectory)/\(filename)") // Write the file try writeContents( contents, - outputDirectoryOverride: URL(fileURLWithPath: cacheDir), - to: "\(swiftModule).swift-java.classpath", + outputDirectory: URL(fileURLWithPath: outputDirectory), + to: filename, description: "swift-java.classpath file for module \(swiftModule)" ) } @@ -184,8 +222,6 @@ extension SwiftJava { var searchDir = URL(fileURLWithPath: FileManager.default.currentDirectoryPath) while searchDir.pathComponents.count > 1 { - print("[COPY] Search dir: \(searchDir)") - let gradlewFile = searchDir.appendingPathComponent("gradlew") let gradlewExists = FileManager.default.fileExists(atPath: gradlewFile.path) guard gradlewExists else { diff --git a/Sources/SwiftJavaTool/Commands/SwiftJava+JExtract.swift b/Sources/SwiftJavaTool/Commands/SwiftJava+JExtract.swift deleted file mode 100644 index 79c96d3e..00000000 --- a/Sources/SwiftJavaTool/Commands/SwiftJava+JExtract.swift +++ /dev/null @@ -1,40 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of Swift.org project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -import Foundation -import ArgumentParser -import SwiftJavaLib -import JavaKit -import JavaKitJar -import SwiftJavaLib -import JExtractSwiftLib -import JavaKitConfigurationShared - -/// Extract Java bindings from Swift sources or interface files. -/// -/// Example usage: -/// ``` -/// > swift-java --input-swift Sources/SwiftyBusiness \ -/// --output-swift .build/.../outputs/SwiftyBusiness \ -/// --output-Java .build/.../outputs/Java -/// ``` -extension SwiftJava { - - mutating func jextractSwift( - config: Configuration - ) throws { - try SwiftToJava(config: config).run() - } - -} diff --git a/Sources/SwiftJavaTool/Commands/SwiftJava+GenerateWrappers.swift b/Sources/SwiftJavaTool/Commands/WrapJavaCommand.swift similarity index 53% rename from Sources/SwiftJavaTool/Commands/SwiftJava+GenerateWrappers.swift rename to Sources/SwiftJavaTool/Commands/WrapJavaCommand.swift index 676b278d..349144ab 100644 --- a/Sources/SwiftJavaTool/Commands/SwiftJava+GenerateWrappers.swift +++ b/Sources/SwiftJavaTool/Commands/WrapJavaCommand.swift @@ -2,7 +2,7 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Copyright (c) 2024-2025 Apple Inc. and the Swift.org project authors // Licensed under Apache License v2.0 // // See LICENSE.txt for license information @@ -21,9 +21,109 @@ import SwiftJavaLib import JavaKitConfigurationShared extension SwiftJava { + + struct WrapJavaCommand: SwiftJavaBaseAsyncParsableCommand, HasCommonOptions, HasCommonJVMOptions { + static let configuration = CommandConfiguration( + commandName: "wrap-java", + abstract: "Wrap Java classes with corresponding Swift bindings.") + + @OptionGroup var commonOptions: SwiftJava.CommonOptions + @OptionGroup var commonJVMOptions: SwiftJava.CommonJVMOptions + + @Option(help: "The name of the Swift module into which the resulting Swift types will be generated.") + var swiftModule: String + + var effectiveSwiftModule: String { + swiftModule + } + + @Option( + help: """ + A swift-java configuration file for a given Swift module name on which this module depends, + e.g., JavaKitJar=Sources/JavaKitJar/Java2Swift.config. There should be one of these options + for each Swift module that this module depends on (transitively) that contains wrapped Java sources. + """ + ) + var dependsOn: [String] = [] + + @Option(help: "The names of Java classes whose declared native methods will be implemented in Swift.") + var swiftNativeImplementation: [String] = [] + + @Option(help: "Cache directory for intermediate results and other outputs between runs") + var cacheDirectory: String? + + @Argument(help: "Path to .jar file whose Java classes should be wrapped using Swift bindings") + var input: String + } +} + +extension SwiftJava.WrapJavaCommand { + + mutating func runSwiftJavaCommand(config: inout Configuration) async throws { + // Get base classpath configuration for this target and configuration + var classpathSearchDirs = [self.effectiveSwiftModuleURL] + if let cacheDir = self.cacheDirectory { + print("[trace][swift-java] Cache directory: \(cacheDir)") + classpathSearchDirs += [URL(fileURLWithPath: cacheDir)] + } else { + print("[trace][swift-java] Cache directory: none") + } + print("[trace][swift-java] INPUT: \(input)") + + var classpathEntries = self.configureCommandJVMClasspath( + searchDirs: classpathSearchDirs, config: config) + + // Load all of the dependent configurations and associate them with Swift modules. + let dependentConfigs = try self.loadDependentConfigs() + print("[debug][swift-java] Dependent configs: \(dependentConfigs.count)") + + // Include classpath entries which libs we depend on require... + for (fromModule, config) in dependentConfigs { + print("[trace][swift-java] Add dependent config (\(fromModule)) classpath elements: \(config.classpathEntries.count)") + // TODO: may need to resolve the dependent configs rather than just get their configs + // TODO: We should cache the resolved classpaths as well so we don't do it many times + for entry in config.classpathEntries { + print("[trace][swift-java] Add dependent config (\(fromModule)) classpath element: \(entry)") + classpathEntries.append(entry) + } + } + + let jvm = try self.makeJVM(classpathEntries: classpathEntries) + + try self.generateWrappers( + config: config, + // classpathEntries: classpathEntries, + dependentConfigs: dependentConfigs, + environment: jvm.environment() + ) + } +} + +extension SwiftJava.WrapJavaCommand { + + /// Load all dependent configs configured with `--depends-on` and return a list of + /// `(SwiftModuleName, Configuration)` tuples. + func loadDependentConfigs() throws -> [(String, Configuration)] { + try dependsOn.map { dependentConfig in + guard let equalLoc = dependentConfig.firstIndex(of: "=") else { + throw JavaToSwiftError.badConfigOption(dependentConfig) + } + + let afterEqual = dependentConfig.index(after: equalLoc) + let swiftModuleName = String(dependentConfig[.. [String] { + // Form a class path from all of our input sources: + // * Command-line option --classpath + let classpathOptionEntries: [String] = self.classpathEntries + let classpathFromEnv = ProcessInfo.processInfo.environment["CLASSPATH"]?.split(separator: ":").map(String.init) ?? [] + print("[debug][swift-java] Base classpath from CLASSPATH environment: \(classpathFromEnv)") + let classpathFromConfig: [String] = config.classpath?.split(separator: ":").map(String.init) ?? [] + print("[debug][swift-java] Base classpath from config: \(classpathFromConfig)") + + var classpathEntries: [String] = classpathFromConfig + + for searchDir in searchDirs { + let classPathFilesSearchDirectory = searchDir.path + print("[debug][swift-java] Search *.swift-java.classpath in: \(classPathFilesSearchDirectory)") + let foundSwiftJavaClasspath = findSwiftJavaClasspaths(in: classPathFilesSearchDirectory) + + print("[debug][swift-java] Classpath from *.swift-java.classpath files: \(foundSwiftJavaClasspath)") + classpathEntries += foundSwiftJavaClasspath + } + + if !classpathOptionEntries.isEmpty { + print("[debug][swift-java] Classpath from options: \(classpathOptionEntries)") + classpathEntries += classpathOptionEntries + } else { + // * Base classpath from CLASSPATH env variable + print("[debug][swift-java] Classpath from environment: \(classpathFromEnv)") + classpathEntries += classpathFromEnv + } + + let extraClasspath = self.commonJVMOptions.classpath + let extraClasspathEntries = extraClasspath.split(separator: ":").map(String.init) + print("[debug][swift-java] Extra classpath: \(extraClasspathEntries)") + classpathEntries += extraClasspathEntries + + // Bring up the Java VM when necessary + + // if logLevel >= .debug { + let classpathString = classpathEntries.joined(separator: ":") + print("[debug][swift-java] Initialize JVM with classpath: \(classpathString)") + // } + + return classpathEntries + } + + func makeJVM(classpathEntries: [String]) throws -> JavaVirtualMachine { + try JavaVirtualMachine.shared(classpath: classpathEntries) + } } \ No newline at end of file diff --git a/Sources/SwiftJavaTool/SwiftJava.swift b/Sources/SwiftJavaTool/SwiftJava.swift index 0e6e64ae..07eacce4 100644 --- a/Sources/SwiftJavaTool/SwiftJava.swift +++ b/Sources/SwiftJavaTool/SwiftJava.swift @@ -27,7 +27,7 @@ import JavaKitShared /// Command-line utility to drive the export of Java classes into Swift types. @main -struct SwiftJava: SwiftJavaBaseAsyncParsableCommand { // FIXME: this is just a normal async command, no parsing happening here +struct SwiftJava: AsyncParsableCommand { static var _commandName: String { "swift-java" } static let configuration = CommandConfiguration( @@ -35,257 +35,33 @@ struct SwiftJava: SwiftJavaBaseAsyncParsableCommand { // FIXME: this is just a n subcommands: [ ConfigureCommand.self, ResolveCommand.self, + WrapJavaCommand.self, + JExtractCommand.self ]) - @Option(help: "The name of the Swift module into which the resulting Swift types will be generated.") - var swiftModule: String? - - var effectiveSwiftModule: String { - swiftModule ?? "UnknownSwiftModule" - } - - @Option( - help: - "A Java2Swift configuration file for a given Swift module name on which this module depends, e.g., JavaKitJar=Sources/JavaKitJar/Java2Swift.config. There should be one of these options for each Swift module that this module depends on (transitively) that contains wrapped Java sources." - ) - var dependsOn: [String] = [] - - @Flag(help: "Fetch dependencies from given target (containing swift-java configuration) or dependency string") - var fetch: Bool = false - - @Option( - help: "The names of Java classes whose declared native methods will be implemented in Swift." - ) - var swiftNativeImplementation: [String] = [] - - @Option(help: "The directory where generated Swift files should be written. Generally used with jextract mode.") - var outputSwift: String? = nil - - @Option(help: "The directory where generated Java files should be written. Generally used with jextract mode.") - var outputJava: String? = nil - - @Option(help: "The Java package the generated Java code should be emitted into.") - var javaPackage: String? = nil - - @Option(help: "The mode of generation to use for the output files. Used with jextract mode.") - var mode: GenerationMode = .ffm - -// // TODO: clarify this vs outputSwift (history: outputSwift is jextract, and this was java2swift) -// @Option(name: .shortAndLong, help: "The directory in which to output the generated Swift files or the SwiftJava configuration file.") -// var outputDirectory: String? = nil - - @Option(name: .shortAndLong, help: "Directory where to write cached values (e.g. swift-java.classpath files)") - var cacheDirectory: String? = nil - - @OptionGroup var commonOptions: SwiftJava.CommonOptions - @OptionGroup var commonJVMOptions: SwiftJava.CommonJVMOptions - - var effectiveCacheDirectory: String? { - if let cacheDirectory { - return cacheDirectory - } else if let outputDirectory = commonOptions.outputDirectory { - return outputDirectory - } else { - return nil + public static func main() async { + do { + var command = try parseAsRoot(nil) + if var asyncCommand = command as? AsyncParsableCommand { + try await asyncCommand.run() + } else { + try command.run() + } + } catch { + print("Invocation: \(CommandLine.arguments.joined(separator: " "))") + exit(withError: error) } } - @Argument( - help: "The input file, which is either a Java2Swift configuration file or (if '-jar' was specified) a Jar file." - ) - var input: String? // FIXME: top level command cannot have input argument like this - - // FIXME: this is subcommands - /// Describes what kind of generation action is being performed by swift-java. - enum ToolMode { - // /// Generate a configuration file given a Jar file. - // case configuration(extraClasspath: String) // FIXME: this is more like "extract" configuration from classpath - - /// Generate Swift wrappers for Java classes based on the given - /// configuration. - case classWrappers - - /// Fetch dependencies for a module - case fetchDependencies - - /// Extract Java bindings from provided Swift sources. - case jextract // TODO: carry jextract specific config here? - } - - mutating func runSwiftJavaCommand(config: inout Configuration) async throws { - guard CommandLine.arguments.count > 2 else { + mutating func run() async throws { + guard CommandLine.arguments.count >= 2 else { // there's no "default" command, print USAGE when no arguments/parameters are passed. print("error: Must specify mode subcommand (e.g. configure, resolve, jextract, ...).\n\n\(Self.helpMessage())") return } - if let javaPackage { - config.javaPackage = javaPackage - } - - // Determine the mode in which we'll execute. - let toolMode: ToolMode - // TODO: some options are exclusive to each other so we should detect that - if let inputSwift = commonOptions.inputSwift { - guard let inputSwift = commonOptions.inputSwift else { - print("[swift-java] --input-swift enabled 'jextract' mode, however no --output-swift directory was provided!\n\(Self.helpMessage())") - return - } - guard let outputSwift else { - print("[swift-java] --output-swift enabled 'jextract' mode, however no --output-swift directory was provided!\n\(Self.helpMessage())") - return - } - guard let outputJava else { - print("[swift-java] --output-java enabled 'jextract' mode, however no --output-java directory was provided!\n\(Self.helpMessage())") - return - } - config.swiftModule = self.swiftModule ?? "UnknownModule" - config.inputSwiftDirectory = inputSwift - config.outputSwiftDirectory = outputSwift - config.outputJavaDirectory = outputJava - - toolMode = .jextract -// } else if jar { -// guard let input else { -// fatalError("Mode -jar requires path\n\(Self.helpMessage())") -// } -// toolMode = .configuration(extraClasspath: input) - } else if fetch { - guard let input else { - fatalError("Mode 'fetch' requires path\n\(Self.helpMessage())") - } - config = try JavaTranslator.readConfiguration(from: URL(fileURLWithPath: input)) - guard let dependencies = config.dependencies else { - print("[swift-java] Running in 'fetch dependencies' mode but dependencies list was empty!") - print("[swift-java] Nothing to do: done.") - return - } - toolMode = .fetchDependencies - } else { - guard let input else { - fatalError("Mode -jar requires path\n\(Self.helpMessage())") - } - config = try JavaTranslator.readConfiguration(from: URL(fileURLWithPath: input)) - toolMode = .classWrappers - } - - print("[debug][swift-java] Running swift-java in mode: " + "\(toolMode.prettyName)".bold) - - let swiftModule: String = - self.swiftModule ?? - self.effectiveSwiftModule.split(separator: "/").dropLast().last.map(String.init) ?? "__UnknownModule" - - // Load all of the dependent configurations and associate them with Swift - // modules. - let dependentConfigs = try dependsOn.map { dependentConfig in - guard let equalLoc = dependentConfig.firstIndex(of: "=") else { - throw JavaToSwiftError.badConfigOption(dependentConfig) - } - - let afterEqual = dependentConfig.index(after: equalLoc) - let swiftModuleName = String(dependentConfig[.. (javaClassName: String, swiftName: String) { @@ -324,14 +100,3 @@ extension JavaToSwiftError: CustomStringConvertible { } } -extension SwiftJava.ToolMode { - var prettyName: String { - switch self { - case .fetchDependencies: "Fetch dependencies" - case .classWrappers: "Wrap Java classes" - case .jextract: "JExtract Swift for Java" - } - } -} - -extension GenerationMode: ExpressibleByArgument {} diff --git a/Sources/SwiftJavaTool/SwiftJavaBaseAsyncParsableCommand.swift b/Sources/SwiftJavaTool/SwiftJavaBaseAsyncParsableCommand.swift index afe4f80c..20b177af 100644 --- a/Sources/SwiftJavaTool/SwiftJavaBaseAsyncParsableCommand.swift +++ b/Sources/SwiftJavaTool/SwiftJavaBaseAsyncParsableCommand.swift @@ -28,6 +28,7 @@ import JavaKitShared protocol SwiftJavaBaseAsyncParsableCommand: AsyncParsableCommand { var logLevel: Logger.Level { get set } + /// Must be implemented with an `@OptionGroup` in Command implementations var commonOptions: SwiftJava.CommonOptions { get set } var effectiveSwiftModule: String { get } @@ -36,10 +37,16 @@ protocol SwiftJavaBaseAsyncParsableCommand: AsyncParsableCommand { } +extension SwiftJavaBaseAsyncParsableCommand { + var outputDirectory: String? { + self.commonOptions.outputDirectory + } +} + extension SwiftJavaBaseAsyncParsableCommand { public mutating func run() async { - print("[info][swift-java] Run: \(CommandLine.arguments.joined(separator: " "))") - print("[info][swift-java] Current work directory: \(URL(fileURLWithPath: "."))") + print("[info][swift-java] Run \(Self.self): \(CommandLine.arguments.joined(separator: " "))") + print("[info][swift-java] Current work directory: \(URL(fileURLWithPath: ".").path)") do { var config = try readInitialConfiguration(command: self) @@ -59,20 +66,10 @@ extension SwiftJavaBaseAsyncParsableCommand { extension SwiftJavaBaseAsyncParsableCommand { mutating func writeContents( _ contents: String, - to filename: String, description: String) throws { - try writeContents( - contents, - outputDirectoryOverride: self.actualOutputDirectory, - to: filename, - description: description) - } - - mutating func writeContents( - _ contents: String, - outputDirectoryOverride: Foundation.URL?, + outputDirectory: Foundation.URL?, to filename: String, description: String) throws { - guard let outputDir = (outputDirectoryOverride ?? actualOutputDirectory) else { + guard let outputDir = outputDirectory else { print("// \(filename) - \(description)") print(contents) return @@ -90,7 +87,7 @@ extension SwiftJavaBaseAsyncParsableCommand { // Write the file: let file = outputDir.appendingPathComponent(filename) - print("[debug][swift-java] Writing \(description) to '\(file.path)'... ", terminator: "") + print("[trace][swift-java] Writing \(description) to '\(file.path)'... ", terminator: "") try contents.write(to: file, atomically: true, encoding: .utf8) print("done.".green) } @@ -106,22 +103,22 @@ extension SwiftJavaBaseAsyncParsableCommand { self.commonOptions.logLevel = newValue } } + + var effectiveSwiftModuleURL: Foundation.URL { + let fm = FileManager.default + return URL(fileURLWithPath: fm.currentDirectoryPath + "/Sources/\(self.effectiveSwiftModule)") + } } extension SwiftJavaBaseAsyncParsableCommand { var moduleBaseDir: Foundation.URL? { -// if let outputDirectory = commonOptions.outputDirectory { -// if outputDirectory == "-" { -// return nil -// } -// + if let outputDirectory = commonOptions.outputDirectory { + if outputDirectory == "-" { + return nil + } // print("[debug][swift-java] Module base directory based on outputDirectory!") // return URL(fileURLWithPath: outputDirectory) -// } - -// guard let swiftModule else { -// return nil -// } + } // Put the result into Sources/\(swiftModule). let baseDir = URL(fileURLWithPath: ".") @@ -137,7 +134,7 @@ extension SwiftJavaBaseAsyncParsableCommand { /// /// Returns `nil` only when we should emit the files to standard output. var actualOutputDirectory: Foundation.URL? { - if let outputDirectory = commonOptions.outputDirectory { + if let outputDirectory = self.commonOptions.outputDirectory { if outputDirectory == "-" { return nil } @@ -152,15 +149,7 @@ extension SwiftJavaBaseAsyncParsableCommand { // For generated Swift sources, put them into a "generated" subdirectory. // The configuration file goes at the top level. - let outputDir: Foundation.URL - // if jar { - // precondition(self.input != nil, "-jar mode requires path to jar to be specified as input path") - outputDir = baseDir - // } else { - // outputDir = baseDir - // .appendingPathComponent("generated", isDirectory: true) - // } - + let outputDir: Foundation.URL = baseDir return outputDir } diff --git a/Sources/_CShims/process_shims.c b/Sources/_CShims/process_shims.c deleted file mode 100644 index fe96c675..00000000 --- a/Sources/_CShims/process_shims.c +++ /dev/null @@ -1,340 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of Swift.org project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -#include "include/_CShimsTargetConditionals.h" -#include "include/process_shims.h" - -#if !TARGET_OS_WINDOWS -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -int _was_process_exited(int status) { - return WIFEXITED(status); -} - -int _get_exit_code(int status) { - return WEXITSTATUS(status); -} - -int _was_process_signaled(int status) { - return WIFSIGNALED(status); -} - -int _get_signal_code(int status) { - return WTERMSIG(status); -} - -int _was_process_suspended(int status) { - return WIFSTOPPED(status); -} - -#if TARGET_OS_LINUX -#include - -int _shims_snprintf( - char * _Nonnull str, - int len, - const char * _Nonnull format, - char * _Nonnull str1, - char * _Nonnull str2 -) { - return snprintf(str, len, format, str1, str2); -} -#endif - -// MARK: - Darwin (posix_spawn) -#if TARGET_OS_MAC - -int _subprocess_spawn( - pid_t * _Nonnull pid, - const char * _Nonnull exec_path, - const posix_spawn_file_actions_t _Nullable * _Nonnull file_actions, - const posix_spawnattr_t _Nullable * _Nonnull spawn_attrs, - char * _Nullable const args[_Nonnull], - char * _Nullable const env[_Nullable], - uid_t * _Nullable uid, - gid_t * _Nullable gid, - int number_of_sgroups, const gid_t * _Nullable sgroups, - int create_session -) { - int require_pre_fork = uid != NULL || - gid != NULL || - number_of_sgroups > 0 || - create_session > 0; - - if (require_pre_fork != 0) { -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wdeprecated" - pid_t childPid = vfork(); -#pragma GCC diagnostic pop - if (childPid != 0) { - *pid = childPid; - return childPid < 0 ? errno : 0; - } - - if (number_of_sgroups > 0 && sgroups != NULL) { - if (setgroups(number_of_sgroups, sgroups) != 0) { - return errno; - } - } - - if (uid != NULL) { - if (setuid(*uid) != 0) { - return errno; - } - } - - if (gid != NULL) { - if (setgid(*gid) != 0) { - return errno; - } - } - - if (create_session != 0) { - (void)setsid(); - } - } - - // Set POSIX_SPAWN_SETEXEC if we already forked - if (require_pre_fork) { - short flags = 0; - int rc = posix_spawnattr_getflags(spawn_attrs, &flags); - if (rc != 0) { - return rc; - } - - rc = posix_spawnattr_setflags( - (posix_spawnattr_t *)spawn_attrs, flags | POSIX_SPAWN_SETEXEC - ); - if (rc != 0) { - return rc; - } - } - - // Spawn - return posix_spawn(pid, exec_path, file_actions, spawn_attrs, args, env); -} - -#endif // TARGET_OS_MAC - -// MARK: - Linux (fork/exec + posix_spawn fallback) - -#if _POSIX_SPAWN -static int _subprocess_posix_spawn_fallback( - pid_t * _Nonnull pid, - const char * _Nonnull exec_path, - const char * _Nullable working_directory, - const int file_descriptors[_Nonnull], - char * _Nullable const args[_Nonnull], - char * _Nullable const env[_Nullable], - gid_t * _Nullable process_group_id -) { - // Setup stdin, stdout, and stderr - posix_spawn_file_actions_t file_actions; - - int rc = posix_spawn_file_actions_init(&file_actions); - if (rc != 0) { return rc; } - if (file_descriptors[0] >= 0) { - rc = posix_spawn_file_actions_adddup2( - &file_actions, file_descriptors[0], STDIN_FILENO - ); - if (rc != 0) { return rc; } - } - if (file_descriptors[2] >= 0) { - rc = posix_spawn_file_actions_adddup2( - &file_actions, file_descriptors[2], STDOUT_FILENO - ); - if (rc != 0) { return rc; } - } - if (file_descriptors[4] >= 0) { - rc = posix_spawn_file_actions_adddup2( - &file_actions, file_descriptors[4], STDERR_FILENO - ); - if (rc != 0) { return rc; } - } - - // Close parent side - if (file_descriptors[1] >= 0) { - rc = posix_spawn_file_actions_addclose(&file_actions, file_descriptors[1]); - if (rc != 0) { return rc; } - } - if (file_descriptors[3] >= 0) { - rc = posix_spawn_file_actions_addclose(&file_actions, file_descriptors[3]); - if (rc != 0) { return rc; } - } - if (file_descriptors[5] >= 0) { - rc = posix_spawn_file_actions_addclose(&file_actions, file_descriptors[5]); - if (rc != 0) { return rc; } - } - - // Setup spawnattr - posix_spawnattr_t spawn_attr; - rc = posix_spawnattr_init(&spawn_attr); - if (rc != 0) { return rc; } - // Masks - sigset_t no_signals; - sigset_t all_signals; - sigemptyset(&no_signals); - sigfillset(&all_signals); - rc = posix_spawnattr_setsigmask(&spawn_attr, &no_signals); - if (rc != 0) { return rc; } - rc = posix_spawnattr_setsigdefault(&spawn_attr, &all_signals); - if (rc != 0) { return rc; } - // Flags - short flags = POSIX_SPAWN_SETSIGMASK | POSIX_SPAWN_SETSIGDEF; - if (process_group_id != NULL) { - flags |= POSIX_SPAWN_SETPGROUP; - rc = posix_spawnattr_setpgroup(&spawn_attr, *process_group_id); - if (rc != 0) { return rc; } - } - rc = posix_spawnattr_setflags(&spawn_attr, flags); - - // Spawn! - rc = posix_spawn( - pid, exec_path, - &file_actions, &spawn_attr, - args, env - ); - posix_spawn_file_actions_destroy(&file_actions); - posix_spawnattr_destroy(&spawn_attr); - return rc; -} -#endif // _POSIX_SPAWN - -int _subprocess_fork_exec( - pid_t * _Nonnull pid, - const char * _Nonnull exec_path, - const char * _Nullable working_directory, - const int file_descriptors[_Nonnull], - char * _Nullable const args[_Nonnull], - char * _Nullable const env[_Nullable], - uid_t * _Nullable uid, - gid_t * _Nullable gid, - gid_t * _Nullable process_group_id, - int number_of_sgroups, const gid_t * _Nullable sgroups, - int create_session, - void (* _Nullable configurator)(void) -) { - int require_pre_fork = working_directory != NULL || - uid != NULL || - gid != NULL || - process_group_id != NULL || - (number_of_sgroups > 0 && sgroups != NULL) || - create_session || - configurator != NULL; - -#if _POSIX_SPAWN - // If posix_spawn is available on this platform and - // we do not require prefork, use posix_spawn if possible. - // - // (Glibc's posix_spawn does not support - // `POSIX_SPAWN_SETEXEC` therefore we have to keep - // using fork/exec if `require_pre_fork` is true. - if (require_pre_fork == 0) { - return _subprocess_posix_spawn_fallback( - pid, exec_path, - working_directory, - file_descriptors, - args, env, - process_group_id - ); - } -#endif - - pid_t child_pid = fork(); - if (child_pid != 0) { - *pid = child_pid; - return child_pid < 0 ? errno : 0; - } - - if (working_directory != NULL) { - if (chdir(working_directory) != 0) { - return errno; - } - } - - - if (uid != NULL) { - if (setuid(*uid) != 0) { - return errno; - } - } - - if (gid != NULL) { - if (setgid(*gid) != 0) { - return errno; - } - } - - if (number_of_sgroups > 0 && sgroups != NULL) { - if (setgroups(number_of_sgroups, sgroups) != 0) { - return errno; - } - } - - if (create_session != 0) { - (void)setsid(); - } - - if (process_group_id != NULL) { - (void)setpgid(0, *process_group_id); - } - - // Bind stdin, stdout, and stderr - int rc = 0; - if (file_descriptors[0] >= 0) { - rc = dup2(file_descriptors[0], STDIN_FILENO); - if (rc < 0) { return errno; } - } - if (file_descriptors[2] >= 0) { - rc = dup2(file_descriptors[2], STDOUT_FILENO); - if (rc < 0) { return errno; } - } - if (file_descriptors[4] >= 0) { - rc = dup2(file_descriptors[4], STDERR_FILENO); - if (rc < 0) { return errno; } - } - // Close parent side - if (file_descriptors[1] >= 0) { - rc = close(file_descriptors[1]); - } - if (file_descriptors[3] >= 0) { - rc = close(file_descriptors[3]); - } - if (file_descriptors[4] >= 0) { - rc = close(file_descriptors[5]); - } - if (rc != 0) { - return errno; - } - // Run custom configuratior - if (configurator != NULL) { - configurator(); - } - // Finally, exec - execve(exec_path, args, env); - // If we got here, something went wrong - return errno; -} - -#endif // !TARGET_OS_WINDOWS - diff --git a/Sources/_Subprocess/API.swift b/Sources/_Subprocess/API.swift new file mode 100644 index 00000000..9673d3e1 --- /dev/null +++ b/Sources/_Subprocess/API.swift @@ -0,0 +1,370 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// +//===----------------------------------------------------------------------===// + +#if canImport(System) +import System +#else +@preconcurrency import SystemPackage +#endif + +// MARK: - Collected Result + +/// Run a executable with given parameters asynchrously and returns +/// a `CollectedResult` containing the output of the child process. +/// - Parameters: +/// - executable: The executable to run. +/// - arguments: The arguments to pass to the executable. +/// - environment: The environment in which to run the executable. +/// - workingDirectory: The working directory in which to run the executable. +/// - platformOptions: The platform specific options to use +/// when running the executable. +/// - input: The input to send to the executable. +/// - output: The method to use for redirecting the standard output. +/// - error: The method to use for redirecting the standard error. +/// - Returns a CollectedResult containing the result of the run. +@available(macOS 15.0, *) // FIXME: manually added availability +public func run< + Input: InputProtocol, + Output: OutputProtocol, + Error: OutputProtocol +>( + _ executable: Executable, + arguments: Arguments = [], + environment: Environment = .inherit, + workingDirectory: FilePath? = nil, + platformOptions: PlatformOptions = PlatformOptions(), + input: Input = .none, + output: Output = .string, + error: Error = .discarded +) async throws -> CollectedResult { + let configuration = Configuration( + executable: executable, + arguments: arguments, + environment: environment, + workingDirectory: workingDirectory, + platformOptions: platformOptions + ) + return try await run( + configuration, + input: input, + output: output, + error: error + ) +} + +// MARK: - Custom Execution Body + +/// Run a executable with given parameters and a custom closure +/// to manage the running subprocess' lifetime and its IOs. +/// - Parameters: +/// - executable: The executable to run. +/// - arguments: The arguments to pass to the executable. +/// - environment: The environment in which to run the executable. +/// - workingDirectory: The working directory in which to run the executable. +/// - platformOptions: The platform specific options to use +/// when running the executable. +/// - input: The input to send to the executable. +/// - output: How to manage the executable standard ouput. +/// - error: How to manager executable standard error. +/// - isolation: the isolation context to run the body closure. +/// - body: The custom execution body to manually control the running process +/// - Returns a ExecutableResult type containing the return value +/// of the closure. +@available(macOS 15.0, *) // FIXME: manually added availability +public func run( + _ executable: Executable, + arguments: Arguments = [], + environment: Environment = .inherit, + workingDirectory: FilePath? = nil, + platformOptions: PlatformOptions = PlatformOptions(), + input: Input = .none, + output: Output, + error: Error, + isolation: isolated (any Actor)? = #isolation, + body: ((Execution) async throws -> Result) +) async throws -> ExecutionResult where Output.OutputType == Void, Error.OutputType == Void { + return try await Configuration( + executable: executable, + arguments: arguments, + environment: environment, + workingDirectory: workingDirectory, + platformOptions: platformOptions + ) + .run(input: input, output: output, error: error, body) +} + +/// Run a executable with given parameters and a custom closure +/// to manage the running subprocess' lifetime and write to its +/// standard input via `StandardInputWriter` +/// - Parameters: +/// - executable: The executable to run. +/// - arguments: The arguments to pass to the executable. +/// - environment: The environment in which to run the executable. +/// - workingDirectory: The working directory in which to run the executable. +/// - platformOptions: The platform specific options to use +/// when running the executable. +/// - output:How to handle executable's standard output +/// - error: How to handle executable's standard error +/// - isolation: the isolation context to run the body closure. +/// - body: The custom execution body to manually control the running process +/// - Returns a ExecutableResult type containing the return value +/// of the closure. +@available(macOS 15.0, *) // FIXME: manually added availability +public func run( + _ executable: Executable, + arguments: Arguments = [], + environment: Environment = .inherit, + workingDirectory: FilePath? = nil, + platformOptions: PlatformOptions = PlatformOptions(), + output: Output, + error: Error, + isolation: isolated (any Actor)? = #isolation, + body: ((Execution, StandardInputWriter) async throws -> Result) +) async throws -> ExecutionResult where Output.OutputType == Void, Error.OutputType == Void { + return try await Configuration( + executable: executable, + arguments: arguments, + environment: environment, + workingDirectory: workingDirectory, + platformOptions: platformOptions + ) + .run(output: output, error: error, body) +} + +// MARK: - Configuration Based + +/// Run a `Configuration` asynchrously and returns +/// a `CollectedResult` containing the output of the child process. +/// - Parameters: +/// - configuration: The `Subprocess` configuration to run. +/// - input: The input to send to the executable. +/// - output: The method to use for redirecting the standard output. +/// - error: The method to use for redirecting the standard error. +/// - Returns a CollectedResult containing the result of the run. +@available(macOS 15.0, *) // FIXME: manually added availability +public func run< + Input: InputProtocol, + Output: OutputProtocol, + Error: OutputProtocol +>( + _ configuration: Configuration, + input: Input = .none, + output: Output = .string, + error: Error = .discarded +) async throws -> CollectedResult { + let result = try await configuration.run( + input: input, + output: output, + error: error + ) { execution in + let ( + standardOutput, + standardError + ) = try await execution.captureIOs() + return ( + processIdentifier: execution.processIdentifier, + standardOutput: standardOutput, + standardError: standardError + ) + } + return CollectedResult( + processIdentifier: result.value.processIdentifier, + terminationStatus: result.terminationStatus, + standardOutput: result.value.standardOutput, + standardError: result.value.standardError + ) +} + +/// Run a executable with given parameters specified by a `Configuration` +/// - Parameters: +/// - configuration: The `Subprocess` configuration to run. +/// - output: The method to use for redirecting the standard output. +/// - error: The method to use for redirecting the standard error. +/// - isolation: the isolation context to run the body closure. +/// - body: The custom configuration body to manually control +/// the running process and write to its standard input. +/// - Returns a ExecutableResult type containing the return value +/// of the closure. +@available(macOS 15.0, *) // FIXME: manually added availability +public func run( + _ configuration: Configuration, + output: Output, + error: Error, + isolation: isolated (any Actor)? = #isolation, + body: ((Execution, StandardInputWriter) async throws -> Result) +) async throws -> ExecutionResult where Output.OutputType == Void, Error.OutputType == Void { + return try await configuration.run(output: output, error: error, body) +} + +// MARK: - Detached + +/// Run a executable with given parameters and return its process +/// identifier immediately without monitoring the state of the +/// subprocess nor waiting until it exits. +/// +/// This method is useful for launching subprocesses that outlive their +/// parents (for example, daemons and trampolines). +/// +/// - Parameters: +/// - executable: The executable to run. +/// - arguments: The arguments to pass to the executable. +/// - environment: The environment to use for the process. +/// - workingDirectory: The working directory for the process. +/// - platformOptions: The platform specific options to use for the process. +/// - input: A file descriptor to bind to the subprocess' standard input. +/// - output: A file descriptor to bind to the subprocess' standard output. +/// - error: A file descriptor to bind to the subprocess' standard error. +/// - Returns: the process identifier for the subprocess. +@available(macOS 15.0, *) // FIXME: manually added availability +public func runDetached( + _ executable: Executable, + arguments: Arguments = [], + environment: Environment = .inherit, + workingDirectory: FilePath? = nil, + platformOptions: PlatformOptions = PlatformOptions(), + input: FileDescriptor? = nil, + output: FileDescriptor? = nil, + error: FileDescriptor? = nil +) throws -> ProcessIdentifier { + let config: Configuration = Configuration( + executable: executable, + arguments: arguments, + environment: environment, + workingDirectory: workingDirectory, + platformOptions: platformOptions + ) + return try runDetached(config, input: input, output: output, error: error) +} + +/// Run a executable with given configuration and return its process +/// identifier immediately without monitoring the state of the +/// subprocess nor waiting until it exits. +/// +/// This method is useful for launching subprocesses that outlive their +/// parents (for example, daemons and trampolines). +/// +/// - Parameters: +/// - configuration: The `Subprocess` configuration to run. +/// - input: A file descriptor to bind to the subprocess' standard input. +/// - output: A file descriptor to bind to the subprocess' standard output. +/// - error: A file descriptor to bind to the subprocess' standard error. +/// - Returns: the process identifier for the subprocess. +@available(macOS 15.0, *) // FIXME: manually added availability +public func runDetached( + _ configuration: Configuration, + input: FileDescriptor? = nil, + output: FileDescriptor? = nil, + error: FileDescriptor? = nil +) throws -> ProcessIdentifier { + switch (input, output, error) { + case (.none, .none, .none): + let processOutput = DiscardedOutput() + let processError = DiscardedOutput() + return try configuration.spawn( + withInput: NoInput().createPipe(), + output: processOutput, + outputPipe: try processOutput.createPipe(), + error: processError, + errorPipe: try processError.createPipe() + ).processIdentifier + case (.none, .none, .some(let errorFd)): + let processOutput = DiscardedOutput() + let processError = FileDescriptorOutput(fileDescriptor: errorFd, closeAfterSpawningProcess: false) + return try configuration.spawn( + withInput: NoInput().createPipe(), + output: processOutput, + outputPipe: try processOutput.createPipe(), + error: processError, + errorPipe: try processError.createPipe() + ).processIdentifier + case (.none, .some(let outputFd), .none): + let processOutput = FileDescriptorOutput(fileDescriptor: outputFd, closeAfterSpawningProcess: false) + let processError = DiscardedOutput() + return try configuration.spawn( + withInput: NoInput().createPipe(), + output: processOutput, + outputPipe: try processOutput.createPipe(), + error: processError, + errorPipe: try processError.createPipe() + ).processIdentifier + case (.none, .some(let outputFd), .some(let errorFd)): + let processOutput = FileDescriptorOutput( + fileDescriptor: outputFd, + closeAfterSpawningProcess: false + ) + let processError = FileDescriptorOutput( + fileDescriptor: errorFd, + closeAfterSpawningProcess: false + ) + return try configuration.spawn( + withInput: NoInput().createPipe(), + output: processOutput, + outputPipe: try processOutput.createPipe(), + error: processError, + errorPipe: try processError.createPipe() + ).processIdentifier + case (.some(let inputFd), .none, .none): + let processOutput = DiscardedOutput() + let processError = DiscardedOutput() + return try configuration.spawn( + withInput: FileDescriptorInput( + fileDescriptor: inputFd, + closeAfterSpawningProcess: false + ).createPipe(), + output: processOutput, + outputPipe: try processOutput.createPipe(), + error: processError, + errorPipe: try processError.createPipe() + ).processIdentifier + case (.some(let inputFd), .none, .some(let errorFd)): + let processOutput = DiscardedOutput() + let processError = FileDescriptorOutput( + fileDescriptor: errorFd, + closeAfterSpawningProcess: false + ) + return try configuration.spawn( + withInput: FileDescriptorInput(fileDescriptor: inputFd, closeAfterSpawningProcess: false).createPipe(), + output: processOutput, + outputPipe: try processOutput.createPipe(), + error: processError, + errorPipe: try processError.createPipe() + ).processIdentifier + case (.some(let inputFd), .some(let outputFd), .none): + let processOutput = FileDescriptorOutput( + fileDescriptor: outputFd, + closeAfterSpawningProcess: false + ) + let processError = DiscardedOutput() + return try configuration.spawn( + withInput: FileDescriptorInput(fileDescriptor: inputFd, closeAfterSpawningProcess: false).createPipe(), + output: processOutput, + outputPipe: try processOutput.createPipe(), + error: processError, + errorPipe: try processError.createPipe() + ).processIdentifier + case (.some(let inputFd), .some(let outputFd), .some(let errorFd)): + let processOutput = FileDescriptorOutput( + fileDescriptor: outputFd, + closeAfterSpawningProcess: false + ) + let processError = FileDescriptorOutput( + fileDescriptor: errorFd, + closeAfterSpawningProcess: false + ) + return try configuration.spawn( + withInput: FileDescriptorInput(fileDescriptor: inputFd, closeAfterSpawningProcess: false).createPipe(), + output: processOutput, + outputPipe: try processOutput.createPipe(), + error: processError, + errorPipe: try processError.createPipe() + ).processIdentifier + } +} diff --git a/Sources/_Subprocess/AsyncBufferSequence.swift b/Sources/_Subprocess/AsyncBufferSequence.swift new file mode 100644 index 00000000..4316f7eb --- /dev/null +++ b/Sources/_Subprocess/AsyncBufferSequence.swift @@ -0,0 +1,99 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// +//===----------------------------------------------------------------------===// + +#if canImport(System) +import System +#else +@preconcurrency import SystemPackage +#endif + +internal struct AsyncBufferSequence: AsyncSequence, Sendable { + internal typealias Failure = any Swift.Error + + internal typealias Element = SequenceOutput.Buffer + + @_nonSendable + internal struct Iterator: AsyncIteratorProtocol { + internal typealias Element = SequenceOutput.Buffer + + private let fileDescriptor: TrackedFileDescriptor + private var buffer: [UInt8] + private var currentPosition: Int + private var finished: Bool + + internal init(fileDescriptor: TrackedFileDescriptor) { + self.fileDescriptor = fileDescriptor + self.buffer = [] + self.currentPosition = 0 + self.finished = false + } + + internal mutating func next() async throws -> SequenceOutput.Buffer? { + let data = try await self.fileDescriptor.wrapped.readChunk( + upToLength: readBufferSize + ) + if data == nil { + // We finished reading. Close the file descriptor now + try self.fileDescriptor.safelyClose() + return nil + } + return data + } + } + + private let fileDescriptor: TrackedFileDescriptor + + init(fileDescriptor: TrackedFileDescriptor) { + self.fileDescriptor = fileDescriptor + } + + internal func makeAsyncIterator() -> Iterator { + return Iterator(fileDescriptor: self.fileDescriptor) + } +} + +// MARK: - Page Size +import _SubprocessCShims + +#if canImport(Darwin) +import Darwin +internal import MachO.dyld + +private let _pageSize: Int = { + Int(_subprocess_vm_size()) +}() +#elseif canImport(WinSDK) +import WinSDK +private let _pageSize: Int = { + var sysInfo: SYSTEM_INFO = SYSTEM_INFO() + GetSystemInfo(&sysInfo) + return Int(sysInfo.dwPageSize) +}() +#elseif os(WASI) +// WebAssembly defines a fixed page size +private let _pageSize: Int = 65_536 +#elseif canImport(Android) +@preconcurrency import Android +private let _pageSize: Int = Int(getpagesize()) +#elseif canImport(Glibc) +@preconcurrency import Glibc +private let _pageSize: Int = Int(getpagesize()) +#elseif canImport(Musl) +@preconcurrency import Musl +private let _pageSize: Int = Int(getpagesize()) +#elseif canImport(C) +private let _pageSize: Int = Int(getpagesize()) +#endif // canImport(Darwin) + +@inline(__always) +internal var readBufferSize: Int { + return _pageSize +} diff --git a/Sources/_Subprocess/Buffer.swift b/Sources/_Subprocess/Buffer.swift new file mode 100644 index 00000000..3ce73d7e --- /dev/null +++ b/Sources/_Subprocess/Buffer.swift @@ -0,0 +1,104 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// +//===----------------------------------------------------------------------===// + +@preconcurrency internal import Dispatch + +extension SequenceOutput { + /// A immutable collection of bytes + public struct Buffer: Sendable { + #if os(Windows) + private var data: [UInt8] + + internal init(data: [UInt8]) { + self.data = data + } + #else + private var data: DispatchData + + internal init(data: DispatchData) { + self.data = data + } + #endif + } +} + +// MARK: - Properties +extension SequenceOutput.Buffer { + /// Number of bytes stored in the buffer + public var count: Int { + return self.data.count + } + + /// A Boolean value indicating whether the collection is empty. + public var isEmpty: Bool { + return self.data.isEmpty + } +} + +// MARK: - Accessors +extension SequenceOutput.Buffer { + #if !SubprocessSpan + /// Access the raw bytes stored in this buffer + /// - Parameter body: A closure with an `UnsafeRawBufferPointer` parameter that + /// points to the contiguous storage for the type. If no such storage exists, + /// the method creates it. If body has a return value, this method also returns + /// that value. The argument is valid only for the duration of the + /// closure’s SequenceOutput. + /// - Returns: The return value, if any, of the body closure parameter. + public func withUnsafeBytes( + _ body: (UnsafeRawBufferPointer) throws -> ResultType + ) rethrows -> ResultType { + return try self._withUnsafeBytes(body) + } + #endif // !SubprocessSpan + + internal func _withUnsafeBytes( + _ body: (UnsafeRawBufferPointer) throws -> ResultType + ) rethrows -> ResultType { + #if os(Windows) + return try self.data.withUnsafeBytes(body) + #else + // Although DispatchData was designed to be uncontiguous, in practice + // we found that almost all DispatchData are contiguous. Therefore + // we can access this body in O(1) most of the time. + return try self.data.withUnsafeBytes { ptr in + let bytes = UnsafeRawBufferPointer(start: ptr, count: self.data.count) + return try body(bytes) + } + #endif + } + + private enum SpanBacking { + case pointer(UnsafeBufferPointer) + case array([UInt8]) + } +} + +// MARK: - Hashable, Equatable +extension SequenceOutput.Buffer: Equatable, Hashable { + #if os(Windows) + // Compiler generated conformances + #else + public static func == (lhs: SequenceOutput.Buffer, rhs: SequenceOutput.Buffer) -> Bool { + return lhs.data.elementsEqual(rhs.data) + } + + public func hash(into hasher: inout Hasher) { + self.data.withUnsafeBytes { ptr in + let bytes = UnsafeRawBufferPointer( + start: ptr, + count: self.data.count + ) + hasher.combine(bytes: bytes) + } + } + #endif +} diff --git a/Sources/_Subprocess/Configuration.swift b/Sources/_Subprocess/Configuration.swift new file mode 100644 index 00000000..4dad1a47 --- /dev/null +++ b/Sources/_Subprocess/Configuration.swift @@ -0,0 +1,851 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// +//===----------------------------------------------------------------------===// + +#if canImport(System) +import System +#else +@preconcurrency import SystemPackage +#endif + +#if canImport(Darwin) +import Darwin +#elseif canImport(Bionic) +import Bionic +#elseif canImport(Glibc) +import Glibc +#elseif canImport(Musl) +import Musl +#elseif canImport(WinSDK) +import WinSDK +#endif + +internal import Dispatch + +/// A collection of configurations parameters to use when +/// spawning a subprocess. +public struct Configuration: Sendable { + /// The executable to run. + public var executable: Executable + /// The arguments to pass to the executable. + public var arguments: Arguments + /// The environment to use when running the executable. + public var environment: Environment + /// The working directory to use when running the executable. + public var workingDirectory: FilePath + /// The platform specifc options to use when + /// running the subprocess. + public var platformOptions: PlatformOptions + + public init( + executable: Executable, + arguments: Arguments = [], + environment: Environment = .inherit, + workingDirectory: FilePath? = nil, + platformOptions: PlatformOptions = PlatformOptions() + ) { + self.executable = executable + self.arguments = arguments + self.environment = environment + self.workingDirectory = workingDirectory ?? .currentWorkingDirectory + self.platformOptions = platformOptions + } + + @available(macOS 15.0, *) // FIXME: manually added availability + internal func run< + Result, + Output: OutputProtocol, + Error: OutputProtocol + >( + output: Output, + error: Error, + isolation: isolated (any Actor)? = #isolation, + _ body: ( + Execution, + StandardInputWriter + ) async throws -> Result + ) async throws -> ExecutionResult { + let input = CustomWriteInput() + + let inputPipe = try input.createPipe() + let outputPipe = try output.createPipe() + let errorPipe = try error.createPipe() + + let execution = try self.spawn( + withInput: inputPipe, + output: output, + outputPipe: outputPipe, + error: error, + errorPipe: errorPipe + ) + // After spawn, cleanup child side fds + try await self.cleanup( + execution: execution, + inputPipe: inputPipe, + outputPipe: outputPipe, + errorPipe: errorPipe, + childSide: true, + parentSide: false, + attemptToTerminateSubProcess: false + ) + return try await withAsyncTaskCleanupHandler { + async let waitingStatus = try await monitorProcessTermination( + forProcessWithIdentifier: execution.processIdentifier + ) + // Body runs in the same isolation + let result = try await body( + execution, + .init(fileDescriptor: inputPipe.writeFileDescriptor!) + ) + return ExecutionResult( + terminationStatus: try await waitingStatus, + value: result + ) + } onCleanup: { + // Attempt to terminate the child process + // Since the task has already been cancelled, + // this is the best we can do + try? await self.cleanup( + execution: execution, + inputPipe: inputPipe, + outputPipe: outputPipe, + errorPipe: errorPipe, + childSide: false, + parentSide: true, + attemptToTerminateSubProcess: true + ) + } + } + + @available(macOS 15.0, *) // FIXME: manually added availability + internal func run< + Result, + Input: InputProtocol, + Output: OutputProtocol, + Error: OutputProtocol + >( + input: Input, + output: Output, + error: Error, + isolation: isolated (any Actor)? = #isolation, + _ body: ((Execution) async throws -> Result) + ) async throws -> ExecutionResult { + + let inputPipe = try input.createPipe() + let outputPipe = try output.createPipe() + let errorPipe = try error.createPipe() + + let execution = try self.spawn( + withInput: inputPipe, + output: output, + outputPipe: outputPipe, + error: error, + errorPipe: errorPipe + ) + // After spawn, clean up child side + try await self.cleanup( + execution: execution, + inputPipe: inputPipe, + outputPipe: outputPipe, + errorPipe: errorPipe, + childSide: true, + parentSide: false, + attemptToTerminateSubProcess: false + ) + + return try await withAsyncTaskCleanupHandler { + return try await withThrowingTaskGroup( + of: TerminationStatus?.self, + returning: ExecutionResult.self + ) { group in + group.addTask { + if let writeFd = inputPipe.writeFileDescriptor { + let writer = StandardInputWriter(fileDescriptor: writeFd) + try await input.write(with: writer) + try await writer.finish() + } + return nil + } + group.addTask { + return try await monitorProcessTermination( + forProcessWithIdentifier: execution.processIdentifier + ) + } + + // Body runs in the same isolation + let result = try await body(execution) + var status: TerminationStatus? = nil + while let monitorResult = try await group.next() { + if let monitorResult = monitorResult { + status = monitorResult + } + } + return ExecutionResult(terminationStatus: status!, value: result) + } + } onCleanup: { + // Attempt to terminate the child process + // Since the task has already been cancelled, + // this is the best we can do + try? await self.cleanup( + execution: execution, + inputPipe: inputPipe, + outputPipe: outputPipe, + errorPipe: errorPipe, + childSide: false, + parentSide: true, + attemptToTerminateSubProcess: true + ) + } + } +} + +extension Configuration: CustomStringConvertible, CustomDebugStringConvertible { + public var description: String { + return """ + Configuration( + executable: \(self.executable.description), + arguments: \(self.arguments.description), + environment: \(self.environment.description), + workingDirectory: \(self.workingDirectory), + platformOptions: \(self.platformOptions.description(withIndent: 1)) + ) + """ + } + + public var debugDescription: String { + return """ + Configuration( + executable: \(self.executable.debugDescription), + arguments: \(self.arguments.debugDescription), + environment: \(self.environment.debugDescription), + workingDirectory: \(self.workingDirectory), + platformOptions: \(self.platformOptions.description(withIndent: 1)) + ) + """ + } +} + +// MARK: - Cleanup +extension Configuration { + /// Close each input individually, and throw the first error if there's multiple errors thrown + @Sendable + @available(macOS 15.0, *) // FIXME: manually added availability + private func cleanup< + Output: OutputProtocol, + Error: OutputProtocol + >( + execution: Execution, + inputPipe: CreatedPipe, + outputPipe: CreatedPipe, + errorPipe: CreatedPipe, + childSide: Bool, + parentSide: Bool, + attemptToTerminateSubProcess: Bool + ) async throws { + func captureError(_ work: () throws -> Void) -> Swift.Error? { + do { + try work() + return nil + } catch { + // Ignore badFileDescriptor for double close + return error + } + } + + guard childSide || parentSide || attemptToTerminateSubProcess else { + return + } + + // Attempt to teardown the subprocess + if attemptToTerminateSubProcess { + await execution.teardown( + using: self.platformOptions.teardownSequence + ) + } + + var inputError: Swift.Error? + var outputError: Swift.Error? + var errorError: Swift.Error? // lol + + if childSide { + inputError = captureError { + try inputPipe.readFileDescriptor?.safelyClose() + } + outputError = captureError { + try outputPipe.writeFileDescriptor?.safelyClose() + } + errorError = captureError { + try errorPipe.writeFileDescriptor?.safelyClose() + } + } + + if parentSide { + inputError = captureError { + try inputPipe.writeFileDescriptor?.safelyClose() + } + outputError = captureError { + try outputPipe.readFileDescriptor?.safelyClose() + } + errorError = captureError { + try errorPipe.readFileDescriptor?.safelyClose() + } + } + + if let inputError = inputError { + throw inputError + } + + if let outputError = outputError { + throw outputError + } + + if let errorError = errorError { + throw errorError + } + } + + /// Close each input individually, and throw the first error if there's multiple errors thrown + @Sendable + internal func cleanupPreSpawn( + input: CreatedPipe, + output: CreatedPipe, + error: CreatedPipe + ) throws { + var inputError: Swift.Error? + var outputError: Swift.Error? + var errorError: Swift.Error? + + do { + try input.readFileDescriptor?.safelyClose() + try input.writeFileDescriptor?.safelyClose() + } catch { + inputError = error + } + + do { + try output.readFileDescriptor?.safelyClose() + try output.writeFileDescriptor?.safelyClose() + } catch { + outputError = error + } + + do { + try error.readFileDescriptor?.safelyClose() + try error.writeFileDescriptor?.safelyClose() + } catch { + errorError = error + } + + if let inputError = inputError { + throw inputError + } + if let outputError = outputError { + throw outputError + } + if let errorError = errorError { + throw errorError + } + } +} + +// MARK: - Executable + +/// `Executable` defines how the executable should +/// be looked up for execution. +public struct Executable: Sendable, Hashable { + internal enum Storage: Sendable, Hashable { + case executable(String) + case path(FilePath) + } + + internal let storage: Storage + + private init(_config: Storage) { + self.storage = _config + } + + /// Locate the executable by its name. + /// `Subprocess` will use `PATH` value to + /// determine the full path to the executable. + public static func name(_ executableName: String) -> Self { + return .init(_config: .executable(executableName)) + } + /// Locate the executable by its full path. + /// `Subprocess` will use this path directly. + public static func path(_ filePath: FilePath) -> Self { + return .init(_config: .path(filePath)) + } + /// Returns the full executable path given the environment value. + public func resolveExecutablePath(in environment: Environment) throws -> FilePath { + let path = try self.resolveExecutablePath(withPathValue: environment.pathValue()) + return FilePath(path) + } +} + +extension Executable: CustomStringConvertible, CustomDebugStringConvertible { + public var description: String { + switch storage { + case .executable(let executableName): + return executableName + case .path(let filePath): + return filePath.string + } + } + + public var debugDescription: String { + switch storage { + case .executable(let string): + return "executable(\(string))" + case .path(let filePath): + return "path(\(filePath.string))" + } + } +} + +extension Executable { + internal func possibleExecutablePaths( + withPathValue pathValue: String? + ) -> Set { + switch self.storage { + case .executable(let executableName): + #if os(Windows) + // Windows CreateProcessW accepts executable name directly + return Set([executableName]) + #else + var results: Set = [] + // executableName could be a full path + results.insert(executableName) + // Get $PATH from environment + let searchPaths: Set + if let pathValue = pathValue { + let localSearchPaths = pathValue.split(separator: ":").map { String($0) } + searchPaths = Set(localSearchPaths).union(Self.defaultSearchPaths) + } else { + searchPaths = Self.defaultSearchPaths + } + for path in searchPaths { + results.insert( + FilePath(path).appending(executableName).string + ) + } + return results + #endif + case .path(let executablePath): + return Set([executablePath.string]) + } + } +} + +// MARK: - Arguments + +/// A collection of arguments to pass to the subprocess. +public struct Arguments: Sendable, ExpressibleByArrayLiteral, Hashable { + public typealias ArrayLiteralElement = String + + internal let storage: [StringOrRawBytes] + internal let executablePathOverride: StringOrRawBytes? + + /// Create an Arguments object using the given literal values + public init(arrayLiteral elements: String...) { + self.storage = elements.map { .string($0) } + self.executablePathOverride = nil + } + /// Create an Arguments object using the given array + public init(_ array: [String]) { + self.storage = array.map { .string($0) } + self.executablePathOverride = nil + } + + #if !os(Windows) // Windows does NOT support arg0 override + /// Create an `Argument` object using the given values, but + /// override the first Argument value to `executablePathOverride`. + /// If `executablePathOverride` is nil, + /// `Arguments` will automatically use the executable path + /// as the first argument. + /// - Parameters: + /// - executablePathOverride: the value to override the first argument. + /// - remainingValues: the rest of the argument value + public init(executablePathOverride: String?, remainingValues: [String]) { + self.storage = remainingValues.map { .string($0) } + if let executablePathOverride = executablePathOverride { + self.executablePathOverride = .string(executablePathOverride) + } else { + self.executablePathOverride = nil + } + } + + /// Create an `Argument` object using the given values, but + /// override the first Argument value to `executablePathOverride`. + /// If `executablePathOverride` is nil, + /// `Arguments` will automatically use the executable path + /// as the first argument. + /// - Parameters: + /// - executablePathOverride: the value to override the first argument. + /// - remainingValues: the rest of the argument value + public init(executablePathOverride: [UInt8]?, remainingValues: [[UInt8]]) { + self.storage = remainingValues.map { .rawBytes($0) } + if let override = executablePathOverride { + self.executablePathOverride = .rawBytes(override) + } else { + self.executablePathOverride = nil + } + } + + public init(_ array: [[UInt8]]) { + self.storage = array.map { .rawBytes($0) } + self.executablePathOverride = nil + } + #endif +} + +extension Arguments: CustomStringConvertible, CustomDebugStringConvertible { + public var description: String { + var result: [String] = self.storage.map(\.description) + + if let override = self.executablePathOverride { + result.insert("override\(override.description)", at: 0) + } + return result.description + } + + public var debugDescription: String { return self.description } +} + +// MARK: - Environment + +/// A set of environment variables to use when executing the subprocess. +public struct Environment: Sendable, Hashable { + internal enum Configuration: Sendable, Hashable { + case inherit([String: String]) + case custom([String: String]) + #if !os(Windows) + case rawBytes([[UInt8]]) + #endif + } + + internal let config: Configuration + + init(config: Configuration) { + self.config = config + } + /// Child process should inherit the same environment + /// values from its parent process. + public static var inherit: Self { + return .init(config: .inherit([:])) + } + /// Override the provided `newValue` in the existing `Environment` + public func updating(_ newValue: [String: String]) -> Self { + return .init(config: .inherit(newValue)) + } + /// Use custom environment variables + public static func custom(_ newValue: [String: String]) -> Self { + return .init(config: .custom(newValue)) + } + + #if !os(Windows) + /// Use custom environment variables of raw bytes + public static func custom(_ newValue: [[UInt8]]) -> Self { + return .init(config: .rawBytes(newValue)) + } + #endif +} + +extension Environment: CustomStringConvertible, CustomDebugStringConvertible { + public var description: String { + switch self.config { + case .custom(let customDictionary): + return """ + Custom environment: + \(customDictionary) + """ + case .inherit(let updateValue): + return """ + Inherting current environment with updates: + \(updateValue) + """ + #if !os(Windows) + case .rawBytes(let rawBytes): + return """ + Raw bytes: + \(rawBytes) + """ + #endif + } + } + + public var debugDescription: String { + return self.description + } + + internal static func currentEnvironmentValues() -> [String: String] { + return self.withCopiedEnv { environments in + var results: [String: String] = [:] + for env in environments { + let environmentString = String(cString: env) + + #if os(Windows) + // Windows GetEnvironmentStringsW API can return + // magic environment variables set by the cmd shell + // that starts with `=` + // We should exclude these values + if environmentString.utf8.first == Character("=").utf8.first { + continue + } + #endif // os(Windows) + + guard let delimiter = environmentString.firstIndex(of: "=") else { + continue + } + + let key = String(environmentString[environmentString.startIndex.. UnsafeMutablePointer { + switch self { + case .string(let string): + return strdup(string) + case .rawBytes(let rawBytes): + return strdup(rawBytes) + } + } + + var stringValue: String? { + switch self { + case .string(let string): + return string + case .rawBytes(let rawBytes): + return String(decoding: rawBytes, as: UTF8.self) + } + } + + var description: String { + switch self { + case .string(let string): + return string + case .rawBytes(let bytes): + return bytes.description + } + } + + var count: Int { + switch self { + case .string(let string): + return string.count + case .rawBytes(let rawBytes): + return strnlen(rawBytes, Int.max) + } + } + + func hash(into hasher: inout Hasher) { + // If Raw bytes is valid UTF8, hash it as so + switch self { + case .string(let string): + hasher.combine(string) + case .rawBytes(let bytes): + if let stringValue = self.stringValue { + hasher.combine(stringValue) + } else { + hasher.combine(bytes) + } + } + } +} + +/// A simple wrapper on `FileDescriptor` plus a flag indicating +/// whether it should be closed automactially when done. +internal struct TrackedFileDescriptor: Hashable { + internal let closeWhenDone: Bool + internal let wrapped: FileDescriptor + + internal init( + _ wrapped: FileDescriptor, + closeWhenDone: Bool + ) { + self.wrapped = wrapped + self.closeWhenDone = closeWhenDone + } + + internal func safelyClose() throws { + guard self.closeWhenDone else { + return + } + + do { + try self.wrapped.close() + } catch { + guard let errno: Errno = error as? Errno else { + throw error + } + if errno != .badFileDescriptor { + throw errno + } + } + } + + internal var platformDescriptor: PlatformFileDescriptor { + return self.wrapped.platformDescriptor + } +} + +internal struct CreatedPipe { + internal let readFileDescriptor: TrackedFileDescriptor? + internal let writeFileDescriptor: TrackedFileDescriptor? + + internal init( + readFileDescriptor: TrackedFileDescriptor?, + writeFileDescriptor: TrackedFileDescriptor? + ) { + self.readFileDescriptor = readFileDescriptor + self.writeFileDescriptor = writeFileDescriptor + } + + internal init(closeWhenDone: Bool) throws { + let pipe = try FileDescriptor.pipe() + + self.readFileDescriptor = .init( + pipe.readEnd, + closeWhenDone: closeWhenDone + ) + self.writeFileDescriptor = .init( + pipe.writeEnd, + closeWhenDone: closeWhenDone + ) + } +} + +extension FilePath { + static var currentWorkingDirectory: Self { + let path = getcwd(nil, 0)! + defer { free(path) } + return .init(String(cString: path)) + } +} + +extension Optional where Wrapped: Collection { + func withOptionalUnsafeBufferPointer( + _ body: ((UnsafeBufferPointer)?) throws -> Result + ) rethrows -> Result { + switch self { + case .some(let wrapped): + guard let array: [Wrapped.Element] = wrapped as? Array else { + return try body(nil) + } + return try array.withUnsafeBufferPointer { ptr in + return try body(ptr) + } + case .none: + return try body(nil) + } + } +} + +extension Optional where Wrapped == String { + func withOptionalCString( + _ body: ((UnsafePointer)?) throws -> Result + ) rethrows -> Result { + switch self { + case .none: + return try body(nil) + case .some(let wrapped): + return try wrapped.withCString { + return try body($0) + } + } + } + + var stringValue: String { + return self ?? "nil" + } +} + +internal func withAsyncTaskCleanupHandler( + _ body: () async throws -> Result, + onCleanup handler: @Sendable @escaping () async -> Void, + isolation: isolated (any Actor)? = #isolation +) async rethrows -> Result { + return try await withThrowingTaskGroup( + of: Void.self, + returning: Result.self + ) { group in + group.addTask { + // Keep this task sleep indefinitely until the parent task is cancelled. + // `Task.sleep` throws `CancellationError` when the task is canceled + // before the time ends. We then run the cancel handler. + do { while true { try await Task.sleep(nanoseconds: 1_000_000_000) } } catch {} + // Run task cancel handler + await handler() + } + + do { + let result = try await body() + group.cancelAll() + return result + } catch { + await handler() + throw error + } + } +} diff --git a/Sources/_Subprocess/Error.swift b/Sources/_Subprocess/Error.swift new file mode 100644 index 00000000..bf1c9114 --- /dev/null +++ b/Sources/_Subprocess/Error.swift @@ -0,0 +1,141 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// +//===----------------------------------------------------------------------===// + +#if canImport(Darwin) +import Darwin +#elseif canImport(Bionic) +import Bionic +#elseif canImport(Glibc) +import Glibc +#elseif canImport(Musl) +import Musl +#elseif canImport(WinSDK) +import WinSDK +#endif + +/// Error thrown from Subprocess +public struct SubprocessError: Swift.Error, Hashable, Sendable { + /// The error code of this error + public let code: SubprocessError.Code + /// The underlying error that caused this error, if any + public let underlyingError: UnderlyingError? +} + +// MARK: - Error Codes +extension SubprocessError { + /// A SubprocessError Code + public struct Code: Hashable, Sendable { + internal enum Storage: Hashable, Sendable { + case spawnFailed + case executableNotFound(String) + case failedToChangeWorkingDirectory(String) + case failedToReadFromSubprocess + case failedToWriteToSubprocess + case failedToMonitorProcess + // Signal + case failedToSendSignal(Int32) + // Windows Only + case failedToTerminate + case failedToSuspend + case failedToResume + case failedToCreatePipe + case invalidWindowsPath(String) + } + + public var value: Int { + switch self.storage { + case .spawnFailed: + return 0 + case .executableNotFound(_): + return 1 + case .failedToChangeWorkingDirectory(_): + return 2 + case .failedToReadFromSubprocess: + return 3 + case .failedToWriteToSubprocess: + return 4 + case .failedToMonitorProcess: + return 5 + case .failedToSendSignal(_): + return 6 + case .failedToTerminate: + return 7 + case .failedToSuspend: + return 8 + case .failedToResume: + return 9 + case .failedToCreatePipe: + return 10 + case .invalidWindowsPath(_): + return 11 + } + } + + internal let storage: Storage + + internal init(_ storage: Storage) { + self.storage = storage + } + } +} + +// MARK: - Description +extension SubprocessError: CustomStringConvertible, CustomDebugStringConvertible { + public var description: String { + switch self.code.storage { + case .spawnFailed: + return "Failed to spawn the new process." + case .executableNotFound(let executableName): + return "Executable \"\(executableName)\" is not found or cannot be executed." + case .failedToChangeWorkingDirectory(let workingDirectory): + return "Failed to set working directory to \"\(workingDirectory)\"." + case .failedToReadFromSubprocess: + return "Failed to read bytes from the child process with underlying error: \(self.underlyingError!)" + case .failedToWriteToSubprocess: + return "Failed to write bytes to the child process." + case .failedToMonitorProcess: + return "Failed to monitor the state of child process with underlying error: \(self.underlyingError!)" + case .failedToSendSignal(let signal): + return "Failed to send signal \(signal) to the child process." + case .failedToTerminate: + return "Failed to terminate the child process." + case .failedToSuspend: + return "Failed to suspend the child process." + case .failedToResume: + return "Failed to resume the child process." + case .failedToCreatePipe: + return "Failed to create a pipe to communicate to child process." + case .invalidWindowsPath(let badPath): + return "\"\(badPath)\" is not a valid Windows path." + } + } + + public var debugDescription: String { self.description } +} + +extension SubprocessError { + /// The underlying error that caused this SubprocessError. + /// - On Unix-like systems, `UnderlyingError` wraps `errno` from libc; + /// - On Windows, `UnderlyingError` wraps Windows Error code + public struct UnderlyingError: Swift.Error, RawRepresentable, Hashable, Sendable { + #if os(Windows) + public typealias RawValue = DWORD + #else + public typealias RawValue = Int32 + #endif + + public let rawValue: RawValue + + public init(rawValue: RawValue) { + self.rawValue = rawValue + } + } +} diff --git a/Sources/_Subprocess/Execution.swift b/Sources/_Subprocess/Execution.swift new file mode 100644 index 00000000..8da9b492 --- /dev/null +++ b/Sources/_Subprocess/Execution.swift @@ -0,0 +1,192 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// +//===----------------------------------------------------------------------===// + +#if canImport(System) +import System +#else +@preconcurrency import SystemPackage +#endif + +#if canImport(Darwin) +import Darwin +#elseif canImport(Bionic) +import Bionic +#elseif canImport(Glibc) +import Glibc +#elseif canImport(Musl) +import Musl +#elseif canImport(WinSDK) +import WinSDK +#endif + +import Synchronization + +/// An object that repersents a subprocess that has been +/// executed. You can use this object to send signals to the +/// child process as well as stream its output and error. +@available(macOS 15.0, *) // FIXME: manually added availability +public final class Execution< + Output: OutputProtocol, + Error: OutputProtocol +>: Sendable { + /// The process identifier of the current execution + public let processIdentifier: ProcessIdentifier + + internal let output: Output + internal let error: Error + internal let outputPipe: CreatedPipe + internal let errorPipe: CreatedPipe + internal let outputConsumptionState: Atomic + #if os(Windows) + internal let consoleBehavior: PlatformOptions.ConsoleBehavior + + init( + processIdentifier: ProcessIdentifier, + output: Output, + error: Error, + outputPipe: CreatedPipe, + errorPipe: CreatedPipe, + consoleBehavior: PlatformOptions.ConsoleBehavior + ) { + self.processIdentifier = processIdentifier + self.output = output + self.error = error + self.outputPipe = outputPipe + self.errorPipe = errorPipe + self.outputConsumptionState = Atomic(0) + self.consoleBehavior = consoleBehavior + } + #else + init( + processIdentifier: ProcessIdentifier, + output: Output, + error: Error, + outputPipe: CreatedPipe, + errorPipe: CreatedPipe + ) { + self.processIdentifier = processIdentifier + self.output = output + self.error = error + self.outputPipe = outputPipe + self.errorPipe = errorPipe + self.outputConsumptionState = Atomic(0) + } + #endif // os(Windows) +} + +@available(macOS 15.0, *) // FIXME: manually added availability +extension Execution where Output == SequenceOutput { + /// The standard output of the subprocess. + /// + /// Accessing this property will **fatalError** if this property was + /// accessed multiple times. Subprocess communicates with parent process + /// via pipe under the hood and each pipe can only be consumed once. + @available(macOS 15.0, *) // FIXME: manually added availability + public var standardOutput: some AsyncSequence { + let consumptionState = self.outputConsumptionState.bitwiseXor( + OutputConsumptionState.standardOutputConsumed.rawValue, + ordering: .relaxed + ).newValue + + guard OutputConsumptionState(rawValue: consumptionState).contains(.standardOutputConsumed), + let fd = self.outputPipe.readFileDescriptor + else { + fatalError("The standard output has already been consumed") + } + return AsyncBufferSequence(fileDescriptor: fd) + } +} + +@available(macOS 15.0, *) // FIXME: manually added availability +extension Execution where Error == SequenceOutput { + /// The standard error of the subprocess. + /// + /// Accessing this property will **fatalError** if this property was + /// accessed multiple times. Subprocess communicates with parent process + /// via pipe under the hood and each pipe can only be consumed once. + @available(macOS 15.0, *) // FIXME: manually added availability + public var standardError: some AsyncSequence { + let consumptionState = self.outputConsumptionState.bitwiseXor( + OutputConsumptionState.standardErrorConsumed.rawValue, + ordering: .relaxed + ).newValue + + guard OutputConsumptionState(rawValue: consumptionState).contains(.standardErrorConsumed), + let fd = self.errorPipe.readFileDescriptor + else { + fatalError("The standard output has already been consumed") + } + return AsyncBufferSequence(fileDescriptor: fd) + } +} + +// MARK: - Output Capture +internal enum OutputCapturingState: Sendable { + case standardOutputCaptured(Output) + case standardErrorCaptured(Error) +} + +internal struct OutputConsumptionState: OptionSet { + typealias RawValue = UInt8 + + internal let rawValue: UInt8 + + internal init(rawValue: UInt8) { + self.rawValue = rawValue + } + + static let standardOutputConsumed: Self = .init(rawValue: 0b0001) + static let standardErrorConsumed: Self = .init(rawValue: 0b0010) +} + +internal typealias CapturedIOs< + Output: Sendable, + Error: Sendable +> = (standardOutput: Output, standardError: Error) + +@available(macOS 15.0, *) // FIXME: manually added availability +extension Execution { + internal func captureIOs() async throws -> CapturedIOs< + Output.OutputType, Error.OutputType + > { + return try await withThrowingTaskGroup( + of: OutputCapturingState.self + ) { group in + group.addTask { + let stdout = try await self.output.captureOutput( + from: self.outputPipe.readFileDescriptor + ) + return .standardOutputCaptured(stdout) + } + group.addTask { + let stderr = try await self.error.captureOutput( + from: self.errorPipe.readFileDescriptor + ) + return .standardErrorCaptured(stderr) + } + + var stdout: Output.OutputType! + var stderror: Error.OutputType! + while let state = try await group.next() { + switch state { + case .standardOutputCaptured(let output): + stdout = output + case .standardErrorCaptured(let error): + stderror = error + } + } + return ( + standardOutput: stdout, + standardError: stderror + ) + } + } +} diff --git a/Sources/_Subprocess/IO/Input.swift b/Sources/_Subprocess/IO/Input.swift new file mode 100644 index 00000000..5aad5d94 --- /dev/null +++ b/Sources/_Subprocess/IO/Input.swift @@ -0,0 +1,315 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// +//===----------------------------------------------------------------------===// + +#if canImport(System) +import System +#else +@preconcurrency import SystemPackage +#endif + +#if SubprocessFoundation + +#if canImport(Darwin) +// On Darwin always prefer system Foundation +import Foundation +#else +// On other platforms prefer FoundationEssentials +import FoundationEssentials +#endif + +#endif // SubprocessFoundation + +// MARK: - Input + +/// `InputProtocol` defines the `write(with:)` method that a type +/// must implement to serve as the input source for a subprocess. +public protocol InputProtocol: Sendable, ~Copyable { + /// Asynchronously write the input to the subprocess using the + /// write file descriptor + func write(with writer: StandardInputWriter) async throws +} + +/// A concrete `Input` type for subprocesses that indicates +/// the absence of input to the subprocess. On Unix-like systems, +/// `NoInput` redirects the standard input of the subprocess +/// to `/dev/null`, while on Windows, it does not bind any +/// file handle to the subprocess standard input handle. +public struct NoInput: InputProtocol { + internal func createPipe() throws -> CreatedPipe { + #if os(Windows) + // On Windows, instead of binding to dev null, + // we don't set the input handle in the `STARTUPINFOW` + // to signal no input + return CreatedPipe( + readFileDescriptor: nil, + writeFileDescriptor: nil + ) + #else + let devnull: FileDescriptor = try .openDevNull(withAcessMode: .readOnly) + return CreatedPipe( + readFileDescriptor: .init(devnull, closeWhenDone: true), + writeFileDescriptor: nil + ) + #endif + } + + public func write(with writer: StandardInputWriter) async throws { + // noop + } + + internal init() {} +} + +/// A concrete `Input` type for subprocesses that +/// reads input from a specified `FileDescriptor`. +/// Developers have the option to instruct the `Subprocess` to +/// automatically close the provided `FileDescriptor` +/// after the subprocess is spawned. +public struct FileDescriptorInput: InputProtocol { + private let fileDescriptor: FileDescriptor + private let closeAfterSpawningProcess: Bool + + internal func createPipe() throws -> CreatedPipe { + return CreatedPipe( + readFileDescriptor: .init( + self.fileDescriptor, + closeWhenDone: self.closeAfterSpawningProcess + ), + writeFileDescriptor: nil + ) + } + + public func write(with writer: StandardInputWriter) async throws { + // noop + } + + internal init( + fileDescriptor: FileDescriptor, + closeAfterSpawningProcess: Bool + ) { + self.fileDescriptor = fileDescriptor + self.closeAfterSpawningProcess = closeAfterSpawningProcess + } +} + +/// A concrete `Input` type for subprocesses that reads input +/// from a given type conforming to `StringProtocol`. +/// Developers can specify the string encoding to use when +/// encoding the string to data, which defaults to UTF-8. +public struct StringInput< + InputString: StringProtocol & Sendable, + Encoding: Unicode.Encoding +>: InputProtocol { + private let string: InputString + + public func write(with writer: StandardInputWriter) async throws { + guard let array = self.string.byteArray(using: Encoding.self) else { + return + } + _ = try await writer.write(array) + } + + internal init(string: InputString, encoding: Encoding.Type) { + self.string = string + } +} + +/// A concrete `Input` type for subprocesses that reads input +/// from a given `UInt8` Array. +public struct ArrayInput: InputProtocol { + private let array: [UInt8] + + public func write(with writer: StandardInputWriter) async throws { + _ = try await writer.write(self.array) + } + + internal init(array: [UInt8]) { + self.array = array + } +} + +/// A concrete `Input` type for subprocess that indicates that +/// the Subprocess should read its input from `StandardInputWriter`. +public struct CustomWriteInput: InputProtocol { + public func write(with writer: StandardInputWriter) async throws { + // noop + } + + internal init() {} +} + +extension InputProtocol where Self == NoInput { + /// Create a Subprocess input that specfies there is no input + public static var none: Self { .init() } +} + +extension InputProtocol where Self == FileDescriptorInput { + /// Create a Subprocess input from a `FileDescriptor` and + /// specify whether the `FileDescriptor` should be closed + /// after the process is spawned. + public static func fileDescriptor( + _ fd: FileDescriptor, + closeAfterSpawningProcess: Bool + ) -> Self { + return .init( + fileDescriptor: fd, + closeAfterSpawningProcess: closeAfterSpawningProcess + ) + } +} + +extension InputProtocol { + /// Create a Subprocess input from a `Array` of `UInt8`. + public static func array( + _ array: [UInt8] + ) -> Self where Self == ArrayInput { + return ArrayInput(array: array) + } + + /// Create a Subprocess input from a type that conforms to `StringProtocol` + public static func string< + InputString: StringProtocol & Sendable + >( + _ string: InputString + ) -> Self where Self == StringInput { + return .init(string: string, encoding: UTF8.self) + } + + /// Create a Subprocess input from a type that conforms to `StringProtocol` + public static func string< + InputString: StringProtocol & Sendable, + Encoding: Unicode.Encoding + >( + _ string: InputString, + using encoding: Encoding.Type + ) -> Self where Self == StringInput { + return .init(string: string, encoding: encoding) + } +} + +extension InputProtocol { + internal func createPipe() throws -> CreatedPipe { + if let noInput = self as? NoInput { + return try noInput.createPipe() + } else if let fdInput = self as? FileDescriptorInput { + return try fdInput.createPipe() + } + // Base implementation + return try CreatedPipe(closeWhenDone: true) + } +} + +// MARK: - StandardInputWriter + +/// A writer that writes to the standard input of the subprocess. +public final actor StandardInputWriter: Sendable { + + internal let fileDescriptor: TrackedFileDescriptor + + init(fileDescriptor: TrackedFileDescriptor) { + self.fileDescriptor = fileDescriptor + } + + /// Write an array of UInt8 to the standard input of the subprocess. + /// - Parameter array: The sequence of bytes to write. + /// - Returns number of bytes written. + public func write( + _ array: [UInt8] + ) async throws -> Int { + return try await self.fileDescriptor.wrapped.write(array) + } + + /// Write a StringProtocol to the standard input of the subprocess. + /// - Parameters: + /// - string: The string to write. + /// - encoding: The encoding to use when converting string to bytes + /// - Returns number of bytes written. + public func write( + _ string: some StringProtocol, + using encoding: Encoding.Type = UTF8.self + ) async throws -> Int { + if let array = string.byteArray(using: encoding) { + return try await self.write(array) + } + return 0 + } + + /// Signal all writes are finished + public func finish() async throws { + try self.fileDescriptor.safelyClose() + } +} + +extension StringProtocol { + #if SubprocessFoundation + private func convertEncoding( + _ encoding: Encoding.Type + ) -> String.Encoding? { + switch encoding { + case is UTF8.Type: + return .utf8 + case is UTF16.Type: + return .utf16 + case is UTF32.Type: + return .utf32 + default: + return nil + } + } + #endif + package func byteArray(using encoding: Encoding.Type) -> [UInt8]? { + if Encoding.self == Unicode.ASCII.self { + let isASCII = self.utf8.allSatisfy { + return Character(Unicode.Scalar($0)).isASCII + } + + guard isASCII else { + return nil + } + return Array(self.utf8) + } + if Encoding.self == UTF8.self { + return Array(self.utf8) + } + if Encoding.self == UTF16.self { + return Array(self.utf16).flatMap { input in + var uint16: UInt16 = input + return withUnsafeBytes(of: &uint16) { ptr in + Array(ptr) + } + } + } + #if SubprocessFoundation + if let stringEncoding = self.convertEncoding(encoding), + let encoded = self.data(using: stringEncoding) + { + return Array(encoded) + } + return nil + #else + return nil + #endif + } +} + +extension String { + package init( + decodingBytes bytes: [T], + as encoding: Encoding.Type + ) { + self = bytes.withUnsafeBytes { raw in + String( + decoding: raw.bindMemory(to: Encoding.CodeUnit.self).lazy.map { $0 }, + as: encoding + ) + } + } +} diff --git a/Sources/_Subprocess/IO/Output.swift b/Sources/_Subprocess/IO/Output.swift new file mode 100644 index 00000000..be186dd6 --- /dev/null +++ b/Sources/_Subprocess/IO/Output.swift @@ -0,0 +1,298 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// +//===----------------------------------------------------------------------===// + +#if canImport(System) +import System +#else +@preconcurrency import SystemPackage +#endif +internal import Dispatch + +// MARK: - Output + +/// `OutputProtocol` specifies the set of methods that a type +/// must implement to serve as the output target for a subprocess. +/// Instead of developing custom implementations of `OutputProtocol`, +/// it is recommended to utilize the default implementations provided +/// by the `Subprocess` library to specify the output handling requirements. +public protocol OutputProtocol: Sendable, ~Copyable { + associatedtype OutputType: Sendable + + /// Convert the output from buffer to expected output type + func output(from buffer: some Sequence) throws -> OutputType + + /// The max amount of data to collect for this output. + var maxSize: Int { get } +} + +extension OutputProtocol { + /// The max amount of data to collect for this output. + public var maxSize: Int { 128 * 1024 } +} + +/// A concrete `Output` type for subprocesses that indicates that +/// the `Subprocess` should not collect or redirect output +/// from the child process. On Unix-like systems, `DiscardedOutput` +/// redirects the standard output of the subprocess to `/dev/null`, +/// while on Windows, it does not bind any file handle to the +/// subprocess standard output handle. +public struct DiscardedOutput: OutputProtocol { + public typealias OutputType = Void + + internal func createPipe() throws -> CreatedPipe { + #if os(Windows) + // On Windows, instead of binding to dev null, + // we don't set the input handle in the `STARTUPINFOW` + // to signal no output + return CreatedPipe( + readFileDescriptor: nil, + writeFileDescriptor: nil + ) + #else + let devnull: FileDescriptor = try .openDevNull(withAcessMode: .readOnly) + return CreatedPipe( + readFileDescriptor: .init(devnull, closeWhenDone: true), + writeFileDescriptor: nil + ) + #endif + } + + internal init() {} +} + +/// A concrete `Output` type for subprocesses that +/// writes output to a specified `FileDescriptor`. +/// Developers have the option to instruct the `Subprocess` to +/// automatically close the provided `FileDescriptor` +/// after the subprocess is spawned. +public struct FileDescriptorOutput: OutputProtocol { + public typealias OutputType = Void + + private let closeAfterSpawningProcess: Bool + private let fileDescriptor: FileDescriptor + + internal func createPipe() throws -> CreatedPipe { + return CreatedPipe( + readFileDescriptor: nil, + writeFileDescriptor: .init( + self.fileDescriptor, + closeWhenDone: self.closeAfterSpawningProcess + ) + ) + } + + internal init( + fileDescriptor: FileDescriptor, + closeAfterSpawningProcess: Bool + ) { + self.fileDescriptor = fileDescriptor + self.closeAfterSpawningProcess = closeAfterSpawningProcess + } +} + +/// A concrete `Output` type for subprocesses that collects output +/// from the subprocess as `String` with the given encoding. +/// This option must be used with he `run()` method that +/// returns a `CollectedResult`. +public struct StringOutput: OutputProtocol { + public typealias OutputType = String? + public let maxSize: Int + private let encoding: Encoding.Type + + public func output(from buffer: some Sequence) throws -> String? { + // FIXME: Span to String + let array = Array(buffer) + return String(decodingBytes: array, as: Encoding.self) + } + + internal init(limit: Int, encoding: Encoding.Type) { + self.maxSize = limit + self.encoding = encoding + } +} + +/// A concrete `Output` type for subprocesses that collects output +/// from the subprocess as `[UInt8]`. This option must be used with +/// the `run()` method that returns a `CollectedResult` +public struct BytesOutput: OutputProtocol { + public typealias OutputType = [UInt8] + public let maxSize: Int + + internal func captureOutput(from fileDescriptor: TrackedFileDescriptor?) async throws -> [UInt8] { + return try await withCheckedThrowingContinuation { continuation in + guard let fileDescriptor = fileDescriptor else { + // Show not happen due to type system constraints + fatalError("Trying to capture output without file descriptor") + } + fileDescriptor.wrapped.readUntilEOF(upToLength: self.maxSize) { result in + switch result { + case .success(let data): + // FIXME: remove workaround for + // rdar://143992296 + // https://github.com/swiftlang/swift-subprocess/issues/3 + #if os(Windows) + continuation.resume(returning: data) + #else + continuation.resume(returning: data.array()) + #endif + case .failure(let error): + continuation.resume(throwing: error) + } + } + } + } + + public func output(from buffer: some Sequence) throws -> [UInt8] { + fatalError("Not implemented") + } + + internal init(limit: Int) { + self.maxSize = limit + } +} + +/// A concrete `Output` type for subprocesses that redirects +/// the child output to the `.standardOutput` (a sequence) or `.standardError` +/// property of `Execution`. This output type is +/// only applicable to the `run()` family that takes a custom closure. +public struct SequenceOutput: OutputProtocol { + public typealias OutputType = Void + + internal init() {} +} + +extension OutputProtocol where Self == DiscardedOutput { + /// Create a Subprocess output that discards the output + public static var discarded: Self { .init() } +} + +extension OutputProtocol where Self == FileDescriptorOutput { + /// Create a Subprocess output that writes output to a `FileDescriptor` + /// and optionally close the `FileDescriptor` once process spawned. + public static func fileDescriptor( + _ fd: FileDescriptor, + closeAfterSpawningProcess: Bool + ) -> Self { + return .init(fileDescriptor: fd, closeAfterSpawningProcess: closeAfterSpawningProcess) + } +} + +extension OutputProtocol where Self == StringOutput { + /// Create a `Subprocess` output that collects output as + /// UTF8 String with 128kb limit. + public static var string: Self { + .init(limit: 128 * 1024, encoding: UTF8.self) + } +} + +extension OutputProtocol { + /// Create a `Subprocess` output that collects output as + /// `String` using the given encoding up to limit it bytes. + public static func string( + limit: Int, + encoding: Encoding.Type + ) -> Self where Self == StringOutput { + return .init(limit: limit, encoding: encoding) + } +} + +extension OutputProtocol where Self == BytesOutput { + /// Create a `Subprocess` output that collects output as + /// `Buffer` with 128kb limit. + public static var bytes: Self { .init(limit: 128 * 1024) } + + /// Create a `Subprocess` output that collects output as + /// `Buffer` up to limit it bytes. + public static func bytes(limit: Int) -> Self { + return .init(limit: limit) + } +} + +extension OutputProtocol where Self == SequenceOutput { + /// Create a `Subprocess` output that redirects the output + /// to the `.standardOutput` (or `.standardError`) property + /// of `Execution` as `AsyncSequence`. + public static var sequence: Self { .init() } +} + +// MARK: - Default Implementations +extension OutputProtocol { + @_disfavoredOverload + internal func createPipe() throws -> CreatedPipe { + if let discard = self as? DiscardedOutput { + return try discard.createPipe() + } else if let fdOutput = self as? FileDescriptorOutput { + return try fdOutput.createPipe() + } + // Base pipe based implementation for everything else + return try CreatedPipe(closeWhenDone: true) + } + + /// Capture the output from the subprocess up to maxSize + @_disfavoredOverload + internal func captureOutput( + from fileDescriptor: TrackedFileDescriptor? + ) async throws -> OutputType { + if let bytesOutput = self as? BytesOutput { + return try await bytesOutput.captureOutput(from: fileDescriptor) as! Self.OutputType + } + return try await withCheckedThrowingContinuation { continuation in + if OutputType.self == Void.self { + continuation.resume(returning: () as! OutputType) + return + } + guard let fileDescriptor = fileDescriptor else { + // Show not happen due to type system constraints + fatalError("Trying to capture output without file descriptor") + } + + fileDescriptor.wrapped.readUntilEOF(upToLength: self.maxSize) { result in + do { + switch result { + case .success(let data): + // FIXME: remove workaround for + // rdar://143992296 + // https://github.com/swiftlang/swift-subprocess/issues/3 + let output = try self.output(from: data) + continuation.resume(returning: output) + case .failure(let error): + continuation.resume(throwing: error) + } + } catch { + continuation.resume(throwing: error) + } + } + } + } +} + +extension OutputProtocol where OutputType == Void { + internal func captureOutput(from fileDescriptor: TrackedFileDescriptor?) async throws {} + + public func output(from buffer: some Sequence) throws { + // noop + } +} + +extension DispatchData { + internal func array() -> [UInt8] { + var result: [UInt8]? + self.enumerateBytes { buffer, byteIndex, stop in + let currentChunk = Array(UnsafeRawBufferPointer(buffer)) + if result == nil { + result = currentChunk + } else { + result?.append(contentsOf: currentChunk) + } + } + return result ?? [] + } +} diff --git a/Sources/_Subprocess/LockedState.swift b/Sources/_Subprocess/LockedState.swift deleted file mode 100644 index e095668c..00000000 --- a/Sources/_Subprocess/LockedState.swift +++ /dev/null @@ -1,160 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of Swift.org project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -#if canImport(os) -internal import os -#if FOUNDATION_FRAMEWORK && canImport(C.os.lock) -internal import C.os.lock -#endif -#elseif canImport(Bionic) -import Bionic -#elseif canImport(Glibc) -import Glibc -#elseif canImport(Musl) -import Musl -#elseif canImport(WinSDK) -import WinSDK -#endif - -package struct LockedState { - - // Internal implementation for a cheap lock to aid sharing code across platforms - private struct _Lock { -#if canImport(os) - typealias Primitive = os_unfair_lock -#elseif canImport(Bionic) || canImport(Glibc) || canImport(Musl) - typealias Primitive = pthread_mutex_t -#elseif canImport(WinSDK) - typealias Primitive = SRWLOCK -#elseif os(WASI) - // WASI is single-threaded, so we don't need a lock. - typealias Primitive = Void -#endif - - typealias PlatformLock = UnsafeMutablePointer - var _platformLock: PlatformLock - - fileprivate static func initialize(_ platformLock: PlatformLock) { -#if canImport(os) - platformLock.initialize(to: os_unfair_lock()) -#elseif canImport(Bionic) || canImport(Glibc) - pthread_mutex_init(platformLock, nil) -#elseif canImport(WinSDK) - InitializeSRWLock(platformLock) -#elseif os(WASI) - // no-op -#endif - } - - fileprivate static func deinitialize(_ platformLock: PlatformLock) { -#if canImport(Bionic) || canImport(Glibc) - pthread_mutex_destroy(platformLock) -#endif - platformLock.deinitialize(count: 1) - } - - static fileprivate func lock(_ platformLock: PlatformLock) { -#if canImport(os) - os_unfair_lock_lock(platformLock) -#elseif canImport(Bionic) || canImport(Glibc) - pthread_mutex_lock(platformLock) -#elseif canImport(WinSDK) - AcquireSRWLockExclusive(platformLock) -#elseif os(WASI) - // no-op -#endif - } - - static fileprivate func unlock(_ platformLock: PlatformLock) { -#if canImport(os) - os_unfair_lock_unlock(platformLock) -#elseif canImport(Bionic) || canImport(Glibc) - pthread_mutex_unlock(platformLock) -#elseif canImport(WinSDK) - ReleaseSRWLockExclusive(platformLock) -#elseif os(WASI) - // no-op -#endif - } - } - - private class _Buffer: ManagedBuffer { - deinit { - withUnsafeMutablePointerToElements { - _Lock.deinitialize($0) - } - } - } - - private let _buffer: ManagedBuffer - - package init(initialState: State) { - _buffer = _Buffer.create(minimumCapacity: 1, makingHeaderWith: { buf in - buf.withUnsafeMutablePointerToElements { - _Lock.initialize($0) - } - return initialState - }) - } - - package func withLock(_ body: @Sendable (inout State) throws -> T) rethrows -> T { - try withLockUnchecked(body) - } - - package func withLockUnchecked(_ body: (inout State) throws -> T) rethrows -> T { - try _buffer.withUnsafeMutablePointers { state, lock in - _Lock.lock(lock) - defer { _Lock.unlock(lock) } - return try body(&state.pointee) - } - } - - // Ensures the managed state outlives the locked scope. - package func withLockExtendingLifetimeOfState(_ body: @Sendable (inout State) throws -> T) rethrows -> T { - try _buffer.withUnsafeMutablePointers { state, lock in - _Lock.lock(lock) - return try withExtendedLifetime(state.pointee) { - defer { _Lock.unlock(lock) } - return try body(&state.pointee) - } - } - } -} - -extension LockedState where State == Void { - package init() { - self.init(initialState: ()) - } - - package func withLock(_ body: @Sendable () throws -> R) rethrows -> R { - return try withLock { _ in - try body() - } - } - - package func lock() { - _buffer.withUnsafeMutablePointerToElements { lock in - _Lock.lock(lock) - } - } - - package func unlock() { - _buffer.withUnsafeMutablePointerToElements { lock in - _Lock.unlock(lock) - } - } -} - -extension LockedState: @unchecked Sendable where State: Sendable {} - diff --git a/Sources/_Subprocess/Platforms/Subprocess+Darwin.swift b/Sources/_Subprocess/Platforms/Subprocess+Darwin.swift index 4ac2276e..cd5c310a 100644 --- a/Sources/_Subprocess/Platforms/Subprocess+Darwin.swift +++ b/Sources/_Subprocess/Platforms/Subprocess+Darwin.swift @@ -2,306 +2,144 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 +// Copyright (c) 2025 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception // -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of Swift.org project authors -// -// SPDX-License-Identifier: Apache-2.0 +// See https://swift.org/LICENSE.txt for license information // //===----------------------------------------------------------------------===// #if canImport(Darwin) -#if canImport(FoundationEssentials) -import FoundationEssentials -#elseif canImport(Foundation) -import Foundation -#endif - import Darwin -import Dispatch -import SystemPackage - -#if FOUNDATION_FRAMEWORK -@_implementationOnly import _FoundationCShims +internal import Dispatch +#if canImport(System) +import System #else -import _CShims +@preconcurrency import SystemPackage #endif -// Darwin specific implementation -extension Subprocess.Configuration { - internal typealias StringOrRawBytes = Subprocess.StringOrRawBytes +import _SubprocessCShims - internal func spawn( - withInput input: Subprocess.ExecutionInput, - output: Subprocess.ExecutionOutput, - error: Subprocess.ExecutionOutput - ) throws -> Subprocess { - let (executablePath, - env, argv, - intendedWorkingDir, - uidPtr, gidPtr, supplementaryGroups - ) = try self.preSpawn() - defer { - for ptr in env { ptr?.deallocate() } - for ptr in argv { ptr?.deallocate() } - uidPtr?.deallocate() - gidPtr?.deallocate() - } +#if SubprocessFoundation - // Setup file actions and spawn attributes - var fileActions: posix_spawn_file_actions_t? = nil - var spawnAttributes: posix_spawnattr_t? = nil - // Setup stdin, stdout, and stderr - posix_spawn_file_actions_init(&fileActions) - defer { - posix_spawn_file_actions_destroy(&fileActions) - } - // Input - var result: Int32 = -1 - if let inputRead = input.getReadFileDescriptor() { - result = posix_spawn_file_actions_adddup2(&fileActions, inputRead.rawValue, 0) - guard result == 0 else { - try self.cleanupAll(input: input, output: output, error: error) - throw POSIXError(.init(rawValue: result) ?? .ENODEV) - } - } - if let inputWrite = input.getWriteFileDescriptor() { - // Close parent side - result = posix_spawn_file_actions_addclose(&fileActions, inputWrite.rawValue) - guard result == 0 else { - try self.cleanupAll(input: input, output: output, error: error) - throw POSIXError(.init(rawValue: result) ?? .ENODEV) - } - } - // Output - if let outputWrite = output.getWriteFileDescriptor() { - result = posix_spawn_file_actions_adddup2(&fileActions, outputWrite.rawValue, 1) - guard result == 0 else { - try self.cleanupAll(input: input, output: output, error: error) - throw POSIXError(.init(rawValue: result) ?? .ENODEV) - } - } - if let outputRead = output.getReadFileDescriptor() { - // Close parent side - result = posix_spawn_file_actions_addclose(&fileActions, outputRead.rawValue) - guard result == 0 else { - try self.cleanupAll(input: input, output: output, error: error) - throw POSIXError(.init(rawValue: result) ?? .ENODEV) - } - } - // Error - if let errorWrite = error.getWriteFileDescriptor() { - result = posix_spawn_file_actions_adddup2(&fileActions, errorWrite.rawValue, 2) - guard result == 0 else { - try self.cleanupAll(input: input, output: output, error: error) - throw POSIXError(.init(rawValue: result) ?? .ENODEV) - } - } - if let errorRead = error.getReadFileDescriptor() { - // Close parent side - result = posix_spawn_file_actions_addclose(&fileActions, errorRead.rawValue) - guard result == 0 else { - try self.cleanupAll(input: input, output: output, error: error) - throw POSIXError(.init(rawValue: result) ?? .ENODEV) - } - } - // Setup spawnAttributes - posix_spawnattr_init(&spawnAttributes) - defer { - posix_spawnattr_destroy(&spawnAttributes) - } - var noSignals = sigset_t() - var allSignals = sigset_t() - sigemptyset(&noSignals) - sigfillset(&allSignals) - posix_spawnattr_setsigmask(&spawnAttributes, &noSignals) - posix_spawnattr_setsigdefault(&spawnAttributes, &allSignals) - // Configure spawnattr - var spawnAttributeError: Int32 = 0 - var flags: Int32 = POSIX_SPAWN_CLOEXEC_DEFAULT | - POSIX_SPAWN_SETSIGMASK | POSIX_SPAWN_SETSIGDEF - if let pgid = self.platformOptions.processGroupID { - flags |= POSIX_SPAWN_SETPGROUP - spawnAttributeError = posix_spawnattr_setpgroup(&spawnAttributes, pid_t(pgid)) - } - spawnAttributeError = posix_spawnattr_setflags(&spawnAttributes, Int16(flags)) - // Set QualityOfService - // spanattr_qos seems to only accept `QOS_CLASS_UTILITY` or `QOS_CLASS_BACKGROUND` - // and returns an error of `EINVAL` if anything else is provided - if spawnAttributeError == 0 && self.platformOptions.qualityOfService == .utility{ - spawnAttributeError = posix_spawnattr_set_qos_class_np(&spawnAttributes, QOS_CLASS_UTILITY) - } else if spawnAttributeError == 0 && self.platformOptions.qualityOfService == .background { - spawnAttributeError = posix_spawnattr_set_qos_class_np(&spawnAttributes, QOS_CLASS_BACKGROUND) - } - - // Setup cwd - var chdirError: Int32 = 0 - if intendedWorkingDir != .currentWorkingDirectory { - chdirError = intendedWorkingDir.withPlatformString { workDir in - return posix_spawn_file_actions_addchdir_np(&fileActions, workDir) - } - } - - // Error handling - if chdirError != 0 || spawnAttributeError != 0 { - try self.cleanupAll(input: input, output: output, error: error) - if spawnAttributeError != 0 { - throw POSIXError(.init(rawValue: result) ?? .ENODEV) - } +#if canImport(Darwin) +// On Darwin always prefer system Foundation +import Foundation +#else +// On other platforms prefer FoundationEssentials +import FoundationEssentials +#endif - if chdirError != 0 { - throw CocoaError(.fileNoSuchFile, userInfo: [ - .debugDescriptionErrorKey: "Cannot failed to change the working directory to \(intendedWorkingDir) with errno \(chdirError)" - ]) - } - } - // Run additional config - if let spawnConfig = self.platformOptions.preSpawnProcessConfigurator { - try spawnConfig(&spawnAttributes, &fileActions) - } - // Spawn - var pid: pid_t = 0 - let spawnError: CInt = executablePath.withCString { exePath in - return supplementaryGroups.withOptionalUnsafeBufferPointer { sgroups in - return _subprocess_spawn( - &pid, exePath, - &fileActions, &spawnAttributes, - argv, env, - uidPtr, gidPtr, - Int32(supplementaryGroups?.count ?? 0), sgroups?.baseAddress, - self.platformOptions.createSession ? 1 : 0 - ) - } - } - // Spawn error - if spawnError != 0 { - try self.cleanupAll(input: input, output: output, error: error) - throw POSIXError(.init(rawValue: spawnError) ?? .ENODEV) - } - return Subprocess( - processIdentifier: .init(value: pid), - executionInput: input, - executionOutput: output, - executionError: error - ) - } -} +#endif // SubprocessFoundation -// Special keys used in Error's user dictionary -extension String { - static let debugDescriptionErrorKey = "NSDebugDescription" -} +// MARK: - PlatformOptions -// MARK: - Platform Specific Options -extension Subprocess { - /// The collection of platform-specific settings - /// to configure the subprocess when running - public struct PlatformOptions: Sendable { - public var qualityOfService: QualityOfService = .default - /// Set user ID for the subprocess - public var userID: uid_t? = nil - /// Set the real and effective group ID and the saved - /// set-group-ID of the subprocess, equivalent to calling - /// `setgid()` on the child process. - /// Group ID is used to control permissions, particularly - /// for file access. - public var groupID: gid_t? = nil - /// Set list of supplementary group IDs for the subprocess - public var supplementaryGroups: [gid_t]? = nil - /// Set the process group for the subprocess, equivalent to - /// calling `setpgid()` on the child process. - /// Process group ID is used to group related processes for - /// controlling signals. - public var processGroupID: pid_t? = nil - /// Creates a session and sets the process group ID - /// i.e. Detach from the terminal. - public var createSession: Bool = false - /// A lightweight code requirement that you use to - /// evaluate the executable for a launching process. - public var launchRequirementData: Data? = nil - /// An ordered list of steps in order to tear down the child - /// process in case the parent task is cancelled before - /// the child proces terminates. - /// Always ends in sending a `.kill` signal at the end. - public var teardownSequence: [TeardownStep] = [] - /// A closure to configure platform-specific - /// spawning constructs. This closure enables direct - /// configuration or override of underlying platform-specific - /// spawn settings that `Subprocess` utilizes internally, - /// in cases where Subprocess does not provide higher-level - /// APIs for such modifications. - /// - /// On Darwin, Subprocess uses `posix_spawn()` as the - /// underlying spawning mechanism. This closure allows - /// modification of the `posix_spawnattr_t` spawn attribute - /// and file actions `posix_spawn_file_actions_t` before - /// they are sent to `posix_spawn()`. - public var preSpawnProcessConfigurator: ( +/// The collection of platform-specific settings +/// to configure the subprocess when running +public struct PlatformOptions: Sendable { + public var qualityOfService: QualityOfService = .default + /// Set user ID for the subprocess + public var userID: uid_t? = nil + /// Set the real and effective group ID and the saved + /// set-group-ID of the subprocess, equivalent to calling + /// `setgid()` on the child process. + /// Group ID is used to control permissions, particularly + /// for file access. + public var groupID: gid_t? = nil + /// Set list of supplementary group IDs for the subprocess + public var supplementaryGroups: [gid_t]? = nil + /// Set the process group for the subprocess, equivalent to + /// calling `setpgid()` on the child process. + /// Process group ID is used to group related processes for + /// controlling signals. + public var processGroupID: pid_t? = nil + /// Creates a session and sets the process group ID + /// i.e. Detach from the terminal. + public var createSession: Bool = false + /// An ordered list of steps in order to tear down the child + /// process in case the parent task is cancelled before + /// the child proces terminates. + /// Always ends in sending a `.kill` signal at the end. + public var teardownSequence: [TeardownStep] = [] + /// A closure to configure platform-specific + /// spawning constructs. This closure enables direct + /// configuration or override of underlying platform-specific + /// spawn settings that `Subprocess` utilizes internally, + /// in cases where Subprocess does not provide higher-level + /// APIs for such modifications. + /// + /// On Darwin, Subprocess uses `posix_spawn()` as the + /// underlying spawning mechanism. This closure allows + /// modification of the `posix_spawnattr_t` spawn attribute + /// and file actions `posix_spawn_file_actions_t` before + /// they are sent to `posix_spawn()`. + public var preSpawnProcessConfigurator: + ( @Sendable ( inout posix_spawnattr_t?, inout posix_spawn_file_actions_t? ) throws -> Void )? = nil - public init() {} - } + public init() {} } -extension Subprocess.PlatformOptions: Hashable { - public static func == (lhs: Subprocess.PlatformOptions, rhs: Subprocess.PlatformOptions) -> Bool { - // Since we can't compare closure equality, - // as long as preSpawnProcessConfigurator is set - // always returns false so that `PlatformOptions` - // with it set will never equal to each other - if lhs.preSpawnProcessConfigurator != nil || - rhs.preSpawnProcessConfigurator != nil { - return false - } - return lhs.qualityOfService == rhs.qualityOfService && - lhs.userID == rhs.userID && - lhs.groupID == rhs.groupID && - lhs.supplementaryGroups == rhs.supplementaryGroups && - lhs.processGroupID == rhs.processGroupID && - lhs.createSession == rhs.createSession && - lhs.launchRequirementData == rhs.launchRequirementData - } - - public func hash(into hasher: inout Hasher) { - hasher.combine(self.qualityOfService) - hasher.combine(self.userID) - hasher.combine(self.groupID) - hasher.combine(self.supplementaryGroups) - hasher.combine(self.processGroupID) - hasher.combine(self.createSession) - hasher.combine(self.launchRequirementData) - // Since we can't really hash closures, - // use an UUID such that as long as - // `preSpawnProcessConfigurator` is set, it will - // never equal to other PlatformOptions - if self.preSpawnProcessConfigurator != nil { - hasher.combine(UUID()) - } +extension PlatformOptions { + #if SubprocessFoundation + public typealias QualityOfService = Foundation.QualityOfService + #else + /// Constants that indicate the nature and importance of work to the system. + /// + /// Work with higher quality of service classes receive more resources + /// than work with lower quality of service classes whenever + /// there’s resource contention. + public enum QualityOfService: Int, Sendable { + /// Used for work directly involved in providing an + /// interactive UI. For example, processing control + /// events or drawing to the screen. + case userInteractive = 0x21 + /// Used for performing work that has been explicitly requested + /// by the user, and for which results must be immediately + /// presented in order to allow for further user interaction. + /// For example, loading an email after a user has selected + /// it in a message list. + case userInitiated = 0x19 + /// Used for performing work which the user is unlikely to be + /// immediately waiting for the results. This work may have been + /// requested by the user or initiated automatically, and often + /// operates at user-visible timescales using a non-modal + /// progress indicator. For example, periodic content updates + /// or bulk file operations, such as media import. + case utility = 0x11 + /// Used for work that is not user initiated or visible. + /// In general, a user is unaware that this work is even happening. + /// For example, pre-fetching content, search indexing, backups, + /// or syncing of data with external systems. + case background = 0x09 + /// Indicates no explicit quality of service information. + /// Whenever possible, an appropriate quality of service is determined + /// from available sources. Otherwise, some quality of service level + /// between `.userInteractive` and `.utility` is used. + case `default` = -1 } + #endif } -extension Subprocess.PlatformOptions : CustomStringConvertible, CustomDebugStringConvertible { +extension PlatformOptions: CustomStringConvertible, CustomDebugStringConvertible { internal func description(withIndent indent: Int) -> String { let indent = String(repeating: " ", count: indent * 4) return """ -PlatformOptions( -\(indent) qualityOfService: \(self.qualityOfService), -\(indent) userID: \(String(describing: userID)), -\(indent) groupID: \(String(describing: groupID)), -\(indent) supplementaryGroups: \(String(describing: supplementaryGroups)), -\(indent) processGroupID: \(String(describing: processGroupID)), -\(indent) createSession: \(createSession), -\(indent) launchRequirementData: \(String(describing: launchRequirementData)), -\(indent) preSpawnProcessConfigurator: \(self.preSpawnProcessConfigurator == nil ? "not set" : "set") -\(indent)) -""" + PlatformOptions( + \(indent) qualityOfService: \(self.qualityOfService), + \(indent) userID: \(String(describing: userID)), + \(indent) groupID: \(String(describing: groupID)), + \(indent) supplementaryGroups: \(String(describing: supplementaryGroups)), + \(indent) processGroupID: \(String(describing: processGroupID)), + \(indent) createSession: \(createSession), + \(indent) preSpawnProcessConfigurator: \(self.preSpawnProcessConfigurator == nil ? "not set" : "set") + \(indent)) + """ } public var description: String { @@ -313,11 +151,243 @@ PlatformOptions( } } +// MARK: - Spawn +extension Configuration { + @available(macOS 15.0, *) // FIXME: manually added availability + internal func spawn< + Output: OutputProtocol, + Error: OutputProtocol + >( + withInput inputPipe: CreatedPipe, + output: Output, + outputPipe: CreatedPipe, + error: Error, + errorPipe: CreatedPipe + ) throws -> Execution { + // Instead of checking if every possible executable path + // is valid, spawn each directly and catch ENOENT + let possiblePaths = self.executable.possibleExecutablePaths( + withPathValue: self.environment.pathValue() + ) + return try self.preSpawn { args throws -> Execution in + let (env, uidPtr, gidPtr, supplementaryGroups) = args + for possibleExecutablePath in possiblePaths { + var pid: pid_t = 0 + + // Setup Arguments + let argv: [UnsafeMutablePointer?] = self.arguments.createArgs( + withExecutablePath: possibleExecutablePath + ) + defer { + for ptr in argv { ptr?.deallocate() } + } + + // Setup file actions and spawn attributes + var fileActions: posix_spawn_file_actions_t? = nil + var spawnAttributes: posix_spawnattr_t? = nil + // Setup stdin, stdout, and stderr + posix_spawn_file_actions_init(&fileActions) + defer { + posix_spawn_file_actions_destroy(&fileActions) + } + // Input + var result: Int32 = -1 + if let inputRead = inputPipe.readFileDescriptor { + result = posix_spawn_file_actions_adddup2(&fileActions, inputRead.wrapped.rawValue, 0) + guard result == 0 else { + try self.cleanupPreSpawn(input: inputPipe, output: outputPipe, error: errorPipe) + throw SubprocessError( + code: .init(.spawnFailed), + underlyingError: .init(rawValue: result) + ) + } + } + if let inputWrite = inputPipe.writeFileDescriptor { + // Close parent side + result = posix_spawn_file_actions_addclose(&fileActions, inputWrite.wrapped.rawValue) + guard result == 0 else { + try self.cleanupPreSpawn(input: inputPipe, output: outputPipe, error: errorPipe) + throw SubprocessError( + code: .init(.spawnFailed), + underlyingError: .init(rawValue: result) + ) + } + } + // Output + if let outputWrite = outputPipe.writeFileDescriptor { + result = posix_spawn_file_actions_adddup2(&fileActions, outputWrite.wrapped.rawValue, 1) + guard result == 0 else { + try self.cleanupPreSpawn(input: inputPipe, output: outputPipe, error: errorPipe) + throw SubprocessError( + code: .init(.spawnFailed), + underlyingError: .init(rawValue: result) + ) + } + } + if let outputRead = outputPipe.readFileDescriptor { + // Close parent side + result = posix_spawn_file_actions_addclose(&fileActions, outputRead.wrapped.rawValue) + guard result == 0 else { + try self.cleanupPreSpawn(input: inputPipe, output: outputPipe, error: errorPipe) + throw SubprocessError( + code: .init(.spawnFailed), + underlyingError: .init(rawValue: result) + ) + } + } + // Error + if let errorWrite = errorPipe.writeFileDescriptor { + result = posix_spawn_file_actions_adddup2(&fileActions, errorWrite.wrapped.rawValue, 2) + guard result == 0 else { + try self.cleanupPreSpawn(input: inputPipe, output: outputPipe, error: errorPipe) + throw SubprocessError( + code: .init(.spawnFailed), + underlyingError: .init(rawValue: result) + ) + } + } + if let errorRead = errorPipe.readFileDescriptor { + // Close parent side + result = posix_spawn_file_actions_addclose(&fileActions, errorRead.wrapped.rawValue) + guard result == 0 else { + try self.cleanupPreSpawn(input: inputPipe, output: outputPipe, error: errorPipe) + throw SubprocessError( + code: .init(.spawnFailed), + underlyingError: .init(rawValue: result) + ) + } + } + // Setup spawnAttributes + posix_spawnattr_init(&spawnAttributes) + defer { + posix_spawnattr_destroy(&spawnAttributes) + } + var noSignals = sigset_t() + var allSignals = sigset_t() + sigemptyset(&noSignals) + sigfillset(&allSignals) + posix_spawnattr_setsigmask(&spawnAttributes, &noSignals) + posix_spawnattr_setsigdefault(&spawnAttributes, &allSignals) + // Configure spawnattr + var spawnAttributeError: Int32 = 0 + var flags: Int32 = POSIX_SPAWN_CLOEXEC_DEFAULT | POSIX_SPAWN_SETSIGMASK | POSIX_SPAWN_SETSIGDEF + if let pgid = self.platformOptions.processGroupID { + flags |= POSIX_SPAWN_SETPGROUP + spawnAttributeError = posix_spawnattr_setpgroup(&spawnAttributes, pid_t(pgid)) + } + spawnAttributeError = posix_spawnattr_setflags(&spawnAttributes, Int16(flags)) + // Set QualityOfService + // spanattr_qos seems to only accept `QOS_CLASS_UTILITY` or `QOS_CLASS_BACKGROUND` + // and returns an error of `EINVAL` if anything else is provided + if spawnAttributeError == 0 && self.platformOptions.qualityOfService == .utility { + spawnAttributeError = posix_spawnattr_set_qos_class_np(&spawnAttributes, QOS_CLASS_UTILITY) + } else if spawnAttributeError == 0 && self.platformOptions.qualityOfService == .background { + spawnAttributeError = posix_spawnattr_set_qos_class_np(&spawnAttributes, QOS_CLASS_BACKGROUND) + } + + // Setup cwd + let intendedWorkingDir = self.workingDirectory.string + let chdirError: Int32 = intendedWorkingDir.withPlatformString { workDir in + return posix_spawn_file_actions_addchdir_np(&fileActions, workDir) + } + + // Error handling + if chdirError != 0 || spawnAttributeError != 0 { + try self.cleanupPreSpawn(input: inputPipe, output: outputPipe, error: errorPipe) + if spawnAttributeError != 0 { + throw SubprocessError( + code: .init(.spawnFailed), + underlyingError: .init(rawValue: spawnAttributeError) + ) + } + + if chdirError != 0 { + throw SubprocessError( + code: .init(.spawnFailed), + underlyingError: .init(rawValue: spawnAttributeError) + ) + } + } + // Run additional config + if let spawnConfig = self.platformOptions.preSpawnProcessConfigurator { + try spawnConfig(&spawnAttributes, &fileActions) + } + + // Spawn + let spawnError: CInt = possibleExecutablePath.withCString { exePath in + return supplementaryGroups.withOptionalUnsafeBufferPointer { sgroups in + return _subprocess_spawn( + &pid, + exePath, + &fileActions, + &spawnAttributes, + argv, + env, + uidPtr, + gidPtr, + Int32(supplementaryGroups?.count ?? 0), + sgroups?.baseAddress, + self.platformOptions.createSession ? 1 : 0 + ) + } + } + // Spawn error + if spawnError != 0 { + if spawnError == ENOENT { + // Move on to another possible path + continue + } + // Throw all other errors + try self.cleanupPreSpawn( + input: inputPipe, + output: outputPipe, + error: errorPipe + ) + throw SubprocessError( + code: .init(.spawnFailed), + underlyingError: .init(rawValue: spawnError) + ) + } + return Execution( + processIdentifier: .init(value: pid), + output: output, + error: error, + outputPipe: outputPipe, + errorPipe: errorPipe + ) + } + + // If we reach this point, it means either the executable path + // or working directory is not valid. Since posix_spawn does not + // provide which one is not valid, here we make a best effort guess + // by checking whether the working directory is valid. This technically + // still causes TOUTOC issue, but it's the best we can do for error recovery. + try self.cleanupPreSpawn(input: inputPipe, output: outputPipe, error: errorPipe) + let workingDirectory = self.workingDirectory.string + guard Configuration.pathAccessible(workingDirectory, mode: F_OK) else { + throw SubprocessError( + code: .init(.failedToChangeWorkingDirectory(workingDirectory)), + underlyingError: .init(rawValue: ENOENT) + ) + } + throw SubprocessError( + code: .init(.executableNotFound(self.executable.description)), + underlyingError: .init(rawValue: ENOENT) + ) + } + } +} + +// Special keys used in Error's user dictionary +extension String { + static let debugDescriptionErrorKey = "NSDebugDescription" +} + // MARK: - Process Monitoring @Sendable internal func monitorProcessTermination( - forProcessWithIdentifier pid: Subprocess.ProcessIdentifier -) async throws -> Subprocess.TerminationStatus { + forProcessWithIdentifier pid: ProcessIdentifier +) async throws -> TerminationStatus { return try await withCheckedThrowingContinuation { continuation in let source = DispatchSource.makeProcessSource( identifier: pid.value, @@ -329,7 +399,12 @@ internal func monitorProcessTermination( var siginfo = siginfo_t() let rc = waitid(P_PID, id_t(pid.value), &siginfo, WEXITED) guard rc == 0 else { - continuation.resume(throwing: POSIXError(.init(rawValue: errno) ?? .ENODEV)) + continuation.resume( + throwing: SubprocessError( + code: .init(.failedToMonitorProcess), + underlyingError: .init(rawValue: errno) + ) + ) return } switch siginfo.si_code { @@ -350,4 +425,4 @@ internal func monitorProcessTermination( } } -#endif // canImport(Darwin) +#endif // canImport(Darwin) diff --git a/Sources/_Subprocess/Platforms/Subprocess+Linux.swift b/Sources/_Subprocess/Platforms/Subprocess+Linux.swift index 9debf2e3..23c9b36e 100644 --- a/Sources/_Subprocess/Platforms/Subprocess+Linux.swift +++ b/Sources/_Subprocess/Platforms/Subprocess+Linux.swift @@ -2,196 +2,210 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 +// Copyright (c) 2025 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception // -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of Swift.org project authors -// -// SPDX-License-Identifier: Apache-2.0 +// See https://swift.org/LICENSE.txt for license information // //===----------------------------------------------------------------------===// -#if canImport(Glibc) +#if canImport(Glibc) || canImport(Bionic) || canImport(Musl) + +#if canImport(System) +import System +#else +@preconcurrency import SystemPackage +#endif +#if canImport(Glibc) import Glibc -import Dispatch -import SystemPackage -import FoundationEssentials -import _CShims +#elseif canImport(Bionic) +import Bionic +#elseif canImport(Musl) +import Musl +#endif -// Linux specific implementations -extension Subprocess.Configuration { - internal typealias StringOrRawBytes = Subprocess.StringOrRawBytes +internal import Dispatch - internal func spawn( - withInput input: Subprocess.ExecutionInput, - output: Subprocess.ExecutionOutput, - error: Subprocess.ExecutionOutput - ) throws -> Subprocess { +import Synchronization +import _SubprocessCShims + +// Linux specific implementations +extension Configuration { + internal func spawn< + Output: OutputProtocol, + Error: OutputProtocol + >( + withInput inputPipe: CreatedPipe, + output: Output, + outputPipe: CreatedPipe, + error: Error, + errorPipe: CreatedPipe + ) throws -> Execution { _setupMonitorSignalHandler() - let (executablePath, - env, argv, - intendedWorkingDir, - uidPtr, gidPtr, - supplementaryGroups - ) = try self.preSpawn() - var processGroupIDPtr: UnsafeMutablePointer? = nil - if let processGroupID = self.platformOptions.processGroupID { - processGroupIDPtr = .allocate(capacity: 1) - processGroupIDPtr?.pointee = gid_t(processGroupID) - } - defer { - for ptr in env { ptr?.deallocate() } - for ptr in argv { ptr?.deallocate() } - uidPtr?.deallocate() - gidPtr?.deallocate() - processGroupIDPtr?.deallocate() - } + // Instead of checking if every possible executable path + // is valid, spawn each directly and catch ENOENT + let possiblePaths = self.executable.possibleExecutablePaths( + withPathValue: self.environment.pathValue() + ) - let fileDescriptors: [CInt] = [ - input.getReadFileDescriptor()?.rawValue ?? -1, - input.getWriteFileDescriptor()?.rawValue ?? -1, - output.getWriteFileDescriptor()?.rawValue ?? -1, - output.getReadFileDescriptor()?.rawValue ?? -1, - error.getWriteFileDescriptor()?.rawValue ?? -1, - error.getReadFileDescriptor()?.rawValue ?? -1 - ] + return try self.preSpawn { args throws -> Execution in + let (env, uidPtr, gidPtr, supplementaryGroups) = args - var workingDirectory: String? - if intendedWorkingDir != FilePath.currentWorkingDirectory { - // Only pass in working directory if it's different - workingDirectory = intendedWorkingDir.string - } - // Spawn - var pid: pid_t = 0 - let spawnError: CInt = executablePath.withCString { exePath in - return workingDirectory.withOptionalCString { workingDir in - return supplementaryGroups.withOptionalUnsafeBufferPointer { sgroups in - return fileDescriptors.withUnsafeBufferPointer { fds in - return _subprocess_fork_exec( - &pid, exePath, workingDir, - fds.baseAddress!, - argv, env, - uidPtr, gidPtr, - processGroupIDPtr, - CInt(supplementaryGroups?.count ?? 0), sgroups?.baseAddress, - self.platformOptions.createSession ? 1 : 0, - self.platformOptions.preSpawnProcessConfigurator - ) + for possibleExecutablePath in possiblePaths { + var processGroupIDPtr: UnsafeMutablePointer? = nil + if let processGroupID = self.platformOptions.processGroupID { + processGroupIDPtr = .allocate(capacity: 1) + processGroupIDPtr?.pointee = gid_t(processGroupID) + } + // Setup Arguments + let argv: [UnsafeMutablePointer?] = self.arguments.createArgs( + withExecutablePath: possibleExecutablePath + ) + defer { + for ptr in argv { ptr?.deallocate() } + } + // Setup input + let fileDescriptors: [CInt] = [ + inputPipe.readFileDescriptor?.wrapped.rawValue ?? -1, + inputPipe.writeFileDescriptor?.wrapped.rawValue ?? -1, + outputPipe.writeFileDescriptor?.wrapped.rawValue ?? -1, + outputPipe.readFileDescriptor?.wrapped.rawValue ?? -1, + errorPipe.writeFileDescriptor?.wrapped.rawValue ?? -1, + errorPipe.readFileDescriptor?.wrapped.rawValue ?? -1, + ] + + let workingDirectory: String = self.workingDirectory.string + // Spawn + var pid: pid_t = 0 + let spawnError: CInt = possibleExecutablePath.withCString { exePath in + return workingDirectory.withCString { workingDir in + return supplementaryGroups.withOptionalUnsafeBufferPointer { sgroups in + return fileDescriptors.withUnsafeBufferPointer { fds in + return _subprocess_fork_exec( + &pid, + exePath, + workingDir, + fds.baseAddress!, + argv, + env, + uidPtr, + gidPtr, + processGroupIDPtr, + CInt(supplementaryGroups?.count ?? 0), + sgroups?.baseAddress, + self.platformOptions.createSession ? 1 : 0, + self.platformOptions.preSpawnProcessConfigurator + ) + } + } } } + // Spawn error + if spawnError != 0 { + if spawnError == ENOENT { + // Move on to another possible path + continue + } + // Throw all other errors + try self.cleanupPreSpawn( + input: inputPipe, + output: outputPipe, + error: errorPipe + ) + throw SubprocessError( + code: .init(.spawnFailed), + underlyingError: .init(rawValue: spawnError) + ) + } + return Execution( + processIdentifier: .init(value: pid), + output: output, + error: error, + outputPipe: outputPipe, + errorPipe: errorPipe + ) } + + // If we reach this point, it means either the executable path + // or working directory is not valid. Since posix_spawn does not + // provide which one is not valid, here we make a best effort guess + // by checking whether the working directory is valid. This technically + // still causes TOUTOC issue, but it's the best we can do for error recovery. + try self.cleanupPreSpawn(input: inputPipe, output: outputPipe, error: errorPipe) + let workingDirectory = self.workingDirectory.string + guard Configuration.pathAccessible(workingDirectory, mode: F_OK) else { + throw SubprocessError( + code: .init(.failedToChangeWorkingDirectory(workingDirectory)), + underlyingError: .init(rawValue: ENOENT) + ) + } + throw SubprocessError( + code: .init(.executableNotFound(self.executable.description)), + underlyingError: .init(rawValue: ENOENT) + ) } - // Spawn error - if spawnError != 0 { - try self.cleanupAll(input: input, output: output, error: error) - throw POSIXError(.init(rawValue: spawnError) ?? .ENODEV) - } - return Subprocess( - processIdentifier: .init(value: pid), - executionInput: input, - executionOutput: output, - executionError: error - ) } } // MARK: - Platform Specific Options -extension Subprocess { - /// The collection of platform-specific settings - /// to configure the subprocess when running - public struct PlatformOptions: Sendable { - // Set user ID for the subprocess - public var userID: uid_t? = nil - /// Set the real and effective group ID and the saved - /// set-group-ID of the subprocess, equivalent to calling - /// `setgid()` on the child process. - /// Group ID is used to control permissions, particularly - /// for file access. - public var groupID: gid_t? = nil - // Set list of supplementary group IDs for the subprocess - public var supplementaryGroups: [gid_t]? = nil - /// Set the process group for the subprocess, equivalent to - /// calling `setpgid()` on the child process. - /// Process group ID is used to group related processes for - /// controlling signals. - public var processGroupID: pid_t? = nil - // Creates a session and sets the process group ID - // i.e. Detach from the terminal. - public var createSession: Bool = false - /// An ordered list of steps in order to tear down the child - /// process in case the parent task is cancelled before - /// the child proces terminates. - /// Always ends in sending a `.kill` signal at the end. - public var teardownSequence: [TeardownStep] = [] - /// A closure to configure platform-specific - /// spawning constructs. This closure enables direct - /// configuration or override of underlying platform-specific - /// spawn settings that `Subprocess` utilizes internally, - /// in cases where Subprocess does not provide higher-level - /// APIs for such modifications. - /// - /// On Linux, Subprocess uses `fork/exec` as the - /// underlying spawning mechanism. This closure is called - /// after `fork()` but before `exec()`. You may use it to - /// call any necessary process setup functions. - public var preSpawnProcessConfigurator: (@convention(c) @Sendable () -> Void)? = nil - public init() {} - } -} - -extension Subprocess.PlatformOptions: Hashable { - public static func ==( - lhs: Subprocess.PlatformOptions, - rhs: Subprocess.PlatformOptions - ) -> Bool { - // Since we can't compare closure equality, - // as long as preSpawnProcessConfigurator is set - // always returns false so that `PlatformOptions` - // with it set will never equal to each other - if lhs.preSpawnProcessConfigurator != nil || - rhs.preSpawnProcessConfigurator != nil { - return false - } - return lhs.userID == rhs.userID && - lhs.groupID == rhs.groupID && - lhs.supplementaryGroups == rhs.supplementaryGroups && - lhs.processGroupID == rhs.processGroupID && - lhs.createSession == rhs.createSession - } +/// The collection of platform-specific settings +/// to configure the subprocess when running +public struct PlatformOptions: Sendable { + // Set user ID for the subprocess + public var userID: uid_t? = nil + /// Set the real and effective group ID and the saved + /// set-group-ID of the subprocess, equivalent to calling + /// `setgid()` on the child process. + /// Group ID is used to control permissions, particularly + /// for file access. + public var groupID: gid_t? = nil + // Set list of supplementary group IDs for the subprocess + public var supplementaryGroups: [gid_t]? = nil + /// Set the process group for the subprocess, equivalent to + /// calling `setpgid()` on the child process. + /// Process group ID is used to group related processes for + /// controlling signals. + public var processGroupID: pid_t? = nil + // Creates a session and sets the process group ID + // i.e. Detach from the terminal. + public var createSession: Bool = false + /// An ordered list of steps in order to tear down the child + /// process in case the parent task is cancelled before + /// the child proces terminates. + /// Always ends in sending a `.kill` signal at the end. + public var teardownSequence: [TeardownStep] = [] + /// A closure to configure platform-specific + /// spawning constructs. This closure enables direct + /// configuration or override of underlying platform-specific + /// spawn settings that `Subprocess` utilizes internally, + /// in cases where Subprocess does not provide higher-level + /// APIs for such modifications. + /// + /// On Linux, Subprocess uses `fork/exec` as the + /// underlying spawning mechanism. This closure is called + /// after `fork()` but before `exec()`. You may use it to + /// call any necessary process setup functions. + public var preSpawnProcessConfigurator: (@convention(c) @Sendable () -> Void)? = nil - public func hash(into hasher: inout Hasher) { - hasher.combine(userID) - hasher.combine(groupID) - hasher.combine(supplementaryGroups) - hasher.combine(processGroupID) - hasher.combine(createSession) - // Since we can't really hash closures, - // use an UUID such that as long as - // `preSpawnProcessConfigurator` is set, it will - // never equal to other PlatformOptions - if self.preSpawnProcessConfigurator != nil { - hasher.combine(UUID()) - } - } + public init() {} } -extension Subprocess.PlatformOptions : CustomStringConvertible, CustomDebugStringConvertible { +extension PlatformOptions: CustomStringConvertible, CustomDebugStringConvertible { internal func description(withIndent indent: Int) -> String { let indent = String(repeating: " ", count: indent * 4) return """ -PlatformOptions( -\(indent) userID: \(String(describing: userID)), -\(indent) groupID: \(String(describing: groupID)), -\(indent) supplementaryGroups: \(String(describing: supplementaryGroups)), -\(indent) processGroupID: \(String(describing: processGroupID)), -\(indent) createSession: \(createSession), -\(indent) preSpawnProcessConfigurator: \(self.preSpawnProcessConfigurator == nil ? "not set" : "set") -\(indent)) -""" + PlatformOptions( + \(indent) userID: \(String(describing: userID)), + \(indent) groupID: \(String(describing: groupID)), + \(indent) supplementaryGroups: \(String(describing: supplementaryGroups)), + \(indent) processGroupID: \(String(describing: processGroupID)), + \(indent) createSession: \(createSession), + \(indent) preSpawnProcessConfigurator: \(self.preSpawnProcessConfigurator == nil ? "not set" : "set") + \(indent)) + """ } public var description: String { @@ -211,12 +225,13 @@ extension String { // MARK: - Process Monitoring @Sendable internal func monitorProcessTermination( - forProcessWithIdentifier pid: Subprocess.ProcessIdentifier -) async throws -> Subprocess.TerminationStatus { + forProcessWithIdentifier pid: ProcessIdentifier +) async throws -> TerminationStatus { return try await withCheckedThrowingContinuation { continuation in _childProcessContinuations.withLock { continuations in if let existing = continuations.removeValue(forKey: pid.value), - case .status(let existingStatus) = existing { + case .status(let existingStatus) = existing + { // We already have existing status to report continuation.resume(returning: existingStatus) } else { @@ -228,28 +243,26 @@ internal func monitorProcessTermination( } private enum ContinuationOrStatus { - case continuation(CheckedContinuation) - case status(Subprocess.TerminationStatus) + case continuation(CheckedContinuation) + case status(TerminationStatus) } -private let _childProcessContinuations: LockedState< - [pid_t: ContinuationOrStatus] -> = LockedState(initialState: [:]) +private let _childProcessContinuations: + Mutex< + [pid_t: ContinuationOrStatus] + > = Mutex([:]) + +private let signalSource: SendableSourceSignal = SendableSourceSignal() -private var signalSource: (any DispatchSourceSignal)? = nil private let setup: () = { - signalSource = DispatchSource.makeSignalSource( - signal: SIGCHLD, - queue: .global() - ) - signalSource?.setEventHandler { + signalSource.setEventHandler { _childProcessContinuations.withLock { continuations in while true { var siginfo = siginfo_t() guard waitid(P_ALL, id_t(0), &siginfo, WEXITED) == 0 else { return } - var status: Subprocess.TerminationStatus? = nil + var status: TerminationStatus? = nil switch siginfo.si_code { case .init(CLD_EXITED): status = .exited(siginfo._sifields._sigchld.si_status) @@ -265,7 +278,8 @@ private let setup: () = { if let status = status { let pid = siginfo._sifields._sigchld.si_pid if let existing = continuations.removeValue(forKey: pid), - case .continuation(let c) = existing { + case .continuation(let c) = existing + { c.resume(returning: status) } else { // We don't have continuation yet, just state status @@ -275,13 +289,33 @@ private let setup: () = { } } } - signalSource?.resume() + signalSource.resume() }() +/// Unchecked Sendable here since this class is only explicitly +/// initialzied once during the lifetime of the process +final class SendableSourceSignal: @unchecked Sendable { + private let signalSource: DispatchSourceSignal + + func setEventHandler(handler: @escaping DispatchSourceHandler) { + self.signalSource.setEventHandler(handler: handler) + } + + func resume() { + self.signalSource.resume() + } + + init() { + self.signalSource = DispatchSource.makeSignalSource( + signal: SIGCHLD, + queue: .global() + ) + } +} + private func _setupMonitorSignalHandler() { // Only executed once setup } -#endif // canImport(Glibc) - +#endif // canImport(Glibc) || canImport(Bionic) || canImport(Musl) diff --git a/Sources/_Subprocess/Platforms/Subprocess+Unix.swift b/Sources/_Subprocess/Platforms/Subprocess+Unix.swift index bd110301..ae8fd639 100644 --- a/Sources/_Subprocess/Platforms/Subprocess+Unix.swift +++ b/Sources/_Subprocess/Platforms/Subprocess+Unix.swift @@ -2,119 +2,143 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 +// Copyright (c) 2025 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception // -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of Swift.org project authors -// -// SPDX-License-Identifier: Apache-2.0 +// See https://swift.org/LICENSE.txt for license information // //===----------------------------------------------------------------------===// -#if canImport(Darwin) || canImport(Glibc) +#if canImport(Darwin) || canImport(Glibc) || canImport(Bionic) || canImport(Musl) -#if canImport(FoundationEssentials) -import FoundationEssentials -#elseif canImport(Foundation) -import Foundation +#if canImport(System) +import System +#else +@preconcurrency import SystemPackage #endif +import _SubprocessCShims + #if canImport(Darwin) import Darwin +#elseif canImport(Bionic) +import Bionic #elseif canImport(Glibc) import Glibc +#elseif canImport(Musl) +import Musl #endif -#if FOUNDATION_FRAMEWORK -@_implementationOnly import _FoundationCShims -#else -import _CShims -#endif - -import Dispatch -import SystemPackage +package import Dispatch // MARK: - Signals -extension Subprocess { - /// Signals are standardized messages sent to a running program - /// to trigger specific behavior, such as quitting or error handling. - public struct Signal : Hashable, Sendable { - /// The underlying platform specific value for the signal - public let rawValue: Int32 - - private init(rawValue: Int32) { - self.rawValue = rawValue - } - /// The `.interrupt` signal is sent to a process by its - /// controlling terminal when a user wishes to interrupt - /// the process. - public static var interrupt: Self { .init(rawValue: SIGINT) } - /// The `.terminate` signal is sent to a process to request its - /// termination. Unlike the `.kill` signal, it can be caught - /// and interpreted or ignored by the process. This allows - /// the process to perform nice termination releasing resources - /// and saving state if appropriate. `.interrupt` is nearly - /// identical to `.terminate`. - public static var terminate: Self { .init(rawValue: SIGTERM) } - /// The `.suspend` signal instructs the operating system - /// to stop a process for later resumption. - public static var suspend: Self { .init(rawValue: SIGSTOP) } - /// The `resume` signal instructs the operating system to - /// continue (restart) a process previously paused by the - /// `.suspend` signal. - public static var resume: Self { .init(rawValue: SIGCONT) } - /// The `.kill` signal is sent to a process to cause it to - /// terminate immediately (kill). In contrast to `.terminate` - /// and `.interrupt`, this signal cannot be caught or ignored, - /// and the receiving process cannot perform any - /// clean-up upon receiving this signal. - public static var kill: Self { .init(rawValue: SIGKILL) } - /// The `.terminalClosed` signal is sent to a process when - /// its controlling terminal is closed. In modern systems, - /// this signal usually means that the controlling pseudo - /// or virtual terminal has been closed. - public static var terminalClosed: Self { .init(rawValue: SIGHUP) } - /// The `.quit` signal is sent to a process by its controlling - /// terminal when the user requests that the process quit - /// and perform a core dump. - public static var quit: Self { .init(rawValue: SIGQUIT) } - /// The `.userDefinedOne` signal is sent to a process to indicate - /// user-defined conditions. - public static var userDefinedOne: Self { .init(rawValue: SIGUSR1) } - /// The `.userDefinedTwo` signal is sent to a process to indicate - /// user-defined conditions. - public static var userDefinedTwo: Self { .init(rawValue: SIGUSR2) } - /// The `.alarm` signal is sent to a process when the corresponding - /// time limit is reached. - public static var alarm: Self { .init(rawValue: SIGALRM) } - /// The `.windowSizeChange` signal is sent to a process when - /// its controlling terminal changes its size (a window change). - public static var windowSizeChange: Self { .init(rawValue: SIGWINCH) } +/// Signals are standardized messages sent to a running program +/// to trigger specific behavior, such as quitting or error handling. +public struct Signal: Hashable, Sendable { + /// The underlying platform specific value for the signal + public let rawValue: Int32 + + private init(rawValue: Int32) { + self.rawValue = rawValue + } + + /// The `.interrupt` signal is sent to a process by its + /// controlling terminal when a user wishes to interrupt + /// the process. + public static var interrupt: Self { .init(rawValue: SIGINT) } + /// The `.terminate` signal is sent to a process to request its + /// termination. Unlike the `.kill` signal, it can be caught + /// and interpreted or ignored by the process. This allows + /// the process to perform nice termination releasing resources + /// and saving state if appropriate. `.interrupt` is nearly + /// identical to `.terminate`. + public static var terminate: Self { .init(rawValue: SIGTERM) } + /// The `.suspend` signal instructs the operating system + /// to stop a process for later resumption. + public static var suspend: Self { .init(rawValue: SIGSTOP) } + /// The `resume` signal instructs the operating system to + /// continue (restart) a process previously paused by the + /// `.suspend` signal. + public static var resume: Self { .init(rawValue: SIGCONT) } + /// The `.kill` signal is sent to a process to cause it to + /// terminate immediately (kill). In contrast to `.terminate` + /// and `.interrupt`, this signal cannot be caught or ignored, + /// and the receiving process cannot perform any + /// clean-up upon receiving this signal. + public static var kill: Self { .init(rawValue: SIGKILL) } + /// The `.terminalClosed` signal is sent to a process when + /// its controlling terminal is closed. In modern systems, + /// this signal usually means that the controlling pseudo + /// or virtual terminal has been closed. + public static var terminalClosed: Self { .init(rawValue: SIGHUP) } + /// The `.quit` signal is sent to a process by its controlling + /// terminal when the user requests that the process quit + /// and perform a core dump. + public static var quit: Self { .init(rawValue: SIGQUIT) } + /// The `.userDefinedOne` signal is sent to a process to indicate + /// user-defined conditions. + public static var userDefinedOne: Self { .init(rawValue: SIGUSR1) } + /// The `.userDefinedTwo` signal is sent to a process to indicate + /// user-defined conditions. + public static var userDefinedTwo: Self { .init(rawValue: SIGUSR2) } + /// The `.alarm` signal is sent to a process when the corresponding + /// time limit is reached. + public static var alarm: Self { .init(rawValue: SIGALRM) } + /// The `.windowSizeChange` signal is sent to a process when + /// its controlling terminal changes its size (a window change). + public static var windowSizeChange: Self { .init(rawValue: SIGWINCH) } +} + +// MARK: - ProcessIdentifier + +/// A platform independent identifier for a Subprocess. +public struct ProcessIdentifier: Sendable, Hashable, Codable { + /// The platform specific process identifier value + public let value: pid_t + + public init(value: pid_t) { + self.value = value } +} +extension ProcessIdentifier: CustomStringConvertible, CustomDebugStringConvertible { + public var description: String { "\(self.value)" } + + public var debugDescription: String { "\(self.value)" } +} + +@available(macOS 15.0, *) // FIXME: manually added availability +extension Execution { /// Send the given signal to the child process. /// - Parameters: /// - signal: The signal to send. /// - shouldSendToProcessGroup: Whether this signal should be sent to /// the entire process group. - public func send(_ signal: Signal, toProcessGroup shouldSendToProcessGroup: Bool) throws { + public func send( + signal: Signal, + toProcessGroup shouldSendToProcessGroup: Bool = false + ) throws { let pid = shouldSendToProcessGroup ? -(self.processIdentifier.value) : self.processIdentifier.value guard kill(pid, signal.rawValue) == 0 else { - throw POSIXError(.init(rawValue: errno)!) + throw SubprocessError( + code: .init(.failedToSendSignal(signal.rawValue)), + underlyingError: .init(rawValue: errno) + ) } } - internal func tryTerminate() -> Error? { + internal func tryTerminate() -> Swift.Error? { do { - try self.send(.kill, toProcessGroup: true) + try self.send(signal: .kill) } catch { - guard let posixError: POSIXError = error as? POSIXError else { + guard let posixError: SubprocessError = error as? SubprocessError else { return error } // Ignore ESRCH (no such process) - if posixError.code != .ESRCH { + if let underlyingError = posixError.underlyingError, + underlyingError.rawValue != ESRCH + { return error } } @@ -123,21 +147,32 @@ extension Subprocess { } // MARK: - Environment Resolution -extension Subprocess.Environment { - internal static let pathEnvironmentVariableName = "PATH" +extension Environment { + internal static let pathVariableName = "PATH" internal func pathValue() -> String? { switch self.config { case .inherit(let overrides): // If PATH value exists in overrides, use it - if let value = overrides[.string(Self.pathEnvironmentVariableName)] { - return value.stringValue + if let value = overrides[Self.pathVariableName] { + return value } // Fall back to current process - return ProcessInfo.processInfo.environment[Self.pathEnvironmentVariableName] + return Self.currentEnvironmentValues()[Self.pathVariableName] case .custom(let fullEnvironment): - if let value = fullEnvironment[.string(Self.pathEnvironmentVariableName)] { - return value.stringValue + if let value = fullEnvironment[Self.pathVariableName] { + return value + } + return nil + case .rawBytes(let rawBytesArray): + let needle: [UInt8] = Array("\(Self.pathVariableName)=".utf8) + for row in rawBytesArray { + guard row.starts(with: needle) else { + continue + } + // Attempt to + let pathValue = row.dropFirst(needle.count) + return String(decoding: pathValue, as: UTF8.self) } return nil } @@ -147,8 +182,8 @@ extension Subprocess.Environment { // manually deallocated internal func createEnv() -> [UnsafeMutablePointer?] { func createFullCString( - fromKey keyContainer: Subprocess.StringOrRawBytes, - value valueContainer: Subprocess.StringOrRawBytes + fromKey keyContainer: StringOrRawBytes, + value valueContainer: StringOrRawBytes ) -> UnsafeMutablePointer { let rawByteKey: UnsafeMutablePointer = keyContainer.createRawBytes() let rawByteValue: UnsafeMutablePointer = valueContainer.createRawBytes() @@ -170,21 +205,12 @@ extension Subprocess.Environment { var env: [UnsafeMutablePointer?] = [] switch self.config { case .inherit(let updates): - var current = ProcessInfo.processInfo.environment - for (keyContainer, valueContainer) in updates { - if let stringKey = keyContainer.stringValue { - // Remove the value from current to override it - current.removeValue(forKey: stringKey) - } - // Fast path - if case .string(let stringKey) = keyContainer, - case .string(let stringValue) = valueContainer { - let fullString = "\(stringKey)=\(stringValue)" - env.append(strdup(fullString)) - continue - } - - env.append(createFullCString(fromKey: keyContainer, value: valueContainer)) + var current = Self.currentEnvironmentValues() + for (key, value) in updates { + // Remove the value from current to override it + current.removeValue(forKey: key) + let fullString = "\(key)=\(value)" + env.append(strdup(fullString)) } // Add the rest of `current` to env for (key, value) in current { @@ -192,24 +218,43 @@ extension Subprocess.Environment { env.append(strdup(fullString)) } case .custom(let customValues): - for (keyContainer, valueContainer) in customValues { - // Fast path - if case .string(let stringKey) = keyContainer, - case .string(let stringValue) = valueContainer { - let fullString = "\(stringKey)=\(stringValue)" - env.append(strdup(fullString)) - continue - } - env.append(createFullCString(fromKey: keyContainer, value: valueContainer)) + for (key, value) in customValues { + let fullString = "\(key)=\(value)" + env.append(strdup(fullString)) + } + case .rawBytes(let rawBytesArray): + for rawBytes in rawBytesArray { + env.append(strdup(rawBytes)) } } env.append(nil) return env } + + internal static func withCopiedEnv(_ body: ([UnsafeMutablePointer]) -> R) -> R { + var values: [UnsafeMutablePointer] = [] + // This lock is taken by calls to getenv, so we want as few callouts to other code as possible here. + _subprocess_lock_environ() + guard + let environments: UnsafeMutablePointer?> = + _subprocess_get_environ() + else { + _subprocess_unlock_environ() + return body([]) + } + var curr = environments + while let value = curr.pointee { + values.append(strdup(value)) + curr = curr.advanced(by: 1) + } + _subprocess_unlock_environ() + defer { values.forEach { free($0) } } + return body(values) + } } // MARK: Args Creation -extension Subprocess.Arguments { +extension Arguments { // This method follows the standard "create" rule: `args` needs to be // manually deallocated internal func createArgs(withExecutablePath executablePath: String) -> [UnsafeMutablePointer?] { @@ -225,42 +270,23 @@ extension Subprocess.Arguments { } } -// MARK: - ProcessIdentifier -extension Subprocess { - /// A platform independent identifier for a subprocess. - public struct ProcessIdentifier: Sendable, Hashable, Codable { - /// The platform specific process identifier value - public let value: pid_t - - public init(value: pid_t) { - self.value = value - } - } -} - -extension Subprocess.ProcessIdentifier : CustomStringConvertible, CustomDebugStringConvertible { - public var description: String { "\(self.value)" } - - public var debugDescription: String { "\(self.value)" } -} - // MARK: - Executable Searching -extension Subprocess.Executable { +extension Executable { internal static var defaultSearchPaths: Set { return Set([ "/usr/bin", "/bin", "/usr/sbin", "/sbin", - "/usr/local/bin" + "/usr/local/bin", ]) } - internal func resolveExecutablePath(withPathValue pathValue: String?) -> String? { + internal func resolveExecutablePath(withPathValue pathValue: String?) throws -> String { switch self.storage { case .executable(let executableName): // If the executableName in is already a full path, return it directly - if Subprocess.Configuration.pathAccessible(executableName, mode: X_OK) { + if Configuration.pathAccessible(executableName, mode: X_OK) { return executableName } // Get $PATH from environment @@ -274,50 +300,38 @@ extension Subprocess.Executable { for path in searchPaths { let fullPath = "\(path)/\(executableName)" - let fileExists = Subprocess.Configuration.pathAccessible(fullPath, mode: X_OK) + let fileExists = Configuration.pathAccessible(fullPath, mode: X_OK) if fileExists { return fullPath } } + throw SubprocessError( + code: .init(.executableNotFound(executableName)), + underlyingError: nil + ) case .path(let executablePath): // Use path directly return executablePath.string } - return nil } } -// MARK: - Configuration -extension Subprocess.Configuration { - internal func preSpawn() throws -> ( - executablePath: String, +// MARK: - PreSpawn +extension Configuration { + internal typealias PreSpawnArgs = ( env: [UnsafeMutablePointer?], - argv: [UnsafeMutablePointer?], - intendedWorkingDir: FilePath, uidPtr: UnsafeMutablePointer?, gidPtr: UnsafeMutablePointer?, supplementaryGroups: [gid_t]? - ) { + ) + + internal func preSpawn( + _ work: (PreSpawnArgs) throws -> Result + ) throws -> Result { // Prepare environment let env = self.environment.createEnv() - // Prepare executable path - guard let executablePath = self.executable.resolveExecutablePath( - withPathValue: self.environment.pathValue()) else { - for ptr in env { ptr?.deallocate() } - throw CocoaError(.executableNotLoadable, userInfo: [ - .debugDescriptionErrorKey : "\(self.executable.description) is not an executable" - ]) - } - // Prepare arguments - let argv: [UnsafeMutablePointer?] = self.arguments.createArgs(withExecutablePath: executablePath) - // Prepare workingDir - let intendedWorkingDir = self.workingDirectory - guard Self.pathAccessible(intendedWorkingDir.string, mode: F_OK) else { + defer { for ptr in env { ptr?.deallocate() } - for ptr in argv { ptr?.deallocate() } - throw CocoaError(.fileNoSuchFile, userInfo: [ - .debugDescriptionErrorKey : "Failed to set working directory to \(intendedWorkingDir)" - ]) } var uidPtr: UnsafeMutablePointer? = nil @@ -325,21 +339,28 @@ extension Subprocess.Configuration { uidPtr = .allocate(capacity: 1) uidPtr?.pointee = userID } + defer { + uidPtr?.deallocate() + } var gidPtr: UnsafeMutablePointer? = nil if let groupID = self.platformOptions.groupID { gidPtr = .allocate(capacity: 1) gidPtr?.pointee = groupID } + defer { + gidPtr?.deallocate() + } var supplementaryGroups: [gid_t]? if let groupsValue = self.platformOptions.supplementaryGroups { supplementaryGroups = groupsValue } - return ( - executablePath: executablePath, - env: env, argv: argv, - intendedWorkingDir: intendedWorkingDir, - uidPtr: uidPtr, gidPtr: gidPtr, - supplementaryGroups: supplementaryGroups + return try work( + ( + env: env, + uidPtr: uidPtr, + gidPtr: gidPtr, + supplementaryGroups: supplementaryGroups + ) ) } @@ -359,11 +380,11 @@ extension FileDescriptor { return devnull } - internal var platformDescriptor: Subprocess.PlatformFileDescriptor { + internal var platformDescriptor: PlatformFileDescriptor { return self } - internal func readChunk(upToLength maxLength: Int) async throws -> Data? { + package func readChunk(upToLength maxLength: Int) async throws -> SequenceOutput.Buffer? { return try await withCheckedThrowingContinuation { continuation in DispatchIO.read( fromFileDescriptor: self.rawValue, @@ -371,88 +392,125 @@ extension FileDescriptor { runningHandlerOn: .global() ) { data, error in if error != 0 { - continuation.resume(throwing: POSIXError(.init(rawValue: error) ?? .ENODEV)) + continuation.resume( + throwing: SubprocessError( + code: .init(.failedToReadFromSubprocess), + underlyingError: .init(rawValue: error) + ) + ) return } if data.isEmpty { continuation.resume(returning: nil) } else { - continuation.resume(returning: Data(data)) + continuation.resume(returning: SequenceOutput.Buffer(data: data)) } } } } - internal func readUntilEOF(upToLength maxLength: Int) async throws -> Data { - return try await withCheckedThrowingContinuation { continuation in - let dispatchIO = DispatchIO( - type: .stream, - fileDescriptor: self.rawValue, - queue: .global() - ) { error in - if error != 0 { - continuation.resume(throwing: POSIXError(.init(rawValue: error) ?? .ENODEV)) - } + internal func readUntilEOF( + upToLength maxLength: Int, + resultHandler: sending @escaping (Swift.Result) -> Void + ) { + let dispatchIO = DispatchIO( + type: .stream, + fileDescriptor: self.rawValue, + queue: .global() + ) { error in } + var buffer: DispatchData? + dispatchIO.read( + offset: 0, + length: maxLength, + queue: .global() + ) { done, data, error in + guard error == 0, let chunkData = data else { + dispatchIO.close() + resultHandler( + .failure( + SubprocessError( + code: .init(.failedToReadFromSubprocess), + underlyingError: .init(rawValue: error) + ) + ) + ) + return } - var buffer: Data = Data() - dispatchIO.read( - offset: 0, - length: maxLength, - queue: .global() - ) { done, data, error in - guard error == 0 else { - continuation.resume(throwing: POSIXError(.init(rawValue: error) ?? .ENODEV)) - return - } - if let data = data { - buffer += Data(data) - } - if done { - dispatchIO.close() - continuation.resume(returning: buffer) - } + // Easy case: if we are done and buffer is nil, this means + // there is only one chunk of data + if done && buffer == nil { + dispatchIO.close() + buffer = chunkData + resultHandler(.success(chunkData)) + return + } + + if buffer == nil { + buffer = chunkData + } else { + buffer?.append(chunkData) + } + + if done { + dispatchIO.close() + resultHandler(.success(buffer!)) + return } } } - internal func write(_ data: S) async throws where S.Element == UInt8 { - try await withCheckedThrowingContinuation { (continuation: CheckedContinuation) -> Void in - let dispatchData: DispatchData = Array(data).withUnsafeBytes { - return DispatchData(bytes: $0) - } - DispatchIO.write( - toFileDescriptor: self.rawValue, - data: dispatchData, - runningHandlerOn: .global() - ) { _, error in - guard error == 0 else { - continuation.resume( - throwing: POSIXError( - .init(rawValue: error) ?? .ENODEV) + package func write( + _ array: [UInt8] + ) async throws -> Int { + try await withCheckedThrowingContinuation { (continuation: CheckedContinuation) in + let dispatchData = array.withUnsafeBytes { + return DispatchData( + bytesNoCopy: $0, + deallocator: .custom( + nil, + { + // noop + } ) - return + ) + } + self.write(dispatchData) { writtenLength, error in + if let error = error { + continuation.resume(throwing: error) + } else { + continuation.resume(returning: writtenLength) } - continuation.resume() } } } -} -extension Subprocess { - internal typealias PlatformFileDescriptor = FileDescriptor -} - -// MARK: - Read Buffer Size -extension Subprocess { - @inline(__always) - internal static var readBufferSize: Int { -#if canImport(Darwin) - return 16384 -#else - // FIXME: Use Platform.pageSize here - return 4096 -#endif // canImport(Darwin) + package func write( + _ dispatchData: DispatchData, + queue: DispatchQueue = .global(), + completion: @escaping (Int, Error?) -> Void + ) { + DispatchIO.write( + toFileDescriptor: self.rawValue, + data: dispatchData, + runningHandlerOn: queue + ) { unwritten, error in + let unwrittenLength = unwritten?.count ?? 0 + let writtenLength = dispatchData.count - unwrittenLength + guard error != 0 else { + completion(writtenLength, nil) + return + } + completion( + writtenLength, + SubprocessError( + code: .init(.failedToWriteToSubprocess), + underlyingError: .init(rawValue: error) + ) + ) + } } } -#endif // canImport(Darwin) || canImport(Glibc) +internal typealias PlatformFileDescriptor = FileDescriptor + +#endif // canImport(Darwin) || canImport(Glibc) || canImport(Bionic) || canImport(Musl) diff --git a/Sources/_Subprocess/Platforms/Subprocess+Windows.swift b/Sources/_Subprocess/Platforms/Subprocess+Windows.swift index 978cb139..aaf53ea0 100644 --- a/Sources/_Subprocess/Platforms/Subprocess+Windows.swift +++ b/Sources/_Subprocess/Platforms/Subprocess+Windows.swift @@ -2,53 +2,66 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 +// Copyright (c) 2025 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception // -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of Swift.org project authors -// -// SPDX-License-Identifier: Apache-2.0 +// See https://swift.org/LICENSE.txt for license information // //===----------------------------------------------------------------------===// #if canImport(WinSDK) import WinSDK -import Dispatch -import SystemPackage -import FoundationEssentials +internal import Dispatch +#if canImport(System) +import System +#else +@preconcurrency import SystemPackage +#endif // Windows specific implementation -extension Subprocess.Configuration { - internal func spawn( - withInput input: Subprocess.ExecutionInput, - output: Subprocess.ExecutionOutput, - error: Subprocess.ExecutionOutput - ) throws -> Subprocess { +extension Configuration { + internal func spawn< + Output: OutputProtocol, + Error: OutputProtocol + >( + withInput inputPipe: CreatedPipe, + output: Output, + outputPipe: CreatedPipe, + error: Error, + errorPipe: CreatedPipe + ) throws -> Execution { // Spawn differently depending on whether // we need to spawn as a user - if let userCredentials = self.platformOptions.userCredentials { - return try self.spawnAsUser( - withInput: input, - output: output, - error: error, - userCredentials: userCredentials - ) - } else { + guard let userCredentials = self.platformOptions.userCredentials else { return try self.spawnDirect( - withInput: input, + withInput: inputPipe, output: output, - error: error + outputPipe: outputPipe, + error: error, + errorPipe: errorPipe ) } + return try self.spawnAsUser( + withInput: inputPipe, + output: output, + outputPipe: outputPipe, + error: error, + errorPipe: errorPipe, + userCredentials: userCredentials + ) } - internal func spawnDirect( - withInput input: Subprocess.ExecutionInput, - output: Subprocess.ExecutionOutput, - error: Subprocess.ExecutionOutput - ) throws -> Subprocess { + internal func spawnDirect< + Output: OutputProtocol, + Error: OutputProtocol + >( + withInput inputPipe: CreatedPipe, + output: Output, + outputPipe: CreatedPipe, + error: Error, + errorPipe: CreatedPipe + ) throws -> Execution { let ( applicationName, commandAndArgs, @@ -56,9 +69,9 @@ extension Subprocess.Configuration { intendedWorkingDir ) = try self.preSpawn() var startupInfo = try self.generateStartupInfo( - withInput: input, - output: output, - error: error + withInput: inputPipe, + output: outputPipe, + error: errorPipe ) var processInfo: PROCESS_INFORMATION = PROCESS_INFORMATION() var createProcessFlags = self.generateCreateProcessFlag() @@ -78,8 +91,8 @@ extension Subprocess.Configuration { let created = CreateProcessW( applicationNameW, UnsafeMutablePointer(mutating: commandAndArgsW), - nil, // lpProcessAttributes - nil, // lpThreadAttributes + nil, // lpProcessAttributes + nil, // lpThreadAttributes true, // bInheritHandles createProcessFlags, UnsafeMutableRawPointer(mutating: environmentW), @@ -89,14 +102,14 @@ extension Subprocess.Configuration { ) guard created else { let windowsError = GetLastError() - try self.cleanupAll( - input: input, - output: output, - error: error + try self.cleanupPreSpawn( + input: inputPipe, + output: outputPipe, + error: errorPipe ) - throw CocoaError.windowsError( - underlying: windowsError, - errorCode: .fileWriteUnknown + throw SubprocessError( + code: .init(.spawnFailed), + underlyingError: .init(rawValue: windowsError) ) } } @@ -106,47 +119,52 @@ extension Subprocess.Configuration { // We don't need the handle objects, so close it right away guard CloseHandle(processInfo.hThread) else { let windowsError = GetLastError() - try self.cleanupAll( - input: input, - output: output, - error: error + try self.cleanupPreSpawn( + input: inputPipe, + output: outputPipe, + error: errorPipe ) - throw CocoaError.windowsError( - underlying: windowsError, - errorCode: .fileReadUnknown + throw SubprocessError( + code: .init(.spawnFailed), + underlyingError: .init(rawValue: windowsError) ) } guard CloseHandle(processInfo.hProcess) else { let windowsError = GetLastError() - try self.cleanupAll( - input: input, - output: output, - error: error + try self.cleanupPreSpawn( + input: inputPipe, + output: outputPipe, + error: errorPipe ) - throw CocoaError.windowsError( - underlying: windowsError, - errorCode: .fileReadUnknown + throw SubprocessError( + code: .init(.spawnFailed), + underlyingError: .init(rawValue: windowsError) ) } - let pid = Subprocess.ProcessIdentifier( - processID: processInfo.dwProcessId, - threadID: processInfo.dwThreadId + let pid = ProcessIdentifier( + value: processInfo.dwProcessId ) - return Subprocess( + return Execution( processIdentifier: pid, - executionInput: input, - executionOutput: output, - executionError: error, + output: output, + error: error, + outputPipe: outputPipe, + errorPipe: errorPipe, consoleBehavior: self.platformOptions.consoleBehavior ) } - internal func spawnAsUser( - withInput input: Subprocess.ExecutionInput, - output: Subprocess.ExecutionOutput, - error: Subprocess.ExecutionOutput, - userCredentials: Subprocess.PlatformOptions.UserCredentials - ) throws -> Subprocess { + internal func spawnAsUser< + Output: OutputProtocol, + Error: OutputProtocol + >( + withInput inputPipe: CreatedPipe, + output: Output, + outputPipe: CreatedPipe, + error: Error, + errorPipe: CreatedPipe, + userCredentials: PlatformOptions.UserCredentials + ) throws -> Execution { let ( applicationName, commandAndArgs, @@ -154,9 +172,9 @@ extension Subprocess.Configuration { intendedWorkingDir ) = try self.preSpawn() var startupInfo = try self.generateStartupInfo( - withInput: input, - output: output, - error: error + withInput: inputPipe, + output: outputPipe, + error: errorPipe ) var processInfo: PROCESS_INFORMATION = PROCESS_INFORMATION() var createProcessFlags = self.generateCreateProcessFlag() @@ -197,14 +215,14 @@ extension Subprocess.Configuration { ) guard created else { let windowsError = GetLastError() - try self.cleanupAll( - input: input, - output: output, - error: error + try self.cleanupPreSpawn( + input: inputPipe, + output: outputPipe, + error: errorPipe ) - throw CocoaError.windowsError( - underlying: windowsError, - errorCode: .fileWriteUnknown + throw SubprocessError( + code: .init(.spawnFailed), + underlyingError: .init(rawValue: windowsError) ) } } @@ -217,201 +235,175 @@ extension Subprocess.Configuration { // We don't need the handle objects, so close it right away guard CloseHandle(processInfo.hThread) else { let windowsError = GetLastError() - try self.cleanupAll( - input: input, - output: output, - error: error + try self.cleanupPreSpawn( + input: inputPipe, + output: outputPipe, + error: errorPipe ) - throw CocoaError.windowsError( - underlying: windowsError, - errorCode: .fileReadUnknown + throw SubprocessError( + code: .init(.spawnFailed), + underlyingError: .init(rawValue: windowsError) ) } guard CloseHandle(processInfo.hProcess) else { let windowsError = GetLastError() - try self.cleanupAll( - input: input, - output: output, - error: error + try self.cleanupPreSpawn( + input: inputPipe, + output: outputPipe, + error: errorPipe ) - throw CocoaError.windowsError( - underlying: windowsError, - errorCode: .fileReadUnknown + throw SubprocessError( + code: .init(.spawnFailed), + underlyingError: .init(rawValue: windowsError) ) } - let pid = Subprocess.ProcessIdentifier( - processID: processInfo.dwProcessId, - threadID: processInfo.dwThreadId + let pid = ProcessIdentifier( + value: processInfo.dwProcessId ) - return Subprocess( + return Execution( processIdentifier: pid, - executionInput: input, - executionOutput: output, - executionError: error, + output: output, + error: error, + outputPipe: outputPipe, + errorPipe: errorPipe, consoleBehavior: self.platformOptions.consoleBehavior ) } } // MARK: - Platform Specific Options -extension Subprocess { - /// The collection of platform-specific settings - /// to configure the subprocess when running - public struct PlatformOptions: Sendable { - /// A `UserCredentials` to use spawning the subprocess - /// as a different user - public struct UserCredentials: Sendable, Hashable { - // The name of the user. This is the name - // of the user account to run as. - public var username: String - // The clear-text password for the account. - public var password: String - // The name of the domain or server whose account database - // contains the account. - public var domain: String? - } - /// `ConsoleBehavior` defines how should the console appear - /// when spawning a new process - public struct ConsoleBehavior: Sendable, Hashable { - internal enum Storage: Sendable, Hashable { - case createNew - case detatch - case inherit - } +/// The collection of platform-specific settings +/// to configure the subprocess when running +public struct PlatformOptions: Sendable { + /// A `UserCredentials` to use spawning the subprocess + /// as a different user + public struct UserCredentials: Sendable, Hashable { + // The name of the user. This is the name + // of the user account to run as. + public var username: String + // The clear-text password for the account. + public var password: String + // The name of the domain or server whose account database + // contains the account. + public var domain: String? + } - internal let storage: Storage + /// `ConsoleBehavior` defines how should the console appear + /// when spawning a new process + public struct ConsoleBehavior: Sendable, Hashable { + internal enum Storage: Sendable, Hashable { + case createNew + case detatch + case inherit + } - private init(_ storage: Storage) { - self.storage = storage - } + internal let storage: Storage - /// The subprocess has a new console, instead of - /// inheriting its parent's console (the default). - public static let createNew: Self = .init(.createNew) - /// For console processes, the new process does not - /// inherit its parent's console (the default). - /// The new process can call the `AllocConsole` - /// function at a later time to create a console. - public static let detatch: Self = .init(.detatch) - /// The subprocess inherits its parent's console. - public static let inherit: Self = .init(.inherit) + private init(_ storage: Storage) { + self.storage = storage } - /// `ConsoleBehavior` defines how should the window appear - /// when spawning a new process - public struct WindowStyle: Sendable, Hashable { - internal enum Storage: Sendable, Hashable { - case normal - case hidden - case maximized - case minimized - } + /// The subprocess has a new console, instead of + /// inheriting its parent's console (the default). + public static let createNew: Self = .init(.createNew) + /// For console processes, the new process does not + /// inherit its parent's console (the default). + /// The new process can call the `AllocConsole` + /// function at a later time to create a console. + public static let detatch: Self = .init(.detatch) + /// The subprocess inherits its parent's console. + public static let inherit: Self = .init(.inherit) + } - internal let storage: Storage + /// `ConsoleBehavior` defines how should the window appear + /// when spawning a new process + public struct WindowStyle: Sendable, Hashable { + internal enum Storage: Sendable, Hashable { + case normal + case hidden + case maximized + case minimized + } - internal var platformStyle: WORD { - switch self.storage { - case .hidden: return WORD(SW_HIDE) - case .maximized: return WORD(SW_SHOWMAXIMIZED) - case .minimized: return WORD(SW_SHOWMINIMIZED) - default: return WORD(SW_SHOWNORMAL) - } - } + internal let storage: Storage - private init(_ storage: Storage) { - self.storage = storage + internal var platformStyle: WORD { + switch self.storage { + case .hidden: return WORD(SW_HIDE) + case .maximized: return WORD(SW_SHOWMAXIMIZED) + case .minimized: return WORD(SW_SHOWMINIMIZED) + default: return WORD(SW_SHOWNORMAL) } + } - /// Activates and displays a window of normal size - public static let normal: Self = .init(.normal) - /// Does not activate a new window - public static let hidden: Self = .init(.hidden) - /// Activates the window and displays it as a maximized window. - public static let maximized: Self = .init(.maximized) - /// Activates the window and displays it as a minimized window. - public static let minimized: Self = .init(.minimized) + private init(_ storage: Storage) { + self.storage = storage } - /// Sets user credentials when starting the process as another user - public var userCredentials: UserCredentials? = nil - /// The console behavior of the new process, - /// default to inheriting the console from parent process - public var consoleBehavior: ConsoleBehavior = .inherit - /// Window style to use when the process is started - public var windowStyle: WindowStyle = .normal - /// Whether to create a new process group for the new - /// process. The process group includes all processes - /// that are descendants of this root process. - /// The process identifier of the new process group - /// is the same as the process identifier. - public var createProcessGroup: Bool = false - /// A closure to configure platform-specific - /// spawning constructs. This closure enables direct - /// configuration or override of underlying platform-specific - /// spawn settings that `Subprocess` utilizes internally, - /// in cases where Subprocess does not provide higher-level - /// APIs for such modifications. - /// - /// On Windows, Subprocess uses `CreateProcessW()` as the - /// underlying spawning mechanism. This closure allows - /// modification of the `dwCreationFlags` creation flag - /// and startup info `STARTUPINFOW` before - /// they are sent to `CreateProcessW()`. - public var preSpawnProcessConfigurator: ( + /// Activates and displays a window of normal size + public static let normal: Self = .init(.normal) + /// Does not activate a new window + public static let hidden: Self = .init(.hidden) + /// Activates the window and displays it as a maximized window. + public static let maximized: Self = .init(.maximized) + /// Activates the window and displays it as a minimized window. + public static let minimized: Self = .init(.minimized) + } + + /// Sets user credentials when starting the process as another user + public var userCredentials: UserCredentials? = nil + /// The console behavior of the new process, + /// default to inheriting the console from parent process + public var consoleBehavior: ConsoleBehavior = .inherit + /// Window style to use when the process is started + public var windowStyle: WindowStyle = .normal + /// Whether to create a new process group for the new + /// process. The process group includes all processes + /// that are descendants of this root process. + /// The process identifier of the new process group + /// is the same as the process identifier. + public var createProcessGroup: Bool = false + /// An ordered list of steps in order to tear down the child + /// process in case the parent task is cancelled before + /// the child proces terminates. + /// Always ends in forcefully terminate at the end. + public var teardownSequence: [TeardownStep] = [] + /// A closure to configure platform-specific + /// spawning constructs. This closure enables direct + /// configuration or override of underlying platform-specific + /// spawn settings that `Subprocess` utilizes internally, + /// in cases where Subprocess does not provide higher-level + /// APIs for such modifications. + /// + /// On Windows, Subprocess uses `CreateProcessW()` as the + /// underlying spawning mechanism. This closure allows + /// modification of the `dwCreationFlags` creation flag + /// and startup info `STARTUPINFOW` before + /// they are sent to `CreateProcessW()`. + public var preSpawnProcessConfigurator: + ( @Sendable ( inout DWORD, inout STARTUPINFOW ) throws -> Void )? = nil - public init() {} - } -} - -extension Subprocess.PlatformOptions: Hashable { - public static func == ( - lhs: Subprocess.PlatformOptions, - rhs: Subprocess.PlatformOptions - ) -> Bool { - // Since we can't compare closure equality, - // as long as preSpawnProcessConfigurator is set - // always returns false so that `PlatformOptions` - // with it set will never equal to each other - if lhs.preSpawnProcessConfigurator != nil || rhs.preSpawnProcessConfigurator != nil { - return false - } - return lhs.userCredentials == rhs.userCredentials && lhs.consoleBehavior == rhs.consoleBehavior && lhs.windowStyle == rhs.windowStyle && - lhs.createProcessGroup == rhs.createProcessGroup - } - - public func hash(into hasher: inout Hasher) { - hasher.combine(userCredentials) - hasher.combine(consoleBehavior) - hasher.combine(windowStyle) - hasher.combine(createProcessGroup) - // Since we can't really hash closures, - // use an UUID such that as long as - // `preSpawnProcessConfigurator` is set, it will - // never equal to other PlatformOptions - if self.preSpawnProcessConfigurator != nil { - hasher.combine(UUID()) - } - } + public init() {} } -extension Subprocess.PlatformOptions : CustomStringConvertible, CustomDebugStringConvertible { +extension PlatformOptions: CustomStringConvertible, CustomDebugStringConvertible { internal func description(withIndent indent: Int) -> String { let indent = String(repeating: " ", count: indent * 4) return """ -PlatformOptions( -\(indent) userCredentials: \(String(describing: self.userCredentials)), -\(indent) consoleBehavior: \(String(describing: self.consoleBehavior)), -\(indent) windowStyle: \(String(describing: self.windowStyle)), -\(indent) createProcessGroup: \(self.createProcessGroup), -\(indent) preSpawnProcessConfigurator: \(self.preSpawnProcessConfigurator == nil ? "not set" : "set") -\(indent)) -""" + PlatformOptions( + \(indent) userCredentials: \(String(describing: self.userCredentials)), + \(indent) consoleBehavior: \(String(describing: self.consoleBehavior)), + \(indent) windowStyle: \(String(describing: self.windowStyle)), + \(indent) createProcessGroup: \(self.createProcessGroup), + \(indent) preSpawnProcessConfigurator: \(self.preSpawnProcessConfigurator == nil ? "not set" : "set") + \(indent)) + """ } public var description: String { @@ -426,8 +418,8 @@ PlatformOptions( // MARK: - Process Monitoring @Sendable internal func monitorProcessTermination( - forProcessWithIdentifier pid: Subprocess.ProcessIdentifier -) async throws -> Subprocess.TerminationStatus { + forProcessWithIdentifier pid: ProcessIdentifier +) async throws -> TerminationStatus { // Once the continuation resumes, it will need to unregister the wait, so // yield the wait handle back to the calling scope. var waitHandle: HANDLE? @@ -436,11 +428,13 @@ internal func monitorProcessTermination( _ = UnregisterWait(waitHandle) } } - guard let processHandle = OpenProcess( - DWORD(PROCESS_QUERY_INFORMATION | SYNCHRONIZE), - false, - pid.processID - ) else { + guard + let processHandle = OpenProcess( + DWORD(PROCESS_QUERY_INFORMATION | SYNCHRONIZE), + false, + pid.value + ) + else { return .exited(1) } @@ -449,19 +443,29 @@ internal func monitorProcessTermination( // other work. let context = Unmanaged.passRetained(continuation as AnyObject).toOpaque() let callback: WAITORTIMERCALLBACK = { context, _ in - let continuation = Unmanaged.fromOpaque(context!).takeRetainedValue() as! CheckedContinuation + let continuation = + Unmanaged.fromOpaque(context!).takeRetainedValue() as! CheckedContinuation continuation.resume() } // We only want the callback to fire once (and not be rescheduled.) Waiting // may take an arbitrarily long time, so let the thread pool know that too. let flags = ULONG(WT_EXECUTEONLYONCE | WT_EXECUTELONGFUNCTION) - guard RegisterWaitForSingleObject( - &waitHandle, processHandle, callback, context, INFINITE, flags - ) else { - continuation.resume(throwing: CocoaError.windowsError( - underlying: GetLastError(), - errorCode: .fileWriteUnknown) + guard + RegisterWaitForSingleObject( + &waitHandle, + processHandle, + callback, + context, + INFINITE, + flags + ) + else { + continuation.resume( + throwing: SubprocessError( + code: .init(.failedToMonitorProcess), + underlyingError: .init(rawValue: GetLastError()) + ) ) return } @@ -474,58 +478,62 @@ internal func monitorProcessTermination( return .exited(1) } let exitCodeValue = CInt(bitPattern: .init(status)) - if exitCodeValue >= 0 { - return .exited(status) - } else { + guard exitCodeValue >= 0 else { return .unhandledException(status) } + return .exited(status) } // MARK: - Subprocess Control -extension Subprocess { +@available(macOS 15.0, *) // FIXME: manually added availability +extension Execution { /// Terminate the current subprocess with the given exit code /// - Parameter exitCode: The exit code to use for the subprocess. public func terminate(withExitCode exitCode: DWORD) throws { - guard let processHandle = OpenProcess( - // PROCESS_ALL_ACCESS - DWORD(STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xFFFF), - false, - self.processIdentifier.processID - ) else { - throw CocoaError.windowsError( - underlying: GetLastError(), - errorCode: .fileWriteUnknown + guard + let processHandle = OpenProcess( + // PROCESS_ALL_ACCESS + DWORD(STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xFFFF), + false, + self.processIdentifier.value + ) + else { + throw SubprocessError( + code: .init(.failedToTerminate), + underlyingError: .init(rawValue: GetLastError()) ) } defer { CloseHandle(processHandle) } guard TerminateProcess(processHandle, exitCode) else { - throw CocoaError.windowsError( - underlying: GetLastError(), - errorCode: .fileWriteUnknown + throw SubprocessError( + code: .init(.failedToTerminate), + underlyingError: .init(rawValue: GetLastError()) ) } } /// Suspend the current subprocess public func suspend() throws { - guard let processHandle = OpenProcess( - // PROCESS_ALL_ACCESS - DWORD(STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xFFFF), - false, - self.processIdentifier.processID - ) else { - throw CocoaError.windowsError( - underlying: GetLastError(), - errorCode: .fileWriteUnknown + guard + let processHandle = OpenProcess( + // PROCESS_ALL_ACCESS + DWORD(STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xFFFF), + false, + self.processIdentifier.value + ) + else { + throw SubprocessError( + code: .init(.failedToSuspend), + underlyingError: .init(rawValue: GetLastError()) ) } defer { CloseHandle(processHandle) } - let NTSuspendProcess: Optional<(@convention(c) (HANDLE) -> LONG)> = + let NTSuspendProcess: (@convention(c) (HANDLE) -> LONG)? = unsafeBitCast( GetProcAddress( GetModuleHandleA("ntdll.dll"), @@ -534,53 +542,61 @@ extension Subprocess { to: Optional<(@convention(c) (HANDLE) -> LONG)>.self ) guard let NTSuspendProcess = NTSuspendProcess else { - throw CocoaError(.executableNotLoadable) + throw SubprocessError( + code: .init(.failedToSuspend), + underlyingError: .init(rawValue: GetLastError()) + ) } guard NTSuspendProcess(processHandle) >= 0 else { - throw CocoaError.windowsError( - underlying: GetLastError(), - errorCode: .fileWriteUnknown + throw SubprocessError( + code: .init(.failedToSuspend), + underlyingError: .init(rawValue: GetLastError()) ) } } /// Resume the current subprocess after suspension public func resume() throws { - guard let processHandle = OpenProcess( - // PROCESS_ALL_ACCESS - DWORD(STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xFFFF), - false, - self.processIdentifier.processID - ) else { - throw CocoaError.windowsError( - underlying: GetLastError(), - errorCode: .fileWriteUnknown + guard + let processHandle = OpenProcess( + // PROCESS_ALL_ACCESS + DWORD(STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xFFFF), + false, + self.processIdentifier.value + ) + else { + throw SubprocessError( + code: .init(.failedToResume), + underlyingError: .init(rawValue: GetLastError()) ) } defer { CloseHandle(processHandle) } - let NTResumeProcess: Optional<(@convention(c) (HANDLE) -> LONG)> = - unsafeBitCast( - GetProcAddress( - GetModuleHandleA("ntdll.dll"), - "NtResumeProcess" - ), - to: Optional<(@convention(c) (HANDLE) -> LONG)>.self - ) + let NTResumeProcess: (@convention(c) (HANDLE) -> LONG)? = + unsafeBitCast( + GetProcAddress( + GetModuleHandleA("ntdll.dll"), + "NtResumeProcess" + ), + to: Optional<(@convention(c) (HANDLE) -> LONG)>.self + ) guard let NTResumeProcess = NTResumeProcess else { - throw CocoaError(.executableNotLoadable) + throw SubprocessError( + code: .init(.failedToResume), + underlyingError: .init(rawValue: GetLastError()) + ) } guard NTResumeProcess(processHandle) >= 0 else { - throw CocoaError.windowsError( - underlying: GetLastError(), - errorCode: .fileWriteUnknown + throw SubprocessError( + code: .init(.failedToResume), + underlyingError: .init(rawValue: GetLastError()) ) } } - internal func tryTerminate() -> Error? { + internal func tryTerminate() -> Swift.Error? { do { try self.terminate(withExitCode: 0) } catch { @@ -591,35 +607,44 @@ extension Subprocess { } // MARK: - Executable Searching -extension Subprocess.Executable { +extension Executable { // Technically not needed for CreateProcess since // it takes process name. It's here to support // Executable.resolveExecutablePath - internal func resolveExecutablePath(withPathValue pathValue: String?) -> String? { + internal func resolveExecutablePath(withPathValue pathValue: String?) throws -> String { switch self.storage { case .executable(let executableName): - return executableName.withCString( + return try executableName.withCString( encodedAs: UTF16.self - ) { exeName -> String? in - return pathValue.withOptionalCString( + ) { exeName -> String in + return try pathValue.withOptionalCString( encodedAs: UTF16.self - ) { path -> String? in + ) { path -> String in let pathLenth = SearchPathW( path, exeName, - nil, 0, nil, nil + nil, + 0, + nil, + nil ) guard pathLenth > 0 else { - return nil + throw SubprocessError( + code: .init(.executableNotFound(executableName)), + underlyingError: .init(rawValue: GetLastError()) + ) } return withUnsafeTemporaryAllocation( - of: WCHAR.self, capacity: Int(pathLenth) + 1 + of: WCHAR.self, + capacity: Int(pathLenth) + 1 ) { _ = SearchPathW( path, - exeName, nil, + exeName, + nil, pathLenth + 1, - $0.baseAddress, nil + $0.baseAddress, + nil ) return String(decodingCString: $0.baseAddress!, as: UTF16.self) } @@ -633,49 +658,60 @@ extension Subprocess.Executable { } // MARK: - Environment Resolution -extension Subprocess.Environment { - internal static let pathEnvironmentVariableName = "Path" +extension Environment { + internal static let pathVariableName = "Path" internal func pathValue() -> String? { switch self.config { case .inherit(let overrides): // If PATH value exists in overrides, use it - if let value = overrides[.string(Self.pathEnvironmentVariableName)] { - return value.stringValue + if let value = overrides[Self.pathVariableName] { + return value } // Fall back to current process - return ProcessInfo.processInfo.environment[Self.pathEnvironmentVariableName] + return Self.currentEnvironmentValues()[Self.pathVariableName] case .custom(let fullEnvironment): - if let value = fullEnvironment[.string(Self.pathEnvironmentVariableName)] { - return value.stringValue + if let value = fullEnvironment[Self.pathVariableName] { + return value } return nil } } + + internal static func withCopiedEnv(_ body: ([UnsafeMutablePointer]) -> R) -> R { + var values: [UnsafeMutablePointer] = [] + guard let pwszEnvironmentBlock = GetEnvironmentStringsW() else { + return body([]) + } + defer { FreeEnvironmentStringsW(pwszEnvironmentBlock) } + + var pwszEnvironmentEntry: LPWCH? = pwszEnvironmentBlock + while let value = pwszEnvironmentEntry { + let entry = String(decodingCString: value, as: UTF16.self) + if entry.isEmpty { break } + values.append(entry.withCString { _strdup($0)! }) + pwszEnvironmentEntry = pwszEnvironmentEntry?.advanced(by: wcslen(value) + 1) + } + defer { values.forEach { free($0) } } + return body(values) + } } // MARK: - ProcessIdentifier -extension Subprocess { - /// A platform independent identifier for a subprocess. - public struct ProcessIdentifier: Sendable, Hashable, Codable { - /// Windows specifc process identifier value - public let processID: DWORD - /// Windows specific thread identifier associated with process - public let threadID: DWORD - - internal init( - processID: DWORD, - threadID: DWORD - ) { - self.processID = processID - self.threadID = threadID - } + +/// A platform independent identifier for a subprocess. +public struct ProcessIdentifier: Sendable, Hashable, Codable { + /// Windows specifc process identifier value + public let value: DWORD + + internal init(value: DWORD) { + self.value = value } } -extension Subprocess.ProcessIdentifier: CustomStringConvertible, CustomDebugStringConvertible { +extension ProcessIdentifier: CustomStringConvertible, CustomDebugStringConvertible { public var description: String { - return "(processID: \(self.processID), threadID: \(self.threadID))" + return "(processID: \(self.value))" } public var debugDescription: String { @@ -684,7 +720,7 @@ extension Subprocess.ProcessIdentifier: CustomStringConvertible, CustomDebugStri } // MARK: - Private Utils -extension Subprocess.Configuration { +extension Configuration { private func preSpawn() throws -> ( applicationName: String?, commandAndArgs: String, @@ -692,44 +728,33 @@ extension Subprocess.Configuration { intendedWorkingDir: String ) { // Prepare environment - var env: [String : String] = [:] + var env: [String: String] = [:] switch self.environment.config { case .custom(let customValues): // Use the custom values directly - for customKey in customValues.keys { - guard case .string(let stringKey) = customKey, - let valueContainer = customValues[customKey], - case .string(let stringValue) = valueContainer else { - fatalError("Windows does not support non unicode String as environments") - } - env.updateValue(stringValue, forKey: stringKey) - } + env = customValues case .inherit(let updateValues): // Combine current environment - env = ProcessInfo.processInfo.environment - for updatingKey in updateValues.keys { - // Override the current environment values - guard case .string(let stringKey) = updatingKey, - let valueContainer = updateValues[updatingKey], - case .string(let stringValue) = valueContainer else { - fatalError("Windows does not support non unicode String as environments") - } - env.updateValue(stringValue, forKey: stringKey) + env = Environment.currentEnvironmentValues() + for (key, value) in updateValues { + env.updateValue(value, forKey: key) } } // On Windows, the PATH is required in order to locate dlls needed by // the process so we should also pass that to the child - let pathVariableName = Subprocess.Environment.pathEnvironmentVariableName + let pathVariableName = Environment.pathVariableName if env[pathVariableName] == nil, - let parentPath = ProcessInfo.processInfo.environment[pathVariableName] { + let parentPath = Environment.currentEnvironmentValues()[pathVariableName] + { env[pathVariableName] = parentPath } // The environment string must be terminated by a double // null-terminator. Otherwise, CreateProcess will fail with // INVALID_PARMETER. - let environmentString = env.map { - $0.key + "=" + $0.value - }.joined(separator: "\0") + "\0\0" + let environmentString = + env.map { + $0.key + "=" + $0.value + }.joined(separator: "\0") + "\0\0" // Prepare arguments let ( @@ -738,9 +763,12 @@ extension Subprocess.Configuration { ) = try self.generateWindowsCommandAndAgruments() // Validate workingDir guard Self.pathAccessible(self.workingDirectory.string) else { - throw CocoaError(.fileNoSuchFile, userInfo: [ - .debugDescriptionErrorKey : "Failed to set working directory to \(self.workingDirectory)" - ]) + throw SubprocessError( + code: .init( + .failedToChangeWorkingDirectory(self.workingDirectory.string) + ), + underlyingError: nil + ) } return ( applicationName: applicationName, @@ -767,9 +795,9 @@ extension Subprocess.Configuration { } private func generateStartupInfo( - withInput input: Subprocess.ExecutionInput, - output: Subprocess.ExecutionOutput, - error: Subprocess.ExecutionOutput + withInput input: CreatedPipe, + output: CreatedPipe, + error: CreatedPipe ) throws -> STARTUPINFOW { var info: STARTUPINFOW = STARTUPINFOW() info.cb = DWORD(MemoryLayout.size) @@ -781,10 +809,10 @@ extension Subprocess.Configuration { } // Bind IOs // Input - if let inputRead = input.getReadFileDescriptor() { + if let inputRead = input.readFileDescriptor { info.hStdInput = inputRead.platformDescriptor } - if let inputWrite = input.getWriteFileDescriptor() { + if let inputWrite = input.writeFileDescriptor { // Set parent side to be uninhertable SetHandleInformation( inputWrite.platformDescriptor, @@ -793,10 +821,10 @@ extension Subprocess.Configuration { ) } // Output - if let outputWrite = output.getWriteFileDescriptor() { + if let outputWrite = output.writeFileDescriptor { info.hStdOutput = outputWrite.platformDescriptor } - if let outputRead = output.getReadFileDescriptor() { + if let outputRead = output.readFileDescriptor { // Set parent side to be uninhertable SetHandleInformation( outputRead.platformDescriptor, @@ -805,10 +833,10 @@ extension Subprocess.Configuration { ) } // Error - if let errorWrite = error.getWriteFileDescriptor() { + if let errorWrite = error.writeFileDescriptor { info.hStdError = errorWrite.platformDescriptor } - if let errorRead = error.getReadFileDescriptor() { + if let errorRead = error.readFileDescriptor { // Set parent side to be uninhertable SetHandleInformation( errorRead.platformDescriptor, @@ -834,12 +862,12 @@ extension Subprocess.Configuration { // actually resolve the path. However, to maintain // the same behavior as other platforms, still check // here to make sure the executable actually exists - guard self.executable.resolveExecutablePath( - withPathValue: self.environment.pathValue() - ) != nil else { - throw CocoaError(.executableNotLoadable, userInfo: [ - .debugDescriptionErrorKey : "\(self.executable.description) is not an executable" - ]) + do { + _ = try self.executable.resolveExecutablePath( + withPathValue: self.environment.pathValue() + ) + } catch { + throw error } executableNameOrPath = name } @@ -876,7 +904,7 @@ extension Subprocess.Configuration { func quoteWindowsCommandArg(arg: String) -> String { // Windows escaping, adapted from Daniel Colascione's "Everyone quotes // command line arguments the wrong way" - Microsoft Developer Blog - if !arg.contains(where: {" \t\n\"".contains($0)}) { + if !arg.contains(where: { " \t\n\"".contains($0) }) { return arg } @@ -911,7 +939,7 @@ extension Subprocess.Configuration { break } let backslashCount = unquoted.distance(from: unquoted.startIndex, to: firstNonBackslash) - if (unquoted[firstNonBackslash] == "\"") { + if unquoted[firstNonBackslash] == "\"" { // This is a string of \ followed by a " e.g. foo\"bar. Escape the // backslashes and the quote quoted.append(String(repeating: "\\", count: backslashCount * 2 + 1)) @@ -939,20 +967,7 @@ extension Subprocess.Configuration { } // MARK: - PlatformFileDescriptor Type -extension Subprocess { - internal typealias PlatformFileDescriptor = HANDLE -} - -// MARK: - Read Buffer Size -extension Subprocess { - @inline(__always) - internal static var readBufferSize: Int { - // FIXME: Use Platform.pageSize here - var sysInfo: SYSTEM_INFO = SYSTEM_INFO() - GetSystemInfo(&sysInfo) - return Int(sysInfo.dwPageSize) - } -} +internal typealias PlatformFileDescriptor = HANDLE // MARK: - Pipe Support extension FileDescriptor { @@ -968,13 +983,14 @@ extension FileDescriptor { var readHandle: HANDLE? = nil var writeHandle: HANDLE? = nil guard CreatePipe(&readHandle, &writeHandle, &saAttributes, 0), - readHandle != INVALID_HANDLE_VALUE, - writeHandle != INVALID_HANDLE_VALUE, - let readHandle: HANDLE = readHandle, - let writeHandle: HANDLE = writeHandle else { - throw CocoaError.windowsError( - underlying: GetLastError(), - errorCode: .fileReadUnknown + readHandle != INVALID_HANDLE_VALUE, + writeHandle != INVALID_HANDLE_VALUE, + let readHandle: HANDLE = readHandle, + let writeHandle: HANDLE = writeHandle + else { + throw SubprocessError( + code: .init(.failedToCreatePipe), + underlyingError: .init(rawValue: GetLastError()) ) } let readFd = _open_osfhandle( @@ -992,147 +1008,138 @@ extension FileDescriptor { ) } - internal static func openDevNull( - withAcessMode mode: FileDescriptor.AccessMode - ) throws -> FileDescriptor { - return try "NUL".withPlatformString { - let handle = CreateFileW( - $0, - DWORD(GENERIC_WRITE), - DWORD(FILE_SHARE_WRITE), - nil, - DWORD(OPEN_EXISTING), - DWORD(FILE_ATTRIBUTE_NORMAL), - nil - ) - guard let handle = handle, - handle != INVALID_HANDLE_VALUE else { - throw CocoaError.windowsError( - underlying: GetLastError(), - errorCode: .fileReadUnknown - ) - } - let devnull = _open_osfhandle( - intptr_t(bitPattern: handle), - mode.rawValue - ) - return FileDescriptor(rawValue: devnull) - } - } - - var platformDescriptor: Subprocess.PlatformFileDescriptor { + var platformDescriptor: PlatformFileDescriptor { return HANDLE(bitPattern: _get_osfhandle(self.rawValue))! } - internal func read(upToLength maxLength: Int) async throws -> Data { - // TODO: Figure out a better way to asynchornously read + internal func readChunk(upToLength maxLength: Int) async throws -> SequenceOutput.Buffer? { return try await withCheckedThrowingContinuation { continuation in - DispatchQueue.global(qos: .userInitiated).async { - var totalBytesRead: Int = 0 - var lastError: DWORD? = nil - let values = Array( - unsafeUninitializedCapacity: maxLength - ) { buffer, initializedCount in - while true { - guard let baseAddress = buffer.baseAddress else { - initializedCount = 0 - break - } - let bufferPtr = baseAddress.advanced(by: totalBytesRead) - var bytesRead: DWORD = 0 - let readSucceed = ReadFile( - self.platformDescriptor, - UnsafeMutableRawPointer(mutating: bufferPtr), - DWORD(maxLength - totalBytesRead), - &bytesRead, - nil - ) - if !readSucceed { - // Windows throws ERROR_BROKEN_PIPE when the pipe is closed - let error = GetLastError() - if error == ERROR_BROKEN_PIPE { - // We are done reading - initializedCount = totalBytesRead - } else { - // We got some error - lastError = error - initializedCount = 0 - } - break - } else { - // We succesfully read the current round - totalBytesRead += Int(bytesRead) - } - - if totalBytesRead >= maxLength { - initializedCount = min(maxLength, totalBytesRead) - break - } - } - } - if let lastError = lastError { - continuation.resume(throwing: CocoaError.windowsError( - underlying: lastError, - errorCode: .fileReadUnknown) - ) - } else { - continuation.resume(returning: Data(values)) + self.readUntilEOF( + upToLength: maxLength + ) { result in + switch result { + case .failure(let error): + continuation.resume(throwing: error) + case .success(let bytes): + continuation.resume(returning: SequenceOutput.Buffer(data: bytes)) } } } } - internal func write(_ data: S) async throws where S.Element == UInt8 { - // TODO: Figure out a better way to asynchornously write - try await withCheckedThrowingContinuation { ( - continuation: CheckedContinuation - ) -> Void in - DispatchQueue.global(qos: .userInitiated).async { - let buffer = Array(data) - buffer.withUnsafeBytes { ptr in - var writtenBytes: DWORD = 0 - let writeSucceed = WriteFile( + internal func readUntilEOF( + upToLength maxLength: Int, + resultHandler: @Sendable @escaping (Swift.Result<[UInt8], any (Error & Sendable)>) -> Void + ) { + DispatchQueue.global(qos: .userInitiated).async { + var totalBytesRead: Int = 0 + var lastError: DWORD? = nil + let values = [UInt8]( + unsafeUninitializedCapacity: maxLength + ) { buffer, initializedCount in + while true { + guard let baseAddress = buffer.baseAddress else { + initializedCount = 0 + break + } + let bufferPtr = baseAddress.advanced(by: totalBytesRead) + var bytesRead: DWORD = 0 + let readSucceed = ReadFile( self.platformDescriptor, - ptr.baseAddress, - DWORD(buffer.count), - &writtenBytes, + UnsafeMutableRawPointer(mutating: bufferPtr), + DWORD(maxLength - totalBytesRead), + &bytesRead, nil ) - if !writeSucceed { - continuation.resume(throwing: CocoaError.windowsError( - underlying: GetLastError(), - errorCode: .fileWriteUnknown) - ) + if !readSucceed { + // Windows throws ERROR_BROKEN_PIPE when the pipe is closed + let error = GetLastError() + if error == ERROR_BROKEN_PIPE { + // We are done reading + initializedCount = totalBytesRead + } else { + // We got some error + lastError = error + initializedCount = 0 + } + break } else { - continuation.resume() + // We succesfully read the current round + totalBytesRead += Int(bytesRead) + } + + if totalBytesRead >= maxLength { + initializedCount = min(maxLength, totalBytesRead) + break } } } + if let lastError = lastError { + let windowsError = SubprocessError( + code: .init(.failedToReadFromSubprocess), + underlyingError: .init(rawValue: lastError) + ) + resultHandler(.failure(windowsError)) + } else { + resultHandler(.success(values)) + } } } -} - -extension String { - static let debugDescriptionErrorKey = "DebugDescription" -} -// MARK: - CocoaError + Win32 -internal let NSUnderlyingErrorKey = "NSUnderlyingError" + internal func write( + _ array: [UInt8] + ) async throws -> Int { + try await withCheckedThrowingContinuation { continuation in + // TODO: Figure out a better way to asynchornously write + DispatchQueue.global(qos: .userInitiated).async { + array.withUnsafeBytes { + self.write($0) { writtenLength, error in + if let error = error { + continuation.resume(throwing: error) + } else { + continuation.resume(returning: writtenLength) + } + } + } + } + } + } -extension CocoaError { - static func windowsError(underlying: DWORD, errorCode: Code) -> CocoaError { - let userInfo = [ - NSUnderlyingErrorKey : Win32Error(underlying) - ] - return CocoaError(errorCode, userInfo: userInfo) + package func write( + _ ptr: UnsafeRawBufferPointer, + completion: @escaping (Int, Swift.Error?) -> Void + ) { + func _write( + _ ptr: UnsafeRawBufferPointer, + count: Int, + completion: @escaping (Int, Swift.Error?) -> Void + ) { + var writtenBytes: DWORD = 0 + let writeSucceed = WriteFile( + self.platformDescriptor, + ptr.baseAddress, + DWORD(count), + &writtenBytes, + nil + ) + if !writeSucceed { + let error = SubprocessError( + code: .init(.failedToWriteToSubprocess), + underlyingError: .init(rawValue: GetLastError()) + ) + completion(Int(writtenBytes), error) + } else { + completion(Int(writtenBytes), nil) + } + } } } -private extension Optional where Wrapped == String { - func withOptionalCString( +extension Optional where Wrapped == String { + fileprivate func withOptionalCString( encodedAs targetEncoding: Encoding.Type, _ body: (UnsafePointer?) throws -> Result - ) rethrows -> Result where Encoding : _UnicodeEncoding { + ) rethrows -> Result where Encoding: _UnicodeEncoding { switch self { case .none: return try body(nil) @@ -1141,7 +1148,7 @@ private extension Optional where Wrapped == String { } } - func withOptionalNTPathRepresentation( + fileprivate func withOptionalNTPathRepresentation( _ body: (UnsafePointer?) throws -> Result ) throws -> Result { switch self { @@ -1159,23 +1166,30 @@ extension String { _ body: (UnsafePointer) throws -> Result ) throws -> Result { guard !isEmpty else { - throw CocoaError(.fileReadInvalidFileName) + throw SubprocessError( + code: .init(.invalidWindowsPath(self)), + underlyingError: nil + ) } var iter = self.utf8.makeIterator() - let bLeadingSlash = if [._slash, ._backslash].contains(iter.next()), iter.next()?.isLetter ?? false, iter.next() == ._colon { true } else { false } + let bLeadingSlash = + if [._slash, ._backslash].contains(iter.next()), iter.next()?.isLetter ?? false, iter.next() == ._colon { + true + } else { false } // Strip the leading `/` on a RFC8089 path (`/[drive-letter]:/...` ). A // leading slash indicates a rooted path on the drive for the current // working directory. - return try Substring(self.utf8.dropFirst(bLeadingSlash ? 1 : 0)).withCString(encodedAs: UTF16.self) { pwszPath in + return try Substring(self.utf8.dropFirst(bLeadingSlash ? 1 : 0)).withCString(encodedAs: UTF16.self) { + pwszPath in // 1. Normalize the path first. let dwLength: DWORD = GetFullPathNameW(pwszPath, 0, nil, nil) return try withUnsafeTemporaryAllocation(of: WCHAR.self, capacity: Int(dwLength)) { guard GetFullPathNameW(pwszPath, DWORD($0.count), $0.baseAddress, nil) > 0 else { - throw CocoaError.windowsError( - underlying: GetLastError(), - errorCode: .fileReadUnknown + throw SubprocessError( + code: .init(.invalidWindowsPath(self)), + underlyingError: .init(rawValue: GetLastError()) ) } @@ -1186,27 +1200,23 @@ extension String { } } -struct Win32Error: Error { - public typealias Code = DWORD - public let code: Code - - public static var errorDomain: String { - return "NSWin32ErrorDomain" - } - - public init(_ code: Code) { - self.code = code - } -} - -internal extension UInt8 { +extension UInt8 { static var _slash: UInt8 { UInt8(ascii: "/") } static var _backslash: UInt8 { UInt8(ascii: "\\") } static var _colon: UInt8 { UInt8(ascii: ":") } var isLetter: Bool? { - return (0x41 ... 0x5a) ~= self || (0x61 ... 0x7a) ~= self + return (0x41...0x5a) ~= self || (0x61...0x7a) ~= self + } +} + +extension OutputProtocol { + internal func output(from data: [UInt8]) throws -> OutputType { + return try data.withUnsafeBytes { + let span = RawSpan(_unsafeBytes: $0) + return try self.output(from: span) + } } } -#endif // canImport(WinSDK) +#endif // canImport(WinSDK) diff --git a/Sources/_Subprocess/Result.swift b/Sources/_Subprocess/Result.swift new file mode 100644 index 00000000..e1f79894 --- /dev/null +++ b/Sources/_Subprocess/Result.swift @@ -0,0 +1,123 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// +//===----------------------------------------------------------------------===// + +#if canImport(System) +import System +#else +@preconcurrency import SystemPackage +#endif + +// MARK: - Result + +/// A simple wrapper around the generic result returned by the +/// `run` closures with the corresponding `TerminationStatus` +/// of the child process. +public struct ExecutionResult { + /// The termination status of the child process + public let terminationStatus: TerminationStatus + /// The result returned by the closure passed to `.run` methods + public let value: Result + + internal init(terminationStatus: TerminationStatus, value: Result) { + self.terminationStatus = terminationStatus + self.value = value + } +} + +/// The result of a subprocess execution with its collected +/// standard output and standard error. +public struct CollectedResult< + Output: OutputProtocol, + Error: OutputProtocol +>: Sendable { + /// The process identifier for the executed subprocess + public let processIdentifier: ProcessIdentifier + /// The termination status of the executed subprocess + public let terminationStatus: TerminationStatus + public let standardOutput: Output.OutputType + public let standardError: Error.OutputType + + internal init( + processIdentifier: ProcessIdentifier, + terminationStatus: TerminationStatus, + standardOutput: Output.OutputType, + standardError: Error.OutputType + ) { + self.processIdentifier = processIdentifier + self.terminationStatus = terminationStatus + self.standardOutput = standardOutput + self.standardError = standardError + } +} + +// MARK: - CollectedResult Conformances +extension CollectedResult: Equatable where Output.OutputType: Equatable, Error.OutputType: Equatable {} + +extension CollectedResult: Hashable where Output.OutputType: Hashable, Error.OutputType: Hashable {} + +extension CollectedResult: Codable where Output.OutputType: Codable, Error.OutputType: Codable {} + +extension CollectedResult: CustomStringConvertible +where Output.OutputType: CustomStringConvertible, Error.OutputType: CustomStringConvertible { + public var description: String { + return """ + CollectedResult( + processIdentifier: \(self.processIdentifier), + terminationStatus: \(self.terminationStatus.description), + standardOutput: \(self.standardOutput.description) + standardError: \(self.standardError.description) + ) + """ + } +} + +extension CollectedResult: CustomDebugStringConvertible +where Output.OutputType: CustomDebugStringConvertible, Error.OutputType: CustomDebugStringConvertible { + public var debugDescription: String { + return """ + CollectedResult( + processIdentifier: \(self.processIdentifier), + terminationStatus: \(self.terminationStatus.description), + standardOutput: \(self.standardOutput.debugDescription) + standardError: \(self.standardError.debugDescription) + ) + """ + } +} + +// MARK: - ExecutionResult Conformances +extension ExecutionResult: Equatable where Result: Equatable {} + +extension ExecutionResult: Hashable where Result: Hashable {} + +extension ExecutionResult: Codable where Result: Codable {} + +extension ExecutionResult: CustomStringConvertible where Result: CustomStringConvertible { + public var description: String { + return """ + ExecutionResult( + terminationStatus: \(self.terminationStatus.description), + value: \(self.value.description) + ) + """ + } +} + +extension ExecutionResult: CustomDebugStringConvertible where Result: CustomDebugStringConvertible { + public var debugDescription: String { + return """ + ExecutionResult( + terminationStatus: \(self.terminationStatus.debugDescription), + value: \(self.value.debugDescription) + ) + """ + } +} diff --git a/Sources/_Subprocess/Subprocess+API.swift b/Sources/_Subprocess/Subprocess+API.swift deleted file mode 100644 index f9c8b1ec..00000000 --- a/Sources/_Subprocess/Subprocess+API.swift +++ /dev/null @@ -1,465 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of Swift.org project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -import SystemPackage -#if canImport(FoundationEssentials) -import FoundationEssentials -#elseif canImport(Foundation) -import Foundation -#endif - -extension Subprocess { - /// Run a executable with given parameters and capture its - /// standard output and standard error. - /// - Parameters: - /// - executable: The executable to run. - /// - arguments: The arguments to pass to the executable. - /// - environment: The environment to use for the process. - /// - workingDirectory: The working directory to use for the subprocess. - /// - platformOptions: The platform specific options to use - /// when running the executable. - /// - input: The input to send to the executable. - /// - output: The method to use for collecting the standard output. - /// - error: The method to use for collecting the standard error. - /// - Returns: `CollectedResult` which contains process identifier, - /// termination status, captured standard output and standard error. - public static func run( - _ executable: Executable, - arguments: Arguments = [], - environment: Environment = .inherit, - workingDirectory: FilePath? = nil, - platformOptions: PlatformOptions = PlatformOptions(), - input: InputMethod = .noInput, - output: CollectedOutputMethod = .collect(), - error: CollectedOutputMethod = .collect() - ) async throws -> CollectedResult { - let result = try await self.run( - executable, - arguments: arguments, - environment: environment, - workingDirectory: workingDirectory, - platformOptions: platformOptions, - input: input, - output: .init(method: output.method), - error: .init(method: error.method) - ) { subprocess in - let (standardOutput, standardError) = try await subprocess.captureIOs() - return ( - processIdentifier: subprocess.processIdentifier, - standardOutput: standardOutput, - standardError: standardError - ) - } - return CollectedResult( - processIdentifier: result.value.processIdentifier, - terminationStatus: result.terminationStatus, - standardOutput: result.value.standardOutput, - standardError: result.value.standardError - ) - } - - /// Run a executable with given parameters and capture its - /// standard output and standard error. - /// - Parameters: - /// - executable: The executable to run. - /// - arguments: The arguments to pass to the executable. - /// - environment: The environment to use for the process. - /// - workingDirectory: The working directory to use for the subprocess. - /// - platformOptions: The platform specific options to use - /// when running the executable. - /// - input: The input to send to the executable. - /// - output: The method to use for collecting the standard output. - /// - error: The method to use for collecting the standard error. - /// - Returns: `CollectedResult` which contains process identifier, - /// termination status, captured standard output and standard error. - public static func run( - _ executable: Executable, - arguments: Arguments = [], - environment: Environment = .inherit, - workingDirectory: FilePath? = nil, - platformOptions: PlatformOptions = PlatformOptions(), - input: some Sequence, - output: CollectedOutputMethod = .collect(), - error: CollectedOutputMethod = .collect() - ) async throws -> CollectedResult { - let result = try await self.run( - executable, - arguments: arguments, - environment: environment, - workingDirectory: workingDirectory, - platformOptions: platformOptions, - output: .init(method: output.method), - error: .init(method: output.method) - ) { subprocess, writer in - return try await withThrowingTaskGroup(of: CapturedIOs?.self) { group in - group.addTask { - try await writer.write(input) - try await writer.finish() - return nil - } - group.addTask { - return try await subprocess.captureIOs() - } - var capturedIOs: CapturedIOs! - while let result = try await group.next() { - if result != nil { - capturedIOs = result - } - } - return ( - processIdentifier: subprocess.processIdentifier, - standardOutput: capturedIOs.standardOutput, - standardError: capturedIOs.standardError - ) - } - } - return CollectedResult( - processIdentifier: result.value.processIdentifier, - terminationStatus: result.terminationStatus, - standardOutput: result.value.standardOutput, - standardError: result.value.standardError - ) - } - - /// Run a executable with given parameters and capture its - /// standard output and standard error. - /// - Parameters: - /// - executable: The executable to run. - /// - arguments: The arguments to pass to the executable. - /// - environment: The environment to use for the process. - /// - workingDirectory: The working directory to use for the subprocess. - /// - platformOptions: The platform specific options to use - /// when running the executable. - /// - input: The input to send to the executable. - /// - output: The method to use for collecting the standard output. - /// - error: The method to use for collecting the standard error. - /// - Returns: `CollectedResult` which contains process identifier, - /// termination status, captured standard output and standard error. - public static func run( - _ executable: Executable, - arguments: Arguments = [], - environment: Environment = .inherit, - workingDirectory: FilePath? = nil, - platformOptions: PlatformOptions = PlatformOptions(), - input: S, - output: CollectedOutputMethod = .collect(), - error: CollectedOutputMethod = .collect() - ) async throws -> CollectedResult where S.Element == UInt8 { - let result = try await self.run( - executable, - arguments: arguments, - environment: environment, - workingDirectory: workingDirectory, - platformOptions: platformOptions, - output: .init(method: output.method), - error: .init(method: output.method) - ) { subprocess, writer in - return try await withThrowingTaskGroup(of: CapturedIOs?.self) { group in - group.addTask { - try await writer.write(input) - try await writer.finish() - return nil - } - group.addTask { - return try await subprocess.captureIOs() - } - var capturedIOs: CapturedIOs! - while let result = try await group.next() { - capturedIOs = result - } - return ( - processIdentifier: subprocess.processIdentifier, - standardOutput: capturedIOs.standardOutput, - standardError: capturedIOs.standardError - ) - } - } - return CollectedResult( - processIdentifier: result.value.processIdentifier, - terminationStatus: result.terminationStatus, - standardOutput: result.value.standardOutput, - standardError: result.value.standardError - ) - } -} - -// MARK: Custom Execution Body -extension Subprocess { - /// Run a executable with given parameters and a custom closure - /// to manage the running subprocess' lifetime and its IOs. - /// - Parameters: - /// - executable: The executable to run. - /// - arguments: The arguments to pass to the executable. - /// - environment: The environment in which to run the executable. - /// - workingDirectory: The working directory in which to run the executable. - /// - platformOptions: The platform specific options to use - /// when running the executable. - /// - input: The input to send to the executable. - /// - output: The method to use for redirecting the standard output. - /// - error: The method to use for redirecting the standard error. - /// - body: The custom execution body to manually control the running process - /// - Returns a ExecutableResult type containing the return value - /// of the closure. - public static func run( - _ executable: Executable, - arguments: Arguments = [], - environment: Environment = .inherit, - workingDirectory: FilePath? = nil, - platformOptions: PlatformOptions = PlatformOptions(), - input: InputMethod = .noInput, - output: RedirectedOutputMethod = .redirectToSequence, - error: RedirectedOutputMethod = .redirectToSequence, - _ body: (sending @escaping (Subprocess) async throws -> R) - ) async throws -> ExecutionResult { - return try await Configuration( - executable: executable, - arguments: arguments, - environment: environment, - workingDirectory: workingDirectory, - platformOptions: platformOptions - ) - .run(input: input, output: output, error: error, body) - } - - /// Run a executable with given parameters and a custom closure - /// to manage the running subprocess' lifetime and its IOs. - /// - Parameters: - /// - executable: The executable to run. - /// - arguments: The arguments to pass to the executable. - /// - environment: The environment in which to run the executable. - /// - workingDirectory: The working directory in which to run the executable. - /// - platformOptions: The platform specific options to use - /// when running the executable. - /// - input: The input to send to the executable. - /// - output: The method to use for redirecting the standard output. - /// - error: The method to use for redirecting the standard error. - /// - body: The custom execution body to manually control the running process - /// - Returns a `ExecutableResult` type containing the return value - /// of the closure. - public static func run( - _ executable: Executable, - arguments: Arguments = [], - environment: Environment = .inherit, - workingDirectory: FilePath? = nil, - platformOptions: PlatformOptions = PlatformOptions(), - input: some Sequence, - output: RedirectedOutputMethod = .redirectToSequence, - error: RedirectedOutputMethod = .redirectToSequence, - _ body: (sending @escaping (Subprocess) async throws -> R) - ) async throws -> ExecutionResult { - return try await Configuration( - executable: executable, - arguments: arguments, - environment: environment, - workingDirectory: workingDirectory, - platformOptions: platformOptions - ) - .run(output: output, error: error) { execution, writer in - return try await withThrowingTaskGroup(of: R?.self) { group in - group.addTask { - try await writer.write(input) - try await writer.finish() - return nil - } - group.addTask { - return try await body(execution) - } - var result: R! - while let next = try await group.next() { - result = next - } - return result - } - } - } - - /// Run a executable with given parameters and a custom closure - /// to manage the running subprocess' lifetime and its IOs. - /// - Parameters: - /// - executable: The executable to run. - /// - arguments: The arguments to pass to the executable. - /// - environment: The environment in which to run the executable. - /// - workingDirectory: The working directory in which to run the executable. - /// - platformOptions: The platform specific options to use - /// when running the executable. - /// - input: The input to send to the executable. - /// - output: The method to use for redirecting the standard output. - /// - error: The method to use for redirecting the standard error. - /// - body: The custom execution body to manually control the running process - /// - Returns a `ExecutableResult` type containing the return value - /// of the closure. - public static func run( - _ executable: Executable, - arguments: Arguments = [], - environment: Environment = .inherit, - workingDirectory: FilePath? = nil, - platformOptions: PlatformOptions = PlatformOptions(), - input: S, - output: RedirectedOutputMethod = .redirectToSequence, - error: RedirectedOutputMethod = .redirectToSequence, - _ body: (sending @escaping (Subprocess) async throws -> R) - ) async throws -> ExecutionResult where S.Element == UInt8 { - return try await Configuration( - executable: executable, - arguments: arguments, - environment: environment, - workingDirectory: workingDirectory, - platformOptions: platformOptions - ) - .run(output: output, error: error) { execution, writer in - return try await withThrowingTaskGroup(of: R?.self) { group in - group.addTask { - try await writer.write(input) - try await writer.finish() - return nil - } - group.addTask { - return try await body(execution) - } - var result: R! - while let next = try await group.next() { - result = next - } - return result - } - } - } - - /// Run a executable with given parameters and a custom closure - /// to manage the running subprocess' lifetime and write to its - /// standard input via `StandardInputWriter` - /// - Parameters: - /// - executable: The executable to run. - /// - arguments: The arguments to pass to the executable. - /// - environment: The environment in which to run the executable. - /// - workingDirectory: The working directory in which to run the executable. - /// - platformOptions: The platform specific options to use - /// when running the executable. - /// - output: The method to use for redirecting the standard output. - /// - error: The method to use for redirecting the standard error. - /// - body: The custom execution body to manually control the running process - /// - Returns a ExecutableResult type containing the return value - /// of the closure. - public static func run( - _ executable: Executable, - arguments: Arguments = [], - environment: Environment = .inherit, - workingDirectory: FilePath? = nil, - platformOptions: PlatformOptions = PlatformOptions(), - output: RedirectedOutputMethod = .redirectToSequence, - error: RedirectedOutputMethod = .redirectToSequence, - _ body: (sending @escaping (Subprocess, StandardInputWriter) async throws -> R) - ) async throws -> ExecutionResult { - return try await Configuration( - executable: executable, - arguments: arguments, - environment: environment, - workingDirectory: workingDirectory, - platformOptions: platformOptions - ) - .run(output: output, error: error, body) - } -} - -// MARK: - Configuration Based -extension Subprocess { - /// Run a executable with given parameters specified by a - /// `Subprocess.Configuration` - /// - Parameters: - /// - configuration: The `Subprocess` configuration to run. - /// - output: The method to use for redirecting the standard output. - /// - error: The method to use for redirecting the standard error. - /// - body: The custom configuration body to manually control - /// the running process and write to its standard input. - /// - Returns a ExecutableResult type containing the return value - /// of the closure. - public static func run( - _ configuration: Configuration, - output: RedirectedOutputMethod = .redirectToSequence, - error: RedirectedOutputMethod = .redirectToSequence, - _ body: (sending @escaping (Subprocess, StandardInputWriter) async throws -> R) - ) async throws -> ExecutionResult { - return try await configuration.run(output: output, error: error, body) - } -} - -// MARK: - Detached -extension Subprocess { - /// Run a executable with given parameters and return its process - /// identifier immediately without monitoring the state of the - /// subprocess nor waiting until it exits. - /// - /// This method is useful for launching subprocesses that outlive their - /// parents (for example, daemons and trampolines). - /// - /// - Parameters: - /// - executable: The executable to run. - /// - arguments: The arguments to pass to the executable. - /// - environment: The environment to use for the process. - /// - workingDirectory: The working directory for the process. - /// - platformOptions: The platform specific options to use for the process. - /// - input: A file descriptor to bind to the subprocess' standard input. - /// - output: A file descriptor to bind to the subprocess' standard output. - /// - error: A file descriptor to bind to the subprocess' standard error. - /// - Returns: the process identifier for the subprocess. - public static func runDetached( - _ executable: Executable, - arguments: Arguments = [], - environment: Environment = .inherit, - workingDirectory: FilePath? = nil, - platformOptions: PlatformOptions = PlatformOptions(), - input: FileDescriptor? = nil, - output: FileDescriptor? = nil, - error: FileDescriptor? = nil - ) throws -> ProcessIdentifier { - // Create input - let executionInput: ExecutionInput - let executionOutput: ExecutionOutput - let executionError: ExecutionOutput - if let inputFd = input { - executionInput = .init(storage: .fileDescriptor(inputFd, false)) - } else { - let devnull: FileDescriptor = try .openDevNull(withAcessMode: .readOnly) - executionInput = .init(storage: .noInput(devnull)) - } - if let outputFd = output { - executionOutput = .init(storage: .fileDescriptor(outputFd, false)) - } else { - let devnull: FileDescriptor = try .openDevNull(withAcessMode: .writeOnly) - executionOutput = .init(storage: .discarded(devnull)) - } - if let errorFd = error { - executionError = .init( - storage: .fileDescriptor(errorFd, false) - ) - } else { - let devnull: FileDescriptor = try .openDevNull(withAcessMode: .writeOnly) - executionError = .init(storage: .discarded(devnull)) - } - // Spawn! - let config: Configuration = Configuration( - executable: executable, - arguments: arguments, - environment: environment, - workingDirectory: workingDirectory, - platformOptions: platformOptions - ) - return try config.spawn( - withInput: executionInput, - output: executionOutput, - error: executionError - ).processIdentifier - } -} - diff --git a/Sources/_Subprocess/Subprocess+AsyncDataSequence.swift b/Sources/_Subprocess/Subprocess+AsyncDataSequence.swift deleted file mode 100644 index a3a3e393..00000000 --- a/Sources/_Subprocess/Subprocess+AsyncDataSequence.swift +++ /dev/null @@ -1,86 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of Swift.org project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -import SystemPackage -import Dispatch - -#if canImport(FoundationEssentials) -import FoundationEssentials -#elseif canImport(Foundation) -import Foundation -#endif - -extension Subprocess { - public struct AsyncDataSequence: AsyncSequence, Sendable, _AsyncSequence { - public typealias Error = any Swift.Error - - public typealias Element = Data - - @_nonSendable - public struct Iterator: AsyncIteratorProtocol { - public typealias Element = Data - - private let fileDescriptor: FileDescriptor - private var buffer: [UInt8] - private var currentPosition: Int - private var finished: Bool - - internal init(fileDescriptor: FileDescriptor) { - self.fileDescriptor = fileDescriptor - self.buffer = [] - self.currentPosition = 0 - self.finished = false - } - - public mutating func next() async throws -> Data? { - let data = try await self.fileDescriptor.readChunk( - upToLength: Subprocess.readBufferSize - ) - if data == nil { - // We finished reading. Close the file descriptor now - try self.fileDescriptor.close() - return nil - } - return data - } - } - - private let fileDescriptor: FileDescriptor - - init(fileDescriptor: FileDescriptor) { - self.fileDescriptor = fileDescriptor - } - - public func makeAsyncIterator() -> Iterator { - return Iterator(fileDescriptor: self.fileDescriptor) - } - } -} - -extension RangeReplaceableCollection { - /// Creates a new instance of a collection containing the elements of an asynchronous sequence. - /// - /// - Parameter source: The asynchronous sequence of elements for the new collection. - @inlinable - public init(_ source: Source) async rethrows where Source.Element == Element { - self.init() - for try await item in source { - append(item) - } - } -} - -public protocol _AsyncSequence: AsyncSequence { - associatedtype Error -} diff --git a/Sources/_Subprocess/Subprocess+Configuration.swift b/Sources/_Subprocess/Subprocess+Configuration.swift deleted file mode 100644 index 0b785790..00000000 --- a/Sources/_Subprocess/Subprocess+Configuration.swift +++ /dev/null @@ -1,769 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of Swift.org project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -@preconcurrency import SystemPackage - -#if canImport(Darwin) -import Darwin -#elseif canImport(Glibc) -import Glibc -#elseif canImport(WinSDK) -import WinSDK -#endif - -#if canImport(FoundationEssentials) -import FoundationEssentials -#elseif canImport(Foundation) -import Foundation -#endif - -extension Subprocess { - /// A collection of configurations parameters to use when - /// spawning a subprocess. - public struct Configuration: Sendable, Hashable { - - internal enum RunState: Sendable { - case workBody(Result) - case monitorChildProcess(TerminationStatus) - } - - /// The executable to run. - public var executable: Executable - /// The arguments to pass to the executable. - public var arguments: Arguments - /// The environment to use when running the executable. - public var environment: Environment - /// The working directory to use when running the executable. - public var workingDirectory: FilePath - /// The platform specifc options to use when - /// running the subprocess. - public var platformOptions: PlatformOptions - - public init( - executable: Executable, - arguments: Arguments = [], - environment: Environment = .inherit, - workingDirectory: FilePath? = nil, - platformOptions: PlatformOptions = PlatformOptions() - ) { - self.executable = executable - self.arguments = arguments - self.environment = environment - self.workingDirectory = workingDirectory ?? .currentWorkingDirectory - self.platformOptions = platformOptions - } - - /// Close each input individually, and throw the first error if there's multiple errors thrown - @Sendable - private func cleanup( - process: Subprocess, - childSide: Bool, parentSide: Bool, - attemptToTerminateSubProcess: Bool - ) async throws { - guard childSide || parentSide || attemptToTerminateSubProcess else { - return - } - - // Attempt to teardown the subprocess - if attemptToTerminateSubProcess { - await process.teardown( - using: self.platformOptions.teardownSequence - ) - } - - let inputCloseFunc: () throws -> Void - let outputCloseFunc: () throws -> Void - let errorCloseFunc: () throws -> Void - if childSide && parentSide { - // Close all - inputCloseFunc = process.executionInput.closeAll - outputCloseFunc = process.executionOutput.closeAll - errorCloseFunc = process.executionError.closeAll - } else if childSide { - // Close child only - inputCloseFunc = process.executionInput.closeChildSide - outputCloseFunc = process.executionOutput.closeChildSide - errorCloseFunc = process.executionError.closeChildSide - } else { - // Close parent only - inputCloseFunc = process.executionInput.closeParentSide - outputCloseFunc = process.executionOutput.closeParentSide - errorCloseFunc = process.executionError.closeParentSide - } - - var inputError: Error? - var outputError: Error? - var errorError: Error? // lol - do { - try inputCloseFunc() - } catch { - inputError = error - } - - do { - try outputCloseFunc() - } catch { - outputError = error - } - - do { - try errorCloseFunc() - } catch { - errorError = error // lolol - } - - if let inputError = inputError { - throw inputError - } - - if let outputError = outputError { - throw outputError - } - - if let errorError = errorError { - throw errorError - } - } - - /// Close each input individually, and throw the first error if there's multiple errors thrown - @Sendable - internal func cleanupAll( - input: ExecutionInput, - output: ExecutionOutput, - error: ExecutionOutput - ) throws { - var inputError: Error? - var outputError: Error? - var errorError: Error? - - do { - try input.closeAll() - } catch { - inputError = error - } - - do { - try output.closeAll() - } catch { - outputError = error - } - - do { - try error.closeAll() - } catch { - errorError = error - } - - if let inputError = inputError { - throw inputError - } - if let outputError = outputError { - throw outputError - } - if let errorError = errorError { - throw errorError - } - } - - internal func run( - output: RedirectedOutputMethod, - error: RedirectedOutputMethod, - _ body: sending @escaping (Subprocess, StandardInputWriter) async throws -> R - ) async throws -> ExecutionResult { - let (readFd, writeFd) = try FileDescriptor.pipe() - let executionInput: ExecutionInput = .init(storage: .customWrite(readFd, writeFd)) - let executionOutput: ExecutionOutput = try output.createExecutionOutput() - let executionError: ExecutionOutput = try error.createExecutionOutput() - let process: Subprocess = try self.spawn( - withInput: executionInput, - output: executionOutput, - error: executionError) - // After spawn, cleanup child side fds - try await self.cleanup( - process: process, - childSide: true, - parentSide: false, - attemptToTerminateSubProcess: false - ) - return try await withAsyncTaskCancellationHandler { - return try await withThrowingTaskGroup(of: RunState.self) { group in - group.addTask { - let status = try await monitorProcessTermination( - forProcessWithIdentifier: process.processIdentifier) - return .monitorChildProcess(status) - } - group.addTask { - do { - let result = try await body(process, .init(input: executionInput)) - try await self.cleanup( - process: process, - childSide: false, - parentSide: true, - attemptToTerminateSubProcess: false - ) - return .workBody(result) - } catch { - // Cleanup everything - try await self.cleanup( - process: process, - childSide: false, - parentSide: true, - attemptToTerminateSubProcess: false - ) - throw error - } - } - - var result: R! - var terminationStatus: TerminationStatus! - while let state = try await group.next() { - switch state { - case .monitorChildProcess(let status): - // We don't really care about termination status here - terminationStatus = status - case .workBody(let workResult): - result = workResult - } - } - return ExecutionResult(terminationStatus: terminationStatus, value: result) - } - } onCancel: { - // Attempt to terminate the child process - // Since the task has already been cancelled, - // this is the best we can do - try? await self.cleanup( - process: process, - childSide: true, - parentSide: true, - attemptToTerminateSubProcess: true - ) - } - } - - internal func run( - input: InputMethod, - output: RedirectedOutputMethod, - error: RedirectedOutputMethod, - _ body: (sending @escaping (Subprocess) async throws -> R) - ) async throws -> ExecutionResult { - let executionInput = try input.createExecutionInput() - let executionOutput = try output.createExecutionOutput() - let executionError = try error.createExecutionOutput() - let process = try self.spawn( - withInput: executionInput, - output: executionOutput, - error: executionError) - // After spawn, clean up child side - try await self.cleanup( - process: process, - childSide: true, - parentSide: false, - attemptToTerminateSubProcess: false - ) - return try await withAsyncTaskCancellationHandler { - return try await withThrowingTaskGroup(of: RunState.self) { group in - group.addTask { - let status = try await monitorProcessTermination( - forProcessWithIdentifier: process.processIdentifier) - return .monitorChildProcess(status) - } - group.addTask { - do { - let result = try await body(process) - try await self.cleanup( - process: process, - childSide: false, - parentSide: true, - attemptToTerminateSubProcess: false - ) - return .workBody(result) - } catch { - try await self.cleanup( - process: process, - childSide: false, - parentSide: true, - attemptToTerminateSubProcess: false - ) - throw error - } - } - - var result: R! - var terminationStatus: TerminationStatus! - while let state = try await group.next() { - switch state { - case .monitorChildProcess(let status): - terminationStatus = status - case .workBody(let workResult): - result = workResult - } - } - return ExecutionResult(terminationStatus: terminationStatus, value: result) - } - } onCancel: { - // Attempt to terminate the child process - // Since the task has already been cancelled, - // this is the best we can do - try? await self.cleanup( - process: process, - childSide: true, - parentSide: true, - attemptToTerminateSubProcess: true - ) - } - } - } -} - -extension Subprocess.Configuration : CustomStringConvertible, CustomDebugStringConvertible { - public var description: String { - return """ -Subprocess.Configuration( - executable: \(self.executable.description), - arguments: \(self.arguments.description), - environment: \(self.environment.description), - workingDirectory: \(self.workingDirectory), - platformOptions: \(self.platformOptions.description(withIndent: 1)) -) -""" - } - - public var debugDescription: String { - return """ -Subprocess.Configuration( - executable: \(self.executable.debugDescription), - arguments: \(self.arguments.debugDescription), - environment: \(self.environment.debugDescription), - workingDirectory: \(self.workingDirectory), - platformOptions: \(self.platformOptions.description(withIndent: 1)) -) -""" - } -} - -// MARK: - Executable -extension Subprocess { - /// `Subprocess.Executable` defines how should the executable - /// be looked up for execution. - public struct Executable: Sendable, Hashable { - internal enum Configuration: Sendable, Hashable { - case executable(String) - case path(FilePath) - } - - internal let storage: Configuration - - private init(_config: Configuration) { - self.storage = _config - } - - /// Locate the executable by its name. - /// `Subprocess` will use `PATH` value to - /// determine the full path to the executable. - public static func named(_ executableName: String) -> Self { - return .init(_config: .executable(executableName)) - } - /// Locate the executable by its full path. - /// `Subprocess` will use this path directly. - public static func at(_ filePath: FilePath) -> Self { - return .init(_config: .path(filePath)) - } - /// Returns the full executable path given the environment value. - public func resolveExecutablePath(in environment: Environment) -> FilePath? { - if let path = self.resolveExecutablePath(withPathValue: environment.pathValue()) { - return FilePath(path) - } - return nil - } - } -} - -extension Subprocess.Executable : CustomStringConvertible, CustomDebugStringConvertible { - public var description: String { - switch storage { - case .executable(let executableName): - return executableName - case .path(let filePath): - return filePath.string - } - } - - public var debugDescription: String { - switch storage { - case .executable(let string): - return "executable(\(string))" - case .path(let filePath): - return "path(\(filePath.string))" - } - } -} - -// MARK: - Arguments -extension Subprocess { - /// A collection of arguments to pass to the subprocess. - public struct Arguments: Sendable, ExpressibleByArrayLiteral, Hashable { - public typealias ArrayLiteralElement = String - - internal let storage: [StringOrRawBytes] - internal let executablePathOverride: StringOrRawBytes? - - /// Create an Arguments object using the given literal values - public init(arrayLiteral elements: String...) { - self.storage = elements.map { .string($0) } - self.executablePathOverride = nil - } - /// Create an Arguments object using the given array - public init(_ array: [String]) { - self.storage = array.map { .string($0) } - self.executablePathOverride = nil - } - -#if !os(Windows) // Windows does NOT support arg0 override - /// Create an `Argument` object using the given values, but - /// override the first Argument value to `executablePathOverride`. - /// If `executablePathOverride` is nil, - /// `Arguments` will automatically use the executable path - /// as the first argument. - /// - Parameters: - /// - executablePathOverride: the value to override the first argument. - /// - remainingValues: the rest of the argument value - public init(executablePathOverride: String?, remainingValues: [String]) { - self.storage = remainingValues.map { .string($0) } - if let executablePathOverride = executablePathOverride { - self.executablePathOverride = .string(executablePathOverride) - } else { - self.executablePathOverride = nil - } - } - - /// Create an `Argument` object using the given values, but - /// override the first Argument value to `executablePathOverride`. - /// If `executablePathOverride` is nil, - /// `Arguments` will automatically use the executable path - /// as the first argument. - /// - Parameters: - /// - executablePathOverride: the value to override the first argument. - /// - remainingValues: the rest of the argument value - public init(executablePathOverride: Data?, remainingValues: [Data]) { - self.storage = remainingValues.map { .rawBytes($0.toArray()) } - if let override = executablePathOverride { - self.executablePathOverride = .rawBytes(override.toArray()) - } else { - self.executablePathOverride = nil - } - } - - public init(_ array: [Data]) { - self.storage = array.map { .rawBytes($0.toArray()) } - self.executablePathOverride = nil - } -#endif - } -} - -extension Subprocess.Arguments : CustomStringConvertible, CustomDebugStringConvertible { - public var description: String { - var result: [String] = self.storage.map(\.description) - - if let override = self.executablePathOverride { - result.insert("override\(override.description)", at: 0) - } - return result.description - } - - public var debugDescription: String { return self.description } -} - -// MARK: - Environment -extension Subprocess { - /// A set of environment variables to use when executing the subprocess. - public struct Environment: Sendable, Hashable { - internal enum Configuration: Sendable, Hashable { - case inherit([StringOrRawBytes : StringOrRawBytes]) - case custom([StringOrRawBytes : StringOrRawBytes]) - } - - internal let config: Configuration - - init(config: Configuration) { - self.config = config - } - /// Child process should inherit the same environment - /// values from its parent process. - public static var inherit: Self { - return .init(config: .inherit([:])) - } - /// Override the provided `newValue` in the existing `Environment` - public func updating(_ newValue: [String : String]) -> Self { - return .init(config: .inherit(newValue.wrapToStringOrRawBytes())) - } - /// Use custom environment variables - public static func custom(_ newValue: [String : String]) -> Self { - return .init(config: .custom(newValue.wrapToStringOrRawBytes())) - } - -#if !os(Windows) - /// Override the provided `newValue` in the existing `Environment` - public func updating(_ newValue: [Data : Data]) -> Self { - return .init(config: .inherit(newValue.wrapToStringOrRawBytes())) - } - /// Use custom environment variables - public static func custom(_ newValue: [Data : Data]) -> Self { - return .init(config: .custom(newValue.wrapToStringOrRawBytes())) - } -#endif - } -} - -extension Subprocess.Environment : CustomStringConvertible, CustomDebugStringConvertible { - public var description: String { - switch self.config { - case .custom(let customDictionary): - return customDictionary.dictionaryDescription - case .inherit(let updateValue): - return "Inherting current environment with updates: \(updateValue.dictionaryDescription)" - } - } - - public var debugDescription: String { - return self.description - } -} - -fileprivate extension Dictionary where Key == String, Value == String { - func wrapToStringOrRawBytes() -> [Subprocess.StringOrRawBytes : Subprocess.StringOrRawBytes] { - var result = Dictionary< - Subprocess.StringOrRawBytes, - Subprocess.StringOrRawBytes - >(minimumCapacity: self.count) - for (key, value) in self { - result[.string(key)] = .string(value) - } - return result - } -} - -fileprivate extension Dictionary where Key == Data, Value == Data { - func wrapToStringOrRawBytes() -> [Subprocess.StringOrRawBytes : Subprocess.StringOrRawBytes] { - var result = Dictionary< - Subprocess.StringOrRawBytes, - Subprocess.StringOrRawBytes - >(minimumCapacity: self.count) - for (key, value) in self { - result[.rawBytes(key.toArray())] = .rawBytes(value.toArray()) - } - return result - } -} - -fileprivate extension Dictionary where Key == Subprocess.StringOrRawBytes, Value == Subprocess.StringOrRawBytes { - var dictionaryDescription: String { - var result = "[\n" - for (key, value) in self { - result += "\t\(key.description) : \(value.description),\n" - } - result += "]" - return result - } -} - -fileprivate extension Data { - func toArray() -> [T] { - return self.withUnsafeBytes { ptr in - return Array(ptr.bindMemory(to: T.self)) - } - } -} - -// MARK: - TerminationStatus -extension Subprocess { - /// An exit status of a subprocess. - @frozen - public enum TerminationStatus: Sendable, Hashable, Codable { - #if canImport(WinSDK) - public typealias Code = DWORD - #else - public typealias Code = CInt - #endif - - /// The subprocess was existed with the given code - case exited(Code) - /// The subprocess was signalled with given exception value - case unhandledException(Code) - /// Whether the current TerminationStatus is successful. - public var isSuccess: Bool { - switch self { - case .exited(let exitCode): - return exitCode == 0 - case .unhandledException(_): - return false - } - } - } -} - -extension Subprocess.TerminationStatus : CustomStringConvertible, CustomDebugStringConvertible { - public var description: String { - switch self { - case .exited(let code): - return "exited(\(code))" - case .unhandledException(let code): - return "unhandledException(\(code))" - } - } - - public var debugDescription: String { - return self.description - } -} - -// MARK: - Internal -extension Subprocess { - internal enum StringOrRawBytes: Sendable, Hashable { - case string(String) - case rawBytes([CChar]) - - // Return value needs to be deallocated manually by callee - func createRawBytes() -> UnsafeMutablePointer { - switch self { - case .string(let string): - return strdup(string) - case .rawBytes(let rawBytes): - return strdup(rawBytes) - } - } - - var stringValue: String? { - switch self { - case .string(let string): - return string - case .rawBytes(let rawBytes): - return String(validatingUTF8: rawBytes) - } - } - - var description: String { - switch self { - case .string(let string): - return string - case .rawBytes(let bytes): - return bytes.description - } - } - - var count: Int { - switch self { - case .string(let string): - return string.count - case .rawBytes(let rawBytes): - return strnlen(rawBytes, Int.max) - } - } - - func hash(into hasher: inout Hasher) { - // If Raw bytes is valid UTF8, hash it as so - switch self { - case .string(let string): - hasher.combine(string) - case .rawBytes(let bytes): - if let stringValue = self.stringValue { - hasher.combine(stringValue) - } else { - hasher.combine(bytes) - } - } - } - } -} - -extension FilePath { - static var currentWorkingDirectory: Self { - let path = getcwd(nil, 0)! - defer { free(path) } - return .init(String(cString: path)) - } -} - -extension Optional where Wrapped : Collection { - func withOptionalUnsafeBufferPointer(_ body: ((UnsafeBufferPointer)?) throws -> R) rethrows -> R { - switch self { - case .some(let wrapped): - guard let array: Array = wrapped as? Array else { - return try body(nil) - } - return try array.withUnsafeBufferPointer { ptr in - return try body(ptr) - } - case .none: - return try body(nil) - } - } -} - -extension Optional where Wrapped == String { - func withOptionalCString(_ body: ((UnsafePointer)?) throws -> R) rethrows -> R { - switch self { - case .none: - return try body(nil) - case .some(let wrapped): - return try wrapped.withCString { - return try body($0) - } - } - } - - var stringValue: String { - return self ?? "nil" - } -} - -// MARK: - Stubs for the one from Foundation -public enum QualityOfService: Int, Sendable { - case userInteractive = 0x21 - case userInitiated = 0x19 - case utility = 0x11 - case background = 0x09 - case `default` = -1 -} - -internal func withAsyncTaskCancellationHandler( - _ body: sending @escaping () async throws -> R, - onCancel handler: sending @escaping () async -> Void -) async rethrows -> R { - return try await withThrowingTaskGroup( - of: R?.self, - returning: R.self - ) { group in - group.addTask { - return try await body() - } - group.addTask { - // wait until cancelled - do { while true { try await Task.sleep(nanoseconds: 1_000_000_000) } } catch {} - // Run task cancel handler - await handler() - return nil - } - - while let result = try await group.next() { - if let result = result { - // As soon as the body finishes, cancel the group - group.cancelAll() - return result - } - } - fatalError("Unreachable") - } -} - diff --git a/Sources/_Subprocess/Subprocess+IO.swift b/Sources/_Subprocess/Subprocess+IO.swift deleted file mode 100644 index 1b43e421..00000000 --- a/Sources/_Subprocess/Subprocess+IO.swift +++ /dev/null @@ -1,437 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of Swift.org project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -#if canImport(FoundationEssentials) -import FoundationEssentials -#elseif canImport(Foundation) -import Foundation -#endif - -import Dispatch -import SystemPackage - -// Naive Mutex so we don't have to update the macOS dependency -final class _Mutex: Sendable { - let lock = Lock() - - var value: Value - - init(_ value: Value) { - self.value = value - } - - func withLock(_ body: (inout Value) throws -> R) rethrows -> R { - self.lock.lock() - defer { self.lock.unlock() } - return try body(&self.value) - } -} - -// MARK: - Input -extension Subprocess { - /// `InputMethod` defines how should the standard input - /// of the subprocess receive inputs. - public struct InputMethod: Sendable, Hashable { - internal enum Storage: Sendable, Hashable { - case noInput - case fileDescriptor(FileDescriptor, Bool) - } - - internal let method: Storage - - internal init(method: Storage) { - self.method = method - } - - internal func createExecutionInput() throws -> ExecutionInput { - switch self.method { - case .noInput: - let devnull: FileDescriptor = try .openDevNull(withAcessMode: .readOnly) - return .init(storage: .noInput(devnull)) - case .fileDescriptor(let fileDescriptor, let closeWhenDone): - return .init(storage: .fileDescriptor(fileDescriptor, closeWhenDone)) - } - } - - /// Subprocess should read no input. This option is equivalent - /// to bind the stanard input to `/dev/null`. - public static var noInput: Self { - return .init(method: .noInput) - } - - /// Subprocess should read input from a given file descriptor. - /// - Parameters: - /// - fd: the file descriptor to read from - /// - closeAfterSpawningProcess: whether the file descriptor - /// should be automatically closed after subprocess is spawned. - public static func readFrom( - _ fd: FileDescriptor, - closeAfterSpawningProcess: Bool - ) -> Self { - return .init(method: .fileDescriptor(fd, closeAfterSpawningProcess)) - } - } -} - -extension Subprocess { - /// `CollectedOutputMethod` defines how should Subprocess collect - /// output from child process' standard output and standard error - public struct CollectedOutputMethod: Sendable, Hashable { - internal enum Storage: Sendable, Hashable { - case discarded - case fileDescriptor(FileDescriptor, Bool) - case collected(Int) - } - - internal let method: Storage - - internal init(method: Storage) { - self.method = method - } - - /// Subprocess shold dicard the child process output. - /// This option is equivalent to binding the child process - /// output to `/dev/null`. - public static var discard: Self { - return .init(method: .discarded) - } - /// Subprocess should write the child process output - /// to the file descriptor specified. - /// - Parameters: - /// - fd: the file descriptor to write to - /// - closeAfterSpawningProcess: whether to close the - /// file descriptor once the process is spawned. - public static func writeTo(_ fd: FileDescriptor, closeAfterSpawningProcess: Bool) -> Self { - return .init(method: .fileDescriptor(fd, closeAfterSpawningProcess)) - } - /// Subprocess should collect the child process output - /// as `Data` with the given limit in bytes. The default - /// limit is 128kb. - public static func collect(upTo limit: Int = 128 * 1024) -> Self { - return .init(method: .collected(limit)) - } - - internal func createExecutionOutput() throws -> ExecutionOutput { - switch self.method { - case .discarded: - // Bind to /dev/null - let devnull: FileDescriptor = try .openDevNull(withAcessMode: .writeOnly) - return .init(storage: .discarded(devnull)) - case .fileDescriptor(let fileDescriptor, let closeWhenDone): - return .init(storage: .fileDescriptor(fileDescriptor, closeWhenDone)) - case .collected(let limit): - let (readFd, writeFd) = try FileDescriptor.pipe() - return .init(storage: .collected(limit, readFd, writeFd)) - } - } - } - - /// `CollectedOutputMethod` defines how should Subprocess redirect - /// output from child process' standard output and standard error. - public struct RedirectedOutputMethod: Sendable, Hashable { - typealias Storage = CollectedOutputMethod.Storage - - internal let method: Storage - - internal init(method: Storage) { - self.method = method - } - - /// Subprocess shold dicard the child process output. - /// This option is equivalent to binding the child process - /// output to `/dev/null`. - public static var discard: Self { - return .init(method: .discarded) - } - /// Subprocess should redirect the child process output - /// to `Subprocess.standardOutput` or `Subprocess.standardError` - /// so they can be consumed as an AsyncSequence - public static var redirectToSequence: Self { - return .init(method: .collected(128 * 1024)) - } - /// Subprocess shold write the child process output - /// to the file descriptor specified. - /// - Parameters: - /// - fd: the file descriptor to write to - /// - closeAfterSpawningProcess: whether to close the - /// file descriptor once the process is spawned. - public static func writeTo( - _ fd: FileDescriptor, - closeAfterSpawningProcess: Bool - ) -> Self { - return .init(method: .fileDescriptor(fd, closeAfterSpawningProcess)) - } - - internal func createExecutionOutput() throws -> ExecutionOutput { - switch self.method { - case .discarded: - // Bind to /dev/null - let devnull: FileDescriptor = try .openDevNull(withAcessMode: .writeOnly) - return .init(storage: .discarded(devnull)) - case .fileDescriptor(let fileDescriptor, let closeWhenDone): - return .init(storage: .fileDescriptor(fileDescriptor, closeWhenDone)) - case .collected(let limit): - let (readFd, writeFd) = try FileDescriptor.pipe() - return .init(storage: .collected(limit, readFd, writeFd)) - } - } - } -} - -// MARK: - Execution IO -extension Subprocess { - internal final class ExecutionInput: Sendable, Hashable { - - - internal enum Storage: Sendable, Hashable { - case noInput(FileDescriptor?) - case customWrite(FileDescriptor?, FileDescriptor?) - case fileDescriptor(FileDescriptor?, Bool) - } - - let storage: _Mutex - - internal init(storage: Storage) { - self.storage = .init(storage) - } - - internal func getReadFileDescriptor() -> FileDescriptor? { - return self.storage.withLock { - switch $0 { - case .noInput(let readFd): - return readFd - case .customWrite(let readFd, _): - return readFd - case .fileDescriptor(let readFd, _): - return readFd - } - } - } - - internal func getWriteFileDescriptor() -> FileDescriptor? { - return self.storage.withLock { - switch $0 { - case .noInput(_), .fileDescriptor(_, _): - return nil - case .customWrite(_, let writeFd): - return writeFd - } - } - } - - internal func closeChildSide() throws { - try self.storage.withLock { - switch $0 { - case .noInput(let devnull): - try devnull?.close() - $0 = .noInput(nil) - case .customWrite(let readFd, let writeFd): - try readFd?.close() - $0 = .customWrite(nil, writeFd) - case .fileDescriptor(let fd, let closeWhenDone): - // User passed in fd - if closeWhenDone { - try fd?.close() - $0 = .fileDescriptor(nil, closeWhenDone) - } - } - } - } - - internal func closeParentSide() throws { - try self.storage.withLock { - switch $0 { - case .noInput(_), .fileDescriptor(_, _): - break - case .customWrite(let readFd, let writeFd): - // The parent fd should have been closed - // in the `body` when writer.finish() is called - // But in case it isn't call it agian - try writeFd?.close() - $0 = .customWrite(readFd, nil) - } - } - } - - internal func closeAll() throws { - try self.storage.withLock { - switch $0 { - case .noInput(let readFd): - try readFd?.close() - $0 = .noInput(nil) - case .customWrite(let readFd, let writeFd): - var readFdCloseError: Error? - var writeFdCloseError: Error? - do { - try readFd?.close() - } catch { - readFdCloseError = error - } - do { - try writeFd?.close() - } catch { - writeFdCloseError = error - } - $0 = .customWrite(nil, nil) - if let readFdCloseError { - throw readFdCloseError - } - if let writeFdCloseError { - throw writeFdCloseError - } - case .fileDescriptor(let fd, let closeWhenDone): - if closeWhenDone { - try fd?.close() - $0 = .fileDescriptor(nil, closeWhenDone) - } - } - } - } - - public func hash(into hasher: inout Hasher) { - self.storage.withLock { - hasher.combine($0) - } - } - - public static func == ( - lhs: Subprocess.ExecutionInput, - rhs: Subprocess.ExecutionInput - ) -> Bool { - return lhs.storage.withLock { lhsStorage in - rhs.storage.withLock { rhsStorage in - return lhsStorage == rhsStorage - } - } - } - } - - internal final class ExecutionOutput: Sendable { - internal enum Storage: Sendable { - case discarded(FileDescriptor?) - case fileDescriptor(FileDescriptor?, Bool) - case collected(Int, FileDescriptor?, FileDescriptor?) - } - - private let storage: _Mutex - - internal init(storage: Storage) { - self.storage = .init(storage) - } - - internal func getWriteFileDescriptor() -> FileDescriptor? { - return self.storage.withLock { - switch $0 { - case .discarded(let writeFd): - return writeFd - case .fileDescriptor(let writeFd, _): - return writeFd - case .collected(_, _, let writeFd): - return writeFd - } - } - } - - internal func getReadFileDescriptor() -> FileDescriptor? { - return self.storage.withLock { - switch $0 { - case .discarded(_), .fileDescriptor(_, _): - return nil - case .collected(_, let readFd, _): - return readFd - } - } - } - - internal func consumeCollectedFileDescriptor() -> (limit: Int, fd: FileDescriptor?)? { - return self.storage.withLock { - switch $0 { - case .discarded(_), .fileDescriptor(_, _): - // The output has been written somewhere else - return nil - case .collected(let limit, let readFd, let writeFd): - $0 = .collected(limit, nil, writeFd) - return (limit, readFd) - } - } - } - - internal func closeChildSide() throws { - try self.storage.withLock { - switch $0 { - case .discarded(let writeFd): - try writeFd?.close() - $0 = .discarded(nil) - case .fileDescriptor(let fd, let closeWhenDone): - // User passed fd - if closeWhenDone { - try fd?.close() - $0 = .fileDescriptor(nil, closeWhenDone) - } - case .collected(let limit, let readFd, let writeFd): - try writeFd?.close() - $0 = .collected(limit, readFd, nil) - } - } - } - - internal func closeParentSide() throws { - try self.storage.withLock { - switch $0 { - case .discarded(_), .fileDescriptor(_, _): - break - case .collected(let limit, let readFd, let writeFd): - try readFd?.close() - $0 = .collected(limit, nil, writeFd) - } - } - } - - internal func closeAll() throws { - try self.storage.withLock { - switch $0 { - case .discarded(let writeFd): - try writeFd?.close() - $0 = .discarded(nil) - case .fileDescriptor(let fd, let closeWhenDone): - if closeWhenDone { - try fd?.close() - $0 = .fileDescriptor(nil, closeWhenDone) - } - case .collected(let limit, let readFd, let writeFd): - var readFdCloseError: Error? - var writeFdCloseError: Error? - do { - try readFd?.close() - } catch { - readFdCloseError = error - } - do { - try writeFd?.close() - } catch { - writeFdCloseError = error - } - $0 = .collected(limit, nil, nil) - if let readFdCloseError { - throw readFdCloseError - } - if let writeFdCloseError { - throw writeFdCloseError - } - } - } - } - } -} - diff --git a/Sources/_Subprocess/Subprocess+Teardown.swift b/Sources/_Subprocess/Subprocess+Teardown.swift deleted file mode 100644 index 8b9af32d..00000000 --- a/Sources/_Subprocess/Subprocess+Teardown.swift +++ /dev/null @@ -1,125 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of Swift.org project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -#if canImport(Darwin) || canImport(Glibc) - -#if canImport(Darwin) -import Darwin -#elseif canImport(Glibc) -import Glibc -#endif - -#if canImport(FoundationEssentials) -import FoundationEssentials -#elseif canImport(Foundation) -import Foundation -#endif - -extension Subprocess { - /// A step in the graceful shutdown teardown sequence. - /// It consists of a signal to send to the child process and the - /// number of nanoseconds allowed for the child process to exit - /// before proceeding to the next step. - public struct TeardownStep: Sendable, Hashable { - internal enum Storage: Sendable, Hashable { - case sendSignal(Signal, allowedNanoseconds: UInt64) - case kill - } - var storage: Storage - - /// Sends `signal` to the process and provides `allowedNanoSecondsToExit` - /// nanoseconds for the process to exit before proceeding to the next step. - /// The final step in the sequence will always send a `.kill` signal. - public static func sendSignal( - _ signal: Signal, - allowedNanoSecondsToExit: UInt64 - ) -> Self { - return Self( - storage: .sendSignal( - signal, - allowedNanoseconds: allowedNanoSecondsToExit - ) - ) - } - } -} - -extension Subprocess { - internal func runTeardownSequence(_ sequence: [TeardownStep]) async { - // First insert the `.kill` step - let finalSequence = sequence + [TeardownStep(storage: .kill)] - for step in finalSequence { - enum TeardownStepCompletion { - case processHasExited - case processStillAlive - case killedTheProcess - } - let stepCompletion: TeardownStepCompletion - - guard self.isAlive() else { - return - } - - switch step.storage { - case .sendSignal(let signal, let allowedNanoseconds): - stepCompletion = await withTaskGroup(of: TeardownStepCompletion.self) { group in - group.addTask { - do { - try await Task.sleep(nanoseconds: allowedNanoseconds) - return .processStillAlive - } catch { - // teardown(using:) cancells this task - // when process has exited - return .processHasExited - } - } - try? self.send(signal, toProcessGroup: false) - return await group.next()! - } - case .kill: - try? self.send(.kill, toProcessGroup: false) - stepCompletion = .killedTheProcess - } - - switch stepCompletion { - case .killedTheProcess, .processHasExited: - return - case .processStillAlive: - // Continue to next step - break - } - } - } -} - -extension Subprocess { - private func isAlive() -> Bool { - return kill(self.processIdentifier.value, 0) == 0 - } -} - -func withUncancelledTask( - returning: R.Type = R.self, - _ body: @Sendable @escaping () async -> R -) async -> R { - // This looks unstructured but it isn't, please note that we `await` `.value` of this task. - // The reason we need this separate `Task` is that in general, we cannot assume that code performs to our - // expectations if the task we run it on is already cancelled. However, in some cases we need the code to - // run regardless -- even if our task is already cancelled. Therefore, we create a new, uncancelled task here. - await Task { - await body() - }.value -} - -#endif // canImport(Darwin) || canImport(Glibc) diff --git a/Sources/_Subprocess/Subprocess.swift b/Sources/_Subprocess/Subprocess.swift deleted file mode 100644 index 35f4a2c2..00000000 --- a/Sources/_Subprocess/Subprocess.swift +++ /dev/null @@ -1,315 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of Swift.org project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -import SystemPackage - -#if canImport(FoundationEssentials) -import FoundationEssentials -#elseif canImport(Foundation) -import Foundation -#endif - -/// An object that represents a subprocess of the current process. -/// -/// Using `Subprocess`, your program can run another program as a subprocess -/// and can monitor that program’s execution. A `Subprocess` object creates a -/// **separate executable** entity; it’s different from `Thread` because it doesn’t -/// share memory space with the process that creates it. -public struct Subprocess: Sendable { - /// The process identifier of the current subprocess - public let processIdentifier: ProcessIdentifier - - internal let executionInput: ExecutionInput - internal let executionOutput: ExecutionOutput - internal let executionError: ExecutionOutput -#if os(Windows) - internal let consoleBehavior: PlatformOptions.ConsoleBehavior -#endif - - /// The standard output of the subprocess. - /// Accessing this property will **fatalError** if - /// - `.output` wasn't set to `.redirectToSequence` when the subprocess was spawned; - /// - This property was accessed multiple times. Subprocess communicates with - /// parent process via pipe under the hood and each pipe can only be consumed ones. - public var standardOutput: some _AsyncSequence { - guard let (_, fd) = self.executionOutput - .consumeCollectedFileDescriptor() else { - fatalError("The standard output was not redirected") - } - guard let fd = fd else { - fatalError("The standard output has already been closed") - } - return AsyncDataSequence(fileDescriptor: fd) - } - - /// The standard error of the subprocess. - /// Accessing this property will **fatalError** if - /// - `.error` wasn't set to `.redirectToSequence` when the subprocess was spawned; - /// - This property was accessed multiple times. Subprocess communicates with - /// parent process via pipe under the hood and each pipe can only be consumed ones. - public var standardError: some _AsyncSequence { - guard let (_, fd) = self.executionError - .consumeCollectedFileDescriptor() else { - fatalError("The standard error was not redirected") - } - guard let fd = fd else { - fatalError("The standard error has already been closed") - } - return AsyncDataSequence(fileDescriptor: fd) - } -} - -// MARK: - Teardown -#if canImport(Darwin) || canImport(Glibc) -extension Subprocess { - /// Performs a sequence of teardown steps on the Subprocess. - /// Teardown sequence always ends with a `.kill` signal - /// - Parameter sequence: The steps to perform. - public func teardown(using sequence: [TeardownStep]) async { - await withUncancelledTask { - await self.runTeardownSequence(sequence) - } - } -} -#endif - -// MARK: - StandardInputWriter -extension Subprocess { - /// A writer that writes to the standard input of the subprocess. - public struct StandardInputWriter { - - private let input: ExecutionInput - - init(input: ExecutionInput) { - self.input = input - } - - /// Write a sequence of UInt8 to the standard input of the subprocess. - /// - Parameter sequence: The sequence of bytes to write. - public func write(_ sequence: S) async throws where S : Sequence, S.Element == UInt8 { - guard let fd: FileDescriptor = self.input.getWriteFileDescriptor() else { - fatalError("Attempting to write to a file descriptor that's already closed") - } - try await fd.write(sequence) - } - - /// Write a sequence of CChar to the standard input of the subprocess. - /// - Parameter sequence: The sequence of bytes to write. - public func write(_ sequence: S) async throws where S : Sequence, S.Element == CChar { - try await self.write(sequence.map { UInt8($0) }) - } - - /// Write a AsyncSequence of CChar to the standard input of the subprocess. - /// - Parameter sequence: The sequence of bytes to write. - public func write(_ asyncSequence: S) async throws where S.Element == CChar { - let sequence = try await Array(asyncSequence).map { UInt8($0) } - try await self.write(sequence) - } - - /// Write a AsyncSequence of UInt8 to the standard input of the subprocess. - /// - Parameter sequence: The sequence of bytes to write. - public func write(_ asyncSequence: S) async throws where S.Element == UInt8 { - let sequence = try await Array(asyncSequence) - try await self.write(sequence) - } - - /// Signal all writes are finished - public func finish() async throws { - try self.input.closeParentSide() - } - } -} - -@available(macOS, unavailable) -@available(iOS, unavailable) -@available(tvOS, unavailable) -@available(watchOS, unavailable) -@available(*, unavailable) -extension Subprocess.StandardInputWriter : Sendable {} - -// MARK: - Result -extension Subprocess { - /// A simple wrapper around the generic result returned by the - /// `run` closures with the corresponding `TerminationStatus` - /// of the child process. - public struct ExecutionResult: Sendable { - /// The termination status of the child process - public let terminationStatus: TerminationStatus - /// The result returned by the closure passed to `.run` methods - public let value: T - - internal init(terminationStatus: TerminationStatus, value: T) { - self.terminationStatus = terminationStatus - self.value = value - } - } - - /// The result of a subprocess execution with its collected - /// standard output and standard error. - public struct CollectedResult: Sendable, Hashable, Codable { - /// The process identifier for the executed subprocess - public let processIdentifier: ProcessIdentifier - /// The termination status of the executed subprocess - public let terminationStatus: TerminationStatus - private let _standardOutput: Data? - private let _standardError: Data? - - /// The collected standard output value for the subprocess. - /// Accessing this property will *fatalError* if the - /// corresponding `CollectedOutputMethod` is not set to - /// `.collect` or `.collect(upTo:)` - public var standardOutput: Data { - guard let output = self._standardOutput else { - fatalError("standardOutput is only available if the Subprocess was ran with .collect as output") - } - return output - } - /// The collected standard error value for the subprocess. - /// Accessing this property will *fatalError* if the - /// corresponding `CollectedOutputMethod` is not set to - /// `.collect` or `.collect(upTo:)` - public var standardError: Data { - guard let output = self._standardError else { - fatalError("standardError is only available if the Subprocess was ran with .collect as error ") - } - return output - } - - internal init( - processIdentifier: ProcessIdentifier, - terminationStatus: TerminationStatus, - standardOutput: Data?, - standardError: Data?) { - self.processIdentifier = processIdentifier - self.terminationStatus = terminationStatus - self._standardOutput = standardOutput - self._standardError = standardError - } - } -} - -extension Subprocess.ExecutionResult: Equatable where T : Equatable {} - -extension Subprocess.ExecutionResult: Hashable where T : Hashable {} - -extension Subprocess.ExecutionResult: Codable where T : Codable {} - -extension Subprocess.ExecutionResult: CustomStringConvertible where T : CustomStringConvertible { - public var description: String { - return """ -Subprocess.ExecutionResult( - terminationStatus: \(self.terminationStatus.description), - value: \(self.value.description) -) -""" - } -} - -extension Subprocess.ExecutionResult: CustomDebugStringConvertible where T : CustomDebugStringConvertible { - public var debugDescription: String { - return """ -Subprocess.ExecutionResult( - terminationStatus: \(self.terminationStatus.debugDescription), - value: \(self.value.debugDescription) -) -""" - } -} - -extension Subprocess.CollectedResult : CustomStringConvertible, CustomDebugStringConvertible { - public var description: String { - return """ -Subprocess.CollectedResult( - processIdentifier: \(self.processIdentifier.description), - terminationStatus: \(self.terminationStatus.description), - standardOutput: \(self._standardOutput?.description ?? "not captured"), - standardError: \(self._standardError?.description ?? "not captured") -) -""" - } - - public var debugDescription: String { - return """ -Subprocess.CollectedResult( - processIdentifier: \(self.processIdentifier.debugDescription), - terminationStatus: \(self.terminationStatus.debugDescription), - standardOutput: \(self._standardOutput?.debugDescription ?? "not captured"), - standardError: \(self._standardError?.debugDescription ?? "not captured") -) -""" - } -} - -// MARK: - Internal -extension Subprocess { - internal enum OutputCapturingState { - case standardOutputCaptured(Data?) - case standardErrorCaptured(Data?) - } - - internal typealias CapturedIOs = (standardOutput: Data?, standardError: Data?) - - private func capture(fileDescriptor: FileDescriptor, maxLength: Int) async throws -> Data { - return try await fileDescriptor.readUntilEOF(upToLength: maxLength) - } - - internal func captureStandardOutput() async throws -> Data? { - guard let (limit, readFd) = self.executionOutput - .consumeCollectedFileDescriptor(), - let readFd = readFd else { - return nil - } - defer { - try? readFd.close() - } - return try await self.capture(fileDescriptor: readFd, maxLength: limit) - } - - internal func captureStandardError() async throws -> Data? { - guard let (limit, readFd) = self.executionError - .consumeCollectedFileDescriptor(), - let readFd = readFd else { - return nil - } - defer { - try? readFd.close() - } - return try await self.capture(fileDescriptor: readFd, maxLength: limit) - } - - internal func captureIOs() async throws -> CapturedIOs { - return try await withThrowingTaskGroup(of: OutputCapturingState.self) { group in - group.addTask { - let stdout = try await self.captureStandardOutput() - return .standardOutputCaptured(stdout) - } - group.addTask { - let stderr = try await self.captureStandardError() - return .standardErrorCaptured(stderr) - } - - var stdout: Data? - var stderror: Data? - while let state = try await group.next() { - switch state { - case .standardOutputCaptured(let output): - stdout = output - case .standardErrorCaptured(let error): - stderror = error - } - } - return (standardOutput: stdout, standardError: stderror) - } - } -} diff --git a/Sources/_Subprocess/SubprocessFoundation/Input+Foundation.swift b/Sources/_Subprocess/SubprocessFoundation/Input+Foundation.swift new file mode 100644 index 00000000..3ec42173 --- /dev/null +++ b/Sources/_Subprocess/SubprocessFoundation/Input+Foundation.swift @@ -0,0 +1,179 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// +//===----------------------------------------------------------------------===// + +#if SubprocessFoundation + +#if canImport(Darwin) +// On Darwin always prefer system Foundation +import Foundation +#else +// On other platforms prefer FoundationEssentials +import FoundationEssentials +#endif // canImport(Darwin) + +#if canImport(System) +import System +#else +@preconcurrency import SystemPackage +#endif + +internal import Dispatch + +/// A concrete `Input` type for subprocesses that reads input +/// from a given `Data`. +public struct DataInput: InputProtocol { + private let data: Data + + public func write(with writer: StandardInputWriter) async throws { + _ = try await writer.write(self.data) + } + + internal init(data: Data) { + self.data = data + } +} + +/// A concrete `Input` type for subprocesses that accepts input +/// from a specified sequence of `Data`. +public struct DataSequenceInput< + InputSequence: Sequence & Sendable +>: InputProtocol where InputSequence.Element == Data { + private let sequence: InputSequence + + public func write(with writer: StandardInputWriter) async throws { + var buffer = Data() + for chunk in self.sequence { + buffer.append(chunk) + } + _ = try await writer.write(buffer) + } + + internal init(underlying: InputSequence) { + self.sequence = underlying + } +} + +/// A concrete `Input` type for subprocesses that reads input +/// from a given async sequence of `Data`. +public struct DataAsyncSequenceInput< + InputSequence: AsyncSequence & Sendable +>: InputProtocol where InputSequence.Element == Data { + private let sequence: InputSequence + + private func writeChunk(_ chunk: Data, with writer: StandardInputWriter) async throws { + _ = try await writer.write(chunk) + } + + public func write(with writer: StandardInputWriter) async throws { + for try await chunk in self.sequence { + try await self.writeChunk(chunk, with: writer) + } + } + + internal init(underlying: InputSequence) { + self.sequence = underlying + } +} + +extension InputProtocol { + /// Create a Subprocess input from a `Data` + public static func data(_ data: Data) -> Self where Self == DataInput { + return DataInput(data: data) + } + + /// Create a Subprocess input from a `Sequence` of `Data`. + public static func sequence( + _ sequence: InputSequence + ) -> Self where Self == DataSequenceInput { + return .init(underlying: sequence) + } + + /// Create a Subprocess input from a `AsyncSequence` of `Data`. + public static func sequence( + _ asyncSequence: InputSequence + ) -> Self where Self == DataAsyncSequenceInput { + return .init(underlying: asyncSequence) + } +} + +extension StandardInputWriter { + /// Write a `Data` to the standard input of the subprocess. + /// - Parameter data: The sequence of bytes to write. + /// - Returns number of bytes written. + public func write( + _ data: Data + ) async throws -> Int { + return try await self.fileDescriptor.wrapped.write(data) + } + + /// Write a AsyncSequence of Data to the standard input of the subprocess. + /// - Parameter sequence: The sequence of bytes to write. + /// - Returns number of bytes written. + public func write( + _ asyncSequence: AsyncSendableSequence + ) async throws -> Int where AsyncSendableSequence.Element == Data { + var buffer = Data() + for try await data in asyncSequence { + buffer.append(data) + } + return try await self.write(buffer) + } +} + +extension FileDescriptor { + #if os(Windows) + internal func write( + _ data: Data + ) async throws -> Int { + try await withCheckedThrowingContinuation { continuation in + // TODO: Figure out a better way to asynchornously write + DispatchQueue.global(qos: .userInitiated).async { + data.withUnsafeBytes { + self.write($0) { writtenLength, error in + if let error = error { + continuation.resume(throwing: error) + } else { + continuation.resume(returning: writtenLength) + } + } + } + } + } + } + #else + internal func write( + _ data: Data + ) async throws -> Int { + try await withCheckedThrowingContinuation { (continuation: CheckedContinuation) in + let dispatchData = data.withUnsafeBytes { + return DispatchData( + bytesNoCopy: $0, + deallocator: .custom( + nil, + { + // noop + } + ) + ) + } + self.write(dispatchData) { writtenLength, error in + if let error = error { + continuation.resume(throwing: error) + } else { + continuation.resume(returning: writtenLength) + } + } + } + } + #endif +} + +#endif // SubprocessFoundation diff --git a/Sources/_Subprocess/SubprocessFoundation/Output+Foundation.swift b/Sources/_Subprocess/SubprocessFoundation/Output+Foundation.swift new file mode 100644 index 00000000..fac0bb8f --- /dev/null +++ b/Sources/_Subprocess/SubprocessFoundation/Output+Foundation.swift @@ -0,0 +1,53 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// +//===----------------------------------------------------------------------===// + +#if SubprocessFoundation + +#if canImport(Darwin) +// On Darwin always prefer system Foundation +import Foundation +#else +// On other platforms prefer FoundationEssentials +import FoundationEssentials +#endif + +/// A concrete `Output` type for subprocesses that collects output +/// from the subprocess as `Data`. This option must be used with +/// the `run()` method that returns a `CollectedResult` +public struct DataOutput: OutputProtocol { + public typealias OutputType = Data + public let maxSize: Int + + public func output(from buffer: some Sequence) throws -> Data { + return Data(buffer) + } + + internal init(limit: Int) { + self.maxSize = limit + } +} + +extension OutputProtocol where Self == DataOutput { + /// Create a `Subprocess` output that collects output as `Data` + /// up to 128kb. + public static var data: Self { + return .data(limit: 128 * 1024) + } + + /// Create a `Subprocess` output that collects output as `Data` + /// with given max number of bytes to collect. + public static func data(limit: Int) -> Self { + return .init(limit: limit) + } +} + + +#endif // SubprocessFoundation diff --git a/Sources/_Subprocess/SubprocessFoundation/Span+SubprocessFoundation.swift b/Sources/_Subprocess/SubprocessFoundation/Span+SubprocessFoundation.swift new file mode 100644 index 00000000..10697091 --- /dev/null +++ b/Sources/_Subprocess/SubprocessFoundation/Span+SubprocessFoundation.swift @@ -0,0 +1,76 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// +//===----------------------------------------------------------------------===// + +#if SubprocessFoundation && SubprocessSpan + +#if canImport(Darwin) +// On Darwin always prefer system Foundation +import Foundation +#else +// On other platforms prefer FoundationEssentials +import FoundationEssentials +#endif // canImport(Darwin) + +internal import Dispatch + + +extension Data { + init(_ s: borrowing RawSpan) { + self = s.withUnsafeBytes { Data($0) } + } + + public var bytes: RawSpan { + // FIXME: For demo purpose only + let ptr = self.withUnsafeBytes { ptr in + return ptr + } + let span = RawSpan(_unsafeBytes: ptr) + return _overrideLifetime(of: span, to: self) + } +} + + +extension DataProtocol { + var bytes: RawSpan { + _read { + if self.regions.isEmpty { + let empty = UnsafeRawBufferPointer(start: nil, count: 0) + let span = RawSpan(_unsafeBytes: empty) + yield _overrideLifetime(of: span, to: self) + } else if self.regions.count == 1 { + // Easy case: there is only one region in the data + let ptr = self.regions.first!.withUnsafeBytes { ptr in + return ptr + } + let span = RawSpan(_unsafeBytes: ptr) + yield _overrideLifetime(of: span, to: self) + } else { + // This data contains discontiguous chunks. We have to + // copy and make a contiguous chunk + var contiguous: ContiguousArray? + for region in self.regions { + if contiguous != nil { + contiguous?.append(contentsOf: region) + } else { + contiguous = .init(region) + } + } + let ptr = contiguous!.withUnsafeBytes { ptr in + return ptr + } + let span = RawSpan(_unsafeBytes: ptr) + yield _overrideLifetime(of: span, to: self) + } + } + } +} + +#endif // SubprocessFoundation diff --git a/Sources/_Subprocess/Teardown.swift b/Sources/_Subprocess/Teardown.swift new file mode 100644 index 00000000..b2da85a5 --- /dev/null +++ b/Sources/_Subprocess/Teardown.swift @@ -0,0 +1,217 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// +//===----------------------------------------------------------------------===// + +import _SubprocessCShims + +#if canImport(Darwin) +import Darwin +#elseif canImport(Bionic) +import Bionic +#elseif canImport(Glibc) +import Glibc +#elseif canImport(Musl) +import Musl +#elseif canImport(WinSDK) +import WinSDK +#endif + +/// A step in the graceful shutdown teardown sequence. +/// It consists of an action to perform on the child process and the +/// duration allowed for the child process to exit before proceeding +/// to the next step. +public struct TeardownStep: Sendable, Hashable { + internal enum Storage: Sendable, Hashable { + #if !os(Windows) + case sendSignal(Signal, allowedDuration: Duration) + #endif + case gracefulShutDown(allowedDuration: Duration) + case kill + } + var storage: Storage + + #if !os(Windows) + /// Sends `signal` to the process and allows `allowedDurationToExit` + /// for the process to exit before proceeding to the next step. + /// The final step in the sequence will always send a `.kill` signal. + public static func send( + signal: Signal, + allowedDurationToNextStep: Duration + ) -> Self { + return Self( + storage: .sendSignal( + signal, + allowedDuration: allowedDurationToNextStep + ) + ) + } + #endif // !os(Windows) + + /// Attempt to perform a graceful shutdown and allows + /// `allowedDurationToNextStep` for the process to exit + /// before proceeding to the next step: + /// - On Unix: send `SIGTERM` + /// - On Windows: + /// 1. Attempt to send `VM_CLOSE` if the child process is a GUI process; + /// 2. Attempt to send `CTRL_C_EVENT` to console; + /// 3. Attempt to send `CTRL_BREAK_EVENT` to process group. + public static func gracefulShutDown( + allowedDurationToNextStep: Duration + ) -> Self { + return Self( + storage: .gracefulShutDown( + allowedDuration: allowedDurationToNextStep + ) + ) + } +} + +@available(macOS 15.0, *) // FIXME: manually added availability +extension Execution { + /// Performs a sequence of teardown steps on the Subprocess. + /// Teardown sequence always ends with a `.kill` signal + /// - Parameter sequence: The steps to perform. + public func teardown(using sequence: some Sequence & Sendable) async { + await withUncancelledTask { + await self.runTeardownSequence(sequence) + } + } +} + +internal enum TeardownStepCompletion { + case processHasExited + case processStillAlive + case killedTheProcess +} + +@available(macOS 15.0, *) // FIXME: manually added availability +extension Execution { + internal func gracefulShutDown( + allowedDurationToNextStep duration: Duration + ) async { + #if os(Windows) + guard + let processHandle = OpenProcess( + DWORD(PROCESS_QUERY_INFORMATION | SYNCHRONIZE), + false, + self.processIdentifier.value + ) + else { + // Nothing more we can do + return + } + defer { + CloseHandle(processHandle) + } + + // 1. Attempt to send WM_CLOSE to the main window + if _subprocess_windows_send_vm_close( + self.processIdentifier.value + ) { + try? await Task.sleep(for: duration) + } + + // 2. Attempt to attach to the console and send CTRL_C_EVENT + if AttachConsole(self.processIdentifier.value) { + // Disable Ctrl-C handling in this process + if SetConsoleCtrlHandler(nil, true) { + if GenerateConsoleCtrlEvent(DWORD(CTRL_C_EVENT), 0) { + // We successfully sent the event. wait for the process to exit + try? await Task.sleep(for: duration) + } + // Re-enable Ctrl-C handling + SetConsoleCtrlHandler(nil, false) + } + // Detach console + FreeConsole() + } + + // 3. Attempt to send CTRL_BREAK_EVENT to the process group + if GenerateConsoleCtrlEvent(DWORD(CTRL_BREAK_EVENT), self.processIdentifier.value) { + // Wait for process to exit + try? await Task.sleep(for: duration) + } + #else + // Send SIGTERM + try? self.send(signal: .terminate) + #endif + } + + internal func runTeardownSequence(_ sequence: some Sequence & Sendable) async { + // First insert the `.kill` step + let finalSequence = sequence + [TeardownStep(storage: .kill)] + for step in finalSequence { + let stepCompletion: TeardownStepCompletion + + switch step.storage { + case .gracefulShutDown(let allowedDuration): + stepCompletion = await withTaskGroup(of: TeardownStepCompletion.self) { group in + group.addTask { + do { + try await Task.sleep(for: allowedDuration) + return .processStillAlive + } catch { + // teardown(using:) cancells this task + // when process has exited + return .processHasExited + } + } + await self.gracefulShutDown(allowedDurationToNextStep: allowedDuration) + return await group.next()! + } + #if !os(Windows) + case .sendSignal(let signal, let allowedDuration): + stepCompletion = await withTaskGroup(of: TeardownStepCompletion.self) { group in + group.addTask { + do { + try await Task.sleep(for: allowedDuration) + return .processStillAlive + } catch { + // teardown(using:) cancells this task + // when process has exited + return .processHasExited + } + } + try? self.send(signal: signal) + return await group.next()! + } + #endif // !os(Windows) + case .kill: + #if os(Windows) + try? self.terminate(withExitCode: 0) + #else + try? self.send(signal: .kill) + #endif + stepCompletion = .killedTheProcess + } + + switch stepCompletion { + case .killedTheProcess, .processHasExited: + return + case .processStillAlive: + // Continue to next step + break + } + } + } +} + +func withUncancelledTask( + returning: Result.Type = Result.self, + _ body: @Sendable @escaping () async -> Result +) async -> Result { + // This looks unstructured but it isn't, please note that we `await` `.value` of this task. + // The reason we need this separate `Task` is that in general, we cannot assume that code performs to our + // expectations if the task we run it on is already cancelled. However, in some cases we need the code to + // run regardless -- even if our task is already cancelled. Therefore, we create a new, uncancelled task here. + await Task { + await body() + }.value +} diff --git a/Sources/_Subprocess/_nio_locks.swift b/Sources/_Subprocess/_nio_locks.swift deleted file mode 100644 index 49053d04..00000000 --- a/Sources/_Subprocess/_nio_locks.swift +++ /dev/null @@ -1,526 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the SwiftNIO open source project -// -// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of SwiftNIO project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -#if canImport(Darwin) -import Darwin -#elseif os(Windows) -import ucrt -import WinSDK -#elseif canImport(Glibc) -import Glibc -#elseif canImport(Musl) -import Musl -#else -#error("The concurrency lock module was unable to identify your C library.") -#endif - -/// A threading lock based on `libpthread` instead of `libdispatch`. -/// -/// This object provides a lock on top of a single `pthread_mutex_t`. This kind -/// of lock is safe to use with `libpthread`-based threading models, such as the -/// one used by NIO. On Windows, the lock is based on the substantially similar -/// `SRWLOCK` type. -@available(*, deprecated, renamed: "NIOLock") -public final class Lock { -#if os(Windows) - fileprivate let mutex: UnsafeMutablePointer = - UnsafeMutablePointer.allocate(capacity: 1) -#else - fileprivate let mutex: UnsafeMutablePointer = - UnsafeMutablePointer.allocate(capacity: 1) -#endif - - /// Create a new lock. - public init() { -#if os(Windows) - InitializeSRWLock(self.mutex) -#else - var attr = pthread_mutexattr_t() - pthread_mutexattr_init(&attr) - debugOnly { - pthread_mutexattr_settype(&attr, .init(PTHREAD_MUTEX_ERRORCHECK)) - } - - let err = pthread_mutex_init(self.mutex, &attr) - precondition(err == 0, "\(#function) failed in pthread_mutex with error \(err)") -#endif - } - - deinit { -#if os(Windows) - // SRWLOCK does not need to be free'd -#else - let err = pthread_mutex_destroy(self.mutex) - precondition(err == 0, "\(#function) failed in pthread_mutex with error \(err)") -#endif - mutex.deallocate() - } - - /// Acquire the lock. - /// - /// Whenever possible, consider using `withLock` instead of this method and - /// `unlock`, to simplify lock handling. - public func lock() { -#if os(Windows) - AcquireSRWLockExclusive(self.mutex) -#else - let err = pthread_mutex_lock(self.mutex) - precondition(err == 0, "\(#function) failed in pthread_mutex with error \(err)") -#endif - } - - /// Release the lock. - /// - /// Whenever possible, consider using `withLock` instead of this method and - /// `lock`, to simplify lock handling. - public func unlock() { -#if os(Windows) - ReleaseSRWLockExclusive(self.mutex) -#else - let err = pthread_mutex_unlock(self.mutex) - precondition(err == 0, "\(#function) failed in pthread_mutex with error \(err)") -#endif - } - - /// Acquire the lock for the duration of the given block. - /// - /// This convenience method should be preferred to `lock` and `unlock` in - /// most situations, as it ensures that the lock will be released regardless - /// of how `body` exits. - /// - /// - Parameter body: The block to execute while holding the lock. - /// - Returns: The value returned by the block. - @inlinable - public func withLock(_ body: () throws -> T) rethrows -> T { - self.lock() - defer { - self.unlock() - } - return try body() - } - - // specialise Void return (for performance) - @inlinable - public func withLockVoid(_ body: () throws -> Void) rethrows -> Void { - try self.withLock(body) - } -} - -/// A `Lock` with a built-in state variable. -/// -/// This class provides a convenience addition to `Lock`: it provides the ability to wait -/// until the state variable is set to a specific value to acquire the lock. -public final class ConditionLock { - private var _value: T - private let mutex: NIOLock -#if os(Windows) - private let cond: UnsafeMutablePointer = - UnsafeMutablePointer.allocate(capacity: 1) -#else - private let cond: UnsafeMutablePointer = - UnsafeMutablePointer.allocate(capacity: 1) -#endif - - /// Create the lock, and initialize the state variable to `value`. - /// - /// - Parameter value: The initial value to give the state variable. - public init(value: T) { - self._value = value - self.mutex = NIOLock() -#if os(Windows) - InitializeConditionVariable(self.cond) -#else - let err = pthread_cond_init(self.cond, nil) - precondition(err == 0, "\(#function) failed in pthread_cond with error \(err)") -#endif - } - - deinit { -#if os(Windows) - // condition variables do not need to be explicitly destroyed -#else - let err = pthread_cond_destroy(self.cond) - precondition(err == 0, "\(#function) failed in pthread_cond with error \(err)") -#endif - self.cond.deallocate() - } - - /// Acquire the lock, regardless of the value of the state variable. - public func lock() { - self.mutex.lock() - } - - /// Release the lock, regardless of the value of the state variable. - public func unlock() { - self.mutex.unlock() - } - - /// The value of the state variable. - /// - /// Obtaining the value of the state variable requires acquiring the lock. - /// This means that it is not safe to access this property while holding the - /// lock: it is only safe to use it when not holding it. - public var value: T { - self.lock() - defer { - self.unlock() - } - return self._value - } - - /// Acquire the lock when the state variable is equal to `wantedValue`. - /// - /// - Parameter wantedValue: The value to wait for the state variable - /// to have before acquiring the lock. - public func lock(whenValue wantedValue: T) { - self.lock() - while true { - if self._value == wantedValue { - break - } - self.mutex.withLockPrimitive { mutex in -#if os(Windows) - let result = SleepConditionVariableSRW(self.cond, mutex, INFINITE, 0) - precondition(result, "\(#function) failed in SleepConditionVariableSRW with error \(GetLastError())") -#else - let err = pthread_cond_wait(self.cond, mutex) - precondition(err == 0, "\(#function) failed in pthread_cond with error \(err)") -#endif - } - } - } - - /// Acquire the lock when the state variable is equal to `wantedValue`, - /// waiting no more than `timeoutSeconds` seconds. - /// - /// - Parameter wantedValue: The value to wait for the state variable - /// to have before acquiring the lock. - /// - Parameter timeoutSeconds: The number of seconds to wait to acquire - /// the lock before giving up. - /// - Returns: `true` if the lock was acquired, `false` if the wait timed out. - public func lock(whenValue wantedValue: T, timeoutSeconds: Double) -> Bool { - precondition(timeoutSeconds >= 0) - -#if os(Windows) - var dwMilliseconds: DWORD = DWORD(timeoutSeconds * 1000) - - self.lock() - while true { - if self._value == wantedValue { - return true - } - - let dwWaitStart = timeGetTime() - if !SleepConditionVariableSRW(self.cond, self.mutex._storage.mutex, - dwMilliseconds, 0) { - let dwError = GetLastError() - if (dwError == ERROR_TIMEOUT) { - self.unlock() - return false - } - fatalError("SleepConditionVariableSRW: \(dwError)") - } - - // NOTE: this may be a spurious wakeup, adjust the timeout accordingly - dwMilliseconds = dwMilliseconds - (timeGetTime() - dwWaitStart) - } -#else - let nsecPerSec: Int64 = 1000000000 - self.lock() - /* the timeout as a (seconds, nano seconds) pair */ - let timeoutNS = Int64(timeoutSeconds * Double(nsecPerSec)) - - var curTime = timeval() - gettimeofday(&curTime, nil) - - let allNSecs: Int64 = timeoutNS + Int64(curTime.tv_usec) * 1000 - var timeoutAbs = timespec(tv_sec: curTime.tv_sec + Int((allNSecs / nsecPerSec)), - tv_nsec: Int(allNSecs % nsecPerSec)) - assert(timeoutAbs.tv_nsec >= 0 && timeoutAbs.tv_nsec < Int(nsecPerSec)) - assert(timeoutAbs.tv_sec >= curTime.tv_sec) - return self.mutex.withLockPrimitive { mutex -> Bool in - while true { - if self._value == wantedValue { - return true - } - switch pthread_cond_timedwait(self.cond, mutex, &timeoutAbs) { - case 0: - continue - case ETIMEDOUT: - self.unlock() - return false - case let e: - fatalError("caught error \(e) when calling pthread_cond_timedwait") - } - } - } -#endif - } - - /// Release the lock, setting the state variable to `newValue`. - /// - /// - Parameter newValue: The value to give to the state variable when we - /// release the lock. - public func unlock(withValue newValue: T) { - self._value = newValue - self.unlock() -#if os(Windows) - WakeAllConditionVariable(self.cond) -#else - let err = pthread_cond_broadcast(self.cond) - precondition(err == 0, "\(#function) failed in pthread_cond with error \(err)") -#endif - } -} - -/// A utility function that runs the body code only in debug builds, without -/// emitting compiler warnings. -/// -/// This is currently the only way to do this in Swift: see -/// https://forums.swift.org/t/support-debug-only-code/11037 for a discussion. -@inlinable -internal func debugOnly(_ body: () -> Void) { - assert({ body(); return true }()) -} - -@available(*, deprecated) -extension Lock: @unchecked Sendable {} -extension ConditionLock: @unchecked Sendable {} - -#if os(Windows) -@usableFromInline -typealias LockPrimitive = SRWLOCK -#else -@usableFromInline -typealias LockPrimitive = pthread_mutex_t -#endif - -@usableFromInline -enum LockOperations { } - -extension LockOperations { - @inlinable - static func create(_ mutex: UnsafeMutablePointer) { - mutex.assertValidAlignment() - -#if os(Windows) - InitializeSRWLock(mutex) -#else - var attr = pthread_mutexattr_t() - pthread_mutexattr_init(&attr) - debugOnly { - pthread_mutexattr_settype(&attr, .init(PTHREAD_MUTEX_ERRORCHECK)) - } - - let err = pthread_mutex_init(mutex, &attr) - precondition(err == 0, "\(#function) failed in pthread_mutex with error \(err)") -#endif - } - - @inlinable - static func destroy(_ mutex: UnsafeMutablePointer) { - mutex.assertValidAlignment() - -#if os(Windows) - // SRWLOCK does not need to be free'd -#else - let err = pthread_mutex_destroy(mutex) - precondition(err == 0, "\(#function) failed in pthread_mutex with error \(err)") -#endif - } - - @inlinable - static func lock(_ mutex: UnsafeMutablePointer) { - mutex.assertValidAlignment() - -#if os(Windows) - AcquireSRWLockExclusive(mutex) -#else - let err = pthread_mutex_lock(mutex) - precondition(err == 0, "\(#function) failed in pthread_mutex with error \(err)") -#endif - } - - @inlinable - static func unlock(_ mutex: UnsafeMutablePointer) { - mutex.assertValidAlignment() - -#if os(Windows) - ReleaseSRWLockExclusive(mutex) -#else - let err = pthread_mutex_unlock(mutex) - precondition(err == 0, "\(#function) failed in pthread_mutex with error \(err)") -#endif - } -} - -// Tail allocate both the mutex and a generic value using ManagedBuffer. -// Both the header pointer and the elements pointer are stable for -// the class's entire lifetime. -// -// However, for safety reasons, we elect to place the lock in the "elements" -// section of the buffer instead of the head. The reasoning here is subtle, -// so buckle in. -// -// _As a practical matter_, the implementation of ManagedBuffer ensures that -// the pointer to the header is stable across the lifetime of the class, and so -// each time you call `withUnsafeMutablePointers` or `withUnsafeMutablePointerToHeader` -// the value of the header pointer will be the same. This is because ManagedBuffer uses -// `Builtin.addressOf` to load the value of the header, and that does ~magic~ to ensure -// that it does not invoke any weird Swift accessors that might copy the value. -// -// _However_, the header is also available via the `.header` field on the ManagedBuffer. -// This presents a problem! The reason there's an issue is that `Builtin.addressOf` and friends -// do not interact with Swift's exclusivity model. That is, the various `with` functions do not -// conceptually trigger a mutating access to `.header`. For elements this isn't a concern because -// there's literally no other way to perform the access, but for `.header` it's entirely possible -// to accidentally recursively read it. -// -// Our implementation is free from these issues, so we don't _really_ need to worry about it. -// However, out of an abundance of caution, we store the Value in the header, and the LockPrimitive -// in the trailing elements. We still don't use `.header`, but it's better to be safe than sorry, -// and future maintainers will be happier that we were cautious. -// -// See also: https://github.com/apple/swift/pull/40000 -@usableFromInline -final class LockStorage: ManagedBuffer { - - @inlinable - static func create(value: Value) -> Self { - let buffer = Self.create(minimumCapacity: 1) { _ in - return value - } - let storage = unsafeDowncast(buffer, to: Self.self) - - storage.withUnsafeMutablePointers { _, lockPtr in - LockOperations.create(lockPtr) - } - - return storage - } - - @inlinable - func lock() { - self.withUnsafeMutablePointerToElements { lockPtr in - LockOperations.lock(lockPtr) - } - } - - @inlinable - func unlock() { - self.withUnsafeMutablePointerToElements { lockPtr in - LockOperations.unlock(lockPtr) - } - } - - @inlinable - deinit { - self.withUnsafeMutablePointerToElements { lockPtr in - LockOperations.destroy(lockPtr) - } - } - - @inlinable - func withLockPrimitive(_ body: (UnsafeMutablePointer) throws -> T) rethrows -> T { - try self.withUnsafeMutablePointerToElements { lockPtr in - return try body(lockPtr) - } - } - - @inlinable - func withLockedValue(_ mutate: (inout Value) throws -> T) rethrows -> T { - try self.withUnsafeMutablePointers { valuePtr, lockPtr in - LockOperations.lock(lockPtr) - defer { LockOperations.unlock(lockPtr) } - return try mutate(&valuePtr.pointee) - } - } -} - -extension LockStorage: @unchecked Sendable { } - -/// A threading lock based on `libpthread` instead of `libdispatch`. -/// -/// - note: ``NIOLock`` has reference semantics. -/// -/// This object provides a lock on top of a single `pthread_mutex_t`. This kind -/// of lock is safe to use with `libpthread`-based threading models, such as the -/// one used by NIO. On Windows, the lock is based on the substantially similar -/// `SRWLOCK` type. -public struct NIOLock { - @usableFromInline - internal let _storage: LockStorage - - /// Create a new lock. - @inlinable - public init() { - self._storage = .create(value: ()) - } - - /// Acquire the lock. - /// - /// Whenever possible, consider using `withLock` instead of this method and - /// `unlock`, to simplify lock handling. - @inlinable - public func lock() { - self._storage.lock() - } - - /// Release the lock. - /// - /// Whenever possible, consider using `withLock` instead of this method and - /// `lock`, to simplify lock handling. - @inlinable - public func unlock() { - self._storage.unlock() - } - - @inlinable - internal func withLockPrimitive(_ body: (UnsafeMutablePointer) throws -> T) rethrows -> T { - return try self._storage.withLockPrimitive(body) - } -} - -extension NIOLock { - /// Acquire the lock for the duration of the given block. - /// - /// This convenience method should be preferred to `lock` and `unlock` in - /// most situations, as it ensures that the lock will be released regardless - /// of how `body` exits. - /// - /// - Parameter body: The block to execute while holding the lock. - /// - Returns: The value returned by the block. - @inlinable - public func withLock(_ body: () throws -> T) rethrows -> T { - self.lock() - defer { - self.unlock() - } - return try body() - } - - @inlinable - public func withLockVoid(_ body: () throws -> Void) rethrows -> Void { - try self.withLock(body) - } -} - -extension NIOLock: Sendable {} - -extension UnsafeMutablePointer { - @inlinable - func assertValidAlignment() { - assert(UInt(bitPattern: self) % UInt(MemoryLayout.alignment) == 0) - } -} diff --git a/Sources/_CShims/include/process_shims.h b/Sources/_SubprocessCShims/include/process_shims.h similarity index 74% rename from Sources/_CShims/include/process_shims.h rename to Sources/_SubprocessCShims/include/process_shims.h index 563b517f..35cbd2fe 100644 --- a/Sources/_CShims/include/process_shims.h +++ b/Sources/_SubprocessCShims/include/process_shims.h @@ -2,20 +2,17 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 +// Copyright (c) 2025 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception // -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of Swift.org project authors -// -// SPDX-License-Identifier: Apache-2.0 +// See https://swift.org/LICENSE.txt for license information // //===----------------------------------------------------------------------===// #ifndef process_shims_h #define process_shims_h -#include "_CShimsTargetConditionals.h" +#include "target_conditionals.h" #if !TARGET_OS_WINDOWS #include @@ -24,6 +21,10 @@ #include #endif +#if __has_include() +vm_size_t _subprocess_vm_size(void); +#endif + #if TARGET_OS_MAC int _subprocess_spawn( pid_t * _Nonnull pid, @@ -60,6 +61,10 @@ int _was_process_signaled(int status); int _get_signal_code(int status); int _was_process_suspended(int status); +void _subprocess_lock_environ(void); +void _subprocess_unlock_environ(void); +char * _Nullable * _Nullable _subprocess_get_environ(void); + #if TARGET_OS_LINUX int _shims_snprintf( char * _Nonnull str, @@ -72,4 +77,15 @@ int _shims_snprintf( #endif // !TARGET_OS_WINDOWS +#if TARGET_OS_WINDOWS + +#ifndef _WINDEF_ +typedef unsigned long DWORD; +typedef int BOOL; +#endif + +BOOL _subprocess_windows_send_vm_close(DWORD pid); + +#endif + #endif /* process_shims_h */ diff --git a/Sources/_CShims/include/_CShimsTargetConditionals.h b/Sources/_SubprocessCShims/include/target_conditionals.h similarity index 76% rename from Sources/_CShims/include/_CShimsTargetConditionals.h rename to Sources/_SubprocessCShims/include/target_conditionals.h index 9e1d80cb..fef2eaf2 100644 --- a/Sources/_CShims/include/_CShimsTargetConditionals.h +++ b/Sources/_SubprocessCShims/include/target_conditionals.h @@ -2,13 +2,11 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 +// Copyright (c) 2021 - 2022 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception // -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of Swift.org project authors -// -// SPDX-License-Identifier: Apache-2.0 +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// diff --git a/Sources/_SubprocessCShims/process_shims.c b/Sources/_SubprocessCShims/process_shims.c new file mode 100644 index 00000000..287e1a8d --- /dev/null +++ b/Sources/_SubprocessCShims/process_shims.c @@ -0,0 +1,682 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// +//===----------------------------------------------------------------------===// + +#include "include/target_conditionals.h" + +#if TARGET_OS_LINUX +// For posix_spawn_file_actions_addchdir_np +#define _GNU_SOURCE 1 +#endif + +#include "include/process_shims.h" + +#if TARGET_OS_WINDOWS +#include +#else +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#if __has_include() +#include +#elif defined(_WIN32) +#include +#elif __has_include() +#include +extern char **environ; +#endif + +int _was_process_exited(int status) { + return WIFEXITED(status); +} + +int _get_exit_code(int status) { + return WEXITSTATUS(status); +} + +int _was_process_signaled(int status) { + return WIFSIGNALED(status); +} + +int _get_signal_code(int status) { + return WTERMSIG(status); +} + +int _was_process_suspended(int status) { + return WIFSTOPPED(status); +} + +#if TARGET_OS_LINUX +#include + +int _shims_snprintf( + char * _Nonnull str, + int len, + const char * _Nonnull format, + char * _Nonnull str1, + char * _Nonnull str2 +) { + return snprintf(str, len, format, str1, str2); +} +#endif + +#if __has_include() +vm_size_t _subprocess_vm_size(void) { + // This shim exists because vm_page_size is not marked const, and therefore looks like global mutable state to Swift. + return vm_page_size; +} +#endif + +// MARK: - Darwin (posix_spawn) +#if TARGET_OS_MAC +static int _subprocess_spawn_prefork( + pid_t * _Nonnull pid, + const char * _Nonnull exec_path, + const posix_spawn_file_actions_t _Nullable * _Nonnull file_actions, + const posix_spawnattr_t _Nullable * _Nonnull spawn_attrs, + char * _Nullable const args[_Nonnull], + char * _Nullable const env[_Nullable], + uid_t * _Nullable uid, + gid_t * _Nullable gid, + int number_of_sgroups, const gid_t * _Nullable sgroups, + int create_session +) { + // Set `POSIX_SPAWN_SETEXEC` flag since we are forking ourselves + short flags = 0; + int rc = posix_spawnattr_getflags(spawn_attrs, &flags); + if (rc != 0) { + return rc; + } + + rc = posix_spawnattr_setflags( + (posix_spawnattr_t *)spawn_attrs, flags | POSIX_SPAWN_SETEXEC + ); + if (rc != 0) { + return rc; + } + // Setup pipe to catch exec failures from child + int pipefd[2]; + if (pipe(pipefd) != 0) { + return errno; + } + // Set FD_CLOEXEC so the pipe is automatically closed when exec succeeds + flags = fcntl(pipefd[0], F_GETFD); + if (flags == -1) { + close(pipefd[0]); + close(pipefd[1]); + return errno; + } + flags |= FD_CLOEXEC; + if (fcntl(pipefd[0], F_SETFD, flags) == -1) { + close(pipefd[0]); + close(pipefd[1]); + return errno; + } + + flags = fcntl(pipefd[1], F_GETFD); + if (flags == -1) { + close(pipefd[0]); + close(pipefd[1]); + return errno; + } + flags |= FD_CLOEXEC; + if (fcntl(pipefd[1], F_SETFD, flags) == -1) { + close(pipefd[0]); + close(pipefd[1]); + return errno; + } + + // Finally, fork +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated" + pid_t childPid = fork(); +#pragma GCC diagnostic pop + if (childPid == -1) { + close(pipefd[0]); + close(pipefd[1]); + return errno; + } + + if (childPid == 0) { + // Child process + close(pipefd[0]); // Close unused read end + + // Perform setups + if (number_of_sgroups > 0 && sgroups != NULL) { + if (setgroups(number_of_sgroups, sgroups) != 0) { + int error = errno; + write(pipefd[1], &error, sizeof(error)); + close(pipefd[1]); + _exit(EXIT_FAILURE); + } + } + + if (uid != NULL) { + if (setuid(*uid) != 0) { + int error = errno; + write(pipefd[1], &error, sizeof(error)); + close(pipefd[1]); + _exit(EXIT_FAILURE); + } + } + + if (gid != NULL) { + if (setgid(*gid) != 0) { + int error = errno; + write(pipefd[1], &error, sizeof(error)); + close(pipefd[1]); + _exit(EXIT_FAILURE); + } + } + + if (create_session != 0) { + (void)setsid(); + } + + // Use posix_spawnas exec + int error = posix_spawn(pid, exec_path, file_actions, spawn_attrs, args, env); + // If we reached this point, something went wrong + write(pipefd[1], &error, sizeof(error)); + close(pipefd[1]); + _exit(EXIT_FAILURE); + } else { + // Parent process + close(pipefd[1]); // Close unused write end + // Communicate child pid back + *pid = childPid; + // Read from the pipe until pipe is closed + // Eitehr due to exec succeeds or error is written + int childError = 0; + if (read(pipefd[0], &childError, sizeof(childError)) > 0) { + // We encountered error + close(pipefd[0]); + return childError; + } else { + // Child process exec was successful + close(pipefd[0]); + return 0; + } + } +} + +int _subprocess_spawn( + pid_t * _Nonnull pid, + const char * _Nonnull exec_path, + const posix_spawn_file_actions_t _Nullable * _Nonnull file_actions, + const posix_spawnattr_t _Nullable * _Nonnull spawn_attrs, + char * _Nullable const args[_Nonnull], + char * _Nullable const env[_Nullable], + uid_t * _Nullable uid, + gid_t * _Nullable gid, + int number_of_sgroups, const gid_t * _Nullable sgroups, + int create_session +) { + int require_pre_fork = uid != NULL || + gid != NULL || + number_of_sgroups > 0 || + create_session > 0; + + if (require_pre_fork != 0) { + int rc = _subprocess_spawn_prefork( + pid, + exec_path, + file_actions, spawn_attrs, + args, env, + uid, gid, number_of_sgroups, sgroups, create_session + ); + return rc; + } + + // Spawn + return posix_spawn(pid, exec_path, file_actions, spawn_attrs, args, env); +} + +#endif // TARGET_OS_MAC + +// MARK: - Linux (fork/exec + posix_spawn fallback) +#if TARGET_OS_LINUX + +#if _POSIX_SPAWN +static int _subprocess_is_addchdir_np_available() { +#if defined(__GLIBC__) && !__GLIBC_PREREQ(2, 29) + // Glibc versions prior to 2.29 don't support posix_spawn_file_actions_addchdir_np, impacting: + // - Amazon Linux 2 (EoL mid-2025) + return 0; +#elif defined(__OpenBSD__) || defined(__QNX__) + // Currently missing as of: + // - OpenBSD 7.5 (April 2024) + // - QNX 8 (December 2023) + return 0; +#elif defined(__GLIBC__) || TARGET_OS_DARWIN || defined(__FreeBSD__) || (defined(__ANDROID__) && __ANDROID_API__ >= 34) || defined(__musl__) + // Pre-standard posix_spawn_file_actions_addchdir_np version available in: + // - Solaris 11.3 (October 2015) + // - Glibc 2.29 (February 2019) + // - macOS 10.15 (October 2019) + // - musl 1.1.24 (October 2019) + // - FreeBSD 13.1 (May 2022) + // - Android 14 (October 2023) + return 1; +#else + // Standardized posix_spawn_file_actions_addchdir version (POSIX.1-2024, June 2024) available in: + // - Solaris 11.4 (August 2018) + // - NetBSD 10.0 (March 2024) + return 1; +#endif +} + +static int _subprocess_addchdir_np( + posix_spawn_file_actions_t *file_actions, + const char * __restrict path +) { +#if defined(__GLIBC__) && !__GLIBC_PREREQ(2, 29) + // Glibc versions prior to 2.29 don't support posix_spawn_file_actions_addchdir_np, impacting: + // - Amazon Linux 2 (EoL mid-2025) + // noop +#elif defined(__OpenBSD__) || defined(__QNX__) + // Currently missing as of: + // - OpenBSD 7.5 (April 2024) + // - QNX 8 (December 2023) + // noop +#elif defined(__GLIBC__) || TARGET_OS_DARWIN || defined(__FreeBSD__) || (defined(__ANDROID__) && __ANDROID_API__ >= 34) || defined(__musl__) + // Pre-standard posix_spawn_file_actions_addchdir_np version available in: + // - Solaris 11.3 (October 2015) + // - Glibc 2.29 (February 2019) + // - macOS 10.15 (October 2019) + // - musl 1.1.24 (October 2019) + // - FreeBSD 13.1 (May 2022) + // - Android 14 (October 2023) + return posix_spawn_file_actions_addchdir_np(file_actions, path); +#else + // Standardized posix_spawn_file_actions_addchdir version (POSIX.1-2024, June 2024) available in: + // - Solaris 11.4 (August 2018) + // - NetBSD 10.0 (March 2024) + return posix_spawn_file_actions_addchdir(file_actions, path); +#endif +} + +static int _subprocess_posix_spawn_fallback( + pid_t * _Nonnull pid, + const char * _Nonnull exec_path, + const char * _Nullable working_directory, + const int file_descriptors[_Nonnull], + char * _Nullable const args[_Nonnull], + char * _Nullable const env[_Nullable], + gid_t * _Nullable process_group_id +) { + // Setup stdin, stdout, and stderr + posix_spawn_file_actions_t file_actions; + + int rc = posix_spawn_file_actions_init(&file_actions); + if (rc != 0) { return rc; } + if (file_descriptors[0] >= 0) { + rc = posix_spawn_file_actions_adddup2( + &file_actions, file_descriptors[0], STDIN_FILENO + ); + if (rc != 0) { return rc; } + } + if (file_descriptors[2] >= 0) { + rc = posix_spawn_file_actions_adddup2( + &file_actions, file_descriptors[2], STDOUT_FILENO + ); + if (rc != 0) { return rc; } + } + if (file_descriptors[4] >= 0) { + rc = posix_spawn_file_actions_adddup2( + &file_actions, file_descriptors[4], STDERR_FILENO + ); + if (rc != 0) { return rc; } + } + // Setup working directory + rc = _subprocess_addchdir_np(&file_actions, working_directory); + if (rc != 0) { + return rc; + } + + // Close parent side + if (file_descriptors[1] >= 0) { + rc = posix_spawn_file_actions_addclose(&file_actions, file_descriptors[1]); + if (rc != 0) { return rc; } + } + if (file_descriptors[3] >= 0) { + rc = posix_spawn_file_actions_addclose(&file_actions, file_descriptors[3]); + if (rc != 0) { return rc; } + } + if (file_descriptors[5] >= 0) { + rc = posix_spawn_file_actions_addclose(&file_actions, file_descriptors[5]); + if (rc != 0) { return rc; } + } + + // Setup spawnattr + posix_spawnattr_t spawn_attr; + rc = posix_spawnattr_init(&spawn_attr); + if (rc != 0) { return rc; } + // Masks + sigset_t no_signals; + sigset_t all_signals; + sigemptyset(&no_signals); + sigfillset(&all_signals); + rc = posix_spawnattr_setsigmask(&spawn_attr, &no_signals); + if (rc != 0) { return rc; } + rc = posix_spawnattr_setsigdefault(&spawn_attr, &all_signals); + if (rc != 0) { return rc; } + // Flags + short flags = POSIX_SPAWN_SETSIGMASK | POSIX_SPAWN_SETSIGDEF; + if (process_group_id != NULL) { + flags |= POSIX_SPAWN_SETPGROUP; + rc = posix_spawnattr_setpgroup(&spawn_attr, *process_group_id); + if (rc != 0) { return rc; } + } + rc = posix_spawnattr_setflags(&spawn_attr, flags); + + // Spawn! + rc = posix_spawn( + pid, exec_path, + &file_actions, &spawn_attr, + args, env + ); + posix_spawn_file_actions_destroy(&file_actions); + posix_spawnattr_destroy(&spawn_attr); + return rc; +} +#endif // _POSIX_SPAWN + +int _subprocess_fork_exec( + pid_t * _Nonnull pid, + const char * _Nonnull exec_path, + const char * _Nullable working_directory, + const int file_descriptors[_Nonnull], + char * _Nullable const args[_Nonnull], + char * _Nullable const env[_Nullable], + uid_t * _Nullable uid, + gid_t * _Nullable gid, + gid_t * _Nullable process_group_id, + int number_of_sgroups, const gid_t * _Nullable sgroups, + int create_session, + void (* _Nullable configurator)(void) +) { + int require_pre_fork = _subprocess_is_addchdir_np_available() == 0 || + uid != NULL || + gid != NULL || + process_group_id != NULL || + (number_of_sgroups > 0 && sgroups != NULL) || + create_session || + configurator != NULL; + +#if _POSIX_SPAWN + // If posix_spawn is available on this platform and + // we do not require prefork, use posix_spawn if possible. + // + // (Glibc's posix_spawn does not support + // `POSIX_SPAWN_SETEXEC` therefore we have to keep + // using fork/exec if `require_pre_fork` is true. + if (require_pre_fork == 0) { + return _subprocess_posix_spawn_fallback( + pid, exec_path, + working_directory, + file_descriptors, + args, env, + process_group_id + ); + } +#endif + + // Setup pipe to catch exec failures from child + int pipefd[2]; + if (pipe(pipefd) != 0) { + return errno; + } + // Set FD_CLOEXEC so the pipe is automatically closed when exec succeeds + short flags = fcntl(pipefd[0], F_GETFD); + if (flags == -1) { + close(pipefd[0]); + close(pipefd[1]); + return errno; + } + flags |= FD_CLOEXEC; + if (fcntl(pipefd[0], F_SETFD, flags) == -1) { + close(pipefd[0]); + close(pipefd[1]); + return errno; + } + + flags = fcntl(pipefd[1], F_GETFD); + if (flags == -1) { + close(pipefd[0]); + close(pipefd[1]); + return errno; + } + flags |= FD_CLOEXEC; + if (fcntl(pipefd[1], F_SETFD, flags) == -1) { + close(pipefd[0]); + close(pipefd[1]); + return errno; + } + + // Finally, fork +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated" + pid_t childPid = fork(); +#pragma GCC diagnostic pop + if (childPid == -1) { + close(pipefd[0]); + close(pipefd[1]); + return errno; + } + + if (childPid == 0) { + // Child process + close(pipefd[0]); // Close unused read end + + // Perform setups + if (working_directory != NULL) { + if (chdir(working_directory) != 0) { + int error = errno; + write(pipefd[1], &error, sizeof(error)); + close(pipefd[1]); + _exit(EXIT_FAILURE); + } + } + + + if (uid != NULL) { + if (setuid(*uid) != 0) { + int error = errno; + write(pipefd[1], &error, sizeof(error)); + close(pipefd[1]); + _exit(EXIT_FAILURE); + } + } + + if (gid != NULL) { + if (setgid(*gid) != 0) { + int error = errno; + write(pipefd[1], &error, sizeof(error)); + close(pipefd[1]); + _exit(EXIT_FAILURE); + } + } + + if (number_of_sgroups > 0 && sgroups != NULL) { + if (setgroups(number_of_sgroups, sgroups) != 0) { + int error = errno; + write(pipefd[1], &error, sizeof(error)); + close(pipefd[1]); + _exit(EXIT_FAILURE); + } + } + + if (create_session != 0) { + (void)setsid(); + } + + if (process_group_id != NULL) { + (void)setpgid(0, *process_group_id); + } + + // Bind stdin, stdout, and stderr + int rc = 0; + if (file_descriptors[0] >= 0) { + rc = dup2(file_descriptors[0], STDIN_FILENO); + if (rc < 0) { + int error = errno; + write(pipefd[1], &error, sizeof(error)); + close(pipefd[1]); + _exit(EXIT_FAILURE); + } + } + if (file_descriptors[2] >= 0) { + rc = dup2(file_descriptors[2], STDOUT_FILENO); + if (rc < 0) { + int error = errno; + write(pipefd[1], &error, sizeof(error)); + close(pipefd[1]); + _exit(EXIT_FAILURE); + } + } + if (file_descriptors[4] >= 0) { + rc = dup2(file_descriptors[4], STDERR_FILENO); + if (rc < 0) { + int error = errno; + write(pipefd[1], &error, sizeof(error)); + close(pipefd[1]); + _exit(EXIT_FAILURE); + } + } + // Close parent side + if (file_descriptors[1] >= 0) { + rc = close(file_descriptors[1]); + } + if (file_descriptors[3] >= 0) { + rc = close(file_descriptors[3]); + } + if (file_descriptors[4] >= 0) { + rc = close(file_descriptors[5]); + } + if (rc != 0) { + int error = errno; + write(pipefd[1], &error, sizeof(error)); + close(pipefd[1]); + _exit(EXIT_FAILURE); + } + // Run custom configuratior + if (configurator != NULL) { + configurator(); + } + // Finally, exec + execve(exec_path, args, env); + // If we reached this point, something went wrong + int error = errno; + write(pipefd[1], &error, sizeof(error)); + close(pipefd[1]); + _exit(EXIT_FAILURE); + } else { + // Parent process + close(pipefd[1]); // Close unused write end + // Communicate child pid back + *pid = childPid; + // Read from the pipe until pipe is closed + // Eitehr due to exec succeeds or error is written + int childError = 0; + if (read(pipefd[0], &childError, sizeof(childError)) > 0) { + // We encountered error + close(pipefd[0]); + return childError; + } else { + // Child process exec was successful + close(pipefd[0]); + return 0; + } + } +} + +#endif // TARGET_OS_LINUX + +#endif // !TARGET_OS_WINDOWS + +#pragma mark - Environment Locking + +#if __has_include() +#import +void _subprocess_lock_environ(void) { + environ_lock_np(); +} + +void _subprocess_unlock_environ(void) { + environ_unlock_np(); +} +#else +void _subprocess_lock_environ(void) { /* noop */ } +void _subprocess_unlock_environ(void) { /* noop */ } +#endif + +char ** _subprocess_get_environ(void) { +#if __has_include() + return *_NSGetEnviron(); +#elif defined(_WIN32) +#include + return _environ; +#elif TARGET_OS_WASI + return __wasilibc_get_environ(); +#elif __has_include() + return environ; +#endif +} + + +#if TARGET_OS_WINDOWS + +typedef struct { + DWORD pid; + HWND mainWindow; +} CallbackContext; + +static BOOL CALLBACK enumWindowsCallback( + HWND hwnd, + LPARAM lParam +) { + CallbackContext *context = (CallbackContext *)lParam; + DWORD pid; + GetWindowThreadProcessId(hwnd, &pid); + if (pid == context->pid) { + context->mainWindow = hwnd; + return FALSE; // Stop enumeration + } + return TRUE; // Continue enumeration +} + +BOOL _subprocess_windows_send_vm_close( + DWORD pid +) { + // First attempt to find the Window associate + // with this process + CallbackContext context = {0}; + context.pid = pid; + EnumWindows(enumWindowsCallback, (LPARAM)&context); + + if (context.mainWindow != NULL) { + if (SendMessage(context.mainWindow, WM_CLOSE, 0, 0)) { + return TRUE; + } + } + + return FALSE; +} + +#endif + diff --git a/SwiftKit/build.gradle b/SwiftKit/build.gradle index e0896e66..8f3b6c51 100644 --- a/SwiftKit/build.gradle +++ b/SwiftKit/build.gradle @@ -25,7 +25,7 @@ repositories { java { toolchain { - languageVersion.set(JavaLanguageVersion.of(22)) + languageVersion.set(JavaLanguageVersion.of(24)) } } diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValueLayout.java b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValueLayout.java index dea52154..8d2d7ad2 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValueLayout.java +++ b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValueLayout.java @@ -41,8 +41,8 @@ public static long addressByteSize() { public static final ValueLayout.OfLong SWIFT_INT64 = ValueLayout.JAVA_LONG; public static final ValueLayout.OfFloat SWIFT_FLOAT = ValueLayout.JAVA_FLOAT; public static final ValueLayout.OfDouble SWIFT_DOUBLE = ValueLayout.JAVA_DOUBLE; - public static final AddressLayout SWIFT_POINTER = ValueLayout.ADDRESS - .withTargetLayout(MemoryLayout.sequenceLayout(Long.MAX_VALUE, JAVA_BYTE)); + public static final AddressLayout SWIFT_POINTER = ValueLayout.ADDRESS; + // .withTargetLayout(MemoryLayout.sequenceLayout(Long.MAX_VALUE, JAVA_BYTE)); public static final SequenceLayout SWIFT_BYTE_ARRAY = MemoryLayout.sequenceLayout(8, ValueLayout.JAVA_BYTE); /** diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValueWitnessTable.java b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValueWitnessTable.java index 53680f5f..2a031b7e 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValueWitnessTable.java +++ b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValueWitnessTable.java @@ -71,7 +71,6 @@ public static MemorySegment fullTypeMetadata(MemorySegment typeMetadata) { public static MemorySegment valueWitnessTable(MemorySegment typeMetadata) { return fullTypeMetadata(typeMetadata) .get(SwiftValueLayout.SWIFT_POINTER, SwiftValueWitnessTable.fullTypeMetadata$vwt$offset); -// .get(ValueLayout.ADDRESS, SwiftValueWitnessTable.fullTypeMetadata$vwt$offset); } diff --git a/SwiftKit/src/test/java/org/swift/swiftkit/SwiftRuntimeMetadataTest.java b/SwiftKit/src/test/java/org/swift/swiftkit/SwiftRuntimeMetadataTest.java index ffefe72e..3419405e 100644 --- a/SwiftKit/src/test/java/org/swift/swiftkit/SwiftRuntimeMetadataTest.java +++ b/SwiftKit/src/test/java/org/swift/swiftkit/SwiftRuntimeMetadataTest.java @@ -20,42 +20,42 @@ public class SwiftRuntimeMetadataTest { - @Test - public void integer_layout_metadata() { - SwiftAnyType swiftType = SwiftKit.getTypeByMangledNameInEnvironment("Si").get(); - - if (SwiftValueLayout.addressByteSize() == 4) { - // 32-bit platform - Assertions.assertEquals(8, SwiftValueWitnessTable.sizeOfSwiftType(swiftType.$memorySegment())); - Assertions.assertEquals(8, SwiftValueWitnessTable.strideOfSwiftType(swiftType.$memorySegment())); - Assertions.assertEquals(8, SwiftValueWitnessTable.alignmentOfSwiftType(swiftType.$memorySegment())); - Assertions.assertEquals("[8%[9:b1]x7](Swift.Int)", SwiftValueWitnessTable.layoutOfSwiftType(swiftType.$memorySegment()).toString()); - } else { - // 64-bit platform - Assertions.assertEquals(8, SwiftValueWitnessTable.sizeOfSwiftType(swiftType.$memorySegment())); - Assertions.assertEquals(8, SwiftValueWitnessTable.strideOfSwiftType(swiftType.$memorySegment())); - Assertions.assertEquals(8, SwiftValueWitnessTable.alignmentOfSwiftType(swiftType.$memorySegment())); - Assertions.assertEquals("[8%[8:b1]](Swift.Int)", SwiftValueWitnessTable.layoutOfSwiftType(swiftType.$memorySegment()).toString()); - } - } - - @Test - public void optional_integer_layout_metadata() { - SwiftAnyType swiftType = SwiftKit.getTypeByMangledNameInEnvironment("SiSg").get(); - - if (SwiftValueLayout.addressByteSize() == 4) { - // 64-bit platform - Assertions.assertEquals(9, SwiftValueWitnessTable.sizeOfSwiftType(swiftType.$memorySegment())); - Assertions.assertEquals(16, SwiftValueWitnessTable.strideOfSwiftType(swiftType.$memorySegment())); - Assertions.assertEquals(8, SwiftValueWitnessTable.alignmentOfSwiftType(swiftType.$memorySegment())); - Assertions.assertEquals("[8%[9:b1]x7](Swift.Optional)", SwiftValueWitnessTable.layoutOfSwiftType(swiftType.$memorySegment()).toString()); - } else { - // 64-bit platform - Assertions.assertEquals(9, SwiftValueWitnessTable.sizeOfSwiftType(swiftType.$memorySegment())); - Assertions.assertEquals(16, SwiftValueWitnessTable.strideOfSwiftType(swiftType.$memorySegment())); - Assertions.assertEquals(8, SwiftValueWitnessTable.alignmentOfSwiftType(swiftType.$memorySegment())); - Assertions.assertEquals("[8%[9:b1]x7](Swift.Optional)", SwiftValueWitnessTable.layoutOfSwiftType(swiftType.$memorySegment()).toString()); - } - } +// @Test +// public void integer_layout_metadata() { +// SwiftAnyType swiftType = SwiftKit.getTypeByMangledNameInEnvironment("Si").get(); +// +// if (SwiftValueLayout.addressByteSize() == 4) { +// // 32-bit platform +// Assertions.assertEquals(8, SwiftValueWitnessTable.sizeOfSwiftType(swiftType.$memorySegment())); +// Assertions.assertEquals(8, SwiftValueWitnessTable.strideOfSwiftType(swiftType.$memorySegment())); +// Assertions.assertEquals(8, SwiftValueWitnessTable.alignmentOfSwiftType(swiftType.$memorySegment())); +// Assertions.assertEquals("[8%[9:b1]x7](Swift.Int)", SwiftValueWitnessTable.layoutOfSwiftType(swiftType.$memorySegment()).toString()); +// } else { +// // 64-bit platform +// Assertions.assertEquals(8, SwiftValueWitnessTable.sizeOfSwiftType(swiftType.$memorySegment())); +// Assertions.assertEquals(8, SwiftValueWitnessTable.strideOfSwiftType(swiftType.$memorySegment())); +// Assertions.assertEquals(8, SwiftValueWitnessTable.alignmentOfSwiftType(swiftType.$memorySegment())); +// Assertions.assertEquals("[8%[8:b1]](Swift.Int)", SwiftValueWitnessTable.layoutOfSwiftType(swiftType.$memorySegment()).toString()); +// } +// } +// +// @Test +// public void optional_integer_layout_metadata() { +// SwiftAnyType swiftType = SwiftKit.getTypeByMangledNameInEnvironment("SiSg").get(); +// +// if (SwiftValueLayout.addressByteSize() == 4) { +// // 64-bit platform +// Assertions.assertEquals(9, SwiftValueWitnessTable.sizeOfSwiftType(swiftType.$memorySegment())); +// Assertions.assertEquals(16, SwiftValueWitnessTable.strideOfSwiftType(swiftType.$memorySegment())); +// Assertions.assertEquals(8, SwiftValueWitnessTable.alignmentOfSwiftType(swiftType.$memorySegment())); +// Assertions.assertEquals("[8%[9:b1]x7](Swift.Optional)", SwiftValueWitnessTable.layoutOfSwiftType(swiftType.$memorySegment()).toString()); +// } else { +// // 64-bit platform +// Assertions.assertEquals(9, SwiftValueWitnessTable.sizeOfSwiftType(swiftType.$memorySegment())); +// Assertions.assertEquals(16, SwiftValueWitnessTable.strideOfSwiftType(swiftType.$memorySegment())); +// Assertions.assertEquals(8, SwiftValueWitnessTable.alignmentOfSwiftType(swiftType.$memorySegment())); +// Assertions.assertEquals("[8%[9:b1]x7](Swift.Optional)", SwiftValueWitnessTable.layoutOfSwiftType(swiftType.$memorySegment()).toString()); +// } +// } } diff --git a/Tests/JExtractSwiftTests/Asserts/LoweringAssertions.swift b/Tests/JExtractSwiftTests/Asserts/LoweringAssertions.swift index f017bc49..05323630 100644 --- a/Tests/JExtractSwiftTests/Asserts/LoweringAssertions.swift +++ b/Tests/JExtractSwiftTests/Asserts/LoweringAssertions.swift @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// @_spi(Testing) import JExtractSwiftLib +import JavaKitConfigurationShared import SwiftSyntax import Testing @@ -31,9 +32,9 @@ func assertLoweredFunction( line: Int = #line, column: Int = #column ) throws { - let translator = Swift2JavaTranslator( - swiftModuleName: swiftModuleName - ) + var config = Configuration() + config.swiftModule = swiftModuleName + let translator = Swift2JavaTranslator(config: config) if let sourceFile { translator.add(filePath: "Fake.swift", text: sourceFile) @@ -117,9 +118,9 @@ func assertLoweredVariableAccessor( line: Int = #line, column: Int = #column ) throws { - let translator = Swift2JavaTranslator( - swiftModuleName: swiftModuleName - ) + var config = Configuration() + config.swiftModule = swiftModuleName + let translator = Swift2JavaTranslator(config: config) if let sourceFile { translator.add(filePath: "Fake.swift", text: sourceFile) diff --git a/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift b/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift index b3a09a22..3c4ad56a 100644 --- a/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift +++ b/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift @@ -25,7 +25,7 @@ enum RenderKind { func assertOutput( dump: Bool = false, input: String, - _ mode: GenerationMode, + _ mode: JExtractGenerationMode, _ renderKind: RenderKind, swiftModuleName: String = "SwiftModule", detectChunkByInitialLines: Int = 4, @@ -35,7 +35,9 @@ func assertOutput( line: Int = #line, column: Int = #column ) throws { - let translator = Swift2JavaTranslator(swiftModuleName: swiftModuleName) + var config = Configuration() + config.swiftModule = swiftModuleName + let translator = Swift2JavaTranslator(config: config) try! translator.analyze(file: "/fake/Fake.swiftinterface", text: input) diff --git a/Tests/JExtractSwiftTests/FuncCallbackImportTests.swift b/Tests/JExtractSwiftTests/FuncCallbackImportTests.swift index c738914a..d81dad8c 100644 --- a/Tests/JExtractSwiftTests/FuncCallbackImportTests.swift +++ b/Tests/JExtractSwiftTests/FuncCallbackImportTests.swift @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// import JExtractSwiftLib +import JavaKitConfigurationShared import Testing final class FuncCallbackImportTests { @@ -36,9 +37,9 @@ final class FuncCallbackImportTests { @Test("Import: public func callMe(callback: () -> Void)") func func_callMeFunc_callback() throws { - let st = Swift2JavaTranslator( - swiftModuleName: "__FakeModule" - ) + var config = Configuration() + config.swiftModule = "__FakeModule" + let st = Swift2JavaTranslator(config: config) st.log.logLevel = .error try st.analyze(file: "Fake.swift", text: Self.class_interfaceFile) @@ -125,9 +126,9 @@ final class FuncCallbackImportTests { @Test("Import: public func callMeMore(callback: (UnsafeRawPointer, Float) -> Int, fn: () -> ())") func func_callMeMoreFunc_callback() throws { - let st = Swift2JavaTranslator( - swiftModuleName: "__FakeModule" - ) + var config = Configuration() + config.swiftModule = "__FakeModule" + let st = Swift2JavaTranslator(config: config) st.log.logLevel = .error try st.analyze(file: "Fake.swift", text: Self.class_interfaceFile) @@ -240,9 +241,9 @@ final class FuncCallbackImportTests { @Test("Import: public func withBuffer(body: (UnsafeRawBufferPointer) -> Int)") func func_withBuffer_body() throws { - let st = Swift2JavaTranslator( - swiftModuleName: "__FakeModule" - ) + var config = Configuration() + config.swiftModule = "__FakeModule" + let st = Swift2JavaTranslator(config: config) st.log.logLevel = .error try st.analyze(file: "Fake.swift", text: Self.class_interfaceFile) diff --git a/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift b/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift index 2cac6218..7af3c706 100644 --- a/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift +++ b/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// import JExtractSwiftLib +import JavaKitConfigurationShared import Testing @Suite @@ -233,9 +234,9 @@ extension FunctionDescriptorTests { logLevel: Logger.Level = .trace, body: (String) throws -> Void ) throws { - let st = Swift2JavaTranslator( - swiftModuleName: swiftModuleName - ) + var config = Configuration() + config.swiftModule = swiftModuleName + let st = Swift2JavaTranslator(config: config) st.log.logLevel = logLevel try st.analyze(file: "/fake/Sample.swiftinterface", text: interfaceFile) @@ -266,9 +267,9 @@ extension FunctionDescriptorTests { logLevel: Logger.Level = .trace, body: (String) throws -> Void ) throws { - let st = Swift2JavaTranslator( - swiftModuleName: swiftModuleName - ) + var config = Configuration() + config.swiftModule = swiftModuleName + let st = Swift2JavaTranslator(config: config) st.log.logLevel = logLevel try st.analyze(file: "/fake/Sample.swiftinterface", text: interfaceFile) diff --git a/Tests/JExtractSwiftTests/MethodImportTests.swift b/Tests/JExtractSwiftTests/MethodImportTests.swift index 2405e0ac..36610dcd 100644 --- a/Tests/JExtractSwiftTests/MethodImportTests.swift +++ b/Tests/JExtractSwiftTests/MethodImportTests.swift @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// import JExtractSwiftLib +import JavaKitConfigurationShared import Testing final class MethodImportTests { @@ -64,9 +65,9 @@ final class MethodImportTests { @Test("Import: public func helloWorld()") func method_helloWorld() throws { - let st = Swift2JavaTranslator( - swiftModuleName: "__FakeModule" - ) + var config = Configuration() + config.swiftModule = "__FakeModule" + let st = Swift2JavaTranslator(config: config) st.log.logLevel = .error try st.analyze(file: "Fake.swift", text: class_interfaceFile) @@ -103,9 +104,9 @@ final class MethodImportTests { @Test("Import: public func globalTakeInt(i: Int)") func func_globalTakeInt() throws { - let st = Swift2JavaTranslator( - swiftModuleName: "__FakeModule" - ) + var config = Configuration() + config.swiftModule = "__FakeModule" + let st = Swift2JavaTranslator(config: config) st.log.logLevel = .error try st.analyze(file: "Fake.swift", text: class_interfaceFile) @@ -144,9 +145,9 @@ final class MethodImportTests { @Test("Import: public func globalTakeIntLongString(i32: Int32, l: Int64, s: String)") func func_globalTakeIntLongString() throws { - let st = Swift2JavaTranslator( - swiftModuleName: "__FakeModule" - ) + var config = Configuration() + config.swiftModule = "__FakeModule" + let st = Swift2JavaTranslator(config: config) st.log.logLevel = .error try st.analyze(file: "Fake.swift", text: class_interfaceFile) @@ -188,9 +189,9 @@ final class MethodImportTests { @Test("Import: public func globalReturnClass() -> MySwiftClass") func func_globalReturnClass() throws { - let st = Swift2JavaTranslator( - swiftModuleName: "__FakeModule" - ) + var config = Configuration() + config.swiftModule = "__FakeModule" + let st = Swift2JavaTranslator(config: config) st.log.logLevel = .error try st.analyze(file: "Fake.swift", text: class_interfaceFile) @@ -232,9 +233,9 @@ final class MethodImportTests { @Test("Import: func swapRawBufferPointer(buffer: _)") func func_globalSwapRawBufferPointer() throws { - let st = Swift2JavaTranslator( - swiftModuleName: "__FakeModule" - ) + var config = Configuration() + config.swiftModule = "__FakeModule" + let st = Swift2JavaTranslator(config: config) st.log.logLevel = .error try st.analyze(file: "Fake.swift", text: class_interfaceFile) @@ -279,9 +280,9 @@ final class MethodImportTests { @Test func method_class_helloMemberFunction() throws { - let st = Swift2JavaTranslator( - swiftModuleName: "__FakeModule" - ) + var config = Configuration() + config.swiftModule = "__FakeModule" + let st = Swift2JavaTranslator(config: config) st.log.logLevel = .error try st.analyze(file: "Fake.swift", text: class_interfaceFile) @@ -321,9 +322,9 @@ final class MethodImportTests { @Test func method_class_makeInt() throws { - let st = Swift2JavaTranslator( - swiftModuleName: "__FakeModule" - ) + var config = Configuration() + config.swiftModule = "__FakeModule" + let st = Swift2JavaTranslator(config: config) st.log.logLevel = .info try st.analyze(file: "Fake.swift", text: class_interfaceFile) @@ -363,9 +364,9 @@ final class MethodImportTests { @Test func class_constructor() throws { - let st = Swift2JavaTranslator( - swiftModuleName: "__FakeModule" - ) + var config = Configuration() + config.swiftModule = "__FakeModule" + let st = Swift2JavaTranslator(config: config) st.log.logLevel = .info try st.analyze(file: "Fake.swift", text: class_interfaceFile) @@ -406,9 +407,10 @@ final class MethodImportTests { @Test func struct_constructor() throws { - let st = Swift2JavaTranslator( - swiftModuleName: "__FakeModule" - ) + var config = Configuration() + config.swiftModule = "__FakeModule" + let st = Swift2JavaTranslator(config: config) + st.log.logLevel = .info try st.analyze(file: "Fake.swift", text: class_interfaceFile) diff --git a/Tests/JavaKitConfigurationSharedTests/GradleDependencyParsingTests.swift b/Tests/JavaKitConfigurationSharedTests/GradleDependencyParsingTests.swift new file mode 100644 index 00000000..dbd05f66 --- /dev/null +++ b/Tests/JavaKitConfigurationSharedTests/GradleDependencyParsingTests.swift @@ -0,0 +1,45 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024-2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import JavaKitConfigurationShared +import Testing + +@Suite +struct GradleDependencyParsingTests { + + @Test + func parseSingleDependency() throws { + let inputString = "com.example:thing:12.2" + let parsed: JavaDependencyDescriptor = parseDependencyDescriptor(inputString)! + + #expect(parsed.groupID == "com.example") + #expect(parsed.artifactID == "thing") + #expect(parsed.version == "12.2") + } + + @Test + func parseMultiple() throws { + let inputString = "com.example:thing:12.2,com.example:another:1.2.3-beta.1," + let parsed: [JavaDependencyDescriptor] = parseDependencyDescriptors(inputString) + + #expect(parsed.count == 2) + #expect(parsed[0].groupID == "com.example") + #expect(parsed[0].artifactID == "thing") + #expect(parsed[0].version == "12.2") + #expect(parsed[1].groupID == "com.example") + #expect(parsed[1].artifactID == "another") + #expect(parsed[1].version == "1.2.3-beta.1") + } +} + diff --git a/docker/Dockerfile b/docker/Dockerfile index c68ccc3c..6604d091 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,6 +1,6 @@ ARG swift_version=nightly-main ARG ubuntu_version=jammy -ARG base_image=docker.io/swiftlang/swift:$swift_version-$ubuntu_version +ARG base_image=docker.io/swiftlang/swift:${swift_version}-${ubuntu_version} FROM $base_image # needed to do again after FROM due to docker limitation ARG swift_version @@ -18,13 +18,9 @@ ENV LC_ALL=en_US.UTF-8 ENV LANG=en_US.UTF-8 ENV LANGUAGE=en_US.UTF-8 -# JDK dependency COPY install_jdk.sh . + +# JDK dependency RUN bash -xc 'JDK_VENDOR=Corretto ./install_jdk.sh' ENV JAVA_HOME="/usr/lib/jvm/default-jdk" ENV PATH="$PATH:/usr/lib/jvm/default-jdk/bin" - -# Install "untested" nightly 'main' Swift -# TODO: Only do this if the released Swift is older than what we require -#COPY install_untested_nightly_swift.sh . -RUN #bash -xc './install_untested_nightly_swift.sh' diff --git a/docker/install_jdk.sh b/docker/install_jdk.sh index 8aa295ce..8d0ddda3 100755 --- a/docker/install_jdk.sh +++ b/docker/install_jdk.sh @@ -14,70 +14,101 @@ ##===----------------------------------------------------------------------===## set -euo pipefail -# Supported JDKs: Corretto or OpenJDK +# We need JDK 24 because that's the supported version with latest FFM +# However, we also need JDK 23 at most because Gradle does not support 24. + +# Supported JDKs: Corretto if [ "$JDK_VENDOR" = "" ]; then declare -r JDK_VENDOR="Corretto" fi -echo "Installing $JDK_VENDOR JDK..." -apt-get update && apt-get install -y wget +apt-get update && apt-get install -y wget tree echo "Download JDK for: $(uname -m)" -if [ "$JDK_VENDOR" = 'OpenJDK' ]; then - if [ "$(uname -m)" = 'aarch64' ]; then - declare -r JDK_URL="https://download.java.net/java/GA/jdk23/3c5b90190c68498b986a97f276efd28a/37/GPL/openjdk-23_linux-aarch64_bin.tar.gz" - declare -r EXPECT_JDK_SHA="076dcf7078cdf941951587bf92733abacf489a6570f1df97ee35945ffebec5b7" - else - declare -r JDK_URL="https://download.java.net/java/GA/jdk23/3c5b90190c68498b986a97f276efd28a/37/GPL/$JDK_NAME" - declare -r EXPECT_JDK_SHA="08fea92724127c6fa0f2e5ea0b07ff4951ccb1e2f22db3c21eebbd7347152a67" - fi +download_and_install_jdk() { + local jdk_version="$1" + local jdk_url="" + local expected_md5="" - wget -q -O jdk.tar.gz "$JDK_URL" + echo "Installing $JDK_VENDOR JDK (${jdk_version})..." - declare JDK_SHA # on separate lines due to: SC2155 (warning): Declare and assign separately to avoid masking return values. - JDK_SHA="$(sha256sum jdk.tar.gz | cut -d ' ' -f 1)" - if [ "$JDK_SHA" != "$EXPECT_JDK_SHA" ]; then - echo "Downloaded JDK SHA does not match expected!" - echo "Expected: $EXPECT_JDK_SHA" - echo " Was: $JDK_SHA" - exit 1; - else - echo "JDK SHA is correct."; - fi -elif [ "$JDK_VENDOR" = 'Corretto' ]; then - if [ "$(uname -m)" = 'aarch64' ]; then - declare -r JDK_URL="https://corretto.aws/downloads/latest/amazon-corretto-22-aarch64-linux-jdk.tar.gz" - declare -r EXPECT_JDK_MD5="1ebe5f5229bb18bc784a1e0f54d3fe39" - else - declare -r JDK_URL="https://corretto.aws/downloads/latest/amazon-corretto-22-x64-linux-jdk.tar.gz" - declare -r EXPECT_JDK_MD5="5bd7fe30eb063699a3b4db7a00455841" - fi + if [ "$JDK_VENDOR" = 'Corretto' ]; then + if [ "$(uname -m)" = 'aarch64' ]; then + case "$jdk_version" in + "21") + jdk_url="https://corretto.aws/downloads/latest/amazon-corretto-21-aarch64-linux-jdk.tar.gz" + expected_md5="87e458029cf9976945dfa3a22af3f850" + ;; + "24") + jdk_url="https://corretto.aws/downloads/latest/amazon-corretto-24-aarch64-linux-jdk.tar.gz" + expected_md5="3b543f4e971350b73d0ab6d8174cc030" + ;; + *) + echo "Unsupported JDK version: '$jdk_version'" + exit 1 + ;; + esac + else + case "$jdk_version" in + "21") + jdk_url="https://corretto.aws/downloads/latest/amazon-corretto-21-x64-linux-jdk.tar.gz" + expected_md5="a123e7f50807c27de521bef7378d3377" + ;; + "24") + jdk_url="https://corretto.aws/downloads/latest/amazon-corretto-24-x64-linux-jdk.tar.gz" + expected_md5="130885ded3cbfc712fbe9f7dace45a52" + ;; + *) + echo "Unsupported JDK version: '$jdk_version'" + exit 1 + ;; + esac + fi + else + echo "Unsupported JDK vendor: '$JDK_VENDOR'" + exit 1 + fi - wget -q -O jdk.tar.gz "$JDK_URL" + # Download JDK + local jdk_filename="jdk_${jdk_version}.tar.gz" + wget -q -O "$jdk_filename" "$jdk_url" - declare JDK_MD5 # on separate lines due to: SC2155 (warning): Declare and assign separately to avoid masking return values. - JDK_MD5="$(md5sum jdk.tar.gz | cut -d ' ' -f 1)" - if [ "$JDK_MD5" != "$EXPECT_JDK_MD5" ]; then - echo "Downloaded JDK MD5 does not match expected!" - echo "Expected: $EXPECT_JDK_MD5" - echo " Was: $JDK_MD5" - exit 1; - else - echo "JDK MD5 is correct."; - fi -else - echo "Unsupported JDK vendor: '$JDK_VENDOR'" - exit 1 -fi + # Verify MD5 + local jdk_md5 + jdk_md5="$(md5sum "$jdk_filename" | cut -d ' ' -f 1)" + if [ "$jdk_md5" != "$expected_md5" ]; then + echo "Downloaded JDK $jdk_version MD5 does not match expected!" + echo "Expected: $expected_md5" + echo " Was: $jdk_md5" + exit 1 + else + echo "JDK $jdk_version MD5 is correct." + fi -# Extract and verify the JDK installation + # Extract and install JDK + mkdir -p "/usr/lib/jvm/jdk-${jdk_version}" + mv "$jdk_filename" "/usr/lib/jvm/jdk-${jdk_version}/" + cd "/usr/lib/jvm/jdk-${jdk_version}/" || exit 1 + tar xzf "$jdk_filename" && rm "$jdk_filename" -mkdir -p /usr/lib/jvm/ -mv jdk.tar.gz /usr/lib/jvm/ -cd /usr/lib/jvm/ -tar xzvf jdk.tar.gz && rm jdk.tar.gz -mv "$(find . -depth -maxdepth 1 -type d | head -n1)" default-jdk + # Move extracted directory to a standard name + local extracted_dir + extracted_dir="$(find . -maxdepth 1 -type d -name '*linux*' | head -n1)" + echo "move $extracted_dir to $(pwd)..." + mv "${extracted_dir}"/* . + echo "JDK $jdk_version installed successfully in /usr/lib/jvm/jdk-${jdk_version}/" + cd "$HOME" +} + +# Usage: Install both JDK versions +download_and_install_jdk "21" +download_and_install_jdk "24" + +ls -la /usr/lib/jvm/ +cd /usr/lib/jvm/ +ln -s jdk-21 default-jdk +find . | grep java | grep bin echo "JAVA_HOME = /usr/lib/jvm/default-jdk" /usr/lib/jvm/default-jdk/bin/java -version \ No newline at end of file diff --git a/docker/install_untested_nightly_swift.sh b/docker/install_untested_nightly_swift.sh deleted file mode 100755 index 9cb920ab..00000000 --- a/docker/install_untested_nightly_swift.sh +++ /dev/null @@ -1,43 +0,0 @@ -#!/bin/bash -##===----------------------------------------------------------------------===## -## -## This source file is part of the Swift.org open source project -## -## Copyright (c) 2024 Apple Inc. and the Swift.org project authors -## Licensed under Apache License v2.0 -## -## See LICENSE.txt for license information -## See CONTRIBUTORS.txt for the list of Swift.org project authors -## -## SPDX-License-Identifier: Apache-2.0 -## -##===----------------------------------------------------------------------===## -set -euo pipefail - -echo "Download [nightly] [untested] Swift toolchain for: $(uname -m)" - -ARCH="$(arch)" -if [[ "$ARCH" = "i386" || "$ARCH" = "x86_64" ]]; then - SWIFT_UNTESTED_TOOLCHAIN_JOB_URL="https://ci.swift.org/job/oss-swift-package-ubuntu-22_04/lastSuccessfulBuild/consoleText" -else - SWIFT_UNTESTED_TOOLCHAIN_JOB_URL="https://ci.swift.org/job/oss-swift-package-ubuntu-22_04-aarch64/lastSuccessfulBuild/consoleText" -fi - -if [[ "$(grep "22.04" /etc/lsb-release)" = "" ]]; then - echo "This script specifically only supports Ubuntu 22.04 due to nightly toolchain availability" - exit 1 -fi - -UNTESTED_TOOLCHAIN_URL=$(curl -s $SWIFT_UNTESTED_TOOLCHAIN_JOB_URL | grep 'Toolchain: ' | sed 's/Toolchain: //g') -UNTESTED_TOOLCHAIN_FILENAME=$"toolchain.tar.gz" - -echo "Download toolchain: $UNTESTED_TOOLCHAIN_URL" - -cd / -curl -s "$UNTESTED_TOOLCHAIN_URL" > "$UNTESTED_TOOLCHAIN_FILENAME" - -swift -version - -echo "Extract toolchain: $UNTESTED_TOOLCHAIN_FILENAME" -tar xzf "$UNTESTED_TOOLCHAIN_FILENAME" -swift -version From e66e490f173e4cdfe7fda45147dccf85c451ddcd Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Wed, 25 Jun 2025 11:14:42 +0900 Subject: [PATCH 292/426] CI: Correct validation & bring back pointer "max" bounds workaround (#284) --- .github/scripts/validate_sample.sh | 14 +++++++------- Samples/SwiftKitSampleApp/ci-validate.sh | 6 ++++++ .../java/org/swift/swiftkit/SwiftValueLayout.java | 6 ++++-- 3 files changed, 17 insertions(+), 9 deletions(-) create mode 100755 Samples/SwiftKitSampleApp/ci-validate.sh diff --git a/.github/scripts/validate_sample.sh b/.github/scripts/validate_sample.sh index 7e0ab3d2..b5780976 100755 --- a/.github/scripts/validate_sample.sh +++ b/.github/scripts/validate_sample.sh @@ -1,5 +1,8 @@ #!/bin/bash +set -e +set -x + # shellcheck disable=SC2034 declare -r GREEN='\033[0;32m' declare -r BOLD='\033[1m' @@ -14,14 +17,11 @@ echo "========================================================================" printf "Validate sample '${BOLD}%s${RESET}' using: " "$sampleDir" cd "$sampleDir" || exit if [[ $(find . -name ${CI_VALIDATE_SCRIPT} -maxdepth 1) ]]; then - echo -e "Custom ${BOLD}${CI_VALIDATE_SCRIPT}${RESET} script..." - ./${CI_VALIDATE_SCRIPT} || exit -elif [[ $(find . -name 'build.gradle*' -maxdepth 1) ]]; then - echo -e "${BOLD}Gradle${RESET} build..." - ./gradlew build || ./gradlew build --info # re-run to get better failure output + echo -e "Run ${BOLD}${CI_VALIDATE_SCRIPT}${RESET} script..." + ./${CI_VALIDATE_SCRIPT} else - echo -e "${BOLD}SwiftPM${RESET} build..." - swift build || exit + echo -e "${BOLD}Missing ${CI_VALIDATE_SCRIPT} file!${RESET}" + exit fi echo -e "Validated sample '${BOLD}${sampleDir}${RESET}': ${BOLD}passed${RESET}." diff --git a/Samples/SwiftKitSampleApp/ci-validate.sh b/Samples/SwiftKitSampleApp/ci-validate.sh new file mode 100755 index 00000000..07b42627 --- /dev/null +++ b/Samples/SwiftKitSampleApp/ci-validate.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +set -x +set -e + +./gradlew run \ No newline at end of file diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValueLayout.java b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValueLayout.java index 8d2d7ad2..00215ef0 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValueLayout.java +++ b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValueLayout.java @@ -41,8 +41,10 @@ public static long addressByteSize() { public static final ValueLayout.OfLong SWIFT_INT64 = ValueLayout.JAVA_LONG; public static final ValueLayout.OfFloat SWIFT_FLOAT = ValueLayout.JAVA_FLOAT; public static final ValueLayout.OfDouble SWIFT_DOUBLE = ValueLayout.JAVA_DOUBLE; - public static final AddressLayout SWIFT_POINTER = ValueLayout.ADDRESS; - // .withTargetLayout(MemoryLayout.sequenceLayout(Long.MAX_VALUE, JAVA_BYTE)); + + // FIXME: this sequence layout is a workaround, we must properly size pointers when we get them. + public static final AddressLayout SWIFT_POINTER = ValueLayout.ADDRESS + .withTargetLayout(MemoryLayout.sequenceLayout(Long.MAX_VALUE, JAVA_BYTE)); public static final SequenceLayout SWIFT_BYTE_ARRAY = MemoryLayout.sequenceLayout(8, ValueLayout.JAVA_BYTE); /** From 8d4e5cd0086300a0f8abd5bf212fdbbf9a0e589e Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Tue, 24 Jun 2025 19:26:07 -0700 Subject: [PATCH 293/426] [JavaRuntime] Add module.modulemap Fix a build error in 6.1 toolchain. Apparently some targets have both `JavaRuntime-tool.build` and `JavaRuntime.build` as the include paths. The auto generated `module.modulemap` in both directories cause the error `error: redefinition of module 'JavaRuntime'`. To avoid that, add `module.modulemap` in the source directory so it's not generated. Fixes: https://github.com/swiftlang/swift-java/issues/229 --- Sources/JavaRuntime/include/module.modulemap | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 Sources/JavaRuntime/include/module.modulemap diff --git a/Sources/JavaRuntime/include/module.modulemap b/Sources/JavaRuntime/include/module.modulemap new file mode 100644 index 00000000..2c0d4a98 --- /dev/null +++ b/Sources/JavaRuntime/include/module.modulemap @@ -0,0 +1,4 @@ +module JavaRuntime { + umbrella header "JavaRuntime.h" + export * +} From 6e53b3b4c4420a0300d6362865418324848d8d11 Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Wed, 25 Jun 2025 18:51:33 -0700 Subject: [PATCH 294/426] [JExtract] Stop using SyntaxVisitor for Swift2JavaVisitor (#290) --- Sources/JExtractSwiftLib/ImportedDecls.swift | 4 +- .../Swift2JavaTranslator.swift | 2 +- .../JExtractSwiftLib/Swift2JavaVisitor.swift | 171 ++++++++---------- 3 files changed, 77 insertions(+), 100 deletions(-) diff --git a/Sources/JExtractSwiftLib/ImportedDecls.swift b/Sources/JExtractSwiftLib/ImportedDecls.swift index ee86fc98..0a5952f3 100644 --- a/Sources/JExtractSwiftLib/ImportedDecls.swift +++ b/Sources/JExtractSwiftLib/ImportedDecls.swift @@ -37,8 +37,8 @@ package class ImportedNominalType: ImportedDecl { self.swiftNominal = swiftNominal } - var javaClassName: String { - swiftNominal.name + var swiftType: SwiftType { + return .nominal(.init(nominalTypeDecl: swiftNominal)) } } diff --git a/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift b/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift index 07d8cafb..89deda9a 100644 --- a/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift +++ b/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift @@ -106,7 +106,7 @@ extension Swift2JavaTranslator { for input in self.inputs { log.trace("Analyzing \(input.filePath)") - visitor.walk(input.syntax) + visitor.visit(sourceFile: input.syntax) } } diff --git a/Sources/JExtractSwiftLib/Swift2JavaVisitor.swift b/Sources/JExtractSwiftLib/Swift2JavaVisitor.swift index 0b4d6bbf..7ce982a2 100644 --- a/Sources/JExtractSwiftLib/Swift2JavaVisitor.swift +++ b/Sources/JExtractSwiftLib/Swift2JavaVisitor.swift @@ -16,98 +16,85 @@ import Foundation import SwiftParser import SwiftSyntax -final class Swift2JavaVisitor: SyntaxVisitor { +final class Swift2JavaVisitor { let translator: Swift2JavaTranslator - /// Type context stack associated with the syntax. - var typeContext: [(syntaxID: Syntax.ID, type: ImportedNominalType)] = [] - - /// Innermost type context. - var currentType: ImportedNominalType? { typeContext.last?.type } - - var currentSwiftType: SwiftType? { - guard let currentType else { return nil } - return .nominal(SwiftNominalType(nominalTypeDecl: currentType.swiftNominal)) - } - - /// The current type name as a nested name like A.B.C. - var currentTypeName: String? { self.currentType?.swiftNominal.qualifiedName } - - var log: Logger { translator.log } - init(translator: Swift2JavaTranslator) { self.translator = translator - - super.init(viewMode: .all) } - /// Push specified type to the type context associated with the syntax. - func pushTypeContext(syntax: some SyntaxProtocol, importedNominal: ImportedNominalType) { - typeContext.append((syntax.id, importedNominal)) - } + var log: Logger { translator.log } - /// Pop type context if the current context is associated with the syntax. - func popTypeContext(syntax: some SyntaxProtocol) -> Bool { - if typeContext.last?.syntaxID == syntax.id { - typeContext.removeLast() - return true - } else { - return false + func visit(sourceFile node: SourceFileSyntax) { + for codeItem in node.statements { + if let declNode = codeItem.item.as(DeclSyntax.self) { + self.visit(decl: declNode, in: nil) + } } } - override func visit(_ node: ClassDeclSyntax) -> SyntaxVisitorContinueKind { - log.debug("Visit \(node.kind): '\(node.qualifiedNameForDebug)'") - guard let importedNominalType = translator.importedNominalType(node, parent: self.currentType) else { - return .skipChildren + func visit(decl node: DeclSyntax, in parent: ImportedNominalType?) { + switch node.as(DeclSyntaxEnum.self) { + case .actorDecl(let node): + self.visit(nominalDecl: node, in: parent) + case .classDecl(let node): + self.visit(nominalDecl: node, in: parent) + case .structDecl(let node): + self.visit(nominalDecl: node, in: parent) + case .enumDecl(let node): + self.visit(nominalDecl: node, in: parent) + case .protocolDecl(let node): + self.visit(nominalDecl: node, in: parent) + case .extensionDecl(let node): + self.visit(extensionDecl: node, in: parent) + case .typeAliasDecl: + break // TODO: Implement + case .associatedTypeDecl: + break // TODO: Implement + + case .initializerDecl(let node): + self.visit(initializerDecl: node, in: parent) + case .functionDecl(let node): + self.visit(functionDecl: node, in: parent) + case .variableDecl(let node): + self.visit(variableDecl: node, in: parent) + case .subscriptDecl: + // TODO: Implement + break + + default: + break } - - self.pushTypeContext(syntax: node, importedNominal: importedNominalType) - return .visitChildren } - override func visitPost(_ node: ClassDeclSyntax) { - if self.popTypeContext(syntax: node) { - log.debug("Completed import: \(node.kind) \(node.name)") + func visit( + nominalDecl node: some DeclSyntaxProtocol & DeclGroupSyntax & NamedDeclSyntax & WithAttributesSyntax & WithModifiersSyntax, + in parent: ImportedNominalType? + ) { + guard let importedNominalType = translator.importedNominalType(node, parent: parent) else { + return } - } - - override func visit(_ node: StructDeclSyntax) -> SyntaxVisitorContinueKind { - log.debug("Visit \(node.kind): \(node.qualifiedNameForDebug)") - guard let importedNominalType = translator.importedNominalType(node, parent: self.currentType) else { - return .skipChildren + for memberItem in node.memberBlock.members { + self.visit(decl: memberItem.decl, in: importedNominalType) } - - self.pushTypeContext(syntax: node, importedNominal: importedNominalType) - return .visitChildren } - override func visitPost(_ node: StructDeclSyntax) { - if self.popTypeContext(syntax: node) { - log.debug("Completed import: \(node.kind) \(node.qualifiedNameForDebug)") + func visit(extensionDecl node: ExtensionDeclSyntax, in parent: ImportedNominalType?) { + guard parent != nil else { + // 'extension' in a nominal type is invalid. Ignore + return } - } - - override func visit(_ node: ExtensionDeclSyntax) -> SyntaxVisitorContinueKind { - // Resolve the extended type of the extension as an imported nominal, and - // recurse if we found it. guard let importedNominalType = translator.importedNominalType(node.extendedType) else { - return .skipChildren + return } - - self.pushTypeContext(syntax: node, importedNominal: importedNominalType) - return .visitChildren - } - - override func visitPost(_ node: ExtensionDeclSyntax) { - if self.popTypeContext(syntax: node) { - log.debug("Completed import: \(node.kind) \(node.qualifiedNameForDebug)") + for memberItem in node.memberBlock.members { + self.visit(decl: memberItem.decl, in: importedNominalType) } } - override func visit(_ node: FunctionDeclSyntax) -> SyntaxVisitorContinueKind { + func visit(functionDecl node: FunctionDeclSyntax, in typeContext: ImportedNominalType?) { guard node.shouldImport(log: log) else { - return .skipChildren + return } self.log.debug("Import function: '\(node.qualifiedNameForDebug)'") @@ -116,12 +103,12 @@ final class Swift2JavaVisitor: SyntaxVisitor { do { signature = try SwiftFunctionSignature( node, - enclosingType: self.currentSwiftType, + enclosingType: typeContext?.swiftType, symbolTable: self.translator.symbolTable ) } catch { self.log.debug("Failed to import: '\(node.qualifiedNameForDebug)'; \(error)") - return .skipChildren + return } let imported = ImportedFunc( @@ -133,22 +120,20 @@ final class Swift2JavaVisitor: SyntaxVisitor { ) log.debug("Record imported method \(node.qualifiedNameForDebug)") - if let currentType { - currentType.methods.append(imported) + if let typeContext { + typeContext.methods.append(imported) } else { translator.importedGlobalFuncs.append(imported) } - - return .skipChildren } - override func visit(_ node: VariableDeclSyntax) -> SyntaxVisitorContinueKind { + func visit(variableDecl node: VariableDeclSyntax, in typeContext: ImportedNominalType?) { guard node.shouldImport(log: log) else { - return .skipChildren + return } guard let binding = node.bindings.first else { - return .skipChildren + return } let varName = "\(binding.pattern.trimmed)" @@ -159,7 +144,7 @@ final class Swift2JavaVisitor: SyntaxVisitor { let signature = try SwiftFunctionSignature( node, isSet: kind == .setter, - enclosingType: self.currentSwiftType, + enclosingType: typeContext?.swiftType, symbolTable: self.translator.symbolTable ) @@ -170,10 +155,10 @@ final class Swift2JavaVisitor: SyntaxVisitor { apiKind: kind, functionSignature: signature ) - + log.debug("Record imported variable accessor \(kind == .getter ? "getter" : "setter"):\(node.qualifiedNameForDebug)") - if let currentType { - currentType.variables.append(imported) + if let typeContext { + typeContext.variables.append(imported) } else { translator.importedGlobalVariables.append(imported) } @@ -189,18 +174,16 @@ final class Swift2JavaVisitor: SyntaxVisitor { } } catch { self.log.debug("Failed to import: \(node.qualifiedNameForDebug); \(error)") - return .skipChildren } - - return .skipChildren } - override func visit(_ node: InitializerDeclSyntax) -> SyntaxVisitorContinueKind { - guard let currentType else { - fatalError("Initializer must be within a current type, was: \(node)") + func visit(initializerDecl node: InitializerDeclSyntax, in typeContext: ImportedNominalType?) { + guard let typeContext else { + self.log.info("Initializer must be within a current type; \(node)") + return } guard node.shouldImport(log: log) else { - return .skipChildren + return } self.log.debug("Import initializer: \(node.kind) '\(node.qualifiedNameForDebug)'") @@ -209,12 +192,12 @@ final class Swift2JavaVisitor: SyntaxVisitor { do { signature = try SwiftFunctionSignature( node, - enclosingType: self.currentSwiftType, + enclosingType: typeContext.swiftType, symbolTable: self.translator.symbolTable ) } catch { self.log.debug("Failed to import: \(node.qualifiedNameForDebug); \(error)") - return .skipChildren + return } let imported = ImportedFunc( module: translator.swiftModuleName, @@ -224,13 +207,7 @@ final class Swift2JavaVisitor: SyntaxVisitor { functionSignature: signature ) - currentType.initializers.append(imported) - - return .skipChildren - } - - override func visit(_ node: DeinitializerDeclSyntax) -> SyntaxVisitorContinueKind { - return .skipChildren + typeContext.initializers.append(imported) } } From 45205e1c726804ff79491b223711af2676a85fd2 Mon Sep 17 00:00:00 2001 From: Alexander <45719053+KeoFoxy@users.noreply.github.com> Date: Fri, 27 Jun 2025 07:59:58 +0300 Subject: [PATCH 295/426] feature: Code enhancement (#267) --- .../src/test/java/org/swift/swiftkit/SwiftArenaTest.java | 4 ++-- Sources/JExtractSwiftLib/CodePrinter.swift | 4 ++-- .../JExtractSwiftLib/Convenience/SwiftSyntax+Extensions.swift | 4 ++-- Sources/JExtractSwiftLib/Logger.swift | 2 +- Sources/JavaKit/JavaKitVM/LockedState.swift | 4 ++-- Sources/JavaKit/JavaValue.swift | 2 +- Sources/SwiftKitSwift/SwiftKit.swift | 2 +- .../main/java/org/swift/swiftkit/SwiftValueWitnessTable.java | 2 +- USER_GUIDE.md | 4 ++-- 9 files changed, 14 insertions(+), 14 deletions(-) diff --git a/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/SwiftArenaTest.java b/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/SwiftArenaTest.java index 0d900a62..52d791a1 100644 --- a/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/SwiftArenaTest.java +++ b/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/SwiftArenaTest.java @@ -63,7 +63,7 @@ public void arena_markAsDestroyed_preventUseAfterFree_class() { try { unsafelyEscapedOutsideArenaScope.echoIntMethod(1); - fail("Expected exception to be thrown! Object was suposed to be dead."); + fail("Expected exception to be thrown! Object was supposed to be dead."); } catch (IllegalStateException ex) { return; } @@ -82,7 +82,7 @@ public void arena_markAsDestroyed_preventUseAfterFree_struct() { try { unsafelyEscapedOutsideArenaScope.echoIntMethod(1); - fail("Expected exception to be thrown! Object was suposed to be dead."); + fail("Expected exception to be thrown! Object was supposed to be dead."); } catch (IllegalStateException ex) { return; } diff --git a/Sources/JExtractSwiftLib/CodePrinter.swift b/Sources/JExtractSwiftLib/CodePrinter.swift index 449cab3d..8c22fbee 100644 --- a/Sources/JExtractSwiftLib/CodePrinter.swift +++ b/Sources/JExtractSwiftLib/CodePrinter.swift @@ -53,14 +53,14 @@ public struct CodePrinter { self.mode = mode } - internal mutating func append(_ text: String) { + mutating func append(_ text: String) { contents.append(text) if self.verbose { Swift.print(text, terminator: "") } } - internal mutating func append(contentsOf text: S) + mutating func append(contentsOf text: S) where S: Sequence, S.Element == Character { contents.append(contentsOf: text) if self.verbose { diff --git a/Sources/JExtractSwiftLib/Convenience/SwiftSyntax+Extensions.swift b/Sources/JExtractSwiftLib/Convenience/SwiftSyntax+Extensions.swift index b732b9f8..da836d45 100644 --- a/Sources/JExtractSwiftLib/Convenience/SwiftSyntax+Extensions.swift +++ b/Sources/JExtractSwiftLib/Convenience/SwiftSyntax+Extensions.swift @@ -16,7 +16,7 @@ import SwiftDiagnostics import SwiftSyntax extension WithModifiersSyntax { - internal var accessControlModifiers: DeclModifierListSyntax { + var accessControlModifiers: DeclModifierListSyntax { modifiers.filter { modifier in modifier.isAccessControl } @@ -24,7 +24,7 @@ extension WithModifiersSyntax { } extension ImplicitlyUnwrappedOptionalTypeSyntax { - internal var asOptionalTypeSyntax: any TypeSyntaxProtocol { + var asOptionalTypeSyntax: any TypeSyntaxProtocol { OptionalTypeSyntax( leadingTrivia: leadingTrivia, unexpectedBeforeWrappedType, diff --git a/Sources/JExtractSwiftLib/Logger.swift b/Sources/JExtractSwiftLib/Logger.swift index 180ffb54..541dbae4 100644 --- a/Sources/JExtractSwiftLib/Logger.swift +++ b/Sources/JExtractSwiftLib/Logger.swift @@ -111,7 +111,7 @@ extension Logger.Level: ExpressibleByArgument { } extension Logger.Level { - internal var naturalIntegralValue: Int { + var naturalIntegralValue: Int { switch self { case .trace: return 0 diff --git a/Sources/JavaKit/JavaKitVM/LockedState.swift b/Sources/JavaKit/JavaKitVM/LockedState.swift index e095668c..b3082efc 100644 --- a/Sources/JavaKit/JavaKitVM/LockedState.swift +++ b/Sources/JavaKit/JavaKitVM/LockedState.swift @@ -13,9 +13,9 @@ //===----------------------------------------------------------------------===// #if canImport(os) -internal import os +import os #if FOUNDATION_FRAMEWORK && canImport(C.os.lock) -internal import C.os.lock +import C.os.lock #endif #elseif canImport(Bionic) import Bionic diff --git a/Sources/JavaKit/JavaValue.swift b/Sources/JavaKit/JavaValue.swift index 310b54df..1bc156a0 100644 --- a/Sources/JavaKit/JavaValue.swift +++ b/Sources/JavaKit/JavaValue.swift @@ -34,7 +34,7 @@ import JavaTypes /// The protocol provides operations to bridge values in both directions: /// - `getJNIValue(in:)`: produces the JNI value (of type `JNIType`) for the /// `self` Swift value in the given JNI environment. -/// - `init(fromJNI:in:)`: intializes a Swift value from the JNI value (of +/// - `init(fromJNI:in:)`: initializes a Swift value from the JNI value (of /// type `JNIType`) in the given JNI environment. /// /// The protocol also provides hooks to tie into JNI, including operations to diff --git a/Sources/SwiftKitSwift/SwiftKit.swift b/Sources/SwiftKitSwift/SwiftKit.swift index 38b3c1c8..fb978163 100644 --- a/Sources/SwiftKitSwift/SwiftKit.swift +++ b/Sources/SwiftKitSwift/SwiftKit.swift @@ -34,7 +34,7 @@ public func _swiftjava_swift_isUniquelyReferenced(object: UnsafeMutableRawPointe @_alwaysEmitIntoClient @_transparent - internal func _swiftjava_withHeapObject( +func _swiftjava_withHeapObject( of object: AnyObject, _ body: (UnsafeMutableRawPointer) -> R ) -> R { diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValueWitnessTable.java b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValueWitnessTable.java index 2a031b7e..8ddff1b6 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValueWitnessTable.java +++ b/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValueWitnessTable.java @@ -56,7 +56,7 @@ public abstract class SwiftValueWitnessTable { MemoryLayout.PathElement.groupElement("vwt")); /** - * Given the address of Swift type metadata for a type, return the addres + * Given the address of Swift type metadata for a type, return the address * of the "full" type metadata that can be accessed via fullTypeMetadataLayout. */ public static MemorySegment fullTypeMetadata(MemorySegment typeMetadata) { diff --git a/USER_GUIDE.md b/USER_GUIDE.md index d7d796fd..351a3d5c 100644 --- a/USER_GUIDE.md +++ b/USER_GUIDE.md @@ -221,7 +221,7 @@ Note that we are passing the Jar file in the `classpath` argument when initializ ### Downcasting -All Java classes available in Swift provide `is` and `as` methods to check whether an object dynamically matches another type. The `is` operation is the equivalent of Java's `instanceof` and Swift's `is` operator, and will checkin whether a given object is of the specified type, e.g., +All Java classes available in Swift provide `is` and `as` methods to check whether an object dynamically matches another type. The `is` operation is the equivalent of Java's `instanceof` and Swift's `is` operator, and will checking whether a given object is of the specified type, e.g., ```swift if myObject.is(URL.self) { @@ -626,7 +626,7 @@ The project is still very early days, however the general outline of using this - These `.swiftinterface` files are imported by jextract-swift which generates `*.java` files - The generated Java files contain generated code for efficient native invocations. -You can then use Swift libraries in Java just by calling the apropriate methods and initializers. +You can then use Swift libraries in Java just by calling the appropriate methods and initializers. ## `jextract-swift`: Generating Java bridging files From df03e23c5ac84da6612ed6aa9cfe34f24bdbcbfb Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Mon, 30 Jun 2025 14:26:30 +0900 Subject: [PATCH 296/426] ci: cleanup samples testing using matrix (#292) --- .github/workflows/pull_request.yml | 114 +++-------------------------- 1 file changed, 12 insertions(+), 102 deletions(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 39fa7ee6..c1af9ca7 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -62,8 +62,8 @@ jobs: - name: Swift Test run: "swift test" - verify-sample-01: - name: Verify Sample JavaDependencySampleApp (swift:${{ matrix.swift_version }} jdk:${{matrix.jdk_vendor}} os:${{ matrix.os_version }}) + verify-samples: + name: Verify Sample ${{ matrix.sample_app }} (swift:${{ matrix.swift_version }} jdk:${{matrix.jdk_vendor}} os:${{ matrix.os_version }}) runs-on: ubuntu-latest strategy: fail-fast: false @@ -71,6 +71,14 @@ jobs: swift_version: ['6.1.2'] os_version: ['jammy'] jdk_vendor: ['Corretto'] + sample_app: [ + 'JavaDependencySampleApp', + 'JavaKitSampleApp', + 'JavaProbablyPrime', + 'JavaSieve', + 'SwiftAndJavaJarSampleLib', + 'SwiftKitSampleApp', + ] container: image: ${{ (contains(matrix.swift_version, 'nightly') && 'swiftlang/swift') || 'swift' }}:${{ matrix.swift_version }}-${{ matrix.os_version }} env: @@ -79,103 +87,5 @@ jobs: - uses: actions/checkout@v4 - name: Prepare CI Environment uses: ./.github/actions/prepare_env - - name: "Verify Sample: JavaDependencySampleApp" - run: .github/scripts/validate_sample.sh Samples/JavaDependencySampleApp - verify-sample-02: - name: Verify Sample JavaKitSampleApp (swift:${{ matrix.swift_version }} jdk:${{matrix.jdk_vendor}} os:${{ matrix.os_version }}) - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - swift_version: ['6.1.2'] - os_version: ['jammy'] - jdk_vendor: ['Corretto'] - container: - image: ${{ (contains(matrix.swift_version, 'nightly') && 'swiftlang/swift') || 'swift' }}:${{ matrix.swift_version }}-${{ matrix.os_version }} - env: - JAVA_HOME: "/usr/lib/jvm/default-jdk" - steps: - - uses: actions/checkout@v4 - - name: Prepare CI Environment - uses: ./.github/actions/prepare_env - - name: "Verify Sample" - run: .github/scripts/validate_sample.sh Samples/JavaKitSampleApp - verify-sample-03: - name: Verify Sample JavaProbablyPrime (swift:${{ matrix.swift_version }} jdk:${{matrix.jdk_vendor}} os:${{ matrix.os_version }}) - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - swift_version: ['6.1.2'] - os_version: ['jammy'] - jdk_vendor: ['Corretto'] - container: - image: ${{ (contains(matrix.swift_version, 'nightly') && 'swiftlang/swift') || 'swift' }}:${{ matrix.swift_version }}-${{ matrix.os_version }} - env: - JAVA_HOME: "/usr/lib/jvm/default-jdk" - steps: - - uses: actions/checkout@v4 - - name: Prepare CI Environment - uses: ./.github/actions/prepare_env - - name: "Verify Sample" - run: .github/scripts/validate_sample.sh Samples/JavaProbablyPrime - verify-sample-04: - name: Verify Sample JavaSieve (swift:${{ matrix.swift_version }} jdk:${{matrix.jdk_vendor}} os:${{ matrix.os_version }}) - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - swift_version: ['6.1.2'] - os_version: ['jammy'] - jdk_vendor: ['Corretto'] - container: - image: ${{ (contains(matrix.swift_version, 'nightly') && 'swiftlang/swift') || 'swift' }}:${{ matrix.swift_version }}-${{ matrix.os_version }} - env: - JAVA_HOME: "/usr/lib/jvm/default-jdk" - steps: - - uses: actions/checkout@v4 - - name: Prepare CI Environment - uses: ./.github/actions/prepare_env - - name: "Verify Sample" - run: .github/scripts/validate_sample.sh Samples/JavaSieve - verify-sample-05: - name: Verify Sample SwiftAndJavaJarSampleLib (swift:${{ matrix.swift_version }} jdk:${{matrix.jdk_vendor}} os:${{ matrix.os_version }}) - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - swift_version: ['6.1.2'] - os_version: ['jammy'] - jdk_vendor: ['Corretto'] - container: - image: ${{ (contains(matrix.swift_version, 'nightly') && 'swiftlang/swift') || 'swift' }}:${{ matrix.swift_version }}-${{ matrix.os_version }} - env: - JAVA_HOME: "/usr/lib/jvm/default-jdk" - steps: - - uses: actions/checkout@v4 - - name: Prepare CI Environment - uses: ./.github/actions/prepare_env - - name: "Verify Sample" - run: .github/scripts/validate_sample.sh Samples/SwiftAndJavaJarSampleLib - verify-sample-06: - name: Verify Sample SwiftKitSampleApp (swift:${{ matrix.swift_version }} jdk:${{matrix.jdk_vendor}} os:${{ matrix.os_version }}) - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - swift_version: ['6.1.2'] - os_version: ['jammy'] - jdk_vendor: ['Corretto'] - container: - image: ${{ (contains(matrix.swift_version, 'nightly') && 'swiftlang/swift') || 'swift' }}:${{ matrix.swift_version }}-${{ matrix.os_version }} - env: - JAVA_HOME: "/usr/lib/jvm/default-jdk" - steps: - - uses: actions/checkout@v4 - - name: Prepare CI Environment - uses: ./.github/actions/prepare_env - - name: "Verify Sample" - run: .github/scripts/validate_sample.sh Samples/SwiftKitSampleApp - # TODO: Benchmark compile crashes in CI, enable when nightly toolchains in better shape. - # - name: Build (Swift) Benchmarks - # run: "swift package --package-path Benchmarks/ benchmark list" + - name: "Verify sample" + run: .github/scripts/validate_sample.sh Samples/${{ matrix.sample_app }} From 8c38d1918cb74b9b6c9f87059a579050f4e0893c Mon Sep 17 00:00:00 2001 From: Mads Odgaard Date: Mon, 30 Jun 2025 17:20:13 +0200 Subject: [PATCH 297/426] Add JExtract JNI sample app (#295) Co-authored-by: Konrad `ktoso` Malawski --- .github/workflows/pull_request.yml | 1 + Samples/JExtractJNISampleApp/Package.swift | 79 +++++++ .../MySwiftLibrary/MySwiftLibrary.swift | 60 ++++++ .../Sources/MySwiftLibrary/swift-java.config | 4 + Samples/JExtractJNISampleApp/build.gradle | 195 ++++++++++++++++++ Samples/JExtractJNISampleApp/ci-validate.sh | 6 + Samples/JExtractJNISampleApp/gradlew | 1 + Samples/JExtractJNISampleApp/gradlew.bat | 1 + .../com/example/swift/HelloJava2SwiftJNI.java | 45 ++++ ...ift2JavaGenerator+SwiftThunkPrinting.swift | 2 +- .../JNI/JNISwift2JavaGenerator.swift | 108 +++++++--- .../JNI/JNIModuleTests.swift | 7 +- 12 files changed, 482 insertions(+), 27 deletions(-) create mode 100644 Samples/JExtractJNISampleApp/Package.swift create mode 100644 Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift create mode 100644 Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/swift-java.config create mode 100644 Samples/JExtractJNISampleApp/build.gradle create mode 100755 Samples/JExtractJNISampleApp/ci-validate.sh create mode 120000 Samples/JExtractJNISampleApp/gradlew create mode 120000 Samples/JExtractJNISampleApp/gradlew.bat create mode 100644 Samples/JExtractJNISampleApp/src/main/java/com/example/swift/HelloJava2SwiftJNI.java diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index c1af9ca7..c9d197e7 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -78,6 +78,7 @@ jobs: 'JavaSieve', 'SwiftAndJavaJarSampleLib', 'SwiftKitSampleApp', + 'JExtractJNISampleApp' ] container: image: ${{ (contains(matrix.swift_version, 'nightly') && 'swiftlang/swift') || 'swift' }}:${{ matrix.swift_version }}-${{ matrix.os_version }} diff --git a/Samples/JExtractJNISampleApp/Package.swift b/Samples/JExtractJNISampleApp/Package.swift new file mode 100644 index 00000000..8c7ce856 --- /dev/null +++ b/Samples/JExtractJNISampleApp/Package.swift @@ -0,0 +1,79 @@ +// swift-tools-version: 6.0 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import CompilerPluginSupport +import PackageDescription + +import class Foundation.FileManager +import class Foundation.ProcessInfo + +// Note: the JAVA_HOME environment variable must be set to point to where +// Java is installed, e.g., +// Library/Java/JavaVirtualMachines/openjdk-21.jdk/Contents/Home. +func findJavaHome() -> String { + if let home = ProcessInfo.processInfo.environment["JAVA_HOME"] { + return home + } + + // This is a workaround for envs (some IDEs) which have trouble with + // picking up env variables during the build process + let path = "\(FileManager.default.homeDirectoryForCurrentUser.path()).java_home" + if let home = try? String(contentsOfFile: path, encoding: .utf8) { + if let lastChar = home.last, lastChar.isNewline { + return String(home.dropLast()) + } + + return home + } + + fatalError("Please set the JAVA_HOME environment variable to point to where Java is installed.") +} +let javaHome = findJavaHome() + +let javaIncludePath = "\(javaHome)/include" +#if os(Linux) + let javaPlatformIncludePath = "\(javaIncludePath)/linux" +#elseif os(macOS) + let javaPlatformIncludePath = "\(javaIncludePath)/darwin" +#else + // TODO: Handle windows as well + #error("Currently only macOS and Linux platforms are supported, this may change in the future.") +#endif + +let package = Package( + name: "JExtractJNISampleApp", + platforms: [ + .macOS(.v15) + ], + products: [ + .library( + name: "MySwiftLibrary", + type: .dynamic, + targets: ["MySwiftLibrary"] + ) + + ], + dependencies: [ + .package(name: "swift-java", path: "../../") + ], + targets: [ + .target( + name: "MySwiftLibrary", + dependencies: [ + .product(name: "JavaKit", package: "swift-java"), + .product(name: "JavaRuntime", package: "swift-java"), + .product(name: "SwiftKitSwift", package: "swift-java"), + ], + exclude: [ + "swift-java.config" + ], + swiftSettings: [ + .swiftLanguageMode(.v5), + .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]), + ], + plugins: [ + .plugin(name: "JExtractSwiftPlugin", package: "swift-java") + ] + ) + ] +) diff --git a/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift b/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift new file mode 100644 index 00000000..be04bc08 --- /dev/null +++ b/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift @@ -0,0 +1,60 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +// This is a "plain Swift" file containing various types of declarations, +// that is exported to Java by using the `jextract-swift` tool. +// +// No annotations are necessary on the Swift side to perform the export. + +#if os(Linux) + import Glibc +#else + import Darwin.C +#endif + +public func helloWorld() { + p("\(#function)") +} + +public func globalTakeInt(i: Int64) { + p("i:\(i)") +} + +public func globalMakeInt() -> Int64 { + return 42 +} + +public func globalWriteString(string: String) -> Int64 { + return Int64(string.count) +} + +public func globalTakeIntInt(i: Int64, j: Int64) { + p("i:\(i), j:\(j)") +} + +// ==== Internal helpers + +func p(_ msg: String, file: String = #fileID, line: UInt = #line, function: String = #function) { + print("[swift][\(file):\(line)](\(function)) \(msg)") + fflush(stdout) +} + +#if os(Linux) + // FIXME: why do we need this workaround? + @_silgen_name("_objc_autoreleaseReturnValue") + public func _objc_autoreleaseReturnValue(a: Any) {} + + @_silgen_name("objc_autoreleaseReturnValue") + public func objc_autoreleaseReturnValue(a: Any) {} +#endif diff --git a/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/swift-java.config b/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/swift-java.config new file mode 100644 index 00000000..46bf1f1c --- /dev/null +++ b/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/swift-java.config @@ -0,0 +1,4 @@ +{ + "javaPackage": "com.example.swift", + "mode": "jni" +} diff --git a/Samples/JExtractJNISampleApp/build.gradle b/Samples/JExtractJNISampleApp/build.gradle new file mode 100644 index 00000000..d0e32857 --- /dev/null +++ b/Samples/JExtractJNISampleApp/build.gradle @@ -0,0 +1,195 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import groovy.json.JsonSlurper +import org.swift.swiftkit.gradle.BuildUtils + +import java.nio.file.* +import kotlinx.serialization.json.* + +plugins { + id("build-logic.java-application-conventions") + id("me.champeau.jmh") version "0.7.2" +} + +group = "org.swift.swiftkit" +version = "1.0-SNAPSHOT" + +repositories { + mavenCentral() +} + +java { + toolchain { + languageVersion.set(JavaLanguageVersion.of(24)) + } +} + +def swiftProductsWithJExtractPlugin() { + def stdout = new ByteArrayOutputStream() + def stderr = new ByteArrayOutputStream() + + def result = exec { + commandLine 'swift', 'package', 'describe', '--type', 'json' + standardOutput = stdout + errorOutput = stderr + ignoreExitValue = true + } + + def jsonOutput = stdout.toString() + + if (result.exitValue == 0) { + def json = new JsonSlurper().parseText(jsonOutput) + def products = json.targets + .findAll { target -> + target.product_dependencies?.contains("JExtractSwiftPlugin") + } + .collectMany { target -> + target.product_memberships ?: [] + } + return products + } else { + logger.warn("Command failed: ${stderr.toString()}") + return [] + } +} + + +def swiftCheckValid = tasks.register("swift-check-valid", Exec) { + commandLine "swift" + args("-version") +} + +def jextract = tasks.register("jextract", Exec) { + description = "Generate Java wrappers for swift target" + dependsOn swiftCheckValid + + // only because we depend on "live developing" the plugin while using this project to test it + inputs.file(new File(rootDir, "Package.swift")) + inputs.dir(new File(rootDir, "Sources")) + + // If the package description changes, we should execute jextract again, maybe we added jextract to new targets + inputs.file(new File(projectDir, "Package.swift")) + + // monitor all targets/products which depend on the JExtract plugin + swiftProductsWithJExtractPlugin().each { + logger.info("[swift-java:jextract (Gradle)] Swift input target: ${it}") + inputs.dir(new File(layout.projectDirectory.asFile, "Sources/${it}".toString())) + } + outputs.dir(layout.buildDirectory.dir("../.build/plugins/outputs/${layout.projectDirectory.asFile.getName().toLowerCase()}")) + + File baseSwiftPluginOutputsDir = layout.buildDirectory.dir("../.build/plugins/outputs/").get().asFile + if (!baseSwiftPluginOutputsDir.exists()) { + baseSwiftPluginOutputsDir.mkdirs() + } + Files.walk(layout.buildDirectory.dir("../.build/plugins/outputs/").get().asFile.toPath()).each { + // Add any Java sources generated by the plugin to our sourceSet + if (it.endsWith("JExtractSwiftPlugin/src/generated/java")) { + outputs.dir(it) + } + } + + workingDir = layout.projectDirectory + commandLine "swift" + args("build") // since Swift targets which need to be jextract-ed have the jextract build plugin, we just need to build + // If we wanted to execute a specific subcommand, we can like this: + // args("run",/* + // "swift-java", "jextract", + // "--swift-module", "MySwiftLibrary", + // // java.package is obtained from the swift-java.config in the swift module + // "--output-java", "${layout.buildDirectory.dir(".build/plugins/outputs/${layout.projectDirectory.asFile.getName().toLowerCase()}/JExtractSwiftPlugin/src/generated/java").get()}", + // "--output-swift", "${layout.buildDirectory.dir(".build/plugins/outputs/${layout.projectDirectory.asFile.getName().toLowerCase()}/JExtractSwiftPlugin/Sources").get()}", + // "--log-level", (logging.level <= LogLevel.INFO ? "debug" : */"info") + // ) +} + +// Add the java-swift generated Java sources +sourceSets { + main { + java { + srcDir(jextract) + } + } + test { + java { + srcDir(jextract) + } + } + jmh { + java { + srcDir(jextract) + } + } +} + +tasks.build { + dependsOn("jextract") +} + + +def cleanSwift = tasks.register("cleanSwift", Exec) { + workingDir = layout.projectDirectory + commandLine "swift" + args("package", "clean") +} +tasks.clean { + dependsOn("cleanSwift") +} + +dependencies { + implementation(project(':SwiftKit')) + + testImplementation(platform("org.junit:junit-bom:5.10.0")) + testImplementation("org.junit.jupiter:junit-jupiter") +} + +tasks.named('test', Test) { + useJUnitPlatform() +} + +application { + mainClass = "com.example.swift.HelloJava2SwiftJNI" + + applicationDefaultJvmArgs = [ + "--enable-native-access=ALL-UNNAMED", + + // Include the library paths where our dylibs are that we want to load and call + "-Djava.library.path=" + + (BuildUtils.javaLibraryPaths(rootDir) + + BuildUtils.javaLibraryPaths(project.projectDir)).join(":"), + + + // Enable tracing downcalls (to Swift) + "-Djextract.trace.downcalls=true" + ] +} + +String jmhIncludes = findProperty("jmhIncludes") + +jmh { + if (jmhIncludes != null) { + includes = [jmhIncludes] + } + + jvmArgsAppend = [ + "--enable-native-access=ALL-UNNAMED", + + "-Djava.library.path=" + + (BuildUtils.javaLibraryPaths(rootDir) + + BuildUtils.javaLibraryPaths(project.projectDir)).join(":"), + + // Enable tracing downcalls (to Swift) + "-Djextract.trace.downcalls=false" + ] +} diff --git a/Samples/JExtractJNISampleApp/ci-validate.sh b/Samples/JExtractJNISampleApp/ci-validate.sh new file mode 100755 index 00000000..07b42627 --- /dev/null +++ b/Samples/JExtractJNISampleApp/ci-validate.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +set -x +set -e + +./gradlew run \ No newline at end of file diff --git a/Samples/JExtractJNISampleApp/gradlew b/Samples/JExtractJNISampleApp/gradlew new file mode 120000 index 00000000..343e0d2c --- /dev/null +++ b/Samples/JExtractJNISampleApp/gradlew @@ -0,0 +1 @@ +../../gradlew \ No newline at end of file diff --git a/Samples/JExtractJNISampleApp/gradlew.bat b/Samples/JExtractJNISampleApp/gradlew.bat new file mode 120000 index 00000000..cb5a9464 --- /dev/null +++ b/Samples/JExtractJNISampleApp/gradlew.bat @@ -0,0 +1 @@ +../../gradlew.bat \ No newline at end of file diff --git a/Samples/JExtractJNISampleApp/src/main/java/com/example/swift/HelloJava2SwiftJNI.java b/Samples/JExtractJNISampleApp/src/main/java/com/example/swift/HelloJava2SwiftJNI.java new file mode 100644 index 00000000..36bad93c --- /dev/null +++ b/Samples/JExtractJNISampleApp/src/main/java/com/example/swift/HelloJava2SwiftJNI.java @@ -0,0 +1,45 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package com.example.swift; + +// Import swift-extract generated sources + +// Import javakit/swiftkit support libraries + +import org.swift.swiftkit.SwiftKit; + +public class HelloJava2SwiftJNI { + + public static void main(String[] args) { + System.out.print("Property: java.library.path = " + SwiftKit.getJavaLibraryPath()); + + examples(); + } + + static void examples() { + MySwiftLibrary.helloWorld(); + + MySwiftLibrary.globalTakeInt(1337); + MySwiftLibrary.globalTakeIntInt(1337, 42); + + long cnt = MySwiftLibrary.globalWriteString("String from Java"); + SwiftKit.trace("count = " + cnt); + + long i = MySwiftLibrary.globalMakeInt(); + SwiftKit.trace("globalMakeInt() = " + i); + + System.out.println("DONE."); + } +} diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+SwiftThunkPrinting.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+SwiftThunkPrinting.swift index 54ce0d72..d6b09b24 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+SwiftThunkPrinting.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+SwiftThunkPrinting.swift @@ -27,7 +27,7 @@ extension FFMSwift2JavaGenerator { var printer = CodePrinter() printer.print("// Empty file generated on purpose") - try printer.writeContents( + _ = try printer.writeContents( outputDirectory: self.swiftOutputDirectory, javaPackagePath: nil, filename: expectedFileName) diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator.swift index 8ec4b437..0f16e697 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator.swift @@ -28,6 +28,10 @@ package class JNISwift2JavaGenerator: Swift2JavaGenerator { var thunkNameRegistry = ThunkNameRegistry() + /// Because we need to write empty files for SwiftPM, keep track which files we didn't write yet, + /// and write an empty file for those. + var expectedOutputSwiftFiles: Set + package init( translator: Swift2JavaTranslator, javaPackage: String, @@ -40,11 +44,31 @@ package class JNISwift2JavaGenerator: Swift2JavaGenerator { self.javaPackage = javaPackage self.swiftOutputDirectory = swiftOutputDirectory self.javaOutputDirectory = javaOutputDirectory + + // If we are forced to write empty files, construct the expected outputs + if translator.config.writeEmptyFiles ?? false { + self.expectedOutputSwiftFiles = Set(translator.inputs.compactMap { (input) -> String? in + guard let filePathPart = input.filePath.split(separator: "/\(translator.swiftModuleName)/").last else { + return nil + } + + return String(filePathPart.replacing(".swift", with: "+SwiftJava.swift")) + }) + self.expectedOutputSwiftFiles.insert("\(translator.swiftModuleName)Module+SwiftJava.swift") + } else { + self.expectedOutputSwiftFiles = [] + } } func generate() throws { try writeSwiftThunkSources() try writeExportedJavaSources() + + let pendingFileCount = self.expectedOutputSwiftFiles.count + if pendingFileCount > 0 { + print("[swift-java] Write empty [\(pendingFileCount)] 'expected' files in: \(swiftOutputDirectory)/") + try writeSwiftExpectedEmptySources() + } } } @@ -73,6 +97,19 @@ extension JNISwift2JavaGenerator { try writeSwiftThunkSources(&printer) } + package func writeSwiftExpectedEmptySources() throws { + for expectedFileName in self.expectedOutputSwiftFiles { + logger.trace("Write empty file: \(expectedFileName) ...") + + var printer = CodePrinter() + printer.print("// Empty file generated on purpose") + _ = try printer.writeContents( + outputDirectory: self.swiftOutputDirectory, + javaPackagePath: nil, + filename: expectedFileName) + } + } + package func writeSwiftThunkSources(_ printer: inout CodePrinter) throws { let moduleFilenameBase = "\(self.swiftModuleName)Module+SwiftJava" let moduleFilename = "\(moduleFilenameBase).swift" @@ -84,10 +121,11 @@ extension JNISwift2JavaGenerator { if let outputFile = try printer.writeContents( outputDirectory: self.swiftOutputDirectory, - javaPackagePath: javaPackagePath, + javaPackagePath: nil, filename: moduleFilename ) { print("[swift-java] Generated: \(moduleFilenameBase.bold).swift (at \(outputFile))") + self.expectedOutputSwiftFiles.remove(moduleFilename) } } catch { logger.warning("Failed to write to Swift thunks: \(moduleFilename)") @@ -113,18 +151,22 @@ extension JNISwift2JavaGenerator { private func printSwiftFunctionThunk(_ printer: inout CodePrinter, _ decl: ImportedFunc) { // TODO: Replace swiftModuleName with class name if non-global - let cName = "Java_" + self.javaPackage.replacingOccurrences(of: ".", with: "_") + "_\(swiftModuleName)_" + decl.name + let cName = + "Java_" + self.javaPackage.replacingOccurrences(of: ".", with: "_") + "_\(swiftModuleName)_" + + decl.name let thunkName = thunkNameRegistry.functionThunkName(decl: decl) let translatedParameters = decl.functionSignature.parameters.enumerated().map { idx, param in (param.parameterName ?? "arg\(idx)", param.type.javaType) } - let thunkParameters = [ - "environment: UnsafeMutablePointer!", - "thisClass: jclass" - ] + translatedParameters.map { "\($0.0): \($0.1.jniTypeName)"} + let thunkParameters = + [ + "environment: UnsafeMutablePointer!", + "thisClass: jclass", + ] + translatedParameters.map { "\($0.0): \($0.1.jniTypeName)" } let swiftReturnType = decl.functionSignature.result.type - let thunkReturnType = !swiftReturnType.isVoid ? " -> \(swiftReturnType.javaType.jniTypeName)" : "" + let thunkReturnType = + !swiftReturnType.isVoid ? " -> \(swiftReturnType.javaType.jniTypeName)" : "" printer.printBraceBlock( """ @@ -132,24 +174,28 @@ extension JNISwift2JavaGenerator { func \(thunkName)(\(thunkParameters.joined(separator: ", ")))\(thunkReturnType) """ ) { printer in - let downcallParameters = zip(decl.functionSignature.parameters, translatedParameters).map { originalParam, translatedParam in - let label = originalParam.argumentLabel.map { "\($0): "} ?? "" + let downcallParameters = zip(decl.functionSignature.parameters, translatedParameters).map { + originalParam, translatedParam in + let label = originalParam.argumentLabel.map { "\($0): " } ?? "" return "\(label)\(originalParam.type)(fromJNI: \(translatedParam.0), in: environment!)" } let tryClause: String = decl.isThrowing ? "try " : "" - let functionDowncall = "\(tryClause)\(swiftModuleName).\(decl.name)(\(downcallParameters.joined(separator: ", ")))" + let functionDowncall = + "\(tryClause)\(swiftModuleName).\(decl.name)(\(downcallParameters.joined(separator: ", ")))" - let innerBody = if swiftReturnType.isVoid { - functionDowncall - } else { - """ - let result = \(functionDowncall) - return result.getJNIValue(in: environment)") - """ - } + let innerBody = + if swiftReturnType.isVoid { + functionDowncall + } else { + """ + let result = \(functionDowncall) + return result.getJNIValue(in: environment) + """ + } if decl.isThrowing { - let dummyReturn = !swiftReturnType.isVoid ? "return \(swiftReturnType).jniPlaceholderValue" : "" + let dummyReturn = + !swiftReturnType.isVoid ? "return \(swiftReturnType).jniPlaceholderValue" : "" printer.print( """ do { @@ -173,6 +219,16 @@ extension JNISwift2JavaGenerator { printPackage(&printer) printModuleClass(&printer) { printer in + printer.print( + """ + static final String LIB_NAME = "\(swiftModuleName)"; + + static { + System.loadLibrary(LIB_NAME); + } + """ + ) + for decl in analysis.importedGlobalFuncs { self.logger.trace("Print global function: \(decl)") printFunctionBinding(&printer, decl) @@ -223,7 +279,9 @@ extension JNISwift2JavaGenerator { */ """ ) - printer.print("public static native \(returnType) \(decl.name)(\(params.joined(separator: ", ")))\(throwsClause);") + printer.print( + "public static native \(returnType) \(decl.name)(\(params.joined(separator: ", ")))\(throwsClause);" + ) } } @@ -253,7 +311,7 @@ extension SwiftStandardLibraryTypeKind { var javaType: JavaType? { switch self { case .bool: .boolean - case .int: .long // TODO: Handle 32-bit or 64-bit + case .int: .long // TODO: Handle 32-bit or 64-bit case .int8: .byte case .uint16: .char case .int16: .short @@ -264,10 +322,10 @@ extension SwiftStandardLibraryTypeKind { case .void: .void case .string: .javaLangString case .uint, .uint8, .uint32, .uint64, - .unsafeRawPointer, .unsafeMutableRawPointer, - .unsafePointer, .unsafeMutablePointer, - .unsafeRawBufferPointer, .unsafeMutableRawBufferPointer, - .unsafeBufferPointer, .unsafeMutableBufferPointer: + .unsafeRawPointer, .unsafeMutableRawPointer, + .unsafePointer, .unsafeMutablePointer, + .unsafeRawBufferPointer, .unsafeMutableRawBufferPointer, + .unsafeBufferPointer, .unsafeMutableBufferPointer: nil } } diff --git a/Tests/JExtractSwiftTests/JNI/JNIModuleTests.swift b/Tests/JExtractSwiftTests/JNI/JNIModuleTests.swift index 2f73cca4..e483a4dd 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIModuleTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIModuleTests.swift @@ -44,6 +44,11 @@ struct JNIModuleTests { package com.example.swift; public final class SwiftModule { + static final String LIB_NAME = "SwiftModule"; + + static { + System.loadLibrary(LIB_NAME); + } """ ]) } @@ -104,7 +109,7 @@ struct JNIModuleTests { @_cdecl("Java_com_example_swift_SwiftModule_takeIntegers") func swiftjava_SwiftModule_takeIntegers_i1_i2_i3_i4(environment: UnsafeMutablePointer!, thisClass: jclass, i1: jbyte, i2: jshort, i3: jint, i4: jlong) -> jchar { let result = SwiftModule.takeIntegers(i1: Int8(fromJNI: i1, in: environment!), i2: Int16(fromJNI: i2, in: environment!), i3: Int32(fromJNI: i3, in: environment!), i4: Int(fromJNI: i4, in: environment!)) - return result.getJNIValue(in: environment)") + return result.getJNIValue(in: environment) } """, """ From ac562975f3e011428f8ddb34b7b23c6fb9bfde2d Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Wed, 2 Jul 2025 08:47:45 +0900 Subject: [PATCH 298/426] ci: simplistic way to get macOS running (#294) --- .github/actions/prepare_env/action.yml | 50 ++++---- .github/scripts/install_swiftly.sh | 88 ++++++++++++++ .github/scripts/validate_sample.sh | 2 + .github/workflows/pull_request.yml | 110 +++++++++++++++--- .licenseignore | 2 + .../JExtractJNISampleApp/gradle.properties | 1 + Samples/JavaDependencySampleApp/Package.swift | 3 + .../JavaDependencySampleApp/gradle.properties | 1 + Samples/JavaKitSampleApp/Package.swift | 9 +- Samples/JavaKitSampleApp/gradle.properties | 1 + Samples/JavaProbablyPrime/Package.swift | 5 +- Samples/JavaProbablyPrime/gradle.properties | 1 + Samples/JavaSieve/Package.swift | 5 +- .../SwiftAndJavaJarSampleLib/Package.swift | 5 +- .../SwiftAndJavaJarSampleLib/ci-validate.sh | 27 +++-- .../gradle.properties | 1 + Samples/SwiftKitSampleApp/Package.swift | 5 +- Samples/SwiftKitSampleApp/gradle.properties | 1 + Samples/gradle.properties | 1 + docker/Dockerfile | 2 +- docker/install_jdk.sh | 6 +- gradle.properties | 1 + 22 files changed, 266 insertions(+), 61 deletions(-) create mode 100755 .github/scripts/install_swiftly.sh create mode 120000 Samples/JExtractJNISampleApp/gradle.properties create mode 120000 Samples/JavaDependencySampleApp/gradle.properties create mode 120000 Samples/JavaKitSampleApp/gradle.properties create mode 120000 Samples/JavaProbablyPrime/gradle.properties create mode 120000 Samples/SwiftAndJavaJarSampleLib/gradle.properties create mode 120000 Samples/SwiftKitSampleApp/gradle.properties create mode 120000 Samples/gradle.properties create mode 100644 gradle.properties diff --git a/.github/actions/prepare_env/action.yml b/.github/actions/prepare_env/action.yml index dfd0a435..33fa1f76 100644 --- a/.github/actions/prepare_env/action.yml +++ b/.github/actions/prepare_env/action.yml @@ -4,36 +4,32 @@ description: 'Prepare the CI environment by installing Swift and selected JDK et runs: using: composite steps: - - name: Install System Dependencies - run: apt-get -qq update && apt-get -qq install -y make curl wget libjemalloc2 libjemalloc-dev - shell: bash - - name: Cache JDKs - id: cache-jdk - uses: actions/cache@v4 - continue-on-error: true + - name: Set up JDK ${{ matrix.jdk_version }} + uses: actions/setup-java@v4 with: - path: /usr/lib/jvm/ - key: ${{ runner.os }}-jdk-${{ matrix.jdk_vendor }}-${{ hashFiles('/usr/lib/jvm/*') }} - restore-keys: | - ${{ runner.os }}-jdk- - - name: Install JDK - if: steps.cache-jdk.outputs.cache-hit != 'true' - run: "bash -xc 'JDK_VENDOR=${{ matrix.jdk_vendor }} ./docker/install_jdk.sh'" + distribution: ${{ matrix.jdk_vendor }} + java-version: | + 24 + 21 + cache: 'gradle' + - name: Set JAVA_HOME_{N} shell: bash - # TODO: not using setup-java since incompatible with the swiftlang/swift base image - # - name: Install Untested Nightly Swift - # run: "bash -xc './docker/install_untested_nightly_swift.sh'" - - name: Cache local Gradle repository - uses: actions/cache@v4 - continue-on-error: true - with: - path: | - /root/.gradle/caches - /root/.gradle/wrapper - key: ${{ runner.os }}-gradle-${{ hashFiles('*/*.gradle*', 'settings.gradle') }} - restore-keys: | - ${{ runner.os }}-gradle- + run: | + if [[ -n "$JAVA_HOME_21_X64" ]]; then + echo "JAVA_HOME_21=$JAVA_HOME_21_X64" >> $GITHUB_ENV + elif [[ -n "$JAVA_HOME_21_ARM64" ]]; then + echo "JAVA_HOME_21=$JAVA_HOME_21_ARM64" >> $GITHUB_ENV + fi + if [[ -n "$JAVA_HOME_24_X64" ]]; then + echo "JAVA_HOME_24=$JAVA_HOME_24_X64" >> $GITHUB_ENV + elif [[ -n "$JAVA_HOME_24_ARM64" ]]; then + echo "JAVA_HOME_24=$JAVA_HOME_24_ARM64" >> $GITHUB_ENV + fi + - name: Check Java environment + shell: bash + run: ./gradlew -q javaToolchains - name: Cache local SwiftPM repository + if: matrix.os_version == 'jammy' uses: actions/cache@v4 continue-on-error: true with: diff --git a/.github/scripts/install_swiftly.sh b/.github/scripts/install_swiftly.sh new file mode 100755 index 00000000..78fa3f6b --- /dev/null +++ b/.github/scripts/install_swiftly.sh @@ -0,0 +1,88 @@ +#!/bin/bash + +# This script is reused from Swiftly itself, see: +# https://github.com/swiftlang/swiftly/blob/main/scripts/prep-gh-action.sh +# +# This script does a bit of extra preparation of the docker containers used to run the GitHub workflows +# that are specific to this project's needs when building/testing. Note that this script runs on +# every supported Linux distribution and macOS so it must adapt to the distribution that it is running. + +if [[ "$(uname -s)" == "Linux" ]]; then + # Install the basic utilities depending on the type of Linux distribution + apt-get --help && apt-get update && TZ=Etc/UTC apt-get -y install curl make gpg tzdata + yum --help && (curl --help && yum -y install curl) && yum install make gpg +fi + +set -e + +while [ $# -ne 0 ]; do + arg="$1" + case "$arg" in + snapshot) + swiftMainSnapshot=true + ;; + *) + ;; + esac + shift +done + +echo "Installing swiftly" + +if [[ "$(uname -s)" == "Linux" ]]; then + curl -O "https://download.swift.org/swiftly/linux/swiftly-$(uname -m).tar.gz" && tar zxf swiftly-*.tar.gz && ./swiftly init -y --skip-install + # shellcheck disable=SC1091 + . "/root/.local/share/swiftly/env.sh" +else + # shellcheck disable=SC2155 + export SWIFTLY_HOME_DIR="$(pwd)/swiftly-bootstrap" + export SWIFTLY_BIN_DIR="$SWIFTLY_HOME_DIR/bin" + export SWIFTLY_TOOLCHAINS_DIR="$SWIFTLY_HOME_DIR/toolchains" + + curl -O https://download.swift.org/swiftly/darwin/swiftly.pkg && pkgutil --check-signature swiftly.pkg && pkgutil --verbose --expand swiftly.pkg "${SWIFTLY_HOME_DIR}" && tar -C "${SWIFTLY_HOME_DIR}" -xvf "${SWIFTLY_HOME_DIR}"/swiftly-*/Payload && "$SWIFTLY_HOME_DIR/bin/swiftly" init -y --skip-install + + # shellcheck disable=SC1091 + . "$SWIFTLY_HOME_DIR/env.sh" +fi + +hash -r + +if [ -n "$GITHUB_ENV" ]; then + echo "Updating GitHub environment" + echo "PATH=$PATH" >> "$GITHUB_ENV" && echo "SWIFTLY_HOME_DIR=$SWIFTLY_HOME_DIR" >> "$GITHUB_ENV" && echo "SWIFTLY_BIN_DIR=$SWIFTLY_BIN_DIR" >> "$GITHUB_ENV" && echo "SWIFTLY_TOOLCHAINS_DIR=$SWIFTLY_TOOLCHAINS_DIR" >> "$GITHUB_ENV" +fi + +selector=() +runSelector=() + +if [ "$swiftMainSnapshot" == true ]; then + echo "Installing latest main-snapshot toolchain" + selector=("main-snapshot") + runSelector=("+main-snapshot") +elif [ -n "${SWIFT_VERSION}" ]; then + echo "Installing selected swift toolchain from SWIFT_VERSION environment variable" + selector=("${SWIFT_VERSION}") + runSelector=() +elif [ -f .swift-version ]; then + echo "Installing selected swift toolchain from .swift-version file" + selector=() + runSelector=() +else + echo "Installing latest toolchain" + selector=("latest") + runSelector=("+latest") +fi + +swiftly install --post-install-file=post-install.sh "${selector[@]}" + +if [ -f post-install.sh ]; then + echo "Performing swift toolchain post-installation" + chmod u+x post-install.sh && ./post-install.sh +fi + +echo "Displaying swift version" +swiftly run "${runSelector[@]}" swift --version + +if [[ "$(uname -s)" == "Linux" ]]; then + CC=clang swiftly run "${runSelector[@]}" "$(dirname "$0")/install-libarchive.sh" +fi diff --git a/.github/scripts/validate_sample.sh b/.github/scripts/validate_sample.sh index b5780976..64265b01 100755 --- a/.github/scripts/validate_sample.sh +++ b/.github/scripts/validate_sample.sh @@ -11,6 +11,8 @@ declare -r RESET='\033[0m' declare -r sampleDir="$1" declare -r CI_VALIDATE_SCRIPT='ci-validate.sh' +echo "Using Swift: $(which swift)" + echo "" echo "" echo "========================================================================" diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index c9d197e7..b55e0489 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -15,18 +15,37 @@ jobs: license_header_check_project_name: Swift.org test-java: - name: Java tests (swift:${{ matrix.swift_version }} jdk:${{matrix.jdk_vendor}} os:${{ matrix.os_version }}) + name: Test (Java) (${{ matrix.os_version }} swift:${{ matrix.swift_version }} jdk:${{matrix.jdk_vendor}}) runs-on: ubuntu-latest strategy: fail-fast: true matrix: swift_version: ['6.1.2'] os_version: ['jammy'] - jdk_vendor: ['Corretto'] + jdk_vendor: ['corretto'] container: image: ${{ (contains(matrix.swift_version, 'nightly') && 'swiftlang/swift') || 'swift' }}:${{ matrix.swift_version }}-${{ matrix.os_version }} env: - JAVA_HOME: "/usr/lib/jvm/default-jdk" + SWIFT_JAVA_VERBOSE: true + steps: + - uses: actions/checkout@v4 + - name: Prepare CI Environment + uses: ./.github/actions/prepare_env + - name: Gradle :SwiftKit:build + run: ./gradlew build -x test + - name: Gradle :SwiftKit:check + run: ./gradlew :SwiftKit:check --info + + test-java-macos: + name: Test (Java) (${{ matrix.os_version }} swift:${{ matrix.swift_version }} jdk:${{matrix.jdk_vendor}}) + runs-on: [self-hosted, macos, sequoia, ARM64] + strategy: + fail-fast: true + matrix: + swift_version: ['6.1.2'] + os_version: ['macos'] + jdk_vendor: ['corretto'] + env: SWIFT_JAVA_VERBOSE: true steps: - uses: actions/checkout@v4 @@ -36,22 +55,59 @@ jobs: run: ./gradlew build -x test - name: Gradle :SwiftKit:check run: ./gradlew :SwiftKit:check --debug + + benchmark-java: + name: Benchmark (JMH) (${{ matrix.os_version }} swift:${{ matrix.swift_version }} jdk:${{matrix.jdk_vendor}}) + runs-on: ubuntu-latest + strategy: + fail-fast: true + matrix: + swift_version: ['6.1.2'] + os_version: ['jammy'] + jdk_vendor: ['corretto'] + container: + image: ${{ (contains(matrix.swift_version, 'nightly') && 'swiftlang/swift') || 'swift' }}:${{ matrix.swift_version }}-${{ matrix.os_version }} + env: + SWIFT_JAVA_VERBOSE: true + steps: + - uses: actions/checkout@v4 + - name: Prepare CI Environment + uses: ./.github/actions/prepare_env - name: Gradle compile JMH benchmarks run: ./gradlew compileJmh --info test-swift: - name: Swift tests (swift:${{ matrix.swift_version }} jdk:${{matrix.jdk_vendor}} os:${{ matrix.os_version }}) + name: Test (Swift) (${{ matrix.os_version }} swift:${{ matrix.swift_version }} jdk:${{matrix.jdk_vendor}}) runs-on: ubuntu-latest strategy: fail-fast: false matrix: swift_version: ['6.1.2'] os_version: ['jammy'] - jdk_vendor: ['Corretto'] + jdk_vendor: ['corretto'] container: image: ${{ (contains(matrix.swift_version, 'nightly') && 'swiftlang/swift') || 'swift' }}:${{ matrix.swift_version }}-${{ matrix.os_version }} env: - JAVA_HOME: "/usr/lib/jvm/default-jdk" + SWIFT_JAVA_VERBOSE: true + steps: + - uses: actions/checkout@v4 + - name: Prepare CI Environment + uses: ./.github/actions/prepare_env + - name: Swift Build + run: "swift build --build-tests --disable-sandbox" + - name: Swift Test + run: "swift test" + + test-swift-macos: + name: Test (Swift) (${{ matrix.os_version }} swift:${{ matrix.swift_version }} jdk:${{matrix.jdk_vendor}}) + runs-on: [self-hosted, macos, sequoia, ARM64] + strategy: + fail-fast: false + matrix: + swift_version: ['6.1.2'] + os_version: ['macos'] + jdk_vendor: ['corretto'] + env: SWIFT_JAVA_VERBOSE: true steps: - uses: actions/checkout@v4 @@ -63,30 +119,58 @@ jobs: run: "swift test" verify-samples: - name: Verify Sample ${{ matrix.sample_app }} (swift:${{ matrix.swift_version }} jdk:${{matrix.jdk_vendor}} os:${{ matrix.os_version }}) + name: Sample ${{ matrix.sample_app }} (${{ matrix.os_version }} swift:${{ matrix.swift_version }} jdk:${{matrix.jdk_vendor}}) runs-on: ubuntu-latest strategy: fail-fast: false matrix: swift_version: ['6.1.2'] os_version: ['jammy'] - jdk_vendor: ['Corretto'] - sample_app: [ + jdk_vendor: ['corretto'] + sample_app: [ # TODO: use a reusable-workflow to generate those names 'JavaDependencySampleApp', 'JavaKitSampleApp', 'JavaProbablyPrime', 'JavaSieve', 'SwiftAndJavaJarSampleLib', 'SwiftKitSampleApp', - 'JExtractJNISampleApp' + 'JExtractJNISampleApp', ] container: image: ${{ (contains(matrix.swift_version, 'nightly') && 'swiftlang/swift') || 'swift' }}:${{ matrix.swift_version }}-${{ matrix.os_version }} - env: - JAVA_HOME: "/usr/lib/jvm/default-jdk" steps: - uses: actions/checkout@v4 - name: Prepare CI Environment uses: ./.github/actions/prepare_env - - name: "Verify sample" + - name: "Verify sample: ${{ matrix.sample_app }}" + run: .github/scripts/validate_sample.sh Samples/${{ matrix.sample_app }} + + + verify-samples-macos: + name: Sample ${{ matrix.sample_app }} (${{ matrix.os_version }} swift:${{ matrix.swift_version }} jdk:${{matrix.jdk_vendor}}) + runs-on: [self-hosted, macos, sequoia, ARM64] + strategy: + fail-fast: false + matrix: + swift_version: ['6.1.2'] + os_version: ['macos'] + jdk_vendor: ['corretto'] + sample_app: [ # TODO: use a reusable-workflow to generate those names + 'JavaDependencySampleApp', + 'JavaKitSampleApp', + 'JavaProbablyPrime', + 'JavaSieve', + 'SwiftAndJavaJarSampleLib', + 'SwiftKitSampleApp', + 'JExtractJNISampleApp', + ] + steps: + - uses: actions/checkout@v4 + - name: Prepare CI Environment + uses: ./.github/actions/prepare_env + - name: Install Swiftly # we specifically install Swiftly in macOS jobs because we want a simpler way to find the right dylib paths for libraries + run: ./.github/scripts/install_swiftly.sh + env: + SWIFT_VERSION: "${{ matrix.swift_version }}" + - name: "Verify sample ${{ matrix.sample_app }}" run: .github/scripts/validate_sample.sh Samples/${{ matrix.sample_app }} diff --git a/.licenseignore b/.licenseignore index 003cac25..a49ab625 100644 --- a/.licenseignore +++ b/.licenseignore @@ -35,6 +35,8 @@ Makefile **/CMakeLists.txt **/*.jar **/generated/*.java +gradle.properties +**/gradle.properties **/generated/*.swift gradle/wrapper/gradle-wrapper.properties gradlew diff --git a/Samples/JExtractJNISampleApp/gradle.properties b/Samples/JExtractJNISampleApp/gradle.properties new file mode 120000 index 00000000..7677fb73 --- /dev/null +++ b/Samples/JExtractJNISampleApp/gradle.properties @@ -0,0 +1 @@ +../gradle.properties \ No newline at end of file diff --git a/Samples/JavaDependencySampleApp/Package.swift b/Samples/JavaDependencySampleApp/Package.swift index 4fa33116..506b8c93 100644 --- a/Samples/JavaDependencySampleApp/Package.swift +++ b/Samples/JavaDependencySampleApp/Package.swift @@ -44,6 +44,9 @@ let package = Package( name: "JavaDependencySampleApp", platforms: [ .macOS(.v15), + .iOS(.v18), + .watchOS(.v11), + .tvOS(.v18), ], products: [ diff --git a/Samples/JavaDependencySampleApp/gradle.properties b/Samples/JavaDependencySampleApp/gradle.properties new file mode 120000 index 00000000..7677fb73 --- /dev/null +++ b/Samples/JavaDependencySampleApp/gradle.properties @@ -0,0 +1 @@ +../gradle.properties \ No newline at end of file diff --git a/Samples/JavaKitSampleApp/Package.swift b/Samples/JavaKitSampleApp/Package.swift index 0956290c..1b545819 100644 --- a/Samples/JavaKitSampleApp/Package.swift +++ b/Samples/JavaKitSampleApp/Package.swift @@ -43,11 +43,10 @@ let javaIncludePath = "\(javaHome)/include" let package = Package( name: "JavaKitSampleApp", platforms: [ - .macOS(.v13), - .iOS(.v13), - .tvOS(.v13), - .watchOS(.v6), - .macCatalyst(.v13), + .macOS(.v15), + .iOS(.v18), + .watchOS(.v11), + .tvOS(.v18), ], products: [ diff --git a/Samples/JavaKitSampleApp/gradle.properties b/Samples/JavaKitSampleApp/gradle.properties new file mode 120000 index 00000000..7677fb73 --- /dev/null +++ b/Samples/JavaKitSampleApp/gradle.properties @@ -0,0 +1 @@ +../gradle.properties \ No newline at end of file diff --git a/Samples/JavaProbablyPrime/Package.swift b/Samples/JavaProbablyPrime/Package.swift index 4cc887f8..9f0ecff2 100644 --- a/Samples/JavaProbablyPrime/Package.swift +++ b/Samples/JavaProbablyPrime/Package.swift @@ -7,7 +7,10 @@ import PackageDescription let package = Package( name: "JavaProbablyPrime", platforms: [ - .macOS(.v10_15), + .macOS(.v15), + .iOS(.v18), + .watchOS(.v11), + .tvOS(.v18), ], products: [ diff --git a/Samples/JavaProbablyPrime/gradle.properties b/Samples/JavaProbablyPrime/gradle.properties new file mode 120000 index 00000000..7677fb73 --- /dev/null +++ b/Samples/JavaProbablyPrime/gradle.properties @@ -0,0 +1 @@ +../gradle.properties \ No newline at end of file diff --git a/Samples/JavaSieve/Package.swift b/Samples/JavaSieve/Package.swift index 65c10481..ee61a021 100644 --- a/Samples/JavaSieve/Package.swift +++ b/Samples/JavaSieve/Package.swift @@ -42,7 +42,10 @@ let javaIncludePath = "\(javaHome)/include" let package = Package( name: "JavaSieve", platforms: [ - .macOS(.v10_15), + .macOS(.v15), + .iOS(.v18), + .watchOS(.v11), + .tvOS(.v18), ], dependencies: [ .package(name: "swift-java", path: "../../"), diff --git a/Samples/SwiftAndJavaJarSampleLib/Package.swift b/Samples/SwiftAndJavaJarSampleLib/Package.swift index c4c604ee..c350a0e7 100644 --- a/Samples/SwiftAndJavaJarSampleLib/Package.swift +++ b/Samples/SwiftAndJavaJarSampleLib/Package.swift @@ -43,7 +43,10 @@ let javaIncludePath = "\(javaHome)/include" let package = Package( name: "SwiftAndJavaJarSampleLib", platforms: [ - .macOS(.v15) + .macOS(.v15), + .iOS(.v18), + .watchOS(.v11), + .tvOS(.v18), ], products: [ .library( diff --git a/Samples/SwiftAndJavaJarSampleLib/ci-validate.sh b/Samples/SwiftAndJavaJarSampleLib/ci-validate.sh index 1b4769e8..f56b611e 100755 --- a/Samples/SwiftAndJavaJarSampleLib/ci-validate.sh +++ b/Samples/SwiftAndJavaJarSampleLib/ci-validate.sh @@ -7,13 +7,21 @@ set -x SWIFT_VERSION="$(swift -version | awk '/Swift version/ { print $3 }')" -# we make sure to build and run with JDK 24 because the runtime needs latest JDK, unlike Gradle which needed 21. -if [ "$(uname -s)" = 'Darwin' ] -then - export OS='osx' +# This is how env variables are set by setup-java +if [ "$(uname -m)" = 'arm64' ]; then + ARCH=ARM64 + JAVAC="${JAVA_HOME_24_ARM64}/bin/javac" + JAVA="${JAVA_HOME_24_ARM64}/bin/java" +else + ARCH=X64 + JAVAC="${JAVA_HOME_24_X64}/bin/javac" + JAVA="${JAVA_HOME_24_X64}/bin/java" +fi + +if [ -n "$JAVA_HOME_24_$ARCH" ]; then + export JAVA_HOME="$JAVA_HOME_24_$ARCH" elif [ "$(uname -s)" = 'Linux' ] then - export OS='linux' export PATH="${PATH}:/usr/lib/jvm/jdk-24/bin" # we need to make sure to use the latest JDK to actually compile/run the executable fi @@ -24,8 +32,9 @@ MYLIB_CLASSPATH="$(pwd)/build/libs/*" CLASSPATH="$(pwd)/:${SWIFTKIT_CLASSPATH}:${MYLIB_CLASSPATH}" echo "CLASSPATH = ${CLASSPATH}" -javac -cp "${CLASSPATH}" Example.java +$JAVAC -cp "${CLASSPATH}" Example.java +# FIXME: move all this into Gradle or SwiftPM and make it easier to get the right classpath for running if [ "$(uname -s)" = 'Linux' ] then SWIFT_LIB_PATHS=/usr/lib/swift/linux @@ -35,6 +44,7 @@ then SWIFT_CORE_LIB=$(find "$HOME"/.local -name "libswiftCore.so" 2>/dev/null | grep "$SWIFT_VERSION" | head -n1) if [ -n "$SWIFT_CORE_LIB" ]; then SWIFT_LIB_PATHS="${SWIFT_LIB_PATHS}:$(dirname "$SWIFT_CORE_LIB")" + ls "$SWIFT_LIB_PATHS" else # maybe there is one installed system-wide in /usr/lib? SWIFT_CORE_LIB2=$(find /usr/lib -name "libswiftCore.so" 2>/dev/null | grep "$SWIFT_VERSION" | head -n1) @@ -44,13 +54,14 @@ then fi elif [ "$(uname -s)" = 'Darwin' ] then - SWIFT_LIB_PATHS=$(find "$(swiftly use --print-location)" | grep dylib$ | grep libswiftCore | grep macos | xargs dirname) + SWIFT_LIB_PATHS=$(find "$(swiftly use --print-location)" | grep dylib$ | grep libswiftCore | grep macos | head -n1 | xargs dirname) SWIFT_LIB_PATHS="${SWIFT_LIB_PATHS}:$(pwd)/$(find . | grep libMySwiftLibrary.dylib$ | sort | head -n1 | xargs dirname)" + fi echo "SWIFT_LIB_PATHS = ${SWIFT_LIB_PATHS}" # Can we run the example? -java --enable-native-access=ALL-UNNAMED \ +${JAVA} --enable-native-access=ALL-UNNAMED \ -Djava.library.path="${SWIFT_LIB_PATHS}" \ -cp "${CLASSPATH}" \ Example diff --git a/Samples/SwiftAndJavaJarSampleLib/gradle.properties b/Samples/SwiftAndJavaJarSampleLib/gradle.properties new file mode 120000 index 00000000..7677fb73 --- /dev/null +++ b/Samples/SwiftAndJavaJarSampleLib/gradle.properties @@ -0,0 +1 @@ +../gradle.properties \ No newline at end of file diff --git a/Samples/SwiftKitSampleApp/Package.swift b/Samples/SwiftKitSampleApp/Package.swift index 34d8fcd3..8501062b 100644 --- a/Samples/SwiftKitSampleApp/Package.swift +++ b/Samples/SwiftKitSampleApp/Package.swift @@ -43,7 +43,10 @@ let javaIncludePath = "\(javaHome)/include" let package = Package( name: "SwiftKitSampleApp", platforms: [ - .macOS(.v15) + .macOS(.v15), + .iOS(.v18), + .watchOS(.v11), + .tvOS(.v18), ], products: [ .library( diff --git a/Samples/SwiftKitSampleApp/gradle.properties b/Samples/SwiftKitSampleApp/gradle.properties new file mode 120000 index 00000000..7677fb73 --- /dev/null +++ b/Samples/SwiftKitSampleApp/gradle.properties @@ -0,0 +1 @@ +../gradle.properties \ No newline at end of file diff --git a/Samples/gradle.properties b/Samples/gradle.properties new file mode 120000 index 00000000..7677fb73 --- /dev/null +++ b/Samples/gradle.properties @@ -0,0 +1 @@ +../gradle.properties \ No newline at end of file diff --git a/docker/Dockerfile b/docker/Dockerfile index 6604d091..06b17a87 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -21,6 +21,6 @@ ENV LANGUAGE=en_US.UTF-8 COPY install_jdk.sh . # JDK dependency -RUN bash -xc 'JDK_VENDOR=Corretto ./install_jdk.sh' +RUN bash -xc 'JDK_VENDOR=corretto ./install_jdk.sh' ENV JAVA_HOME="/usr/lib/jvm/default-jdk" ENV PATH="$PATH:/usr/lib/jvm/default-jdk/bin" diff --git a/docker/install_jdk.sh b/docker/install_jdk.sh index 8d0ddda3..122c0d06 100755 --- a/docker/install_jdk.sh +++ b/docker/install_jdk.sh @@ -17,9 +17,9 @@ set -euo pipefail # We need JDK 24 because that's the supported version with latest FFM # However, we also need JDK 23 at most because Gradle does not support 24. -# Supported JDKs: Corretto +# Supported JDKs: corretto if [ "$JDK_VENDOR" = "" ]; then -declare -r JDK_VENDOR="Corretto" +declare -r JDK_VENDOR="corretto" fi apt-get update && apt-get install -y wget tree @@ -33,7 +33,7 @@ download_and_install_jdk() { echo "Installing $JDK_VENDOR JDK (${jdk_version})..." - if [ "$JDK_VENDOR" = 'Corretto' ]; then + if [ "$JDK_VENDOR" = 'corretto' ]; then if [ "$(uname -m)" = 'aarch64' ]; then case "$jdk_version" in "21") diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 00000000..335b6f40 --- /dev/null +++ b/gradle.properties @@ -0,0 +1 @@ +org.gradle.java.installations.fromEnv=JAVA_HOME_24,JAVA_HOME_24_X64,JAVA_HOME_24_ARM64,JAVA_HOME_21,JAVA_HOME_21_X64,JAVA_HOME_21_ARM64 \ No newline at end of file From 3c3e41185c79266bf671ee8ff4ee3797a6c1c053 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Wed, 2 Jul 2025 18:54:23 +0900 Subject: [PATCH 299/426] wrap-java: add option to match java package style directory nesting (#296) --- Sources/SwiftJavaTool/Commands/WrapJavaCommand.swift | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Sources/SwiftJavaTool/Commands/WrapJavaCommand.swift b/Sources/SwiftJavaTool/Commands/WrapJavaCommand.swift index 349144ab..05ac7651 100644 --- a/Sources/SwiftJavaTool/Commands/WrapJavaCommand.swift +++ b/Sources/SwiftJavaTool/Commands/WrapJavaCommand.swift @@ -52,6 +52,9 @@ extension SwiftJava { @Option(help: "Cache directory for intermediate results and other outputs between runs") var cacheDirectory: String? + @Option(help: "Match java package directory structure with generated Swift files") + var swiftMatchPackageDirectoryStructure: Bool = false + @Argument(help: "Path to .jar file whose Java classes should be wrapped using Swift bindings") var input: String } @@ -229,11 +232,16 @@ extension SwiftJava.WrapJavaCommand { """ + var generatedFileOutputDir = self.actualOutputDirectory + if self.swiftMatchPackageDirectoryStructure { + generatedFileOutputDir?.append(path: javaClass.getPackageName().replacing(".", with: "/")) + } + let swiftFileName = try! translator.getSwiftTypeName(javaClass, preferValueTypes: false) .swiftName.replacing(".", with: "+") + ".swift" try writeContents( swiftFileText, - outputDirectory: self.actualOutputDirectory, + outputDirectory: generatedFileOutputDir, to: swiftFileName, description: "Java class '\(javaClass.getName())' translation" ) From 56dfcfa0a054fee24098bf54eea041dfe2d21729 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Thu, 3 Jul 2025 12:24:45 +0900 Subject: [PATCH 300/426] rename package to fit ecosystem pattern of lowercase and dash (#297) --- Package.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Package.swift b/Package.swift index 58ee1840..403617da 100644 --- a/Package.swift +++ b/Package.swift @@ -84,7 +84,7 @@ let javaIncludePath = "\(javaHome)/include" #endif let package = Package( - name: "SwiftJava", + name: "swift-java", platforms: [ .macOS(.v15) ], From e887a9fdb35f66cf0cfcec38b0d50d5aaa4cda70 Mon Sep 17 00:00:00 2001 From: Mads Odgaard Date: Thu, 3 Jul 2025 13:10:37 +0200 Subject: [PATCH 301/426] [JExtract] Generate JNI code for classes (static methods and initializers) (#298) --- .../Sources/MySwiftLibrary/MySwiftClass.swift | 37 + Samples/JExtractJNISampleApp/build.gradle | 5 + Samples/JExtractJNISampleApp/ci-validate.sh | 3 +- .../com/example/swift/HelloJava2SwiftJNI.java | 5 + .../com/example/swift/MySwiftClassTest.java | 37 + .../com/example/swift/MySwiftLibraryTest.java | 57 ++ .../Convenience/JavaType+Extensions.swift | 38 + ...t2JavaGenerator+JavaBindingsPrinting.swift | 2 +- ...MSwift2JavaGenerator+JavaTranslation.swift | 878 +++++++++--------- Sources/JExtractSwiftLib/ImportedDecls.swift | 18 + ...t2JavaGenerator+JavaBindingsPrinting.swift | 197 ++++ ...ISwift2JavaGenerator+JavaTranslation.swift | 123 +++ ...ift2JavaGenerator+SwiftThunkPrinting.swift | 268 ++++++ .../JNI/JNISwift2JavaGenerator.swift | 262 +----- Sources/JExtractSwiftLib/JavaParameter.swift | 25 + Sources/JavaTypes/JavaType+SwiftNames.swift | 7 + .../JNI/JNIClassTests.swift | 173 ++++ .../JNI/JNIModuleTests.swift | 30 +- 18 files changed, 1444 insertions(+), 721 deletions(-) create mode 100644 Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftClass.swift create mode 100644 Samples/JExtractJNISampleApp/src/test/java/com/example/swift/MySwiftClassTest.java create mode 100644 Samples/JExtractJNISampleApp/src/test/java/com/example/swift/MySwiftLibraryTest.java create mode 100644 Sources/JExtractSwiftLib/Convenience/JavaType+Extensions.swift create mode 100644 Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift create mode 100644 Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift create mode 100644 Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift create mode 100644 Sources/JExtractSwiftLib/JavaParameter.swift create mode 100644 Tests/JExtractSwiftTests/JNI/JNIClassTests.swift diff --git a/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftClass.swift b/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftClass.swift new file mode 100644 index 00000000..fca6236f --- /dev/null +++ b/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftClass.swift @@ -0,0 +1,37 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +public class MySwiftClass { + let x: Int64 + let y: Int64 + + public static func method() { + p("Hello from static method in a class!") + } + + public init(x: Int64, y: Int64) { + self.x = x + self.y = y + p("\(self)") + } + + public init() { + self.x = 10 + self.y = 5 + } + + deinit { + p("deinit called!") + } +} diff --git a/Samples/JExtractJNISampleApp/build.gradle b/Samples/JExtractJNISampleApp/build.gradle index d0e32857..03794ff7 100644 --- a/Samples/JExtractJNISampleApp/build.gradle +++ b/Samples/JExtractJNISampleApp/build.gradle @@ -156,6 +156,11 @@ dependencies { tasks.named('test', Test) { useJUnitPlatform() + + testLogging { + events "failed" + exceptionFormat "full" + } } application { diff --git a/Samples/JExtractJNISampleApp/ci-validate.sh b/Samples/JExtractJNISampleApp/ci-validate.sh index 07b42627..c7a68d22 100755 --- a/Samples/JExtractJNISampleApp/ci-validate.sh +++ b/Samples/JExtractJNISampleApp/ci-validate.sh @@ -3,4 +3,5 @@ set -x set -e -./gradlew run \ No newline at end of file +./gradlew run +./gradlew test \ No newline at end of file diff --git a/Samples/JExtractJNISampleApp/src/main/java/com/example/swift/HelloJava2SwiftJNI.java b/Samples/JExtractJNISampleApp/src/main/java/com/example/swift/HelloJava2SwiftJNI.java index 36bad93c..7d0d77e1 100644 --- a/Samples/JExtractJNISampleApp/src/main/java/com/example/swift/HelloJava2SwiftJNI.java +++ b/Samples/JExtractJNISampleApp/src/main/java/com/example/swift/HelloJava2SwiftJNI.java @@ -40,6 +40,11 @@ static void examples() { long i = MySwiftLibrary.globalMakeInt(); SwiftKit.trace("globalMakeInt() = " + i); + MySwiftClass.method(); + + MySwiftClass myClass = MySwiftClass.init(10, 5); + MySwiftClass myClass2 = MySwiftClass.init(); + System.out.println("DONE."); } } diff --git a/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/MySwiftClassTest.java b/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/MySwiftClassTest.java new file mode 100644 index 00000000..994240cb --- /dev/null +++ b/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/MySwiftClassTest.java @@ -0,0 +1,37 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package com.example.swift; + +import com.example.swift.MySwiftLibrary; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +public class MySwiftClassTest { + @Test + void init_noParameters() { + MySwiftClass c = MySwiftClass.init(); + assertNotNull(c); + } + + @Test + void init_withParameters() { + MySwiftClass c = MySwiftClass.init(1337, 42); + assertNotNull(c); + } + +} \ No newline at end of file diff --git a/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/MySwiftLibraryTest.java b/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/MySwiftLibraryTest.java new file mode 100644 index 00000000..f1cefd19 --- /dev/null +++ b/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/MySwiftLibraryTest.java @@ -0,0 +1,57 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package com.example.swift; + +import com.example.swift.MySwiftLibrary; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +import java.util.Arrays; +import java.util.concurrent.CountDownLatch; +import java.util.stream.Collectors; + +import static org.junit.jupiter.api.Assertions.*; + +public class MySwiftLibraryTest { + @Test + void call_helloWorld() { + MySwiftLibrary.helloWorld(); + } + + @Test + void call_globalTakeInt() { + MySwiftLibrary.globalTakeInt(12); + } + + @Test + void call_globalMakeInt() { + long i = MySwiftLibrary.globalMakeInt(); + assertEquals(42, i); + } + + @Test + void call_globalTakeIntInt() { + MySwiftLibrary.globalTakeIntInt(1337, 42); + } + + @Test + void call_writeString_jextract() { + var string = "Hello Swift!"; + long reply = MySwiftLibrary.globalWriteString(string); + + assertEquals(string.length(), reply); + } +} \ No newline at end of file diff --git a/Sources/JExtractSwiftLib/Convenience/JavaType+Extensions.swift b/Sources/JExtractSwiftLib/Convenience/JavaType+Extensions.swift new file mode 100644 index 00000000..9da3ae5b --- /dev/null +++ b/Sources/JExtractSwiftLib/Convenience/JavaType+Extensions.swift @@ -0,0 +1,38 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import JavaTypes + +extension JavaType { + var jniTypeSignature: String { + switch self { + case .boolean: "Z" + case .byte: "B" + case .char: "C" + case .short: "S" + case .int: "I" + case .long: "J" + case .float: "F" + case .double: "D" + case .class(let package, let name): + if let package { + "L\(package.replacingOccurrences(of: ".", with: "/"))/\(name);" + } else { + "L\(name);" + } + case .array(let javaType): "[\(javaType.jniTypeSignature)" + case .void: fatalError("There is no type signature for 'void'") + } + } +} diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift index a6cc6b26..364fd270 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift @@ -439,7 +439,7 @@ extension FFMSwift2JavaGenerator { } } -extension JavaConversionStep { +extension FFMSwift2JavaGenerator.JavaConversionStep { /// Whether the conversion uses SwiftArena. var requiresSwiftArena: Bool { switch self { diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift index af1ddd09..16efddea 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift @@ -34,538 +34,526 @@ extension FFMSwift2JavaGenerator { translatedDecls[decl] = translated return translated } -} - -/// Represent a parameter in Java code. -struct JavaParameter { - /// The type. - var type: JavaType - /// The name. - var name: String -} + /// Represent a Swift API parameter translated to Java. + struct TranslatedParameter { + /// Java parameter(s) mapped to the Swift parameter. + /// + /// Array because one Swift parameter can be mapped to multiple parameters. + var javaParameters: [JavaParameter] -/// Represent a Swift API parameter translated to Java. -struct TranslatedParameter { - /// Java parameter(s) mapped to the Swift parameter. - /// - /// Array because one Swift parameter can be mapped to multiple parameters. - var javaParameters: [JavaParameter] + /// Describes how to convert the Java parameter to the lowered arguments for + /// the foreign function. + var conversion: JavaConversionStep + } - /// Describes how to convert the Java parameter to the lowered arguments for - /// the foreign function. - var conversion: JavaConversionStep -} + /// Represent a Swift API result translated to Java. + struct TranslatedResult { + /// Java type that represents the Swift result type. + var javaResultType: JavaType + + /// Required indirect return receivers for receiving the result. + /// + /// 'JavaParameter.name' is the suffix for the receiver variable names. For example + /// + /// var _result_pointer = MemorySegment.allocate(...) + /// var _result_count = MemroySegment.allocate(...) + /// downCall(_result_pointer, _result_count) + /// return constructResult(_result_pointer, _result_count) + /// + /// This case, there're two out parameter, named '_pointer' and '_count'. + var outParameters: [JavaParameter] + + /// Describes how to construct the Java result from the foreign function return + /// value and/or the out parameters. + var conversion: JavaConversionStep + } -/// Represent a Swift API result translated to Java. -struct TranslatedResult { - /// Java type that represents the Swift result type. - var javaResultType: JavaType - /// Required indirect return receivers for receiving the result. - /// - /// 'JavaParameter.name' is the suffix for the receiver variable names. For example - /// - /// var _result_pointer = MemorySegment.allocate(...) - /// var _result_count = MemroySegment.allocate(...) - /// downCall(_result_pointer, _result_count) - /// return constructResult(_result_pointer, _result_count) + /// Translated Java API representing a Swift API. /// - /// This case, there're two out parameter, named '_pointer' and '_count'. - var outParameters: [JavaParameter] - - /// Describes how to construct the Java result from the foreign function return - /// value and/or the out parameters. - var conversion: JavaConversionStep -} + /// Since this holds the lowered signature, and the original `SwiftFunctionSignature` + /// in it, this contains all the API information (except the name) to generate the + /// cdecl thunk, Java binding, and the Java wrapper function. + struct TranslatedFunctionDecl { + /// Java function name. + let name: String + /// Functional interfaces required for the Java method. + let functionTypes: [TranslatedFunctionType] -/// Translated Java API representing a Swift API. -/// -/// Since this holds the lowered signature, and the original `SwiftFunctionSignature` -/// in it, this contains all the API information (except the name) to generate the -/// cdecl thunk, Java binding, and the Java wrapper function. -struct TranslatedFunctionDecl { - /// Java function name. - let name: String + /// Function signature. + let translatedSignature: TranslatedFunctionSignature - /// Functional interfaces required for the Java method. - let functionTypes: [TranslatedFunctionType] - - /// Function signature. - let translatedSignature: TranslatedFunctionSignature - - /// Cdecl lowerd signature. - let loweredSignature: LoweredFunctionSignature -} - -/// Function signature for a Java API. -struct TranslatedFunctionSignature { - var selfParameter: TranslatedParameter? - var parameters: [TranslatedParameter] - var result: TranslatedResult -} - -/// Represent a Swift closure type in the user facing Java API. -/// -/// Closures are translated to named functional interfaces in Java. -struct TranslatedFunctionType { - var name: String - var parameters: [TranslatedParameter] - var result: TranslatedResult - var swiftType: SwiftFunctionType - var cdeclType: SwiftFunctionType - - /// Whether or not this functional interface with C ABI compatible. - var isCompatibleWithC: Bool { - result.conversion.isPlaceholder && parameters.allSatisfy(\.conversion.isPlaceholder) + /// Cdecl lowerd signature. + let loweredSignature: LoweredFunctionSignature } -} -extension TranslatedFunctionSignature { - /// Whether or not if the down-calling requires temporary "Arena" which is - /// only used during the down-calling. - var requiresTemporaryArena: Bool { - if self.parameters.contains(where: { $0.conversion.requiresTemporaryArena }) { - return true - } - if self.selfParameter?.conversion.requiresTemporaryArena ?? false { - return true - } - if self.result.conversion.requiresTemporaryArena { - return true - } - return false + /// Function signature for a Java API. + struct TranslatedFunctionSignature { + var selfParameter: TranslatedParameter? + var parameters: [TranslatedParameter] + var result: TranslatedResult } - /// Whether if the down-calling requires "SwiftArena" or not, which should be - /// passed-in by the API caller. This is needed if the API returns a `SwiftValue` - var requiresSwiftArena: Bool { - return self.result.conversion.requiresSwiftArena + /// Represent a Swift closure type in the user facing Java API. + /// + /// Closures are translated to named functional interfaces in Java. + struct TranslatedFunctionType { + var name: String + var parameters: [TranslatedParameter] + var result: TranslatedResult + var swiftType: SwiftFunctionType + var cdeclType: SwiftFunctionType + + /// Whether or not this functional interface with C ABI compatible. + var isCompatibleWithC: Bool { + result.conversion.isPlaceholder && parameters.allSatisfy(\.conversion.isPlaceholder) + } } -} -struct JavaTranslation { - var swiftStdlibTypes: SwiftStandardLibraryTypeDecls + struct JavaTranslation { + var swiftStdlibTypes: SwiftStandardLibraryTypeDecls - func translate( - _ decl: ImportedFunc - ) throws -> TranslatedFunctionDecl { - let lowering = CdeclLowering(swiftStdlibTypes: self.swiftStdlibTypes) - let loweredSignature = try lowering.lowerFunctionSignature(decl.functionSignature) + func translate( + _ decl: ImportedFunc + ) throws -> TranslatedFunctionDecl { + let lowering = CdeclLowering(swiftStdlibTypes: self.swiftStdlibTypes) + let loweredSignature = try lowering.lowerFunctionSignature(decl.functionSignature) - // Name. - let javaName = switch decl.apiKind { - case .getter: "get\(decl.name.toCamelCase)" - case .setter: "set\(decl.name.toCamelCase)" - case .function, .initializer: decl.name - } + // Name. + let javaName = switch decl.apiKind { + case .getter: "get\(decl.name.toCamelCase)" + case .setter: "set\(decl.name.toCamelCase)" + case .function, .initializer: decl.name + } - // Signature. - let translatedSignature = try translate(loweredFunctionSignature: loweredSignature, methodName: javaName) - - // Closures. - var funcTypes: [TranslatedFunctionType] = [] - for (idx, param) in decl.functionSignature.parameters.enumerated() { - switch param.type { - case .function(let funcTy): - let paramName = param.parameterName ?? "_\(idx)" - guard case .function( let cdeclTy) = loweredSignature.parameters[idx].cdeclParameters[0].type else { - preconditionFailure("closure parameter wasn't lowered to a function type; \(funcTy)") + // Signature. + let translatedSignature = try translate(loweredFunctionSignature: loweredSignature, methodName: javaName) + + // Closures. + var funcTypes: [TranslatedFunctionType] = [] + for (idx, param) in decl.functionSignature.parameters.enumerated() { + switch param.type { + case .function(let funcTy): + let paramName = param.parameterName ?? "_\(idx)" + guard case .function( let cdeclTy) = loweredSignature.parameters[idx].cdeclParameters[0].type else { + preconditionFailure("closure parameter wasn't lowered to a function type; \(funcTy)") + } + let translatedClosure = try translateFunctionType(name: paramName, swiftType: funcTy, cdeclType: cdeclTy) + funcTypes.append(translatedClosure) + case .tuple: + // TODO: Implement + break + default: + break } - let translatedClosure = try translateFunctionType(name: paramName, swiftType: funcTy, cdeclType: cdeclTy) - funcTypes.append(translatedClosure) - case .tuple: - // TODO: Implement - break - default: - break } - } - return TranslatedFunctionDecl( - name: javaName, - functionTypes: funcTypes, - translatedSignature: translatedSignature, - loweredSignature: loweredSignature - ) - } - - /// Translate Swift closure type to Java functional interface. - func translateFunctionType( - name: String, - swiftType: SwiftFunctionType, - cdeclType: SwiftFunctionType - ) throws -> TranslatedFunctionType { - var translatedParams: [TranslatedParameter] = [] - - for (i, param) in swiftType.parameters.enumerated() { - let paramName = param.parameterName ?? "_\(i)" - translatedParams.append( - try translateClosureParameter(param.type, convention: param.convention, parameterName: paramName) + return TranslatedFunctionDecl( + name: javaName, + functionTypes: funcTypes, + translatedSignature: translatedSignature, + loweredSignature: loweredSignature ) } - guard let resultCType = try? CType(cdeclType: swiftType.resultType) else { - throw JavaTranslationError.unhandledType(.function(swiftType)) - } + /// Translate Swift closure type to Java functional interface. + func translateFunctionType( + name: String, + swiftType: SwiftFunctionType, + cdeclType: SwiftFunctionType + ) throws -> TranslatedFunctionType { + var translatedParams: [TranslatedParameter] = [] + + for (i, param) in swiftType.parameters.enumerated() { + let paramName = param.parameterName ?? "_\(i)" + translatedParams.append( + try translateClosureParameter(param.type, convention: param.convention, parameterName: paramName) + ) + } - let transltedResult = TranslatedResult( - javaResultType: resultCType.javaType, - outParameters: [], - conversion: .placeholder - ) - - return TranslatedFunctionType( - name: name, - parameters: translatedParams, - result: transltedResult, - swiftType: swiftType, - cdeclType: cdeclType - ) - } + guard let resultCType = try? CType(cdeclType: swiftType.resultType) else { + throw JavaTranslationError.unhandledType(.function(swiftType)) + } - func translateClosureParameter( - _ type: SwiftType, - convention: SwiftParameterConvention, - parameterName: String - ) throws -> TranslatedParameter { - if let cType = try? CType(cdeclType: type) { - return TranslatedParameter( - javaParameters: [ - JavaParameter(type: cType.javaType, name: parameterName) - ], + let transltedResult = TranslatedResult( + javaResultType: resultCType.javaType, + outParameters: [], conversion: .placeholder ) + + return TranslatedFunctionType( + name: name, + parameters: translatedParams, + result: transltedResult, + swiftType: swiftType, + cdeclType: cdeclType + ) } - switch type { - case .nominal(let nominal): - if let knownType = nominal.nominalTypeDecl.knownStandardLibraryType { - switch knownType { - case .unsafeRawBufferPointer, .unsafeMutableRawBufferPointer: - return TranslatedParameter( - javaParameters: [ - JavaParameter(type: .javaForeignMemorySegment, name: parameterName) - ], - conversion: .method( - .explodedName(component: "pointer"), - methodName: "reinterpret", - arguments: [ - .explodedName(component: "count") + func translateClosureParameter( + _ type: SwiftType, + convention: SwiftParameterConvention, + parameterName: String + ) throws -> TranslatedParameter { + if let cType = try? CType(cdeclType: type) { + return TranslatedParameter( + javaParameters: [ + JavaParameter(name: parameterName, type: cType.javaType) + ], + conversion: .placeholder + ) + } + + switch type { + case .nominal(let nominal): + if let knownType = nominal.nominalTypeDecl.knownStandardLibraryType { + switch knownType { + case .unsafeRawBufferPointer, .unsafeMutableRawBufferPointer: + return TranslatedParameter( + javaParameters: [ + JavaParameter(name: parameterName, type: .javaForeignMemorySegment) ], - withArena: false + conversion: .method( + .explodedName(component: "pointer"), + methodName: "reinterpret", + arguments: [ + .explodedName(component: "count") + ], + withArena: false + ) ) - ) - default: - break + default: + break + } } + default: + break } - default: - break + throw JavaTranslationError.unhandledType(type) } - throw JavaTranslationError.unhandledType(type) - } - /// Translate a Swift API signature to the user-facing Java API signature. - /// - /// Note that the result signature is for the high-level Java API, not the - /// low-level FFM down-calling interface. - func translate( - loweredFunctionSignature: LoweredFunctionSignature, - methodName: String - ) throws -> TranslatedFunctionSignature { - let swiftSignature = loweredFunctionSignature.original - - // 'self' - let selfParameter: TranslatedParameter? - if case .instance(let swiftSelf) = swiftSignature.selfParameter { - selfParameter = try self.translate( - swiftParam: swiftSelf, - loweredParam: loweredFunctionSignature.selfParameter!, - methodName: methodName, - parameterName: swiftSelf.parameterName ?? "self" - ) - } else { - selfParameter = nil - } - - // Regular parameters. - let parameters: [TranslatedParameter] = try swiftSignature.parameters.enumerated() - .map { (idx, swiftParam) in - let loweredParam = loweredFunctionSignature.parameters[idx] - let parameterName = swiftParam.parameterName ?? "_\(idx)" - return try self.translate( - swiftParam: swiftParam, - loweredParam: loweredParam, + /// Translate a Swift API signature to the user-facing Java API signature. + /// + /// Note that the result signature is for the high-level Java API, not the + /// low-level FFM down-calling interface. + func translate( + loweredFunctionSignature: LoweredFunctionSignature, + methodName: String + ) throws -> TranslatedFunctionSignature { + let swiftSignature = loweredFunctionSignature.original + + // 'self' + let selfParameter: TranslatedParameter? + if case .instance(let swiftSelf) = swiftSignature.selfParameter { + selfParameter = try self.translate( + swiftParam: swiftSelf, + loweredParam: loweredFunctionSignature.selfParameter!, methodName: methodName, - parameterName: parameterName + parameterName: swiftSelf.parameterName ?? "self" ) + } else { + selfParameter = nil } - // Result. - let result = try self.translate( - swiftResult: swiftSignature.result, - loweredResult: loweredFunctionSignature.result - ) - - return TranslatedFunctionSignature( - selfParameter: selfParameter, - parameters: parameters, - result: result - ) - } - - /// Translate a Swift API parameter to the user-facing Java API parameter. - func translate( - swiftParam: SwiftParameter, - loweredParam: LoweredParameter, - methodName: String, - parameterName: String - ) throws -> TranslatedParameter { - let swiftType = swiftParam.type - - // If there is a 1:1 mapping between this Swift type and a C type, that can - // be expressed as a Java primitive type. - if let cType = try? CType(cdeclType: swiftType) { - let javaType = cType.javaType - return TranslatedParameter( - javaParameters: [ - JavaParameter( - type: javaType, - name: parameterName + // Regular parameters. + let parameters: [TranslatedParameter] = try swiftSignature.parameters.enumerated() + .map { (idx, swiftParam) in + let loweredParam = loweredFunctionSignature.parameters[idx] + let parameterName = swiftParam.parameterName ?? "_\(idx)" + return try self.translate( + swiftParam: swiftParam, + loweredParam: loweredParam, + methodName: methodName, + parameterName: parameterName ) - ], - conversion: .placeholder + } + + // Result. + let result = try self.translate( + swiftResult: swiftSignature.result, + loweredResult: loweredFunctionSignature.result ) - } - switch swiftType { - case .metatype: - // Metatype are expressed as 'org.swift.swiftkit.SwiftAnyType' - return TranslatedParameter( - javaParameters: [ - JavaParameter( - type: JavaType.class(package: "org.swift.swiftkit", name: "SwiftAnyType"), - name: parameterName) - ], - conversion: .swiftValueSelfSegment(.placeholder) + return TranslatedFunctionSignature( + selfParameter: selfParameter, + parameters: parameters, + result: result ) + } - case .nominal(let swiftNominalType): - if let knownType = swiftNominalType.nominalTypeDecl.knownStandardLibraryType { - if swiftParam.convention == .inout { - // FIXME: Support non-trivial 'inout' for builtin types. - throw JavaTranslationError.inoutNotSupported(swiftType) - } - switch knownType { - case .unsafePointer, .unsafeMutablePointer: - // FIXME: Implement - throw JavaTranslationError.unhandledType(swiftType) - case .unsafeBufferPointer, .unsafeMutableBufferPointer: - // FIXME: Implement - throw JavaTranslationError.unhandledType(swiftType) + /// Translate a Swift API parameter to the user-facing Java API parameter. + func translate( + swiftParam: SwiftParameter, + loweredParam: LoweredParameter, + methodName: String, + parameterName: String + ) throws -> TranslatedParameter { + let swiftType = swiftParam.type + + // If there is a 1:1 mapping between this Swift type and a C type, that can + // be expressed as a Java primitive type. + if let cType = try? CType(cdeclType: swiftType) { + let javaType = cType.javaType + return TranslatedParameter( + javaParameters: [ + JavaParameter( + name: parameterName, type: javaType + ) + ], + conversion: .placeholder + ) + } - case .unsafeRawBufferPointer, .unsafeMutableRawBufferPointer: - return TranslatedParameter( - javaParameters: [ - JavaParameter(type: .javaForeignMemorySegment, name: parameterName), - ], - conversion: .commaSeparated([ - .placeholder, - .method(.placeholder, methodName: "byteSize", arguments: [], withArena: false) - ]) - ) + switch swiftType { + case .metatype: + // Metatype are expressed as 'org.swift.swiftkit.SwiftAnyType' + return TranslatedParameter( + javaParameters: [ + JavaParameter( + name: parameterName, type: JavaType.class(package: "org.swift.swiftkit", name: "SwiftAnyType")) + ], + conversion: .swiftValueSelfSegment(.placeholder) + ) - case .string: - return TranslatedParameter( - javaParameters: [ - JavaParameter( - type: .javaLangString, - name: parameterName - ) - ], - conversion: .call(.placeholder, function: "SwiftKit.toCString", withArena: true) - ) + case .nominal(let swiftNominalType): + if let knownType = swiftNominalType.nominalTypeDecl.knownStandardLibraryType { + if swiftParam.convention == .inout { + // FIXME: Support non-trivial 'inout' for builtin types. + throw JavaTranslationError.inoutNotSupported(swiftType) + } + switch knownType { + case .unsafePointer, .unsafeMutablePointer: + // FIXME: Implement + throw JavaTranslationError.unhandledType(swiftType) + case .unsafeBufferPointer, .unsafeMutableBufferPointer: + // FIXME: Implement + throw JavaTranslationError.unhandledType(swiftType) + + case .unsafeRawBufferPointer, .unsafeMutableRawBufferPointer: + return TranslatedParameter( + javaParameters: [ + JavaParameter(name: parameterName, type: .javaForeignMemorySegment), + ], + conversion: .commaSeparated([ + .placeholder, + .method(.placeholder, methodName: "byteSize", arguments: [], withArena: false) + ]) + ) - default: + case .string: + return TranslatedParameter( + javaParameters: [ + JavaParameter( + name: parameterName, type: .javaLangString + ) + ], + conversion: .call(.placeholder, function: "SwiftKit.toCString", withArena: true) + ) + + default: + throw JavaTranslationError.unhandledType(swiftType) + } + } + + // Generic types are not supported yet. + guard swiftNominalType.genericArguments == nil else { throw JavaTranslationError.unhandledType(swiftType) } - } - // Generic types are not supported yet. - guard swiftNominalType.genericArguments == nil else { - throw JavaTranslationError.unhandledType(swiftType) - } + return TranslatedParameter( + javaParameters: [ + JavaParameter( + name: parameterName, type: try translate(swiftType: swiftType) + ) + ], + conversion: .swiftValueSelfSegment(.placeholder) + ) - return TranslatedParameter( - javaParameters: [ - JavaParameter( - type: try translate(swiftType: swiftType), - name: parameterName - ) - ], - conversion: .swiftValueSelfSegment(.placeholder) - ) + case .tuple: + // TODO: Implement. + throw JavaTranslationError.unhandledType(swiftType) - case .tuple: - // TODO: Implement. - throw JavaTranslationError.unhandledType(swiftType) - - case .function: - return TranslatedParameter( - javaParameters: [ - JavaParameter( - type: JavaType.class(package: nil, name: "\(methodName).\(parameterName)"), - name: parameterName) - ], - conversion: .call(.placeholder, function: "\(methodName).$toUpcallStub", withArena: true) - ) + case .function: + return TranslatedParameter( + javaParameters: [ + JavaParameter( + name: parameterName, type: JavaType.class(package: nil, name: "\(methodName).\(parameterName)")) + ], + conversion: .call(.placeholder, function: "\(methodName).$toUpcallStub", withArena: true) + ) - case .optional: - throw JavaTranslationError.unhandledType(swiftType) + case .optional: + throw JavaTranslationError.unhandledType(swiftType) + } } - } - /// Translate a Swift API result to the user-facing Java API result. - func translate( - swiftResult: SwiftResult, - loweredResult: LoweredResult - ) throws -> TranslatedResult { - let swiftType = swiftResult.type - - // If there is a 1:1 mapping between this Swift type and a C type, that can - // be expressed as a Java primitive type. - if let cType = try? CType(cdeclType: swiftType) { - let javaType = cType.javaType - return TranslatedResult( - javaResultType: javaType, - outParameters: [], - conversion: .placeholder - ) - } + /// Translate a Swift API result to the user-facing Java API result. + func translate( + swiftResult: SwiftResult, + loweredResult: LoweredResult + ) throws -> TranslatedResult { + let swiftType = swiftResult.type + + // If there is a 1:1 mapping between this Swift type and a C type, that can + // be expressed as a Java primitive type. + if let cType = try? CType(cdeclType: swiftType) { + let javaType = cType.javaType + return TranslatedResult( + javaResultType: javaType, + outParameters: [], + conversion: .placeholder + ) + } - switch swiftType { - case .metatype(_): - // Metatype are expressed as 'org.swift.swiftkit.SwiftAnyType' - let javaType = JavaType.class(package: "org.swift.swiftkit", name: "SwiftAnyType") - return TranslatedResult( - javaResultType: javaType, - outParameters: [], - conversion: .construct(.placeholder, javaType) - ) + switch swiftType { + case .metatype(_): + // Metatype are expressed as 'org.swift.swiftkit.SwiftAnyType' + let javaType = JavaType.class(package: "org.swift.swiftkit", name: "SwiftAnyType") + return TranslatedResult( + javaResultType: javaType, + outParameters: [], + conversion: .construct(.placeholder, javaType) + ) - case .nominal(let swiftNominalType): - if let knownType = swiftNominalType.nominalTypeDecl.knownStandardLibraryType { - switch knownType { - case .unsafeRawBufferPointer, .unsafeMutableRawBufferPointer: - return TranslatedResult( - javaResultType: .javaForeignMemorySegment, - outParameters: [ - JavaParameter(type: .javaForeignMemorySegment, name: "pointer"), - JavaParameter(type: .long, name: "count"), - ], - conversion: .method( - .readMemorySegment(.explodedName(component: "pointer"), as: .javaForeignMemorySegment), - methodName: "reinterpret", - arguments: [ - .readMemorySegment(.explodedName(component: "count"), as: .long), + case .nominal(let swiftNominalType): + if let knownType = swiftNominalType.nominalTypeDecl.knownStandardLibraryType { + switch knownType { + case .unsafeRawBufferPointer, .unsafeMutableRawBufferPointer: + return TranslatedResult( + javaResultType: .javaForeignMemorySegment, + outParameters: [ + JavaParameter(name: "pointer", type: .javaForeignMemorySegment), + JavaParameter(name: "count", type: .long), ], - withArena: false + conversion: .method( + .readMemorySegment(.explodedName(component: "pointer"), as: .javaForeignMemorySegment), + methodName: "reinterpret", + arguments: [ + .readMemorySegment(.explodedName(component: "count"), as: .long), + ], + withArena: false + ) ) - ) - case .unsafePointer, .unsafeMutablePointer: - // FIXME: Implement - throw JavaTranslationError.unhandledType(swiftType) - case .unsafeBufferPointer, .unsafeMutableBufferPointer: - // FIXME: Implement - throw JavaTranslationError.unhandledType(swiftType) - case .string: - // FIXME: Implement - throw JavaTranslationError.unhandledType(swiftType) - default: + case .unsafePointer, .unsafeMutablePointer: + // FIXME: Implement + throw JavaTranslationError.unhandledType(swiftType) + case .unsafeBufferPointer, .unsafeMutableBufferPointer: + // FIXME: Implement + throw JavaTranslationError.unhandledType(swiftType) + case .string: + // FIXME: Implement + throw JavaTranslationError.unhandledType(swiftType) + default: + throw JavaTranslationError.unhandledType(swiftType) + } + } + + // Generic types are not supported yet. + guard swiftNominalType.genericArguments == nil else { throw JavaTranslationError.unhandledType(swiftType) } - } - // Generic types are not supported yet. - guard swiftNominalType.genericArguments == nil else { - throw JavaTranslationError.unhandledType(swiftType) - } + let javaType: JavaType = .class(package: nil, name: swiftNominalType.nominalTypeDecl.name) + return TranslatedResult( + javaResultType: javaType, + outParameters: [ + JavaParameter(name: "", type: javaType) + ], + conversion: .constructSwiftValue(.placeholder, javaType) + ) - let javaType: JavaType = .class(package: nil, name: swiftNominalType.nominalTypeDecl.name) - return TranslatedResult( - javaResultType: javaType, - outParameters: [ - JavaParameter(type: javaType, name: "") - ], - conversion: .constructSwiftValue(.placeholder, javaType) - ) + case .tuple: + // TODO: Implement. + throw JavaTranslationError.unhandledType(swiftType) - case .tuple: - // TODO: Implement. - throw JavaTranslationError.unhandledType(swiftType) + case .optional, .function: + throw JavaTranslationError.unhandledType(swiftType) + } - case .optional, .function: - throw JavaTranslationError.unhandledType(swiftType) } - } - - func translate( - swiftType: SwiftType - ) throws -> JavaType { - guard let nominalName = swiftType.asNominalTypeDeclaration?.name else { - throw JavaTranslationError.unhandledType(swiftType) + func translate( + swiftType: SwiftType + ) throws -> JavaType { + guard let nominalName = swiftType.asNominalTypeDeclaration?.name else { + throw JavaTranslationError.unhandledType(swiftType) + } + return .class(package: nil, name: nominalName) } - return .class(package: nil, name: nominalName) } -} -/// Describes how to convert values between Java types and FFM types. -enum JavaConversionStep { - // The input - case placeholder + /// Describes how to convert values between Java types and FFM types. + enum JavaConversionStep { + // The input + case placeholder - // The input exploded into components. - case explodedName(component: String) + // The input exploded into components. + case explodedName(component: String) - // A fixed value - case constant(String) + // A fixed value + case constant(String) - // 'value.$memorySegment()' - indirect case swiftValueSelfSegment(JavaConversionStep) + // 'value.$memorySegment()' + indirect case swiftValueSelfSegment(JavaConversionStep) - // call specified function using the placeholder as arguments. - // If `withArena` is true, `arena$` argument is added. - indirect case call(JavaConversionStep, function: String, withArena: Bool) + // call specified function using the placeholder as arguments. + // If `withArena` is true, `arena$` argument is added. + indirect case call(JavaConversionStep, function: String, withArena: Bool) - // Apply a method on the placeholder. - // If `withArena` is true, `arena$` argument is added. - indirect case method(JavaConversionStep, methodName: String, arguments: [JavaConversionStep] = [], withArena: Bool) + // Apply a method on the placeholder. + // If `withArena` is true, `arena$` argument is added. + indirect case method(JavaConversionStep, methodName: String, arguments: [JavaConversionStep] = [], withArena: Bool) - // Call 'new \(Type)(\(placeholder), swiftArena$)'. - indirect case constructSwiftValue(JavaConversionStep, JavaType) + // Call 'new \(Type)(\(placeholder), swiftArena$)'. + indirect case constructSwiftValue(JavaConversionStep, JavaType) - // Construct the type using the placeholder as arguments. - indirect case construct(JavaConversionStep, JavaType) + // Construct the type using the placeholder as arguments. + indirect case construct(JavaConversionStep, JavaType) - // Casting the placeholder to the certain type. - indirect case cast(JavaConversionStep, JavaType) + // Casting the placeholder to the certain type. + indirect case cast(JavaConversionStep, JavaType) - // Convert the results of the inner steps to a comma separated list. - indirect case commaSeparated([JavaConversionStep]) + // Convert the results of the inner steps to a comma separated list. + indirect case commaSeparated([JavaConversionStep]) - // Refer an exploded argument suffixed with `_\(name)`. - indirect case readMemorySegment(JavaConversionStep, as: JavaType) + // Refer an exploded argument suffixed with `_\(name)`. + indirect case readMemorySegment(JavaConversionStep, as: JavaType) - var isPlaceholder: Bool { - return if case .placeholder = self { true } else { false } + var isPlaceholder: Bool { + return if case .placeholder = self { true } else { false } + } } } + +extension FFMSwift2JavaGenerator.TranslatedFunctionSignature { + /// Whether or not if the down-calling requires temporary "Arena" which is + /// only used during the down-calling. + var requiresTemporaryArena: Bool { + if self.parameters.contains(where: { $0.conversion.requiresTemporaryArena }) { + return true + } + if self.selfParameter?.conversion.requiresTemporaryArena ?? false { + return true + } + if self.result.conversion.requiresTemporaryArena { + return true + } + return false + } + + /// Whether if the down-calling requires "SwiftArena" or not, which should be + /// passed-in by the API caller. This is needed if the API returns a `SwiftValue` + var requiresSwiftArena: Bool { + return self.result.conversion.requiresSwiftArena + } +} + + extension CType { /// Map lowered C type to Java type for FFM binding. var javaType: JavaType { diff --git a/Sources/JExtractSwiftLib/ImportedDecls.swift b/Sources/JExtractSwiftLib/ImportedDecls.swift index 0a5952f3..76d53d88 100644 --- a/Sources/JExtractSwiftLib/ImportedDecls.swift +++ b/Sources/JExtractSwiftLib/ImportedDecls.swift @@ -40,6 +40,10 @@ package class ImportedNominalType: ImportedDecl { var swiftType: SwiftType { return .nominal(.init(nominalTypeDecl: swiftNominal)) } + + var qualifiedName: String { + self.swiftNominal.qualifiedName + } } public final class ImportedFunc: ImportedDecl, CustomStringConvertible { @@ -74,6 +78,20 @@ public final class ImportedFunc: ImportedDecl, CustomStringConvertible { } } + var isStatic: Bool { + if case .staticMethod = functionSignature.selfParameter { + return true + } + return false + } + + var isInitializer: Bool { + if case .initializer = functionSignature.selfParameter { + return true + } + return false + } + /// If this function/method is member of a class/struct/protocol, /// this will contain that declaration's imported name. /// diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift new file mode 100644 index 00000000..ac775638 --- /dev/null +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift @@ -0,0 +1,197 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +extension JNISwift2JavaGenerator { + func writeExportedJavaSources() throws { + var printer = CodePrinter() + try writeExportedJavaSources(&printer) + } + + package func writeExportedJavaSources(_ printer: inout CodePrinter) throws { + for (_, ty) in analysis.importedTypes.sorted(by: { (lhs, rhs) in lhs.key < rhs.key }) { + let filename = "\(ty.swiftNominal.name).java" + logger.info("Printing contents: \(filename)") + printImportedNominal(&printer, ty) + + if let outputFile = try printer.writeContents( + outputDirectory: javaOutputDirectory, + javaPackagePath: javaPackagePath, + filename: filename + ) { + logger.info("[swift-java] Generated: \(ty.swiftNominal.name.bold).java (at \(outputFile))") + } + } + + let filename = "\(self.swiftModuleName).java" + logger.trace("Printing module class: \(filename)") + printModule(&printer) + + if let outputFile = try printer.writeContents( + outputDirectory: javaOutputDirectory, + javaPackagePath: javaPackagePath, + filename: filename + ) { + logger.info("[swift-java] Generated: \(self.swiftModuleName).java (at \(outputFile))") + } + } + + private func printModule(_ printer: inout CodePrinter) { + printHeader(&printer) + printPackage(&printer) + + printModuleClass(&printer) { printer in + printer.print( + """ + static final String LIB_NAME = "\(swiftModuleName)"; + + static { + System.loadLibrary(LIB_NAME); + } + """ + ) + + for decl in analysis.importedGlobalFuncs { + self.logger.trace("Print global function: \(decl)") + printFunctionBinding(&printer, decl) + printer.println() + } + } + } + + private func printImportedNominal(_ printer: inout CodePrinter, _ decl: ImportedNominalType) { + printHeader(&printer) + printPackage(&printer) + + printNominal(&printer, decl) { printer in + printer.print( + """ + static final String LIB_NAME = "\(swiftModuleName)"; + + @SuppressWarnings("unused") + private static final boolean INITIALIZED_LIBS = initializeLibs(); + static boolean initializeLibs() { + System.loadLibrary(LIB_NAME); + return true; + } + """ + ) + + printer.println() + + printer.print( + """ + private long selfPointer; + + private \(decl.swiftNominal.name)(long selfPointer) { + this.selfPointer = selfPointer; + } + """ + ) + + printer.println() + + for initializer in decl.initializers { + printInitializerBindings(&printer, initializer, type: decl) + } + + for method in decl.methods { + printFunctionBinding(&printer, method) + } + } + } + + private func printHeader(_ printer: inout CodePrinter) { + printer.print( + """ + // Generated by jextract-swift + // Swift module: \(swiftModuleName) + + """ + ) + } + + private func printPackage(_ printer: inout CodePrinter) { + printer.print( + """ + package \(javaPackage); + + """ + ) + } + + private func printNominal( + _ printer: inout CodePrinter, _ decl: ImportedNominalType, body: (inout CodePrinter) -> Void + ) { + printer.printBraceBlock("public final class \(decl.swiftNominal.name)") { printer in + body(&printer) + } + } + + private func printModuleClass(_ printer: inout CodePrinter, body: (inout CodePrinter) -> Void) { + printer.printBraceBlock("public final class \(swiftModuleName)") { printer in + body(&printer) + } + } + + private func printFunctionBinding(_ printer: inout CodePrinter, _ decl: ImportedFunc) { + printDeclDocumentation(&printer, decl) + printer.print( + "public static native \(renderFunctionSignature(decl));" + ) + } + + private func printInitializerBindings(_ printer: inout CodePrinter, _ decl: ImportedFunc, type: ImportedNominalType) { + let translatedDecl = translatedDecl(for: decl) + + printDeclDocumentation(&printer, decl) + printer.printBraceBlock("public static \(renderFunctionSignature(decl))") { printer in + let initArguments = translatedDecl.translatedFunctionSignature.parameters.map(\.name) + printer.print( + """ + long selfPointer = \(type.qualifiedName).allocatingInit(\(initArguments.joined(separator: ", "))); + return new \(type.qualifiedName)(selfPointer); + """ + ) + } + + let parameters = translatedDecl.translatedFunctionSignature.parameters.map(\.asParameter) + printer.print("private static native long allocatingInit(\(parameters.joined(separator: ", ")));") + } + + private func printDeclDocumentation(_ printer: inout CodePrinter, _ decl: ImportedFunc) { + printer.print( + """ + /** + * Downcall to Swift: + * {@snippet lang=swift : + * \(decl.signatureString) + * } + */ + """ + ) + } + + /// Renders a Java function signature + /// + /// `func method(x: Int, y: Int) -> Int` becomes + /// `long method(long x, long y)` + private func renderFunctionSignature(_ decl: ImportedFunc) -> String { + let translatedDecl = translatedDecl(for: decl) + let resultType = translatedDecl.translatedFunctionSignature.resultType + let parameters = translatedDecl.translatedFunctionSignature.parameters.map(\.asParameter) + let throwsClause = decl.isThrowing ? " throws Exception" : "" + + return "\(resultType) \(translatedDecl.name)(\(parameters.joined(separator: ", ")))\(throwsClause)" + } +} diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift new file mode 100644 index 00000000..a5df702c --- /dev/null +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift @@ -0,0 +1,123 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import JavaTypes + +extension JNISwift2JavaGenerator { + func translatedDecl( + for decl: ImportedFunc + ) -> TranslatedFunctionDecl { + if let cached = translatedDecls[decl] { + return cached + } + + let translation = JavaTranslation(swiftModuleName: self.swiftModuleName) + let translated = translation.translate(decl) + + translatedDecls[decl] = translated + return translated + } + + struct JavaTranslation { + let swiftModuleName: String + + func translate(_ decl: ImportedFunc) -> TranslatedFunctionDecl { + let translatedFunctionSignature = translate(functionSignature: decl.functionSignature) + // Types with no parent will be outputted inside a "module" class. + let parentName = decl.parentType?.asNominalType?.nominalTypeDecl.qualifiedName ?? swiftModuleName + + return TranslatedFunctionDecl( + name: decl.name, + parentName: parentName, + translatedFunctionSignature: translatedFunctionSignature + ) + } + + func translate(functionSignature: SwiftFunctionSignature, isInitializer: Bool = false) -> TranslatedFunctionSignature { + let parameters = functionSignature.parameters.enumerated().map { idx, param in + let parameterName = param.parameterName ?? "arg\(idx))" + return translate(swiftParam: param, parameterName: parameterName) + } + + return TranslatedFunctionSignature( + parameters: parameters, + resultType: translate(swiftType: functionSignature.result.type) + ) + } + + func translate(swiftParam: SwiftParameter, parameterName: String) -> JavaParameter { + return JavaParameter( + name: parameterName, + type: translate(swiftType: swiftParam.type) + ) + } + + func translate(swiftType: SwiftType) -> JavaType { + switch swiftType { + case .nominal(let nominalType): + if let knownType = nominalType.nominalTypeDecl.knownStandardLibraryType { + guard let javaType = translate(standardLibraryType: knownType) else { + fatalError("unsupported known type: \(knownType)") + } + return javaType + } + + return .class(package: nil, name: nominalType.nominalTypeDecl.name) + + case .tuple([]): + return .void + + case .metatype, .optional, .tuple, .function: + fatalError("unsupported type: \(self)") + } + } + + func translate(standardLibraryType: SwiftStandardLibraryTypeKind) -> JavaType? { + switch standardLibraryType { + case .bool: .boolean + case .int8: .byte + case .uint16: .char + case .int16: .short + case .int32: .int + case .int64: .long + case .float: .float + case .double: .double + case .void: .void + case .string: .javaLangString + case .int, .uint, .uint8, .uint32, .uint64, + .unsafeRawPointer, .unsafeMutableRawPointer, + .unsafePointer, .unsafeMutablePointer, + .unsafeRawBufferPointer, .unsafeMutableRawBufferPointer, + .unsafeBufferPointer, .unsafeMutableBufferPointer: + nil + } + } + } + + struct TranslatedFunctionDecl { + /// Java function name + let name: String + + /// The name of the Java parent scope this function is declared in + let parentName: String + + /// Function signature + let translatedFunctionSignature: TranslatedFunctionSignature + } + + struct TranslatedFunctionSignature { + let parameters: [JavaParameter] + let resultType: JavaType + } +} diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift new file mode 100644 index 00000000..c61dd929 --- /dev/null +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift @@ -0,0 +1,268 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import JavaTypes + +extension JNISwift2JavaGenerator { + func writeSwiftThunkSources() throws { + var printer = CodePrinter() + try writeSwiftThunkSources(&printer) + } + + package func writeSwiftExpectedEmptySources() throws { + for expectedFileName in self.expectedOutputSwiftFiles { + logger.trace("Write empty file: \(expectedFileName) ...") + + var printer = CodePrinter() + printer.print("// Empty file generated on purpose") + _ = try printer.writeContents( + outputDirectory: self.swiftOutputDirectory, + javaPackagePath: nil, + filename: expectedFileName) + } + } + + package func writeSwiftThunkSources(_ printer: inout CodePrinter) throws { + let moduleFilenameBase = "\(self.swiftModuleName)Module+SwiftJava" + let moduleFilename = "\(moduleFilenameBase).swift" + + do { + logger.trace("Printing swift module class: \(moduleFilename)") + + try printGlobalSwiftThunkSources(&printer) + + if let outputFile = try printer.writeContents( + outputDirectory: self.swiftOutputDirectory, + javaPackagePath: nil, + filename: moduleFilename + ) { + print("[swift-java] Generated: \(moduleFilenameBase.bold).swift (at \(outputFile))") + self.expectedOutputSwiftFiles.remove(moduleFilename) + } + + for (_, ty) in self.analysis.importedTypes.sorted(by: { (lhs, rhs) in lhs.key < rhs.key }) { + let fileNameBase = "\(ty.swiftNominal.qualifiedName)+SwiftJava" + let filename = "\(fileNameBase).swift" + logger.info("Printing contents: \(filename)") + + do { + try printNominalTypeThunks(&printer, ty) + + if let outputFile = try printer.writeContents( + outputDirectory: self.swiftOutputDirectory, + javaPackagePath: nil, + filename: filename) { + print("[swift-java] Generated: \(fileNameBase.bold).swift (at \(outputFile))") + self.expectedOutputSwiftFiles.remove(filename) + } + } catch { + logger.warning("Failed to write to Swift thunks: \(filename)") + } + } + } catch { + logger.warning("Failed to write to Swift thunks: \(moduleFilename)") + } + } + + private func printGlobalSwiftThunkSources(_ printer: inout CodePrinter) throws { + printHeader(&printer) + + for decl in analysis.importedGlobalFuncs { + printSwiftFunctionThunk(&printer, decl) + printer.println() + } + } + + private func printNominalTypeThunks(_ printer: inout CodePrinter, _ type: ImportedNominalType) throws { + printHeader(&printer) + + for initializer in type.initializers { + printInitializerThunk(&printer, initializer) + printer.println() + } + + for method in type.methods { + printSwiftFunctionThunk(&printer, method) + printer.println() + } + } + + private func printInitializerThunk(_ printer: inout CodePrinter, _ decl: ImportedFunc) { + let translatedDecl = translatedDecl(for: decl) + let typeName = translatedDecl.parentName + + printCDecl( + &printer, + javaMethodName: "allocatingInit", + parentName: translatedDecl.parentName, + parameters: translatedDecl.translatedFunctionSignature.parameters, + isStatic: true, + resultType: .long + ) { printer in + let downcallArguments = renderDowncallArguments( + swiftFunctionSignature: decl.functionSignature, + translatedFunctionSignature: translatedDecl.translatedFunctionSignature + ) + // TODO: Throwing initializers + printer.print( + """ + let selfPointer = UnsafeMutablePointer<\(typeName)>.allocate(capacity: 1) + selfPointer.initialize(to: \(typeName)(\(downcallArguments))) + return Int64(Int(bitPattern: selfPointer)).getJNIValue(in: environment) + """ + ) + } + } + + private func printSwiftFunctionThunk( + _ printer: inout CodePrinter, + _ decl: ImportedFunc + ) { + let translatedDecl = self.translatedDecl(for: decl) + let parentName = translatedDecl.parentName ?? swiftModuleName + let swiftReturnType = decl.functionSignature.result.type + + printCDecl(&printer, decl) { printer in + let downcallParameters = renderDowncallArguments( + swiftFunctionSignature: decl.functionSignature, + translatedFunctionSignature: translatedDecl.translatedFunctionSignature + ) + let tryClause: String = decl.isThrowing ? "try " : "" + let functionDowncall = + "\(tryClause)\(parentName).\(decl.name)(\(downcallParameters))" + + let innerBody = + if swiftReturnType.isVoid { + functionDowncall + } else { + """ + let result = \(functionDowncall) + return result.getJNIValue(in: environment) + """ + } + + if decl.isThrowing { + let dummyReturn = + !swiftReturnType.isVoid ? "return \(swiftReturnType).jniPlaceholderValue" : "" + printer.print( + """ + do { + \(innerBody) + } catch { + environment.throwAsException(error) + \(dummyReturn) + } + """ + ) + } else { + printer.print(innerBody) + } + } + } + + private func printCDecl( + _ printer: inout CodePrinter, + _ decl: ImportedFunc, + _ body: (inout CodePrinter) -> Void + ) { + let translatedDecl = translatedDecl(for: decl) + let parentName = translatedDecl.parentName + + printCDecl( + &printer, + javaMethodName: translatedDecl.name, + parentName: parentName, + parameters: translatedDecl.translatedFunctionSignature.parameters, + isStatic: decl.isStatic || decl.isInitializer || !decl.hasParent, + resultType: translatedDecl.translatedFunctionSignature.resultType, + body + ) + } + + private func printCDecl( + _ printer: inout CodePrinter, + javaMethodName: String, + parentName: String, + parameters: [JavaParameter], + isStatic: Bool, + resultType: JavaType, + _ body: (inout CodePrinter) -> Void + ) { + var jniSignature = parameters.reduce(into: "") { signature, parameter in + signature += parameter.type.jniTypeSignature + } + + // Escape signature characters + jniSignature = jniSignature + .replacingOccurrences(of: "_", with: "_1") + .replacingOccurrences(of: "/", with: "_") + .replacingOccurrences(of: ";", with: "_2") + .replacingOccurrences(of: "[", with: "_3") + + let cName = + "Java_" + + self.javaPackage.replacingOccurrences(of: ".", with: "_") + + "_\(parentName)_" + + javaMethodName + + "__" + + jniSignature + let translatedParameters = parameters.map { + "\($0.name): \($0.type.jniTypeName)" + } + let thisParameter = isStatic ? "thisClass: jclass" : "thisObject: jobject" + + let thunkParameters = + [ + "environment: UnsafeMutablePointer!", + thisParameter + ] + translatedParameters + let thunkReturnType = !resultType.isVoid ? " -> \(resultType.jniTypeName)" : "" + + // TODO: Think about function overloads + printer.printBraceBlock( + """ + @_cdecl("\(cName)") + func \(cName)(\(thunkParameters.joined(separator: ", ")))\(thunkReturnType) + """ + ) { printer in + body(&printer) + } + } + + private func printHeader(_ printer: inout CodePrinter) { + printer.print( + """ + // Generated by swift-java + + import JavaKit + + """ + ) + } + + /// Renders the arguments for making a downcall + private func renderDowncallArguments( + swiftFunctionSignature: SwiftFunctionSignature, + translatedFunctionSignature: TranslatedFunctionSignature + ) -> String { + zip( + swiftFunctionSignature.parameters, + translatedFunctionSignature.parameters + ).map { originalParam, translatedParam in + let label = originalParam.argumentLabel.map { "\($0): " } ?? "" + return "\(label)\(originalParam.type)(fromJNI: \(translatedParam.name), in: environment!)" + } + .joined(separator: ", ") + } +} diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator.swift index 0f16e697..b242cf66 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator.swift @@ -28,6 +28,9 @@ package class JNISwift2JavaGenerator: Swift2JavaGenerator { var thunkNameRegistry = ThunkNameRegistry() + /// Cached Java translation result. 'nil' indicates failed translation. + var translatedDecls: [ImportedFunc: TranslatedFunctionDecl] = [:] + /// Because we need to write empty files for SwiftPM, keep track which files we didn't write yet, /// and write an empty file for those. var expectedOutputSwiftFiles: Set @@ -71,262 +74,3 @@ package class JNISwift2JavaGenerator: Swift2JavaGenerator { } } } - -extension JNISwift2JavaGenerator { - func writeExportedJavaSources() throws { - var printer = CodePrinter() - try writeExportedJavaSources(&printer) - } - - package func writeExportedJavaSources(_ printer: inout CodePrinter) throws { - let filename = "\(self.swiftModuleName).java" - logger.trace("Printing module class: \(filename)") - printModule(&printer) - - if let outputFile = try printer.writeContents( - outputDirectory: javaOutputDirectory, - javaPackagePath: javaPackagePath, - filename: filename - ) { - logger.info("[swift-java] Generated: \(self.swiftModuleName).java (at \(outputFile))") - } - } - - func writeSwiftThunkSources() throws { - var printer = CodePrinter() - try writeSwiftThunkSources(&printer) - } - - package func writeSwiftExpectedEmptySources() throws { - for expectedFileName in self.expectedOutputSwiftFiles { - logger.trace("Write empty file: \(expectedFileName) ...") - - var printer = CodePrinter() - printer.print("// Empty file generated on purpose") - _ = try printer.writeContents( - outputDirectory: self.swiftOutputDirectory, - javaPackagePath: nil, - filename: expectedFileName) - } - } - - package func writeSwiftThunkSources(_ printer: inout CodePrinter) throws { - let moduleFilenameBase = "\(self.swiftModuleName)Module+SwiftJava" - let moduleFilename = "\(moduleFilenameBase).swift" - - do { - logger.trace("Printing swift module class: \(moduleFilename)") - - try printGlobalSwiftThunkSources(&printer) - - if let outputFile = try printer.writeContents( - outputDirectory: self.swiftOutputDirectory, - javaPackagePath: nil, - filename: moduleFilename - ) { - print("[swift-java] Generated: \(moduleFilenameBase.bold).swift (at \(outputFile))") - self.expectedOutputSwiftFiles.remove(moduleFilename) - } - } catch { - logger.warning("Failed to write to Swift thunks: \(moduleFilename)") - } - } -} - -extension JNISwift2JavaGenerator { - private func printGlobalSwiftThunkSources(_ printer: inout CodePrinter) throws { - printer.print( - """ - // Generated by swift-java - - import JavaKit - - """) - - for decl in analysis.importedGlobalFuncs { - printSwiftFunctionThunk(&printer, decl) - printer.println() - } - } - - private func printSwiftFunctionThunk(_ printer: inout CodePrinter, _ decl: ImportedFunc) { - // TODO: Replace swiftModuleName with class name if non-global - let cName = - "Java_" + self.javaPackage.replacingOccurrences(of: ".", with: "_") + "_\(swiftModuleName)_" - + decl.name - let thunkName = thunkNameRegistry.functionThunkName(decl: decl) - let translatedParameters = decl.functionSignature.parameters.enumerated().map { idx, param in - (param.parameterName ?? "arg\(idx)", param.type.javaType) - } - - let thunkParameters = - [ - "environment: UnsafeMutablePointer!", - "thisClass: jclass", - ] + translatedParameters.map { "\($0.0): \($0.1.jniTypeName)" } - let swiftReturnType = decl.functionSignature.result.type - let thunkReturnType = - !swiftReturnType.isVoid ? " -> \(swiftReturnType.javaType.jniTypeName)" : "" - - printer.printBraceBlock( - """ - @_cdecl("\(cName)") - func \(thunkName)(\(thunkParameters.joined(separator: ", ")))\(thunkReturnType) - """ - ) { printer in - let downcallParameters = zip(decl.functionSignature.parameters, translatedParameters).map { - originalParam, translatedParam in - let label = originalParam.argumentLabel.map { "\($0): " } ?? "" - return "\(label)\(originalParam.type)(fromJNI: \(translatedParam.0), in: environment!)" - } - let tryClause: String = decl.isThrowing ? "try " : "" - let functionDowncall = - "\(tryClause)\(swiftModuleName).\(decl.name)(\(downcallParameters.joined(separator: ", ")))" - - let innerBody = - if swiftReturnType.isVoid { - functionDowncall - } else { - """ - let result = \(functionDowncall) - return result.getJNIValue(in: environment) - """ - } - - if decl.isThrowing { - let dummyReturn = - !swiftReturnType.isVoid ? "return \(swiftReturnType).jniPlaceholderValue" : "" - printer.print( - """ - do { - \(innerBody) - } catch { - environment.throwAsException(error) - \(dummyReturn) - } - """ - ) - } else { - printer.print(innerBody) - } - } - } -} - -extension JNISwift2JavaGenerator { - private func printModule(_ printer: inout CodePrinter) { - printHeader(&printer) - printPackage(&printer) - - printModuleClass(&printer) { printer in - printer.print( - """ - static final String LIB_NAME = "\(swiftModuleName)"; - - static { - System.loadLibrary(LIB_NAME); - } - """ - ) - - for decl in analysis.importedGlobalFuncs { - self.logger.trace("Print global function: \(decl)") - printFunctionBinding(&printer, decl) - printer.println() - } - } - } - - private func printHeader(_ printer: inout CodePrinter) { - printer.print( - """ - // Generated by jextract-swift - // Swift module: \(swiftModuleName) - - """ - ) - } - - private func printPackage(_ printer: inout CodePrinter) { - printer.print( - """ - package \(javaPackage); - - """ - ) - } - - private func printModuleClass(_ printer: inout CodePrinter, body: (inout CodePrinter) -> Void) { - printer.printBraceBlock("public final class \(swiftModuleName)") { printer in - body(&printer) - } - } - - private func printFunctionBinding(_ printer: inout CodePrinter, _ decl: ImportedFunc) { - let returnType = decl.functionSignature.result.type.javaType - let params = decl.functionSignature.parameters.enumerated().map { idx, param in - "\(param.type.javaType) \(param.parameterName ?? "arg\(idx))")" - } - let throwsClause = decl.isThrowing ? " throws Exception" : "" - - printer.print( - """ - /** - * Downcall to Swift: - * {@snippet lang=swift : - * \(decl.signatureString) - * } - */ - """ - ) - printer.print( - "public static native \(returnType) \(decl.name)(\(params.joined(separator: ", ")))\(throwsClause);" - ) - } -} - -extension SwiftType { - var javaType: JavaType { - switch self { - case .nominal(let nominalType): - if let knownType = nominalType.nominalTypeDecl.knownStandardLibraryType { - guard let javaType = knownType.javaType else { - fatalError("unsupported known type: \(knownType)") - } - return javaType - } - - fatalError("unsupported nominal type: \(nominalType)") - - case .tuple([]): - return .void - - case .metatype, .optional, .tuple, .function: - fatalError("unsupported type: \(self)") - } - } -} - -extension SwiftStandardLibraryTypeKind { - var javaType: JavaType? { - switch self { - case .bool: .boolean - case .int: .long // TODO: Handle 32-bit or 64-bit - case .int8: .byte - case .uint16: .char - case .int16: .short - case .int32: .int - case .int64: .long - case .float: .float - case .double: .double - case .void: .void - case .string: .javaLangString - case .uint, .uint8, .uint32, .uint64, - .unsafeRawPointer, .unsafeMutableRawPointer, - .unsafePointer, .unsafeMutablePointer, - .unsafeRawBufferPointer, .unsafeMutableRawBufferPointer, - .unsafeBufferPointer, .unsafeMutableBufferPointer: - nil - } - } -} diff --git a/Sources/JExtractSwiftLib/JavaParameter.swift b/Sources/JExtractSwiftLib/JavaParameter.swift new file mode 100644 index 00000000..72896419 --- /dev/null +++ b/Sources/JExtractSwiftLib/JavaParameter.swift @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import JavaTypes + +/// Represent a parameter in Java code. +struct JavaParameter { + let name: String + let type: JavaType + + var asParameter: String { + "\(type) \(name)" + } +} diff --git a/Sources/JavaTypes/JavaType+SwiftNames.swift b/Sources/JavaTypes/JavaType+SwiftNames.swift index d01398b8..492ff459 100644 --- a/Sources/JavaTypes/JavaType+SwiftNames.swift +++ b/Sources/JavaTypes/JavaType+SwiftNames.swift @@ -45,6 +45,13 @@ extension JavaType { } } + public var isVoid: Bool { + if case .void = self { + return true + } + return false + } + public var isString: Bool { switch self { case .boolean, .byte, .char, .short, .int, .long, .float, .double, .void, diff --git a/Tests/JExtractSwiftTests/JNI/JNIClassTests.swift b/Tests/JExtractSwiftTests/JNI/JNIClassTests.swift new file mode 100644 index 00000000..c39d5815 --- /dev/null +++ b/Tests/JExtractSwiftTests/JNI/JNIClassTests.swift @@ -0,0 +1,173 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import JExtractSwiftLib +import Testing + +@Suite +struct JNIClassTests { + let source = """ + public class MyClass { + let x: Int64 + let y: Int64 + + public static func method() {} + + public init(x: Int64, y: Int64) { + self.x = y + self.y = y + } + + public init() { + self.x = 0 + self.y = 0 + } + } + """ + + @Test + func generatesJavaClass() throws { + try assertOutput(input: source, .jni, .java, expectedChunks: [ + """ + // Generated by jextract-swift + // Swift module: SwiftModule + + package com.example.swift; + + public final class MyClass { + static final String LIB_NAME = "SwiftModule"; + + @SuppressWarnings("unused") + private static final boolean INITIALIZED_LIBS = initializeLibs(); + static boolean initializeLibs() { + System.loadLibrary(LIB_NAME); + return true; + } + + private long selfPointer; + + private MyClass(long selfPointer) { + this.selfPointer = selfPointer; + } + """, + ]) + } + + @Test + func staticMethod_javaBindings() throws { + try assertOutput( + input: source, + .jni, + .java, + expectedChunks: [ + """ + /** + * Downcall to Swift: + * {@snippet lang=swift : + * public static func method() + * } + */ + public static native void method(); + """ + ] + ) + } + + @Test + func staticMethod_swiftThunks() throws { + try assertOutput( + input: source, + .jni, + .swift, + detectChunkByInitialLines: 1, + expectedChunks: [ + """ + @_cdecl("Java_com_example_swift_MyClass_method__") + func Java_com_example_swift_MyClass_method__(environment: UnsafeMutablePointer!, thisClass: jclass) { + MyClass.method() + } + """ + ] + ) + } + + @Test + func initializer_javaBindings() throws { + try assertOutput( + input: source, + .jni, + .java, + expectedChunks: [ + """ + /** + * Downcall to Swift: + * {@snippet lang=swift : + * public init(x: Int64, y: Int64) + * } + */ + public static MyClass init(long x, long y) { + long selfPointer = MyClass.allocatingInit(x, y); + return new MyClass(selfPointer); + } + """, + """ + /** + * Downcall to Swift: + * {@snippet lang=swift : + * public init() + * } + */ + public static MyClass init() { + long selfPointer = MyClass.allocatingInit(); + return new MyClass(selfPointer); + } + """, + """ + private static native long allocatingInit(long x, long y); + """, + """ + private static native long allocatingInit(); + """ + ] + ) + } + + @Test + func initializer_swiftThunks() throws { + try assertOutput( + input: source, + .jni, + .swift, + detectChunkByInitialLines: 1, + expectedChunks: [ + """ + @_cdecl("Java_com_example_swift_MyClass_allocatingInit__") + func Java_com_example_swift_MyClass_allocatingInit__(environment: UnsafeMutablePointer!, thisClass: jclass) -> jlong { + let selfPointer = UnsafeMutablePointer.allocate(capacity: 1) + selfPointer.initialize(to: MyClass()) + return Int64(Int(bitPattern: selfPointer)).getJNIValue(in: environment) + } + """, + """ + @_cdecl("Java_com_example_swift_MyClass_allocatingInit__JJ") + func Java_com_example_swift_MyClass_allocatingInit__JJ(environment: UnsafeMutablePointer!, thisClass: jclass, x: jlong, y: jlong) -> jlong { + let selfPointer = UnsafeMutablePointer.allocate(capacity: 1) + selfPointer.initialize(to: MyClass(x: Int64(fromJNI: x, in: environment!), y: Int64(fromJNI: y, in: environment!))) + return Int64(Int(bitPattern: selfPointer)).getJNIValue(in: environment) + } + """ + ] + ) + } +} diff --git a/Tests/JExtractSwiftTests/JNI/JNIModuleTests.swift b/Tests/JExtractSwiftTests/JNI/JNIModuleTests.swift index e483a4dd..d6a030a8 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIModuleTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIModuleTests.swift @@ -19,7 +19,7 @@ import Testing struct JNIModuleTests { let globalMethodWithPrimitives = """ public func helloWorld() - public func takeIntegers(i1: Int8, i2: Int16, i3: Int32, i4: Int) -> UInt16 + public func takeIntegers(i1: Int8, i2: Int16, i3: Int32, i4: Int64) -> UInt16 public func otherPrimitives(b: Bool, f: Float, d: Double) """ @@ -73,7 +73,7 @@ struct JNIModuleTests { /** * Downcall to Swift: * {@snippet lang=swift : - * public func takeIntegers(i1: Int8, i2: Int16, i3: Int32, i4: Int) -> UInt16 + * public func takeIntegers(i1: Int8, i2: Int16, i3: Int32, i4: Int64) -> UInt16 * } */ public static native char takeIntegers(byte i1, short i2, int i3, long i4); @@ -100,21 +100,21 @@ struct JNIModuleTests { detectChunkByInitialLines: 1, expectedChunks: [ """ - @_cdecl("Java_com_example_swift_SwiftModule_helloWorld") - func swiftjava_SwiftModule_helloWorld(environment: UnsafeMutablePointer!, thisClass: jclass) { + @_cdecl("Java_com_example_swift_SwiftModule_helloWorld__") + func Java_com_example_swift_SwiftModule_helloWorld__(environment: UnsafeMutablePointer!, thisClass: jclass) { SwiftModule.helloWorld() } """, """ - @_cdecl("Java_com_example_swift_SwiftModule_takeIntegers") - func swiftjava_SwiftModule_takeIntegers_i1_i2_i3_i4(environment: UnsafeMutablePointer!, thisClass: jclass, i1: jbyte, i2: jshort, i3: jint, i4: jlong) -> jchar { - let result = SwiftModule.takeIntegers(i1: Int8(fromJNI: i1, in: environment!), i2: Int16(fromJNI: i2, in: environment!), i3: Int32(fromJNI: i3, in: environment!), i4: Int(fromJNI: i4, in: environment!)) + @_cdecl("Java_com_example_swift_SwiftModule_takeIntegers__BSIJ") + func Java_com_example_swift_SwiftModule_takeIntegers__BSIJ(environment: UnsafeMutablePointer!, thisClass: jclass, i1: jbyte, i2: jshort, i3: jint, i4: jlong) -> jchar { + let result = SwiftModule.takeIntegers(i1: Int8(fromJNI: i1, in: environment!), i2: Int16(fromJNI: i2, in: environment!), i3: Int32(fromJNI: i3, in: environment!), i4: Int64(fromJNI: i4, in: environment!)) return result.getJNIValue(in: environment) } """, """ - @_cdecl("Java_com_example_swift_SwiftModule_otherPrimitives") - func swiftjava_SwiftModule_otherPrimitives_b_f_d(environment: UnsafeMutablePointer!, thisClass: jclass, b: jboolean, f: jfloat, d: jdouble) { + @_cdecl("Java_com_example_swift_SwiftModule_otherPrimitives__ZFD") + func Java_com_example_swift_SwiftModule_otherPrimitives__ZFD(environment: UnsafeMutablePointer!, thisClass: jclass, b: jboolean, f: jfloat, d: jdouble) { SwiftModule.otherPrimitives(b: Bool(fromJNI: b, in: environment!), f: Float(fromJNI: f, in: environment!), d: Double(fromJNI: d, in: environment!)) } """ @@ -151,8 +151,8 @@ struct JNIModuleTests { detectChunkByInitialLines: 1, expectedChunks: [ """ - @_cdecl("Java_com_example_swift_SwiftModule_copy") - func swiftjava_SwiftModule_copy__(environment: UnsafeMutablePointer!, thisClass: jclass, string: jstring?) -> jstring? { + @_cdecl("Java_com_example_swift_SwiftModule_copy__Ljava_lang_String_2") + func Java_com_example_swift_SwiftModule_copy__Ljava_lang_String_2(environment: UnsafeMutablePointer!, thisClass: jclass, string: jstring?) -> jstring? { let result = SwiftModule.copy(String(fromJNI: string, in: environment!)) return result.getJNIValue(in: environment) } @@ -199,8 +199,8 @@ struct JNIModuleTests { detectChunkByInitialLines: 1, expectedChunks: [ """ - @_cdecl("Java_com_example_swift_SwiftModule_methodA") - func swiftjava_SwiftModule_methodA(environment: UnsafeMutablePointer!, thisClass: jclass) { + @_cdecl("Java_com_example_swift_SwiftModule_methodA__") + func Java_com_example_swift_SwiftModule_methodA__(environment: UnsafeMutablePointer!, thisClass: jclass) { do { try SwiftModule.methodA() } catch { @@ -209,8 +209,8 @@ struct JNIModuleTests { } """, """ - @_cdecl("Java_com_example_swift_SwiftModule_methodB") - func swiftjava_SwiftModule_methodB(environment: UnsafeMutablePointer!, thisClass: jclass) -> jlong { + @_cdecl("Java_com_example_swift_SwiftModule_methodB__") + func Java_com_example_swift_SwiftModule_methodB__(environment: UnsafeMutablePointer!, thisClass: jclass) -> jlong { do { let result = try SwiftModule.methodB() return result.getJNIValue(in: environment) From d266a4452a115f58d0d73f2e89cd921a8f611aab Mon Sep 17 00:00:00 2001 From: Mads Odgaard Date: Tue, 8 Jul 2025 16:03:36 +0200 Subject: [PATCH 302/426] Separate SwiftKit into SwiftKitCore and SwiftKitFFM (#300) --- .github/actions/prepare_env/action.yml | 1 + .github/workflows/pull_request.yml | 24 +++-- ...d-logic.java-common-conventions.gradle.kts | 15 ---- Samples/JExtractJNISampleApp/build.gradle | 2 +- .../com/example/swift/HelloJava2SwiftJNI.java | 6 +- Samples/SwiftAndJavaJarSampleLib/build.gradle | 3 +- .../SwiftAndJavaJarSampleLib/ci-validate.sh | 5 +- .../{ => ffm}/JavaToSwiftBenchmark.java | 2 +- .../com/example/swift/HelloJava2Swift.java | 19 ++-- .../com/example/swift/MySwiftClassTest.java | 12 +-- .../com/example/swift/MySwiftLibraryTest.java | 4 - .../swift/swiftkit/ffm}/MySwiftClassTest.java | 14 +-- .../swiftkit/{ => ffm}/SwiftArenaTest.java | 15 ++-- Samples/SwiftKitSampleApp/build.gradle | 4 +- .../{ => ffm}/JavaToSwiftBenchmark.java | 6 +- .../{ => ffm}/StringPassingBenchmark.java | 9 +- .../com/example/swift/HelloJava2Swift.java | 33 +++---- .../com/example/swift/MySwiftClassTest.java | 12 +-- .../com/example/swift/MySwiftLibraryTest.java | 5 -- .../swift/swiftkitffm}/MySwiftClassTest.java | 16 ++-- .../MySwiftStructTest.java | 5 +- .../SwiftArenaTest.java | 23 +++-- ...t2JavaGenerator+JavaBindingsPrinting.swift | 10 +-- ...MSwift2JavaGenerator+JavaTranslation.swift | 6 +- .../FFM/FFMSwift2JavaGenerator.swift | 21 ++--- ...ift2JavaGenerator+SwiftThunkPrinting.swift | 2 +- .../JExtractSwiftLib/SwiftKit+Printing.swift | 2 +- {SwiftKit => SwiftKitCore}/build.gradle | 8 +- .../swiftkit/core}/ClosableSwiftArena.java | 3 +- .../core}/ConfinedSwiftMemorySession.java | 29 ++----- .../swift/swiftkit/core/JNISwiftInstance.java | 56 ++++++++++++ .../core/JNISwiftInstanceCleanup.java | 31 +++++++ .../org/swift/swiftkit/core}/SwiftArena.java | 29 +------ .../swift/swiftkit/core}/SwiftInstance.java | 43 +++------ .../swiftkit/core/SwiftInstanceCleanup.java | 20 +++++ .../swift/swiftkit/core/SwiftLibraries.java | 83 ++++++++++++++++++ .../org/swift/swiftkit/core}/SwiftValue.java | 2 +- .../swiftkit/core/WrongThreadException.java | 14 ++- .../swiftkit/core}/util/PlatformUtils.java | 2 +- .../swiftkit/core}/util/StringUtils.java | 2 +- SwiftKitFFM/build.gradle | 87 +++++++++++++++++++ .../ffm/AllocatingAutoSwiftMemorySession.java | 22 ++--- .../swiftkit/ffm/AllocatingSwiftArena.java | 34 ++++++++ .../ffm/ClosableAllocatingSwiftArena.java | 22 +++++ .../ffm/FFMConfinedSwiftMemorySession.java | 40 +++++++++ .../swift/swiftkit/ffm/FFMSwiftInstance.java | 69 +++++++++++++++ .../swiftkit/ffm/FFMSwiftInstanceCleanup.java | 22 +++-- .../swiftkit/ffm}/MemorySegmentUtils.java | 2 +- .../org/swift/swiftkit/ffm}/SwiftAnyType.java | 7 +- .../swift/swiftkit/ffm}/SwiftHeapObject.java | 5 +- .../org/swift/swiftkit/ffm/SwiftRuntime.java | 58 ++----------- .../swift/swiftkit/ffm}/SwiftValueLayout.java | 2 +- .../swiftkit/ffm}/SwiftValueWitnessTable.java | 15 ++-- .../swift/swiftkit/ffm}/AutoArenaTest.java | 15 +--- .../ffm}/SwiftRuntimeMetadataTest.java | 6 +- .../ClassPrintingTests.swift | 2 +- .../FuncCallbackImportTests.swift | 20 ++--- .../FunctionDescriptorImportTests.swift | 20 ++--- .../MethodImportTests.swift | 8 +- .../StringPassingTests.swift | 6 +- .../VariableImportTests.swift | 8 +- settings.gradle | 3 +- 62 files changed, 689 insertions(+), 382 deletions(-) rename Samples/SwiftAndJavaJarSampleLib/src/jmh/java/org/swift/swiftkit/{ => ffm}/JavaToSwiftBenchmark.java (98%) rename Samples/{SwiftKitSampleApp/src/test/java/org/swift/swiftkit => SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/ffm}/MySwiftClassTest.java (72%) rename Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/{ => ffm}/SwiftArenaTest.java (77%) rename Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/{ => ffm}/JavaToSwiftBenchmark.java (92%) rename Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/{ => ffm}/StringPassingBenchmark.java (94%) rename Samples/{SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit => SwiftKitSampleApp/src/test/java/org/swift/swiftkitffm}/MySwiftClassTest.java (66%) rename Samples/SwiftKitSampleApp/src/test/java/org/swift/{swiftkit => swiftkitffm}/MySwiftStructTest.java (86%) rename Samples/SwiftKitSampleApp/src/test/java/org/swift/{swiftkit => swiftkitffm}/SwiftArenaTest.java (84%) rename {SwiftKit => SwiftKitCore}/build.gradle (87%) rename {SwiftKit/src/main/java/org/swift/swiftkit => SwiftKitCore/src/main/java/org/swift/swiftkit/core}/ClosableSwiftArena.java (96%) rename {SwiftKit/src/main/java/org/swift/swiftkit => SwiftKitCore/src/main/java/org/swift/swiftkit/core}/ConfinedSwiftMemorySession.java (68%) create mode 100644 SwiftKitCore/src/main/java/org/swift/swiftkit/core/JNISwiftInstance.java create mode 100644 SwiftKitCore/src/main/java/org/swift/swiftkit/core/JNISwiftInstanceCleanup.java rename {SwiftKit/src/main/java/org/swift/swiftkit => SwiftKitCore/src/main/java/org/swift/swiftkit/core}/SwiftArena.java (54%) rename {SwiftKit/src/main/java/org/swift/swiftkit => SwiftKitCore/src/main/java/org/swift/swiftkit/core}/SwiftInstance.java (70%) create mode 100644 SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftInstanceCleanup.java create mode 100644 SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftLibraries.java rename {SwiftKit/src/main/java/org/swift/swiftkit => SwiftKitCore/src/main/java/org/swift/swiftkit/core}/SwiftValue.java (94%) rename SwiftKit/src/main/java/org/swift/swiftkit/ManagedSwiftType.java => SwiftKitCore/src/main/java/org/swift/swiftkit/core/WrongThreadException.java (67%) rename {SwiftKit/src/main/java/org/swift/swiftkit => SwiftKitCore/src/main/java/org/swift/swiftkit/core}/util/PlatformUtils.java (97%) rename {SwiftKit/src/main/java/org/swift/swiftkit => SwiftKitCore/src/main/java/org/swift/swiftkit/core}/util/StringUtils.java (96%) create mode 100644 SwiftKitFFM/build.gradle rename SwiftKit/src/main/java/org/swift/swiftkit/AutoSwiftMemorySession.java => SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/AllocatingAutoSwiftMemorySession.java (78%) create mode 100644 SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/AllocatingSwiftArena.java create mode 100644 SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/ClosableAllocatingSwiftArena.java create mode 100644 SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMConfinedSwiftMemorySession.java create mode 100644 SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMSwiftInstance.java rename SwiftKit/src/main/java/org/swift/swiftkit/SwiftInstanceCleanup.java => SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMSwiftInstanceCleanup.java (63%) rename {SwiftKit/src/main/java/org/swift/swiftkit => SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm}/MemorySegmentUtils.java (97%) rename {SwiftKit/src/main/java/org/swift/swiftkit => SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm}/SwiftAnyType.java (89%) rename {SwiftKit/src/main/java/org/swift/swiftkit => SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm}/SwiftHeapObject.java (91%) rename SwiftKit/src/main/java/org/swift/swiftkit/SwiftKit.java => SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/SwiftRuntime.java (88%) rename {SwiftKit/src/main/java/org/swift/swiftkit => SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm}/SwiftValueLayout.java (98%) rename {SwiftKit/src/main/java/org/swift/swiftkit => SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm}/SwiftValueWitnessTable.java (94%) rename {SwiftKit/src/test/java/org/swift/swiftkit => SwiftKitFFM/src/test/java/org/swift/swiftkit/ffm}/AutoArenaTest.java (78%) rename {SwiftKit/src/test/java/org/swift/swiftkit => SwiftKitFFM/src/test/java/org/swift/swiftkit/ffm}/SwiftRuntimeMetadataTest.java (95%) diff --git a/.github/actions/prepare_env/action.yml b/.github/actions/prepare_env/action.yml index 33fa1f76..c63b87cf 100644 --- a/.github/actions/prepare_env/action.yml +++ b/.github/actions/prepare_env/action.yml @@ -11,6 +11,7 @@ runs: java-version: | 24 21 + 19 cache: 'gradle' - name: Set JAVA_HOME_{N} shell: bash diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index b55e0489..9a0b59b8 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -31,10 +31,14 @@ jobs: - uses: actions/checkout@v4 - name: Prepare CI Environment uses: ./.github/actions/prepare_env - - name: Gradle :SwiftKit:build - run: ./gradlew build -x test - - name: Gradle :SwiftKit:check - run: ./gradlew :SwiftKit:check --info + - name: Gradle :SwiftKitCore:build + run: ./gradlew :SwiftKitCore:build -x test + - name: Gradle :SwiftKitCore:check + run: ./gradlew :SwiftKitCore:check --info + - name: Gradle :SwiftKitFFM:build + run: ./gradlew :SwiftKitFFM:build -x test + - name: Gradle :SwiftKitFFM:check + run: ./gradlew :SwiftKitFFM:check --info test-java-macos: name: Test (Java) (${{ matrix.os_version }} swift:${{ matrix.swift_version }} jdk:${{matrix.jdk_vendor}}) @@ -51,10 +55,14 @@ jobs: - uses: actions/checkout@v4 - name: Prepare CI Environment uses: ./.github/actions/prepare_env - - name: Gradle :SwiftKit:build - run: ./gradlew build -x test - - name: Gradle :SwiftKit:check - run: ./gradlew :SwiftKit:check --debug + - name: Gradle :SwiftKitCore:build + run: ./gradlew :SwiftKitCore:build -x test + - name: Gradle :SwiftKitCore:check + run: ./gradlew :SwiftKitCore:check --debug + - name: Gradle :SwiftKitFFM:build + run: ./gradlew :SwiftKitFFM:build -x test + - name: Gradle :SwiftKitFFM:check + run: ./gradlew :SwiftKitFFM:check --debug benchmark-java: name: Benchmark (JMH) (${{ matrix.os_version }} swift:${{ matrix.swift_version }} jdk:${{matrix.jdk_vendor}}) diff --git a/BuildLogic/src/main/kotlin/build-logic.java-common-conventions.gradle.kts b/BuildLogic/src/main/kotlin/build-logic.java-common-conventions.gradle.kts index fb10bee0..df0a6633 100644 --- a/BuildLogic/src/main/kotlin/build-logic.java-common-conventions.gradle.kts +++ b/BuildLogic/src/main/kotlin/build-logic.java-common-conventions.gradle.kts @@ -31,21 +31,6 @@ repositories { mavenCentral() } -testing { - suites { - val test by getting(JvmTestSuite::class) { - useJUnitJupiter("5.10.3") - } - } -} - -/// Enable access to preview APIs, e.g. java.lang.foreign.* (Panama) -tasks.withType(JavaCompile::class).forEach { - it.options.compilerArgs.add("--enable-preview") - it.options.compilerArgs.add("-Xlint:preview") -} - - fun getSwiftRuntimeLibraryPaths(): List { val process = ProcessBuilder("swiftc", "-print-target-info") .redirectError(ProcessBuilder.Redirect.INHERIT) diff --git a/Samples/JExtractJNISampleApp/build.gradle b/Samples/JExtractJNISampleApp/build.gradle index 03794ff7..54bd725a 100644 --- a/Samples/JExtractJNISampleApp/build.gradle +++ b/Samples/JExtractJNISampleApp/build.gradle @@ -148,7 +148,7 @@ tasks.clean { } dependencies { - implementation(project(':SwiftKit')) + implementation(project(':SwiftKitCore')) testImplementation(platform("org.junit:junit-bom:5.10.0")) testImplementation("org.junit.jupiter:junit-jupiter") diff --git a/Samples/JExtractJNISampleApp/src/main/java/com/example/swift/HelloJava2SwiftJNI.java b/Samples/JExtractJNISampleApp/src/main/java/com/example/swift/HelloJava2SwiftJNI.java index 7d0d77e1..66366a19 100644 --- a/Samples/JExtractJNISampleApp/src/main/java/com/example/swift/HelloJava2SwiftJNI.java +++ b/Samples/JExtractJNISampleApp/src/main/java/com/example/swift/HelloJava2SwiftJNI.java @@ -18,12 +18,12 @@ // Import javakit/swiftkit support libraries -import org.swift.swiftkit.SwiftKit; +import org.swift.swiftkit.core.SwiftLibraries; public class HelloJava2SwiftJNI { public static void main(String[] args) { - System.out.print("Property: java.library.path = " + SwiftKit.getJavaLibraryPath()); + System.out.print("Property: java.library.path = " + SwiftLibraries.getJavaLibraryPath()); examples(); } @@ -35,10 +35,8 @@ static void examples() { MySwiftLibrary.globalTakeIntInt(1337, 42); long cnt = MySwiftLibrary.globalWriteString("String from Java"); - SwiftKit.trace("count = " + cnt); long i = MySwiftLibrary.globalMakeInt(); - SwiftKit.trace("globalMakeInt() = " + i); MySwiftClass.method(); diff --git a/Samples/SwiftAndJavaJarSampleLib/build.gradle b/Samples/SwiftAndJavaJarSampleLib/build.gradle index cc4c79d4..96b25e22 100644 --- a/Samples/SwiftAndJavaJarSampleLib/build.gradle +++ b/Samples/SwiftAndJavaJarSampleLib/build.gradle @@ -43,7 +43,8 @@ java { } dependencies { - implementation(project(':SwiftKit')) + implementation(project(':SwiftKitCore')) + implementation(project(':SwiftKitFFM')) testImplementation(platform("org.junit:junit-bom:5.10.0")) testImplementation("org.junit.jupiter:junit-jupiter") diff --git a/Samples/SwiftAndJavaJarSampleLib/ci-validate.sh b/Samples/SwiftAndJavaJarSampleLib/ci-validate.sh index f56b611e..4fde0ef0 100755 --- a/Samples/SwiftAndJavaJarSampleLib/ci-validate.sh +++ b/Samples/SwiftAndJavaJarSampleLib/ci-validate.sh @@ -27,9 +27,10 @@ fi # check if we can compile a plain Example file that uses the generated Java bindings that should be in the generated jar # The classpath MUST end with a * if it contains jar files, and must not if it directly contains class files. -SWIFTKIT_CLASSPATH="$(pwd)/../../SwiftKit/build/libs/*" +SWIFTKIT_CORE_CLASSPATH="$(pwd)/../../SwiftKitCore/build/libs/*" +SWIFTKIT_FFM_CLASSPATH="$(pwd)/../../SwiftKitFFM/build/libs/*" MYLIB_CLASSPATH="$(pwd)/build/libs/*" -CLASSPATH="$(pwd)/:${SWIFTKIT_CLASSPATH}:${MYLIB_CLASSPATH}" +CLASSPATH="$(pwd)/:${SWIFTKIT_FFM_CLASSPATH}:${SWIFTKIT_CORE_CLASSPATH}:${MYLIB_CLASSPATH}" echo "CLASSPATH = ${CLASSPATH}" $JAVAC -cp "${CLASSPATH}" Example.java diff --git a/Samples/SwiftAndJavaJarSampleLib/src/jmh/java/org/swift/swiftkit/JavaToSwiftBenchmark.java b/Samples/SwiftAndJavaJarSampleLib/src/jmh/java/org/swift/swiftkit/ffm/JavaToSwiftBenchmark.java similarity index 98% rename from Samples/SwiftAndJavaJarSampleLib/src/jmh/java/org/swift/swiftkit/JavaToSwiftBenchmark.java rename to Samples/SwiftAndJavaJarSampleLib/src/jmh/java/org/swift/swiftkit/ffm/JavaToSwiftBenchmark.java index 4e3edf03..7d6b92dc 100644 --- a/Samples/SwiftAndJavaJarSampleLib/src/jmh/java/org/swift/swiftkit/JavaToSwiftBenchmark.java +++ b/Samples/SwiftAndJavaJarSampleLib/src/jmh/java/org/swift/swiftkit/ffm/JavaToSwiftBenchmark.java @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -package org.swift.swiftkit; +package org.swift.swiftkit.ffm; import java.util.concurrent.TimeUnit; diff --git a/Samples/SwiftAndJavaJarSampleLib/src/main/java/com/example/swift/HelloJava2Swift.java b/Samples/SwiftAndJavaJarSampleLib/src/main/java/com/example/swift/HelloJava2Swift.java index cd8af700..e41547bd 100644 --- a/Samples/SwiftAndJavaJarSampleLib/src/main/java/com/example/swift/HelloJava2Swift.java +++ b/Samples/SwiftAndJavaJarSampleLib/src/main/java/com/example/swift/HelloJava2Swift.java @@ -16,15 +16,10 @@ // Import swift-extract generated sources -import com.example.swift.MySwiftLibrary; -import com.example.swift.MySwiftClass; - // Import javakit/swiftkit support libraries -import org.swift.swiftkit.SwiftArena; -import org.swift.swiftkit.SwiftKit; -import org.swift.swiftkit.SwiftValueWitnessTable; - -import java.util.Arrays; +import org.swift.swiftkit.core.SwiftLibraries; +import org.swift.swiftkit.ffm.AllocatingSwiftArena; +import org.swift.swiftkit.ffm.SwiftRuntime; public class HelloJava2Swift { @@ -32,7 +27,7 @@ public static void main(String[] args) { boolean traceDowncalls = Boolean.getBoolean("jextract.trace.downcalls"); System.out.println("Property: jextract.trace.downcalls = " + traceDowncalls); - System.out.print("Property: java.library.path = " +SwiftKit.getJavaLibraryPath()); + System.out.print("Property: java.library.path = " + SwiftLibraries.getJavaLibraryPath()); examples(); } @@ -43,12 +38,12 @@ static void examples() { MySwiftLibrary.globalTakeInt(1337); // Example of using an arena; MyClass.deinit is run at end of scope - try (var arena = SwiftArena.ofConfined()) { + try (var arena = AllocatingSwiftArena.ofConfined()) { MySwiftClass obj = MySwiftClass.init(2222, 7777, arena); // just checking retains/releases work - SwiftKit.retain(obj); - SwiftKit.release(obj); + SwiftRuntime.retain(obj); + SwiftRuntime.release(obj); obj.voidMethod(); obj.takeIntMethod(42); diff --git a/Samples/SwiftAndJavaJarSampleLib/src/test/java/com/example/swift/MySwiftClassTest.java b/Samples/SwiftAndJavaJarSampleLib/src/test/java/com/example/swift/MySwiftClassTest.java index bb46ef3d..6fb7651c 100644 --- a/Samples/SwiftAndJavaJarSampleLib/src/test/java/com/example/swift/MySwiftClassTest.java +++ b/Samples/SwiftAndJavaJarSampleLib/src/test/java/com/example/swift/MySwiftClassTest.java @@ -16,8 +16,8 @@ import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; -import org.swift.swiftkit.SwiftArena; -import org.swift.swiftkit.SwiftKit; +import org.swift.swiftkit.core.SwiftLibraries; +import org.swift.swiftkit.ffm.AllocatingSwiftArena; import java.io.File; import java.util.stream.Stream; @@ -27,7 +27,7 @@ public class MySwiftClassTest { void checkPaths(Throwable throwable) { - var paths = SwiftKit.getJavaLibraryPath().split(":"); + var paths = SwiftLibraries.getJavaLibraryPath().split(":"); for (var path : paths) { System.out.println("CHECKING PATH: " + path); Stream.of(new File(path).listFiles()) @@ -42,7 +42,7 @@ void checkPaths(Throwable throwable) { @Test void test_MySwiftClass_voidMethod() { - try(var arena = SwiftArena.ofConfined()) { + try(var arena = AllocatingSwiftArena.ofConfined()) { MySwiftClass o = MySwiftClass.init(12, 42, arena); o.voidMethod(); } catch (Throwable throwable) { @@ -52,7 +52,7 @@ void test_MySwiftClass_voidMethod() { @Test void test_MySwiftClass_makeIntMethod() { - try(var arena = SwiftArena.ofConfined()) { + try(var arena = AllocatingSwiftArena.ofConfined()) { MySwiftClass o = MySwiftClass.init(12, 42, arena); var got = o.makeIntMethod(); assertEquals(12, got); @@ -62,7 +62,7 @@ void test_MySwiftClass_makeIntMethod() { @Test @Disabled // TODO: Need var mangled names in interfaces void test_MySwiftClass_property_len() { - try(var arena = SwiftArena.ofConfined()) { + try(var arena = AllocatingSwiftArena.ofConfined()) { MySwiftClass o = MySwiftClass.init(12, 42, arena); var got = o.getLen(); assertEquals(12, got); diff --git a/Samples/SwiftAndJavaJarSampleLib/src/test/java/com/example/swift/MySwiftLibraryTest.java b/Samples/SwiftAndJavaJarSampleLib/src/test/java/com/example/swift/MySwiftLibraryTest.java index 74df5da8..13ebb1b0 100644 --- a/Samples/SwiftAndJavaJarSampleLib/src/test/java/com/example/swift/MySwiftLibraryTest.java +++ b/Samples/SwiftAndJavaJarSampleLib/src/test/java/com/example/swift/MySwiftLibraryTest.java @@ -14,14 +14,10 @@ package com.example.swift; -import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; -import org.swift.swiftkit.SwiftKit; -import java.util.Arrays; import java.util.concurrent.CountDownLatch; -import java.util.stream.Collectors; import static org.junit.jupiter.api.Assertions.*; diff --git a/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/MySwiftClassTest.java b/Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/ffm/MySwiftClassTest.java similarity index 72% rename from Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/MySwiftClassTest.java rename to Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/ffm/MySwiftClassTest.java index 78da5a64..fb1c5d1a 100644 --- a/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/MySwiftClassTest.java +++ b/Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/ffm/MySwiftClassTest.java @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -package org.swift.swiftkit; +package org.swift.swiftkit.ffm; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -24,16 +24,16 @@ public class MySwiftClassTest { @Test void call_retain_retainCount_release() { - var arena = SwiftArena.ofConfined(); + var arena = AllocatingSwiftArena.ofConfined(); var obj = MySwiftClass.init(1, 2, arena); - assertEquals(1, SwiftKit.retainCount(obj)); + assertEquals(1, SwiftRuntime.retainCount(obj)); // TODO: test directly on SwiftHeapObject inheriting obj - SwiftKit.retain(obj); - assertEquals(2, SwiftKit.retainCount(obj)); + SwiftRuntime.retain(obj); + assertEquals(2, SwiftRuntime.retainCount(obj)); - SwiftKit.release(obj); - assertEquals(1, SwiftKit.retainCount(obj)); + SwiftRuntime.release(obj); + assertEquals(1, SwiftRuntime.retainCount(obj)); } } diff --git a/Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/SwiftArenaTest.java b/Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/ffm/SwiftArenaTest.java similarity index 77% rename from Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/SwiftArenaTest.java rename to Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/ffm/SwiftArenaTest.java index e8b1ac04..8d786d95 100644 --- a/Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/SwiftArenaTest.java +++ b/Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/ffm/SwiftArenaTest.java @@ -12,20 +12,15 @@ // //===----------------------------------------------------------------------===// -package org.swift.swiftkit; +package org.swift.swiftkit.ffm; import com.example.swift.MySwiftClass; -import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.DisabledIf; -import org.swift.swiftkit.util.PlatformUtils; +import org.swift.swiftkit.core.util.PlatformUtils; -import java.util.Arrays; -import java.util.stream.Collectors; - -import static org.junit.jupiter.api.Assertions.*; -import static org.swift.swiftkit.SwiftKit.*; -import static org.swift.swiftkit.SwiftKit.retainCount; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.swift.swiftkit.ffm.SwiftRuntime.*; public class SwiftArenaTest { @@ -38,7 +33,7 @@ static boolean isAmd64() { @Test @DisabledIf("isAmd64") public void arena_releaseClassOnClose_class_ok() { - try (var arena = SwiftArena.ofConfined()) { + try (var arena = AllocatingSwiftArena.ofConfined()) { var obj = MySwiftClass.init(1, 2, arena); retain(obj); diff --git a/Samples/SwiftKitSampleApp/build.gradle b/Samples/SwiftKitSampleApp/build.gradle index 647eaba9..048c984d 100644 --- a/Samples/SwiftKitSampleApp/build.gradle +++ b/Samples/SwiftKitSampleApp/build.gradle @@ -16,7 +16,6 @@ import groovy.json.JsonSlurper import org.swift.swiftkit.gradle.BuildUtils import java.nio.file.* -import kotlinx.serialization.json.* plugins { id("build-logic.java-application-conventions") @@ -148,7 +147,8 @@ tasks.clean { } dependencies { - implementation(project(':SwiftKit')) + implementation(project(':SwiftKitCore')) + implementation(project(':SwiftKitFFM')) testImplementation(platform("org.junit:junit-bom:5.10.0")) testImplementation("org.junit.jupiter:junit-jupiter") diff --git a/Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/JavaToSwiftBenchmark.java b/Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/ffm/JavaToSwiftBenchmark.java similarity index 92% rename from Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/JavaToSwiftBenchmark.java rename to Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/ffm/JavaToSwiftBenchmark.java index ff313fc6..dffbd090 100644 --- a/Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/JavaToSwiftBenchmark.java +++ b/Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/ffm/JavaToSwiftBenchmark.java @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -package org.swift.swiftkit; +package org.swift.swiftkit.ffm; import com.example.swift.HelloJava2Swift; import com.example.swift.MySwiftLibrary; @@ -31,12 +31,12 @@ public class JavaToSwiftBenchmark { @State(Scope.Benchmark) public static class BenchmarkState { - ClosableSwiftArena arena; + ClosableAllocatingSwiftArena arena; MySwiftClass obj; @Setup(Level.Trial) public void beforeAll() { - arena = SwiftArena.ofConfined(); + arena = AllocatingSwiftArena.ofConfined(); obj = MySwiftClass.init(1, 2, arena); } diff --git a/Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/StringPassingBenchmark.java b/Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/ffm/StringPassingBenchmark.java similarity index 94% rename from Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/StringPassingBenchmark.java rename to Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/ffm/StringPassingBenchmark.java index 0e686fb4..25855842 100644 --- a/Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/StringPassingBenchmark.java +++ b/Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/ffm/StringPassingBenchmark.java @@ -12,15 +12,14 @@ // //===----------------------------------------------------------------------===// -package org.swift.swiftkit; +package org.swift.swiftkit.ffm; import com.example.swift.HelloJava2Swift; import com.example.swift.MySwiftClass; import com.example.swift.MySwiftLibrary; import org.openjdk.jmh.annotations.*; +import org.swift.swiftkit.core.ClosableSwiftArena; -import java.lang.foreign.Arena; -import java.nio.charset.StandardCharsets; import java.util.concurrent.TimeUnit; @BenchmarkMode(Mode.AverageTime) @@ -40,12 +39,12 @@ public class StringPassingBenchmark { public int stringLen; public String string; - ClosableSwiftArena arena; + ClosableAllocatingSwiftArena arena; MySwiftClass obj; @Setup(Level.Trial) public void beforeAll() { - arena = SwiftArena.ofConfined(); + arena = AllocatingSwiftArena.ofConfined(); obj = MySwiftClass.init(1, 2, arena); string = makeString(stringLen); } diff --git a/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java b/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java index c12d82dd..668140b2 100644 --- a/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java +++ b/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java @@ -18,8 +18,9 @@ // Import javakit/swiftkit support libraries -import org.swift.swiftkit.SwiftArena; -import org.swift.swiftkit.SwiftKit; +import org.swift.swiftkit.core.SwiftLibraries; +import org.swift.swiftkit.ffm.AllocatingSwiftArena; +import org.swift.swiftkit.ffm.SwiftRuntime; public class HelloJava2Swift { @@ -27,7 +28,7 @@ public static void main(String[] args) { boolean traceDowncalls = Boolean.getBoolean("jextract.trace.downcalls"); System.out.println("Property: jextract.trace.downcalls = " + traceDowncalls); - System.out.print("Property: java.library.path = " + SwiftKit.getJavaLibraryPath()); + System.out.print("Property: java.library.path = " + SwiftLibraries.getJavaLibraryPath()); examples(); } @@ -39,30 +40,30 @@ static void examples() { long cnt = MySwiftLibrary.globalWriteString("String from Java"); - SwiftKit.trace("count = " + cnt); + SwiftRuntime.trace("count = " + cnt); MySwiftLibrary.globalCallMeRunnable(() -> { - SwiftKit.trace("running runnable"); + SwiftRuntime.trace("running runnable"); }); - SwiftKit.trace("getGlobalBuffer().byteSize()=" + MySwiftLibrary.getGlobalBuffer().byteSize()); + SwiftRuntime.trace("getGlobalBuffer().byteSize()=" + MySwiftLibrary.getGlobalBuffer().byteSize()); MySwiftLibrary.withBuffer((buf) -> { - SwiftKit.trace("withBuffer{$0.byteSize()}=" + buf.byteSize()); + SwiftRuntime.trace("withBuffer{$0.byteSize()}=" + buf.byteSize()); }); // Example of using an arena; MyClass.deinit is run at end of scope - try (var arena = SwiftArena.ofConfined()) { + try (var arena = AllocatingSwiftArena.ofConfined()) { MySwiftClass obj = MySwiftClass.init(2222, 7777, arena); // just checking retains/releases work - SwiftKit.trace("retainCount = " + SwiftKit.retainCount(obj)); - SwiftKit.retain(obj); - SwiftKit.trace("retainCount = " + SwiftKit.retainCount(obj)); - SwiftKit.release(obj); - SwiftKit.trace("retainCount = " + SwiftKit.retainCount(obj)); + SwiftRuntime.trace("retainCount = " + SwiftRuntime.retainCount(obj)); + SwiftRuntime.retain(obj); + SwiftRuntime.trace("retainCount = " + SwiftRuntime.retainCount(obj)); + SwiftRuntime.release(obj); + SwiftRuntime.trace("retainCount = " + SwiftRuntime.retainCount(obj)); obj.setCounter(12); - SwiftKit.trace("obj.counter = " + obj.getCounter()); + SwiftRuntime.trace("obj.counter = " + obj.getCounter()); obj.voidMethod(); obj.takeIntMethod(42); @@ -71,9 +72,9 @@ static void examples() { otherObj.voidMethod(); MySwiftStruct swiftValue = MySwiftStruct.init(2222, 1111, arena); - SwiftKit.trace("swiftValue.capacity = " + swiftValue.getCapacity()); + SwiftRuntime.trace("swiftValue.capacity = " + swiftValue.getCapacity()); swiftValue.withCapLen((cap, len) -> { - SwiftKit.trace("withCapLenCallback: cap=" + cap + ", len=" + len); + SwiftRuntime.trace("withCapLenCallback: cap=" + cap + ", len=" + len); }); } diff --git a/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/MySwiftClassTest.java b/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/MySwiftClassTest.java index 6c0ceb1e..1f0464eb 100644 --- a/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/MySwiftClassTest.java +++ b/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/MySwiftClassTest.java @@ -16,8 +16,8 @@ import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; -import org.swift.swiftkit.SwiftArena; -import org.swift.swiftkit.SwiftKit; +import org.swift.swiftkit.core.SwiftLibraries; +import org.swift.swiftkit.ffm.AllocatingSwiftArena; import java.io.File; import java.util.stream.Stream; @@ -27,7 +27,7 @@ public class MySwiftClassTest { void checkPaths(Throwable throwable) { - var paths = SwiftKit.getJavaLibraryPath().split(":"); + var paths = SwiftLibraries.getJavaLibraryPath().split(":"); for (var path : paths) { Stream.of(new File(path).listFiles()) .filter(file -> !file.isDirectory()) @@ -41,7 +41,7 @@ void checkPaths(Throwable throwable) { @Test void test_MySwiftClass_voidMethod() { - try(var arena = SwiftArena.ofConfined()) { + try(var arena = AllocatingSwiftArena.ofConfined()) { MySwiftClass o = MySwiftClass.init(12, 42, arena); o.voidMethod(); } catch (Throwable throwable) { @@ -51,7 +51,7 @@ void test_MySwiftClass_voidMethod() { @Test void test_MySwiftClass_makeIntMethod() { - try(var arena = SwiftArena.ofConfined()) { + try(var arena = AllocatingSwiftArena.ofConfined()) { MySwiftClass o = MySwiftClass.init(12, 42, arena); var got = o.makeIntMethod(); assertEquals(12, got); @@ -61,7 +61,7 @@ void test_MySwiftClass_makeIntMethod() { @Test @Disabled // TODO: Need var mangled names in interfaces void test_MySwiftClass_property_len() { - try(var arena = SwiftArena.ofConfined()) { + try(var arena = AllocatingSwiftArena.ofConfined()) { MySwiftClass o = MySwiftClass.init(12, 42, arena); var got = o.getLen(); assertEquals(12, got); diff --git a/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/MySwiftLibraryTest.java b/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/MySwiftLibraryTest.java index 2df53843..a6c34b57 100644 --- a/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/MySwiftLibraryTest.java +++ b/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/MySwiftLibraryTest.java @@ -14,15 +14,10 @@ package com.example.swift; -import com.example.swift.MySwiftLibrary; -import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; -import org.swift.swiftkit.SwiftKit; -import java.util.Arrays; import java.util.concurrent.CountDownLatch; -import java.util.stream.Collectors; import static org.junit.jupiter.api.Assertions.*; diff --git a/Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/MySwiftClassTest.java b/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkitffm/MySwiftClassTest.java similarity index 66% rename from Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/MySwiftClassTest.java rename to Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkitffm/MySwiftClassTest.java index 78da5a64..17db4c41 100644 --- a/Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/MySwiftClassTest.java +++ b/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkitffm/MySwiftClassTest.java @@ -12,28 +12,30 @@ // //===----------------------------------------------------------------------===// -package org.swift.swiftkit; +package org.swift.swiftkitffm; import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.Test; import com.example.swift.MySwiftClass; +import org.swift.swiftkit.ffm.AllocatingSwiftArena; +import org.swift.swiftkit.ffm.SwiftRuntime; public class MySwiftClassTest { @Test void call_retain_retainCount_release() { - var arena = SwiftArena.ofConfined(); + var arena = AllocatingSwiftArena.ofConfined(); var obj = MySwiftClass.init(1, 2, arena); - assertEquals(1, SwiftKit.retainCount(obj)); + assertEquals(1, SwiftRuntime.retainCount(obj)); // TODO: test directly on SwiftHeapObject inheriting obj - SwiftKit.retain(obj); - assertEquals(2, SwiftKit.retainCount(obj)); + SwiftRuntime.retain(obj); + assertEquals(2, SwiftRuntime.retainCount(obj)); - SwiftKit.release(obj); - assertEquals(1, SwiftKit.retainCount(obj)); + SwiftRuntime.release(obj); + assertEquals(1, SwiftRuntime.retainCount(obj)); } } diff --git a/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/MySwiftStructTest.java b/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkitffm/MySwiftStructTest.java similarity index 86% rename from Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/MySwiftStructTest.java rename to Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkitffm/MySwiftStructTest.java index 843551a5..6b994137 100644 --- a/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/MySwiftStructTest.java +++ b/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkitffm/MySwiftStructTest.java @@ -12,10 +12,11 @@ // //===----------------------------------------------------------------------===// -package org.swift.swiftkit; +package org.swift.swiftkitffm; import com.example.swift.MySwiftStruct; import org.junit.jupiter.api.Test; +import org.swift.swiftkit.ffm.AllocatingSwiftArena; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -23,7 +24,7 @@ public class MySwiftStructTest { @Test void create_struct() { - try (var arena = SwiftArena.ofConfined()) { + try (var arena = AllocatingSwiftArena.ofConfined()) { long cap = 12; long len = 34; var struct = MySwiftStruct.init(cap, len, arena); diff --git a/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/SwiftArenaTest.java b/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkitffm/SwiftArenaTest.java similarity index 84% rename from Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/SwiftArenaTest.java rename to Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkitffm/SwiftArenaTest.java index 52d791a1..08dd9b1b 100644 --- a/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/SwiftArenaTest.java +++ b/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkitffm/SwiftArenaTest.java @@ -12,21 +12,18 @@ // //===----------------------------------------------------------------------===// -package org.swift.swiftkit; +package org.swift.swiftkitffm; import com.example.swift.MySwiftClass; import com.example.swift.MySwiftStruct; -import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.DisabledIf; -import org.swift.swiftkit.util.PlatformUtils; - -import java.util.Arrays; -import java.util.stream.Collectors; +import org.swift.swiftkit.core.util.PlatformUtils; +import org.swift.swiftkit.ffm.AllocatingSwiftArena; +import org.swift.swiftkit.ffm.SwiftRuntime; import static org.junit.jupiter.api.Assertions.*; -import static org.swift.swiftkit.SwiftKit.*; -import static org.swift.swiftkit.SwiftKit.retainCount; +import static org.swift.swiftkit.ffm.SwiftRuntime.retainCount; public class SwiftArenaTest { @@ -39,13 +36,13 @@ static boolean isAmd64() { @Test @DisabledIf("isAmd64") public void arena_releaseClassOnClose_class_ok() { - try (var arena = SwiftArena.ofConfined()) { + try (var arena = AllocatingSwiftArena.ofConfined()) { var obj = MySwiftClass.init(1, 2, arena); - retain(obj); + SwiftRuntime.retain(obj); assertEquals(2, retainCount(obj)); - release(obj); + SwiftRuntime.release(obj); assertEquals(1, retainCount(obj)); } } @@ -56,7 +53,7 @@ public void arena_releaseClassOnClose_class_ok() { public void arena_markAsDestroyed_preventUseAfterFree_class() { MySwiftClass unsafelyEscapedOutsideArenaScope = null; - try (var arena = SwiftArena.ofConfined()) { + try (var arena = AllocatingSwiftArena.ofConfined()) { var obj = MySwiftClass.init(1, 2, arena); unsafelyEscapedOutsideArenaScope = obj; } @@ -75,7 +72,7 @@ public void arena_markAsDestroyed_preventUseAfterFree_class() { public void arena_markAsDestroyed_preventUseAfterFree_struct() { MySwiftStruct unsafelyEscapedOutsideArenaScope = null; - try (var arena = SwiftArena.ofConfined()) { + try (var arena = AllocatingSwiftArena.ofConfined()) { var s = MySwiftStruct.init(1, 2, arena); unsafelyEscapedOutsideArenaScope = s; } diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift index 364fd270..13230a32 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift @@ -116,8 +116,8 @@ extension FFMSwift2JavaGenerator { """ public static \(returnTy) call(\(paramsStr)) { try { - if (SwiftKit.TRACE_DOWNCALLS) { - SwiftKit.traceDowncall(\(argsStr)); + if (SwiftRuntime.TRACE_DOWNCALLS) { + SwiftRuntime.traceDowncall(\(argsStr)); } \(maybeReturn)HANDLE.invokeExact(\(argsStr)); } catch (Throwable ex$) { @@ -156,7 +156,7 @@ extension FFMSwift2JavaGenerator { /// apply(); /// } /// static final MethodDescriptor DESC = FunctionDescriptor.of(...); - /// static final MethodHandle HANDLE = SwiftKit.upcallHandle(Function.class, "apply", DESC); + /// static final MethodHandle HANDLE = SwiftRuntime.upcallHandle(Function.class, "apply", DESC); /// static MemorySegment toUpcallStub(Function fi, Arena arena) { /// return Linker.nativeLinker().upcallStub(HANDLE.bindTo(fi), DESC, arena); /// } @@ -197,7 +197,7 @@ extension FFMSwift2JavaGenerator { printFunctionDescriptorDefinition(&printer, cResultType, cParams) printer.print( """ - private static final MethodHandle HANDLE = SwiftKit.upcallHandle(Function.class, "apply", DESC); + private static final MethodHandle HANDLE = SwiftRuntime.upcallHandle(Function.class, "apply", DESC); private static MemorySegment toUpcallStub(Function fi, Arena arena) { return Linker.nativeLinker().upcallStub(HANDLE.bindTo(fi), DESC, arena); } @@ -320,7 +320,7 @@ extension FFMSwift2JavaGenerator { .flatMap(\.javaParameters) .map { "\($0.type) \($0.name)" } if translatedSignature.requiresSwiftArena { - paramDecls.append("SwiftArena swiftArena$") + paramDecls.append("AllocatingSwiftArena swiftArena$") } // TODO: we could copy the Swift method's documentation over here, that'd be great UX diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift index 16efddea..d29f6b96 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift @@ -313,7 +313,7 @@ extension FFMSwift2JavaGenerator { return TranslatedParameter( javaParameters: [ JavaParameter( - name: parameterName, type: JavaType.class(package: "org.swift.swiftkit", name: "SwiftAnyType")) + name: parameterName, type: JavaType.class(package: "org.swift.swiftkit.ffm", name: "SwiftAnyType")) ], conversion: .swiftValueSelfSegment(.placeholder) ) @@ -350,7 +350,7 @@ extension FFMSwift2JavaGenerator { name: parameterName, type: .javaLangString ) ], - conversion: .call(.placeholder, function: "SwiftKit.toCString", withArena: true) + conversion: .call(.placeholder, function: "SwiftRuntime.toCString", withArena: true) ) default: @@ -411,7 +411,7 @@ extension FFMSwift2JavaGenerator { switch swiftType { case .metatype(_): // Metatype are expressed as 'org.swift.swiftkit.SwiftAnyType' - let javaType = JavaType.class(package: "org.swift.swiftkit", name: "SwiftAnyType") + let javaType = JavaType.class(package: "org.swift.swiftkit.ffm", name: "SwiftAnyType") return TranslatedResult( javaResultType: javaType, outParameters: [], diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift index 09fcf858..9a140b94 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift @@ -92,9 +92,10 @@ extension FFMSwift2JavaGenerator { /// Default set Java imports for every generated file static let defaultJavaImports: Array = [ - "org.swift.swiftkit.*", - "org.swift.swiftkit.SwiftKit", - "org.swift.swiftkit.util.*", + "org.swift.swiftkit.core.*", + "org.swift.swiftkit.core.util.*", + "org.swift.swiftkit.ffm.*", + "org.swift.swiftkit.ffm.SwiftRuntime", // Necessary for native calls and type mapping "java.lang.foreign.*", @@ -188,7 +189,7 @@ extension FFMSwift2JavaGenerator { @SuppressWarnings("unused") private static final boolean INITIALIZED_LIBS = initializeLibs(); static boolean initializeLibs() { - System.loadLibrary(SwiftKit.STDLIB_DYLIB_NAME); + System.loadLibrary(SwiftLibraries.STDLIB_DYLIB_NAME); System.loadLibrary("SwiftKitSwift"); System.loadLibrary(LIB_NAME); return true; @@ -210,7 +211,7 @@ extension FFMSwift2JavaGenerator { printer.print( """ - public \(decl.swiftNominal.name)(MemorySegment segment, SwiftArena arena) { + public \(decl.swiftNominal.name)(MemorySegment segment, AllocatingSwiftArena arena) { super(segment, arena); } """ @@ -272,7 +273,7 @@ extension FFMSwift2JavaGenerator { parentProtocol = "SwiftValue" } - printer.printBraceBlock("public final class \(decl.swiftNominal.name) extends SwiftInstance implements \(parentProtocol)") { + printer.printBraceBlock("public final class \(decl.swiftNominal.name) extends FFMSwiftInstance implements \(parentProtocol)") { printer in // Constants printClassConstants(printer: &printer) @@ -322,9 +323,9 @@ extension FFMSwift2JavaGenerator { static final SymbolLookup SYMBOL_LOOKUP = getSymbolLookup(); private static SymbolLookup getSymbolLookup() { // Ensure Swift and our Lib are loaded during static initialization of the class. - SwiftKit.loadLibrary("swiftCore"); - SwiftKit.loadLibrary("SwiftKitSwift"); - SwiftKit.loadLibrary(LIB_NAME); + SwiftLibraries.loadLibrary("swiftCore"); + SwiftLibraries.loadLibrary("SwiftKitSwift"); + SwiftLibraries.loadLibrary(LIB_NAME); if (PlatformUtils.isMacOS()) { return SymbolLookup.libraryLookup(System.mapLibraryName(LIB_NAME), LIBRARY_ARENA) @@ -386,7 +387,7 @@ extension FFMSwift2JavaGenerator { public String toString() { return getClass().getSimpleName() + "(" - + SwiftKit.nameOfSwiftType($swiftType().$memorySegment(), true) + + SwiftRuntime.nameOfSwiftType($swiftType().$memorySegment(), true) + ")@" + $memorySegment(); } diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift index c61dd929..b4d73873 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift @@ -130,7 +130,7 @@ extension JNISwift2JavaGenerator { _ decl: ImportedFunc ) { let translatedDecl = self.translatedDecl(for: decl) - let parentName = translatedDecl.parentName ?? swiftModuleName + let parentName = translatedDecl.parentName let swiftReturnType = decl.functionSignature.result.type printCDecl(&printer, decl) { printer in diff --git a/Sources/JExtractSwiftLib/SwiftKit+Printing.swift b/Sources/JExtractSwiftLib/SwiftKit+Printing.swift index aa01502d..0afc9645 100644 --- a/Sources/JExtractSwiftLib/SwiftKit+Printing.swift +++ b/Sources/JExtractSwiftLib/SwiftKit+Printing.swift @@ -23,7 +23,7 @@ package struct SwiftKitPrinting { /// Forms syntax for a Java call to a swiftkit exposed function. static func renderCallGetSwiftType(module: String, nominal: ImportedNominalType) -> String { """ - SwiftKit.swiftjava.getType("\(module)", "\(nominal.swiftNominal.qualifiedName)") + SwiftRuntime.swiftjava.getType("\(module)", "\(nominal.swiftNominal.qualifiedName)") """ } } diff --git a/SwiftKit/build.gradle b/SwiftKitCore/build.gradle similarity index 87% rename from SwiftKit/build.gradle rename to SwiftKitCore/build.gradle index 8f3b6c51..3d5907f2 100644 --- a/SwiftKit/build.gradle +++ b/SwiftKitCore/build.gradle @@ -25,13 +25,15 @@ repositories { java { toolchain { - languageVersion.set(JavaLanguageVersion.of(24)) + // JDK 19 is the last JDK to support Java 7 + languageVersion.set(JavaLanguageVersion.of(19)) } + // Support Android 6+ (Java 7) + sourceCompatibility = JavaVersion.VERSION_1_7 } dependencies { - testImplementation(platform("org.junit:junit-bom:5.10.0")) - testImplementation("org.junit.jupiter:junit-jupiter") + testImplementation 'junit:junit:4.13.2' } tasks.test { diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/ClosableSwiftArena.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/ClosableSwiftArena.java similarity index 96% rename from SwiftKit/src/main/java/org/swift/swiftkit/ClosableSwiftArena.java rename to SwiftKitCore/src/main/java/org/swift/swiftkit/core/ClosableSwiftArena.java index c257ae57..1a089069 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/ClosableSwiftArena.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/ClosableSwiftArena.java @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -package org.swift.swiftkit; +package org.swift.swiftkit.core; /** * Auto-closable version of {@link SwiftArena}. @@ -24,5 +24,4 @@ public interface ClosableSwiftArena extends SwiftArena, AutoCloseable { * Throws if unable to verify all resources have been release (e.g. over retained Swift classes) */ void close(); - } diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/ConfinedSwiftMemorySession.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/ConfinedSwiftMemorySession.java similarity index 68% rename from SwiftKit/src/main/java/org/swift/swiftkit/ConfinedSwiftMemorySession.java rename to SwiftKitCore/src/main/java/org/swift/swiftkit/core/ConfinedSwiftMemorySession.java index 86725ae8..cd8f2dd1 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/ConfinedSwiftMemorySession.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/ConfinedSwiftMemorySession.java @@ -12,15 +12,13 @@ // //===----------------------------------------------------------------------===// -package org.swift.swiftkit; +package org.swift.swiftkit.core; -import java.lang.foreign.Arena; -import java.lang.foreign.MemorySegment; import java.util.LinkedList; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; -final class ConfinedSwiftMemorySession implements ClosableSwiftArena { +public class ConfinedSwiftMemorySession implements ClosableSwiftArena { final static int CLOSED = 0; final static int ACTIVE = 1; @@ -28,21 +26,17 @@ final class ConfinedSwiftMemorySession implements ClosableSwiftArena { final Thread owner; final AtomicInteger state; - final Arena arena; final ConfinedResourceList resources; public ConfinedSwiftMemorySession(Thread owner) { this.owner = owner; this.state = new AtomicInteger(ACTIVE); this.resources = new ConfinedResourceList(); - - this.arena = Arena.ofConfined(); } public void checkValid() throws RuntimeException { if (this.owner != null && this.owner != Thread.currentThread()) { - throw new WrongThreadException("ConfinedSwift arena is confined to %s but was closed from %s!" - .formatted(this.owner, Thread.currentThread())); + throw new WrongThreadException(String.format("ConfinedSwift arena is confined to %s but was closed from %s!", this.owner, Thread.currentThread())); } else if (this.state.get() < ACTIVE) { throw new RuntimeException("SwiftArena is already closed!"); } @@ -53,32 +47,19 @@ public void close() { checkValid(); // Cleanup all resources - if (this.state.compareAndExchange(ACTIVE, CLOSED) == ACTIVE) { + if (this.state.compareAndSet(ACTIVE, CLOSED)) { this.resources.runCleanup(); } // else, was already closed; do nothing - - this.arena.close(); } @Override public void register(SwiftInstance instance) { checkValid(); - var statusDestroyedFlag = instance.$statusDestroyedFlag(); - Runnable markAsDestroyed = () -> statusDestroyedFlag.set(true); - - var cleanup = new SwiftInstanceCleanup( - instance.$memorySegment(), - instance.$swiftType(), - markAsDestroyed); + SwiftInstanceCleanup cleanup = instance.createCleanupAction(); this.resources.add(cleanup); } - @Override - public MemorySegment allocate(long byteSize, long byteAlignment) { - return arena.allocate(byteSize, byteAlignment); - } - static final class ConfinedResourceList implements SwiftResourceList { // TODO: Could use intrusive linked list to avoid one indirection here final List resourceCleanups = new LinkedList<>(); diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/JNISwiftInstance.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/JNISwiftInstance.java new file mode 100644 index 00000000..891745a2 --- /dev/null +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/JNISwiftInstance.java @@ -0,0 +1,56 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package org.swift.swiftkit.core; + +import java.util.concurrent.atomic.AtomicBoolean; + +public abstract class JNISwiftInstance extends SwiftInstance { + /** + * The designated constructor of any imported Swift types. + * + * @param pointer a pointer to the memory containing the value + * @param arena the arena this object belongs to. When the arena goes out of scope, this value is destroyed. + */ + protected JNISwiftInstance(long pointer, SwiftArena arena) { + super(pointer, arena); + } + + /** + * Creates a function that will be called when the value should be destroyed. + * This will be code-generated to call a native method to do deinitialization and deallocation. + *

+ * The reason for this "indirection" is that we cannot have static methods on abstract classes, + * and we can't define the destroy method as a member method, because we assume that the wrapper + * has been released, when we destroy. + *

+ * Warning: The function must not capture {@code this}. + * + * @return a function that is called when the value should be destroyed. + */ + abstract Runnable $createDestroyFunction(); + + @Override + public SwiftInstanceCleanup createCleanupAction() { + final AtomicBoolean statusDestroyedFlag = $statusDestroyedFlag(); + Runnable markAsDestroyed = new Runnable() { + @Override + public void run() { + statusDestroyedFlag.set(true); + } + }; + + return new JNISwiftInstanceCleanup(this.$createDestroyFunction(), markAsDestroyed); + } +} diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/JNISwiftInstanceCleanup.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/JNISwiftInstanceCleanup.java new file mode 100644 index 00000000..08ddcdab --- /dev/null +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/JNISwiftInstanceCleanup.java @@ -0,0 +1,31 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package org.swift.swiftkit.core; + +class JNISwiftInstanceCleanup implements SwiftInstanceCleanup { + private final Runnable destroyFunction; + private final Runnable markAsDestroyed; + + public JNISwiftInstanceCleanup(Runnable destroyFunction, Runnable markAsDestroyed) { + this.destroyFunction = destroyFunction; + this.markAsDestroyed = markAsDestroyed; + } + + @Override + public void run() { + markAsDestroyed.run(); + destroyFunction.run(); + } +} diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftArena.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftArena.java similarity index 54% rename from SwiftKit/src/main/java/org/swift/swiftkit/SwiftArena.java rename to SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftArena.java index f50025cc..ed16d250 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftArena.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftArena.java @@ -12,10 +12,7 @@ // //===----------------------------------------------------------------------===// -package org.swift.swiftkit; - -import java.lang.foreign.SegmentAllocator; -import java.util.concurrent.ThreadFactory; +package org.swift.swiftkit.core; /** * A Swift arena manages Swift allocated memory for classes, structs, enums etc. @@ -24,39 +21,17 @@ *

A confined arena has an associated owner thread that confines some operations to * associated owner thread such as {@link ClosableSwiftArena#close()}. */ -public interface SwiftArena extends SegmentAllocator { - - static ClosableSwiftArena ofConfined() { - return new ConfinedSwiftMemorySession(Thread.currentThread()); - } - - static SwiftArena ofAuto() { - ThreadFactory cleanerThreadFactory = r -> new Thread(r, "AutoSwiftArenaCleanerThread"); - return new AutoSwiftMemorySession(cleanerThreadFactory); - } - +public interface SwiftArena { /** * Register a Swift object. * Its memory should be considered managed by this arena, and be destroyed when the arena is closed. */ void register(SwiftInstance instance); - } /** * Represents a list of resources that need a cleanup, e.g. allocated classes/structs. */ interface SwiftResourceList { - void runCleanup(); - -} - - -final class UnexpectedRetainCountException extends RuntimeException { - public UnexpectedRetainCountException(Object resource, long retainCount, int expectedRetainCount) { - super(("Attempting to cleanup managed memory segment %s, but it's retain count was different than [%d] (was %d)! " + - "This would result in destroying a swift object that is still retained by other code somewhere." - ).formatted(resource, expectedRetainCount, retainCount)); - } } diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftInstance.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftInstance.java similarity index 70% rename from SwiftKit/src/main/java/org/swift/swiftkit/SwiftInstance.java rename to SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftInstance.java index 5b8ff700..638cb8be 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftInstance.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftInstance.java @@ -12,24 +12,28 @@ // //===----------------------------------------------------------------------===// -package org.swift.swiftkit; +package org.swift.swiftkit.core; -import java.lang.foreign.GroupLayout; -import java.lang.foreign.MemorySegment; import java.util.concurrent.atomic.AtomicBoolean; -import java.util.function.Supplier; public abstract class SwiftInstance { /// Pointer to the "self". - private final MemorySegment selfMemorySegment; + private final long selfPointer; /** * The pointer to the instance in memory. I.e. the {@code self} of the Swift object or value. */ - public final MemorySegment $memorySegment() { - return this.selfMemorySegment; + public final long pointer() { + return this.selfPointer; } + /** + * Called when the arena has decided the value should be destroyed. + *

+ * Warning: The cleanup action must not capture {@code this}. + */ + public abstract SwiftInstanceCleanup createCleanupAction(); + // TODO: make this a flagset integer and/or use a field updater /** Used to track additional state of the underlying object, e.g. if it was explicitly destroyed. */ private final AtomicBoolean $state$destroyed = new AtomicBoolean(false); @@ -45,24 +49,14 @@ public abstract class SwiftInstance { return this.$state$destroyed; } - /** - * The in memory layout of an instance of this Swift type. - */ - public abstract GroupLayout $layout(); - - /** - * The Swift type metadata of this type. - */ - public abstract SwiftAnyType $swiftType(); - /** * The designated constructor of any imported Swift types. * - * @param segment the memory segment. + * @param pointer a pointer to the memory containing the value * @param arena the arena this object belongs to. When the arena goes out of scope, this value is destroyed. */ - protected SwiftInstance(MemorySegment segment, SwiftArena arena) { - this.selfMemorySegment = segment; + protected SwiftInstance(long pointer, SwiftArena arena) { + this.selfPointer = pointer; arena.register(this); } @@ -78,13 +72,4 @@ protected SwiftInstance(MemorySegment segment, SwiftArena arena) { throw new IllegalStateException("Attempted to call method on already destroyed instance of " + getClass().getSimpleName() + "!"); } } - - /** - * Returns `true` if this swift instance is a reference type, i.e. a `class` or (`distributed`) `actor`. - * - * @return `true` if this instance is a reference type, `false` otherwise. - */ - public boolean isReferenceType() { - return this instanceof SwiftHeapObject; - } } diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftInstanceCleanup.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftInstanceCleanup.java new file mode 100644 index 00000000..56416968 --- /dev/null +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftInstanceCleanup.java @@ -0,0 +1,20 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package org.swift.swiftkit.core; + +/** + * A Swift memory instance cleanup, e.g. count-down a reference count and destroy a class, or destroy struct/enum etc. + */ +public interface SwiftInstanceCleanup extends Runnable {} \ No newline at end of file diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftLibraries.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftLibraries.java new file mode 100644 index 00000000..2abdaff5 --- /dev/null +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftLibraries.java @@ -0,0 +1,83 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package org.swift.swiftkit.core; + +import org.swift.swiftkit.core.util.PlatformUtils; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; + +public final class SwiftLibraries { + + public static final String STDLIB_DYLIB_NAME = "swiftCore"; + public static final String SWIFTKITSWIFT_DYLIB_NAME = "SwiftKitSwift"; + public static final boolean TRACE_DOWNCALLS = Boolean.getBoolean("jextract.trace.downcalls"); + + private static final String STDLIB_MACOS_DYLIB_PATH = "/usr/lib/swift/libswiftCore.dylib"; + + @SuppressWarnings("unused") + private static final boolean INITIALIZED_LIBS = loadLibraries(false); + + public static boolean loadLibraries(boolean loadSwiftKit) { + System.loadLibrary(STDLIB_DYLIB_NAME); + if (loadSwiftKit) { + System.loadLibrary(SWIFTKITSWIFT_DYLIB_NAME); + } + return true; + } + + // ==== ------------------------------------------------------------------------------------------------------------ + // Loading libraries + + public static void loadLibrary(String libname) { + // TODO: avoid concurrent loadResource calls; one load is enough esp since we cause File IO when we do that + try { + // try to load a dylib from our classpath, e.g. when we included it in our jar + loadResourceLibrary(libname); + } catch (UnsatisfiedLinkError | RuntimeException e) { + // fallback to plain system path loading + System.loadLibrary(libname); + } + } + + public static void loadResourceLibrary(String libname) { + String resourceName = PlatformUtils.dynamicLibraryName(libname); + if (SwiftLibraries.TRACE_DOWNCALLS) { + System.out.println("[swift-java] Loading resource library: " + resourceName); + } + + try (InputStream libInputStream = SwiftLibraries.class.getResourceAsStream("/" + resourceName)) { + if (libInputStream == null) { + throw new RuntimeException("Expected library '" + libname + "' ('" + resourceName + "') was not found as resource!"); + } + + // TODO: we could do an in memory file system here + File tempFile = File.createTempFile(libname, ""); + tempFile.deleteOnExit(); + Files.copy(libInputStream, tempFile.toPath(), StandardCopyOption.REPLACE_EXISTING); + + System.load(tempFile.getAbsolutePath()); + } catch (IOException e) { + throw new RuntimeException("Failed to load dynamic library '" + libname + "' ('" + resourceName + "') as resource!", e); + } + } + + public static String getJavaLibraryPath() { + return System.getProperty("java.library.path"); + } +} diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValue.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftValue.java similarity index 94% rename from SwiftKit/src/main/java/org/swift/swiftkit/SwiftValue.java rename to SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftValue.java index a364c012..3e9c1aff 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValue.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftValue.java @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -package org.swift.swiftkit; +package org.swift.swiftkit.core; /** * Represent a wrapper around a Swift value object. e.g. {@code struct} or {@code enum}. diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/ManagedSwiftType.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/WrongThreadException.java similarity index 67% rename from SwiftKit/src/main/java/org/swift/swiftkit/ManagedSwiftType.java rename to SwiftKitCore/src/main/java/org/swift/swiftkit/core/WrongThreadException.java index da25ae4d..d15436f9 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/ManagedSwiftType.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/WrongThreadException.java @@ -12,14 +12,10 @@ // //===----------------------------------------------------------------------===// -package org.swift.swiftkit; - -import java.lang.foreign.MemorySegment; - -public interface ManagedSwiftType { - /** - * The memory segment of `self` of the managed Swift object/value. - */ - public MemorySegment $memorySegment(); +package org.swift.swiftkit.core; +public class WrongThreadException extends RuntimeException { + public WrongThreadException(String message) { + super(message); + } } diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/util/PlatformUtils.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/util/PlatformUtils.java similarity index 97% rename from SwiftKit/src/main/java/org/swift/swiftkit/util/PlatformUtils.java rename to SwiftKitCore/src/main/java/org/swift/swiftkit/core/util/PlatformUtils.java index 6addb31d..667bd53b 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/util/PlatformUtils.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/util/PlatformUtils.java @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -package org.swift.swiftkit.util; +package org.swift.swiftkit.core.util; public class PlatformUtils { public static boolean isLinux() { diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/util/StringUtils.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/util/StringUtils.java similarity index 96% rename from SwiftKit/src/main/java/org/swift/swiftkit/util/StringUtils.java rename to SwiftKitCore/src/main/java/org/swift/swiftkit/core/util/StringUtils.java index 6753ea73..1ce4259c 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/util/StringUtils.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/util/StringUtils.java @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -package org.swift.swiftkit.util; +package org.swift.swiftkit.core.util; public class StringUtils { public static String stripPrefix(String mangledName, String prefix) { diff --git a/SwiftKitFFM/build.gradle b/SwiftKitFFM/build.gradle new file mode 100644 index 00000000..22f88001 --- /dev/null +++ b/SwiftKitFFM/build.gradle @@ -0,0 +1,87 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +plugins { + id("build-logic.java-application-conventions") +} + +group = "org.swift.swiftkit" +version = "1.0-SNAPSHOT" + +repositories { + mavenCentral() +} + +java { + toolchain { + languageVersion.set(JavaLanguageVersion.of(24)) + } +} + +dependencies { + implementation(project(':SwiftKitCore')) + + testImplementation(platform("org.junit:junit-bom:5.10.0")) + testImplementation("org.junit.jupiter:junit-jupiter") +} + +testing { + suites { + test { + useJUnitJupiter('5.10.3') + } + } +} + +tasks.test { + useJUnitPlatform() + testLogging { + events("passed", "skipped", "failed") + } +} + +/// Enable access to preview APIs, e.g. java.lang.foreign.* (Panama) +tasks.withType(JavaCompile).configureEach { + options.compilerArgs.add("--enable-preview") + options.compilerArgs.add("-Xlint:preview") +} + +// SwiftKit depends on SwiftKitSwift (Swift library that this Java library calls into) + +def compileSwift = tasks.register("compileSwift", Exec) { + description "Compile the swift-java SwiftKitSwift dynamic library that SwiftKit (Java) calls into" + + inputs.file(new File(rootDir, "Package.swift")) + inputs.dir(new File(rootDir, "Sources/")) // a bit generous, but better safe than sorry, and include all Swift source changes + outputs.dir(new File(rootDir, ".build")) + + workingDir = rootDir + commandLine "swift" + args("build", "--target", "SwiftKitSwift") +} +tasks.build { + dependsOn("compileSwift") +} + + + +def cleanSwift = tasks.register("cleanSwift", Exec) { + workingDir = rootDir + commandLine "swift" + args("package", "clean") +} +tasks.clean { + dependsOn("cleanSwift") +} + diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/AutoSwiftMemorySession.java b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/AllocatingAutoSwiftMemorySession.java similarity index 78% rename from SwiftKit/src/main/java/org/swift/swiftkit/AutoSwiftMemorySession.java rename to SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/AllocatingAutoSwiftMemorySession.java index ecbe836e..fecd5202 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/AutoSwiftMemorySession.java +++ b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/AllocatingAutoSwiftMemorySession.java @@ -12,7 +12,10 @@ // //===----------------------------------------------------------------------===// -package org.swift.swiftkit; +package org.swift.swiftkit.ffm; + +import org.swift.swiftkit.core.SwiftArena; +import org.swift.swiftkit.core.SwiftInstance; import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; @@ -26,7 +29,7 @@ *

When registered Java wrapper classes around native Swift instances {@link SwiftInstance}, * are eligible for collection, this will trigger the cleanup of the native resources as well. * - *

This memory session is LESS reliable than using a {@link ConfinedSwiftMemorySession} because + *

This memory session is LESS reliable than using a {@link FFMConfinedSwiftMemorySession} because * the timing of when the native resources are cleaned up is somewhat undefined, and rely on the * system GC. Meaning, that if an object nas been promoted to an old generation, there may be a * long time between the resource no longer being referenced "in Java" and its native memory being released, @@ -37,12 +40,12 @@ * *

Whenever possible, prefer using an explicitly managed {@link SwiftArena}, such as {@link SwiftArena#ofConfined()}. */ -final class AutoSwiftMemorySession implements SwiftArena { +final class AllocatingAutoSwiftMemorySession implements AllocatingSwiftArena { private final Arena arena; private final Cleaner cleaner; - public AutoSwiftMemorySession(ThreadFactory cleanerThreadFactory) { + public AllocatingAutoSwiftMemorySession(ThreadFactory cleanerThreadFactory) { this.cleaner = Cleaner.create(cleanerThreadFactory); this.arena = Arena.ofAuto(); } @@ -51,12 +54,9 @@ public AutoSwiftMemorySession(ThreadFactory cleanerThreadFactory) { public void register(SwiftInstance instance) { Objects.requireNonNull(instance, "value"); - // We're doing this dance to avoid keeping a strong reference to the value itself - var statusDestroyedFlag = instance.$statusDestroyedFlag(); - Runnable markAsDestroyed = () -> statusDestroyedFlag.set(true); - - MemorySegment resource = instance.$memorySegment(); - var cleanupAction = new SwiftInstanceCleanup(resource, instance.$swiftType(), markAsDestroyed); + // We make sure we don't capture `instance` in the + // cleanup action, so we can ignore the warning below. + var cleanupAction = instance.createCleanupAction(); cleaner.register(instance, cleanupAction); } @@ -64,4 +64,4 @@ public void register(SwiftInstance instance) { public MemorySegment allocate(long byteSize, long byteAlignment) { return arena.allocate(byteSize, byteAlignment); } -} +} \ No newline at end of file diff --git a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/AllocatingSwiftArena.java b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/AllocatingSwiftArena.java new file mode 100644 index 00000000..08fad15b --- /dev/null +++ b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/AllocatingSwiftArena.java @@ -0,0 +1,34 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package org.swift.swiftkit.ffm; + +import org.swift.swiftkit.core.SwiftArena; + +import java.lang.foreign.MemorySegment; +import java.lang.foreign.SegmentAllocator; +import java.util.concurrent.ThreadFactory; + +public interface AllocatingSwiftArena extends SwiftArena, SegmentAllocator { + MemorySegment allocate(long byteSize, long byteAlignment); + + static ClosableAllocatingSwiftArena ofConfined() { + return new FFMConfinedSwiftMemorySession(Thread.currentThread()); + } + + static AllocatingSwiftArena ofAuto() { + ThreadFactory cleanerThreadFactory = r -> new Thread(r, "AutoSwiftArenaCleanerThread"); + return new AllocatingAutoSwiftMemorySession(cleanerThreadFactory); + } +} diff --git a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/ClosableAllocatingSwiftArena.java b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/ClosableAllocatingSwiftArena.java new file mode 100644 index 00000000..70cdcbb6 --- /dev/null +++ b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/ClosableAllocatingSwiftArena.java @@ -0,0 +1,22 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package org.swift.swiftkit.ffm; + +import org.swift.swiftkit.core.ClosableSwiftArena; + +/** + * Auto-closable version of {@link AllocatingSwiftArena}. + */ +public interface ClosableAllocatingSwiftArena extends ClosableSwiftArena, AllocatingSwiftArena {} diff --git a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMConfinedSwiftMemorySession.java b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMConfinedSwiftMemorySession.java new file mode 100644 index 00000000..424e54b6 --- /dev/null +++ b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMConfinedSwiftMemorySession.java @@ -0,0 +1,40 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package org.swift.swiftkit.ffm; + +import org.swift.swiftkit.core.ConfinedSwiftMemorySession; + +import java.lang.foreign.Arena; +import java.lang.foreign.MemorySegment; + +final class FFMConfinedSwiftMemorySession extends ConfinedSwiftMemorySession implements AllocatingSwiftArena, ClosableAllocatingSwiftArena { + final Arena arena; + + public FFMConfinedSwiftMemorySession(Thread owner) { + super(owner); + this.arena = Arena.ofConfined(); + } + + @Override + public void close() { + super.close(); + this.arena.close(); + } + + @Override + public MemorySegment allocate(long byteSize, long byteAlignment) { + return arena.allocate(byteSize, byteAlignment); + } +} diff --git a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMSwiftInstance.java b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMSwiftInstance.java new file mode 100644 index 00000000..f4a01aa4 --- /dev/null +++ b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMSwiftInstance.java @@ -0,0 +1,69 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package org.swift.swiftkit.ffm; + +import org.swift.swiftkit.core.SwiftInstance; +import org.swift.swiftkit.core.SwiftInstanceCleanup; + +import java.lang.foreign.MemorySegment; + +public abstract class FFMSwiftInstance extends SwiftInstance { + private final MemorySegment memorySegment; + + /** + * The pointer to the instance in memory. I.e. the {@code self} of the Swift object or value. + */ + public final MemorySegment $memorySegment() { + return this.memorySegment; + } + + /** + * The Swift type metadata of this type. + */ + public abstract SwiftAnyType $swiftType(); + + /** + * The designated constructor of any imported Swift types. + * + * @param segment the memory segment. + * @param arena the arena this object belongs to. When the arena goes out of scope, this value is destroyed. + */ + protected FFMSwiftInstance(MemorySegment segment, AllocatingSwiftArena arena) { + super(segment.address(), arena); + this.memorySegment = segment; + } + + @Override + public SwiftInstanceCleanup createCleanupAction() { + var statusDestroyedFlag = $statusDestroyedFlag(); + Runnable markAsDestroyed = () -> statusDestroyedFlag.set(true); + + return new FFMSwiftInstanceCleanup( + $memorySegment(), + $swiftType(), + markAsDestroyed + ); + } + + + /** + * Returns `true` if this swift instance is a reference type, i.e. a `class` or (`distributed`) `actor`. + * + * @return `true` if this instance is a reference type, `false` otherwise. + */ + public boolean isReferenceType() { + return this instanceof SwiftHeapObject; + } +} diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftInstanceCleanup.java b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMSwiftInstanceCleanup.java similarity index 63% rename from SwiftKit/src/main/java/org/swift/swiftkit/SwiftInstanceCleanup.java rename to SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMSwiftInstanceCleanup.java index a9fdd9c8..a5d0829a 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftInstanceCleanup.java +++ b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMSwiftInstanceCleanup.java @@ -12,18 +12,22 @@ // //===----------------------------------------------------------------------===// -package org.swift.swiftkit; +package org.swift.swiftkit.ffm; + +import org.swift.swiftkit.core.SwiftInstanceCleanup; import java.lang.foreign.MemorySegment; -/** - * A Swift memory instance cleanup, e.g. count-down a reference count and destroy a class, or destroy struct/enum etc. - */ -record SwiftInstanceCleanup( - MemorySegment selfPointer, - SwiftAnyType selfType, - Runnable markAsDestroyed -) implements Runnable { +public class FFMSwiftInstanceCleanup implements SwiftInstanceCleanup { + private final MemorySegment selfPointer; + private final SwiftAnyType selfType; + private final Runnable markAsDestroyed; + + public FFMSwiftInstanceCleanup(MemorySegment selfPointer, SwiftAnyType selfType, Runnable markAsDestroyed) { + this.selfPointer = selfPointer; + this.selfType = selfType; + this.markAsDestroyed = markAsDestroyed; + } @Override public void run() { diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/MemorySegmentUtils.java b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/MemorySegmentUtils.java similarity index 97% rename from SwiftKit/src/main/java/org/swift/swiftkit/MemorySegmentUtils.java rename to SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/MemorySegmentUtils.java index 660a5500..0890b1d8 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/MemorySegmentUtils.java +++ b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/MemorySegmentUtils.java @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -package org.swift.swiftkit; +package org.swift.swiftkit.ffm; import java.lang.foreign.MemorySegment; import java.lang.foreign.ValueLayout; diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftAnyType.java b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/SwiftAnyType.java similarity index 89% rename from SwiftKit/src/main/java/org/swift/swiftkit/SwiftAnyType.java rename to SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/SwiftAnyType.java index 4d13ecb7..3915725b 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftAnyType.java +++ b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/SwiftAnyType.java @@ -12,7 +12,10 @@ // //===----------------------------------------------------------------------===// -package org.swift.swiftkit; +package org.swift.swiftkit.ffm; + +import org.swift.swiftkit.ffm.SwiftRuntime; +import org.swift.swiftkit.ffm.SwiftValueLayout; import java.lang.foreign.GroupLayout; import java.lang.foreign.MemoryLayout; @@ -46,7 +49,7 @@ public SwiftAnyType(MemorySegment memorySegment) { * Get the human-readable Swift type name of this type. */ public String getSwiftName() { - return SwiftKit.nameOfSwiftType(memorySegment, true); + return SwiftRuntime.nameOfSwiftType(memorySegment, true); } @Override diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftHeapObject.java b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/SwiftHeapObject.java similarity index 91% rename from SwiftKit/src/main/java/org/swift/swiftkit/SwiftHeapObject.java rename to SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/SwiftHeapObject.java index 89050fb5..b506be90 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftHeapObject.java +++ b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/SwiftHeapObject.java @@ -12,7 +12,8 @@ // //===----------------------------------------------------------------------===// -package org.swift.swiftkit; +package org.swift.swiftkit.ffm; + import java.lang.foreign.MemorySegment; @@ -25,7 +26,7 @@ public interface SwiftHeapObject { /** * Pointer to the instance. */ - public default MemorySegment $instance() { + default MemorySegment $instance() { return this.$memorySegment().get(SwiftValueLayout.SWIFT_POINTER, 0); } } diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftKit.java b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/SwiftRuntime.java similarity index 88% rename from SwiftKit/src/main/java/org/swift/swiftkit/SwiftKit.java rename to SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/SwiftRuntime.java index 9c04eded..f734bbef 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftKit.java +++ b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/SwiftRuntime.java @@ -12,28 +12,22 @@ // //===----------------------------------------------------------------------===// -package org.swift.swiftkit; +package org.swift.swiftkit.ffm; -import org.swift.swiftkit.util.PlatformUtils; +import org.swift.swiftkit.core.util.PlatformUtils; -import java.io.File; -import java.io.IOException; import java.lang.foreign.*; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.VarHandle; -import java.nio.file.CopyOption; -import java.nio.file.FileSystems; -import java.nio.file.Files; -import java.nio.file.StandardCopyOption; import java.util.Arrays; import java.util.Optional; import java.util.stream.Collectors; -import static org.swift.swiftkit.util.StringUtils.stripPrefix; -import static org.swift.swiftkit.util.StringUtils.stripSuffix; +import static org.swift.swiftkit.core.util.StringUtils.stripPrefix; +import static org.swift.swiftkit.core.util.StringUtils.stripSuffix; -public class SwiftKit { +public class SwiftRuntime { public static final String STDLIB_DYLIB_NAME = "swiftCore"; public static final String SWIFTKITSWIFT_DYLIB_NAME = "SwiftKitSwift"; @@ -68,7 +62,7 @@ private static SymbolLookup getSymbolLookup() { } } - public SwiftKit() { + public SwiftRuntime() { } public static void traceDowncall(Object... args) { @@ -103,50 +97,10 @@ static MemorySegment findOrThrow(String symbol) { .orElseThrow(() -> new UnsatisfiedLinkError("unresolved symbol: %s".formatted(symbol))); } - public static String getJavaLibraryPath() { - return System.getProperty("java.library.path"); - } - public static boolean getJextractTraceDowncalls() { return Boolean.getBoolean("jextract.trace.downcalls"); } - // ==== ------------------------------------------------------------------------------------------------------------ - // Loading libraries - - public static void loadLibrary(String libname) { - // TODO: avoid concurrent loadResource calls; one load is enough esp since we cause File IO when we do that - try { - // try to load a dylib from our classpath, e.g. when we included it in our jar - loadResourceLibrary(libname); - } catch (UnsatisfiedLinkError | RuntimeException e) { - // fallback to plain system path loading - System.loadLibrary(libname); - } - } - - public static void loadResourceLibrary(String libname) { - var resourceName = PlatformUtils.dynamicLibraryName(libname); - if (SwiftKit.TRACE_DOWNCALLS) { - System.out.println("[swift-java] Loading resource library: " + resourceName); - } - - try (var libInputStream = SwiftKit.class.getResourceAsStream("/" + resourceName)) { - if (libInputStream == null) { - throw new RuntimeException("Expected library '" + libname + "' ('" + resourceName + "') was not found as resource!"); - } - - // TODO: we could do an in memory file system here - var tempFile = File.createTempFile(libname, ""); - tempFile.deleteOnExit(); - Files.copy(libInputStream, tempFile.toPath(), StandardCopyOption.REPLACE_EXISTING); - - System.load(tempFile.getAbsolutePath()); - } catch (IOException e) { - throw new RuntimeException("Failed to load dynamic library '" + libname + "' ('" + resourceName + "') as resource!", e); - } - } - // ==== ------------------------------------------------------------------------------------------------------------ // free diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValueLayout.java b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/SwiftValueLayout.java similarity index 98% rename from SwiftKit/src/main/java/org/swift/swiftkit/SwiftValueLayout.java rename to SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/SwiftValueLayout.java index 00215ef0..c0a75144 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValueLayout.java +++ b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/SwiftValueLayout.java @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -package org.swift.swiftkit; +package org.swift.swiftkit.ffm; import java.lang.foreign.AddressLayout; import java.lang.foreign.MemoryLayout; diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValueWitnessTable.java b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/SwiftValueWitnessTable.java similarity index 94% rename from SwiftKit/src/main/java/org/swift/swiftkit/SwiftValueWitnessTable.java rename to SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/SwiftValueWitnessTable.java index 8ddff1b6..a0a6a79f 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValueWitnessTable.java +++ b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/SwiftValueWitnessTable.java @@ -12,13 +12,12 @@ // //===----------------------------------------------------------------------===// -package org.swift.swiftkit; +package org.swift.swiftkit.ffm; import java.lang.foreign.*; import java.lang.invoke.*; import static java.lang.foreign.ValueLayout.JAVA_BYTE; -import static org.swift.swiftkit.SwiftKit.getSwiftInt; public abstract class SwiftValueWitnessTable { @@ -86,7 +85,7 @@ public static MemorySegment valueWitnessTable(MemorySegment typeMetadata) { * @param typeMetadata the memory segment must point to a Swift metadata */ public static long sizeOfSwiftType(MemorySegment typeMetadata) { - return getSwiftInt(valueWitnessTable(typeMetadata), SwiftValueWitnessTable.$size$offset); + return SwiftRuntime.getSwiftInt(valueWitnessTable(typeMetadata), SwiftValueWitnessTable.$size$offset); } @@ -112,7 +111,7 @@ public static long sizeOfSwiftType(MemorySegment typeMetadata) { * @param typeMetadata the memory segment must point to a Swift metadata */ public static long strideOfSwiftType(MemorySegment typeMetadata) { - return getSwiftInt(valueWitnessTable(typeMetadata), SwiftValueWitnessTable.$stride$offset); + return SwiftRuntime.getSwiftInt(valueWitnessTable(typeMetadata), SwiftValueWitnessTable.$stride$offset); } @@ -122,7 +121,7 @@ public static long strideOfSwiftType(MemorySegment typeMetadata) { * @param typeMetadata the memory segment must point to a Swift metadata */ public static long alignmentOfSwiftType(MemorySegment typeMetadata) { - long flags = getSwiftInt(valueWitnessTable(typeMetadata), SwiftValueWitnessTable.$flags$offset); + long flags = SwiftRuntime.getSwiftInt(valueWitnessTable(typeMetadata), SwiftValueWitnessTable.$flags$offset); return (flags & 0xFF) + 1; } @@ -156,7 +155,7 @@ public static MemoryLayout layoutOfSwiftType(MemorySegment typeMetadata) { return MemoryLayout.structLayout( layouts - ).withName(SwiftKit.nameOfSwiftType(typeMetadata, true)); + ).withName(SwiftRuntime.nameOfSwiftType(typeMetadata, true)); } @@ -198,7 +197,7 @@ static MemorySegment addr(SwiftAnyType ty) { final var vwt = SwiftValueWitnessTable.valueWitnessTable(ty.$memorySegment()); // Get the address of the destroy function stored at the offset of the witness table - long funcAddress = getSwiftInt(vwt, destroy.$offset); + long funcAddress = SwiftRuntime.getSwiftInt(vwt, destroy.$offset); return MemorySegment.ofAddress(funcAddress); } @@ -258,7 +257,7 @@ static MemorySegment addr(SwiftAnyType ty) { final var vwt = SwiftValueWitnessTable.valueWitnessTable(ty.$memorySegment()); // Get the address of the function stored at the offset of the witness table - long funcAddress = getSwiftInt(vwt, initializeWithCopy.$offset); + long funcAddress = SwiftRuntime.getSwiftInt(vwt, initializeWithCopy.$offset); return MemorySegment.ofAddress(funcAddress); } diff --git a/SwiftKit/src/test/java/org/swift/swiftkit/AutoArenaTest.java b/SwiftKitFFM/src/test/java/org/swift/swiftkit/ffm/AutoArenaTest.java similarity index 78% rename from SwiftKit/src/test/java/org/swift/swiftkit/AutoArenaTest.java rename to SwiftKitFFM/src/test/java/org/swift/swiftkit/ffm/AutoArenaTest.java index 23365de9..b95f6c45 100644 --- a/SwiftKit/src/test/java/org/swift/swiftkit/AutoArenaTest.java +++ b/SwiftKitFFM/src/test/java/org/swift/swiftkit/ffm/AutoArenaTest.java @@ -12,21 +12,19 @@ // //===----------------------------------------------------------------------===// -package org.swift.swiftkit; +package org.swift.swiftkit.ffm; import org.junit.jupiter.api.Test; import java.lang.foreign.GroupLayout; import java.lang.foreign.MemorySegment; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.atomic.AtomicBoolean; public class AutoArenaTest { @Test @SuppressWarnings("removal") // System.runFinalization() will be removed public void cleaner_releases_native_resource() { - SwiftArena arena = SwiftArena.ofAuto(); + AllocatingSwiftArena arena = AllocatingSwiftArena.ofAuto(); // This object is registered to the arena. var object = new FakeSwiftInstance(arena); @@ -48,16 +46,11 @@ public void cleaner_releases_native_resource() { } } - private static class FakeSwiftInstance extends SwiftInstance implements SwiftHeapObject { - public FakeSwiftInstance(SwiftArena arena) { + private static class FakeSwiftInstance extends FFMSwiftInstance implements SwiftHeapObject { + public FakeSwiftInstance(AllocatingSwiftArena arena) { super(MemorySegment.NULL, arena); } - @Override - public GroupLayout $layout() { - return null; - } - @Override public SwiftAnyType $swiftType() { return null; diff --git a/SwiftKit/src/test/java/org/swift/swiftkit/SwiftRuntimeMetadataTest.java b/SwiftKitFFM/src/test/java/org/swift/swiftkit/ffm/SwiftRuntimeMetadataTest.java similarity index 95% rename from SwiftKit/src/test/java/org/swift/swiftkit/SwiftRuntimeMetadataTest.java rename to SwiftKitFFM/src/test/java/org/swift/swiftkit/ffm/SwiftRuntimeMetadataTest.java index 3419405e..0ec82123 100644 --- a/SwiftKit/src/test/java/org/swift/swiftkit/SwiftRuntimeMetadataTest.java +++ b/SwiftKitFFM/src/test/java/org/swift/swiftkit/ffm/SwiftRuntimeMetadataTest.java @@ -12,11 +12,7 @@ // //===----------------------------------------------------------------------===// -package org.swift.swiftkit; - -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; +package org.swift.swiftkit.ffm; public class SwiftRuntimeMetadataTest { diff --git a/Tests/JExtractSwiftTests/ClassPrintingTests.swift b/Tests/JExtractSwiftTests/ClassPrintingTests.swift index 6c0d8d0a..12b11d38 100644 --- a/Tests/JExtractSwiftTests/ClassPrintingTests.swift +++ b/Tests/JExtractSwiftTests/ClassPrintingTests.swift @@ -44,7 +44,7 @@ struct ClassPrintingTests { try assertOutput(input: class_interfaceFile, .ffm, .java, swiftModuleName: "__FakeModule", expectedChunks: [ """ public static final SwiftAnyType TYPE_METADATA = - new SwiftAnyType(SwiftKit.swiftjava.getType("__FakeModule", "MySwiftClass")); + new SwiftAnyType(SwiftRuntime.swiftjava.getType("__FakeModule", "MySwiftClass")); public final SwiftAnyType $swiftType() { return TYPE_METADATA; } diff --git a/Tests/JExtractSwiftTests/FuncCallbackImportTests.swift b/Tests/JExtractSwiftTests/FuncCallbackImportTests.swift index d81dad8c..5f80dd28 100644 --- a/Tests/JExtractSwiftTests/FuncCallbackImportTests.swift +++ b/Tests/JExtractSwiftTests/FuncCallbackImportTests.swift @@ -77,8 +77,8 @@ final class FuncCallbackImportTests { private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); public static void call(java.lang.foreign.MemorySegment callback) { try { - if (SwiftKit.TRACE_DOWNCALLS) { - SwiftKit.traceDowncall(callback); + if (SwiftRuntime.TRACE_DOWNCALLS) { + SwiftRuntime.traceDowncall(callback); } HANDLE.invokeExact(callback); } catch (Throwable ex$) { @@ -96,7 +96,7 @@ final class FuncCallbackImportTests { void apply(); } private static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid(); - private static final MethodHandle HANDLE = SwiftKit.upcallHandle(Function.class, "apply", DESC); + private static final MethodHandle HANDLE = SwiftRuntime.upcallHandle(Function.class, "apply", DESC); private static MemorySegment toUpcallStub(Function fi, Arena arena) { return Linker.nativeLinker().upcallStub(HANDLE.bindTo(fi), DESC, arena); } @@ -167,8 +167,8 @@ final class FuncCallbackImportTests { private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); public static void call(java.lang.foreign.MemorySegment callback, java.lang.foreign.MemorySegment fn) { try { - if (SwiftKit.TRACE_DOWNCALLS) { - SwiftKit.traceDowncall(callback, fn); + if (SwiftRuntime.TRACE_DOWNCALLS) { + SwiftRuntime.traceDowncall(callback, fn); } HANDLE.invokeExact(callback, fn); } catch (Throwable ex$) { @@ -190,7 +190,7 @@ final class FuncCallbackImportTests { /* _0: */SwiftValueLayout.SWIFT_POINTER, /* _1: */SwiftValueLayout.SWIFT_FLOAT ); - private static final MethodHandle HANDLE = SwiftKit.upcallHandle(Function.class, "apply", DESC); + private static final MethodHandle HANDLE = SwiftRuntime.upcallHandle(Function.class, "apply", DESC); private static MemorySegment toUpcallStub(Function fi, Arena arena) { return Linker.nativeLinker().upcallStub(HANDLE.bindTo(fi), DESC, arena); } @@ -206,7 +206,7 @@ final class FuncCallbackImportTests { void apply(); } private static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid(); - private static final MethodHandle HANDLE = SwiftKit.upcallHandle(Function.class, "apply", DESC); + private static final MethodHandle HANDLE = SwiftRuntime.upcallHandle(Function.class, "apply", DESC); private static MemorySegment toUpcallStub(Function fi, Arena arena) { return Linker.nativeLinker().upcallStub(HANDLE.bindTo(fi), DESC, arena); } @@ -281,8 +281,8 @@ final class FuncCallbackImportTests { private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); public static void call(java.lang.foreign.MemorySegment body) { try { - if (SwiftKit.TRACE_DOWNCALLS) { - SwiftKit.traceDowncall(body); + if (SwiftRuntime.TRACE_DOWNCALLS) { + SwiftRuntime.traceDowncall(body); } HANDLE.invokeExact(body); } catch (Throwable ex$) { @@ -304,7 +304,7 @@ final class FuncCallbackImportTests { /* _0: */SwiftValueLayout.SWIFT_POINTER, /* _1: */SwiftValueLayout.SWIFT_INT ); - private static final MethodHandle HANDLE = SwiftKit.upcallHandle(Function.class, "apply", DESC); + private static final MethodHandle HANDLE = SwiftRuntime.upcallHandle(Function.class, "apply", DESC); private static MemorySegment toUpcallStub(Function fi, Arena arena) { return Linker.nativeLinker().upcallStub(HANDLE.bindTo(fi), DESC, arena); } diff --git a/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift b/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift index 7af3c706..a714367e 100644 --- a/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift +++ b/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift @@ -66,8 +66,8 @@ final class FunctionDescriptorTests { private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); public static void call(long i) { try { - if (SwiftKit.TRACE_DOWNCALLS) { - SwiftKit.traceDowncall(i); + if (SwiftRuntime.TRACE_DOWNCALLS) { + SwiftRuntime.traceDowncall(i); } HANDLE.invokeExact(i); } catch (Throwable ex$) { @@ -102,8 +102,8 @@ final class FunctionDescriptorTests { private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); public static void call(long l, int i32) { try { - if (SwiftKit.TRACE_DOWNCALLS) { - SwiftKit.traceDowncall(l, i32); + if (SwiftRuntime.TRACE_DOWNCALLS) { + SwiftRuntime.traceDowncall(l, i32); } HANDLE.invokeExact(l, i32); } catch (Throwable ex$) { @@ -138,8 +138,8 @@ final class FunctionDescriptorTests { private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); public static long call(long i) { try { - if (SwiftKit.TRACE_DOWNCALLS) { - SwiftKit.traceDowncall(i); + if (SwiftRuntime.TRACE_DOWNCALLS) { + SwiftRuntime.traceDowncall(i); } return (long) HANDLE.invokeExact(i); } catch (Throwable ex$) { @@ -174,8 +174,8 @@ final class FunctionDescriptorTests { private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); public static int call(java.lang.foreign.MemorySegment self) { try { - if (SwiftKit.TRACE_DOWNCALLS) { - SwiftKit.traceDowncall(self); + if (SwiftRuntime.TRACE_DOWNCALLS) { + SwiftRuntime.traceDowncall(self); } return (int) HANDLE.invokeExact(self); } catch (Throwable ex$) { @@ -209,8 +209,8 @@ final class FunctionDescriptorTests { private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); public static void call(int newValue, java.lang.foreign.MemorySegment self) { try { - if (SwiftKit.TRACE_DOWNCALLS) { - SwiftKit.traceDowncall(newValue, self); + if (SwiftRuntime.TRACE_DOWNCALLS) { + SwiftRuntime.traceDowncall(newValue, self); } HANDLE.invokeExact(newValue, self); } catch (Throwable ex$) { diff --git a/Tests/JExtractSwiftTests/MethodImportTests.swift b/Tests/JExtractSwiftTests/MethodImportTests.swift index 36610dcd..118ca789 100644 --- a/Tests/JExtractSwiftTests/MethodImportTests.swift +++ b/Tests/JExtractSwiftTests/MethodImportTests.swift @@ -180,7 +180,7 @@ final class MethodImportTests { */ public static void globalTakeIntLongString(int i32, long l, java.lang.String s) { try(var arena$ = Arena.ofConfined()) { - swiftjava___FakeModule_globalTakeIntLongString_i32_l_s.call(i32, l, SwiftKit.toCString(s, arena$)); + swiftjava___FakeModule_globalTakeIntLongString_i32_l_s.call(i32, l, SwiftRuntime.toCString(s, arena$)); } } """ @@ -222,7 +222,7 @@ final class MethodImportTests { * public func globalReturnClass() -> MySwiftClass * } */ - public static MySwiftClass globalReturnClass(SwiftArena swiftArena$) { + public static MySwiftClass globalReturnClass(AllocatingSwiftArena swiftArena$) { MemorySegment _result = swiftArena$.allocate(MySwiftClass.$LAYOUT); swiftjava___FakeModule_globalReturnClass.call(_result); return new MySwiftClass(_result, swiftArena$); @@ -396,7 +396,7 @@ final class MethodImportTests { * public init(len: Swift.Int, cap: Swift.Int) * } */ - public static MySwiftClass init(long len, long cap, SwiftArena swiftArena$) { + public static MySwiftClass init(long len, long cap, AllocatingSwiftArena swiftArena$) { MemorySegment _result = swiftArena$.allocate(MySwiftClass.$LAYOUT); swiftjava___FakeModule_MySwiftClass_init_len_cap.call(len, cap, _result) return new MySwiftClass(_result, swiftArena$); @@ -440,7 +440,7 @@ final class MethodImportTests { * public init(len: Swift.Int, cap: Swift.Int) * } */ - public static MySwiftStruct init(long len, long cap, SwiftArena swiftArena$) { + public static MySwiftStruct init(long len, long cap, AllocatingSwiftArena swiftArena$) { MemorySegment _result = swiftArena$.allocate(MySwiftStruct.$LAYOUT); swiftjava___FakeModule_MySwiftStruct_init_len_cap.call(len, cap, _result) return new MySwiftStruct(_result, swiftArena$); diff --git a/Tests/JExtractSwiftTests/StringPassingTests.swift b/Tests/JExtractSwiftTests/StringPassingTests.swift index 99dfab5c..6a5c1c80 100644 --- a/Tests/JExtractSwiftTests/StringPassingTests.swift +++ b/Tests/JExtractSwiftTests/StringPassingTests.swift @@ -45,8 +45,8 @@ final class StringPassingTests { private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); public static long call(java.lang.foreign.MemorySegment string) { try { - if (SwiftKit.TRACE_DOWNCALLS) { - SwiftKit.traceDowncall(string); + if (SwiftRuntime.TRACE_DOWNCALLS) { + SwiftRuntime.traceDowncall(string); } return (long) HANDLE.invokeExact(string); } catch (Throwable ex$) { @@ -64,7 +64,7 @@ final class StringPassingTests { */ public static long writeString(java.lang.String string) { try(var arena$ = Arena.ofConfined()) { - return swiftjava___FakeModule_writeString_string.call(SwiftKit.toCString(string, arena$)); + return swiftjava___FakeModule_writeString_string.call(SwiftRuntime.toCString(string, arena$)); } } """ diff --git a/Tests/JExtractSwiftTests/VariableImportTests.swift b/Tests/JExtractSwiftTests/VariableImportTests.swift index 33f41e20..e0a6678c 100644 --- a/Tests/JExtractSwiftTests/VariableImportTests.swift +++ b/Tests/JExtractSwiftTests/VariableImportTests.swift @@ -51,8 +51,8 @@ final class VariableImportTests { private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); public static long call(java.lang.foreign.MemorySegment self) { try { - if (SwiftKit.TRACE_DOWNCALLS) { - SwiftKit.traceDowncall(self); + if (SwiftRuntime.TRACE_DOWNCALLS) { + SwiftRuntime.traceDowncall(self); } return (long) HANDLE.invokeExact(self); } catch (Throwable ex$) { @@ -84,8 +84,8 @@ final class VariableImportTests { private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); public static void call(long newValue, java.lang.foreign.MemorySegment self) { try { - if (SwiftKit.TRACE_DOWNCALLS) { - SwiftKit.traceDowncall(newValue, self); + if (SwiftRuntime.TRACE_DOWNCALLS) { + SwiftRuntime.traceDowncall(newValue, self); } HANDLE.invokeExact(newValue, self); } catch (Throwable ex$) { diff --git a/settings.gradle b/settings.gradle index fa0fa5bd..9bf38ba5 100644 --- a/settings.gradle +++ b/settings.gradle @@ -18,7 +18,8 @@ pluginManagement { rootProject.name = "swift-java" -include "SwiftKit" +include "SwiftKitCore" +include "SwiftKitFFM" // Include sample apps -- you can run them via `gradle Name:run` new File(rootDir, "Samples").listFiles().each { From d9699337581c6361188be9da27300eb8c50ba638 Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Tue, 8 Jul 2025 11:03:20 -0700 Subject: [PATCH 303/426] [JExtract] Pass type metadata pointer to value witness functions Instead of the pointer to the value witness table. Witnesses expect type metadata. --- .../swiftkit/ffm/SwiftValueWitnessTable.java | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/SwiftValueWitnessTable.java b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/SwiftValueWitnessTable.java index a0a6a79f..2b918523 100644 --- a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/SwiftValueWitnessTable.java +++ b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/SwiftValueWitnessTable.java @@ -185,8 +185,8 @@ private static class destroy { $LAYOUT.byteOffset(MemoryLayout.PathElement.groupElement("destroy")); static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( - ValueLayout.ADDRESS, // witness table functions expect a pointer to self pointer - ValueLayout.ADDRESS // pointer to the witness table + ValueLayout.ADDRESS, // pointer to self + ValueLayout.ADDRESS // pointer to the type metadata ); /** @@ -213,13 +213,9 @@ static MethodHandle handle(SwiftAnyType ty) { * This includes deallocating the Swift managed memory for the object. */ public static void destroy(SwiftAnyType type, MemorySegment object) { - var fullTypeMetadata = fullTypeMetadata(type.$memorySegment()); - var wtable = valueWitnessTable(fullTypeMetadata); - var mh = destroy.handle(type); - try { - mh.invokeExact(object, wtable); + mh.invokeExact(object, type.$memorySegment()); } catch (Throwable th) { throw new AssertionError("Failed to destroy '" + type + "' at " + object, th); } @@ -246,7 +242,7 @@ private static class initializeWithCopy { /* -> */ ValueLayout.ADDRESS, // returns the destination object ValueLayout.ADDRESS, // destination ValueLayout.ADDRESS, // source - ValueLayout.ADDRESS // pointer to the witness table + ValueLayout.ADDRESS // pointer to the type metadata ); /** @@ -274,13 +270,10 @@ static MethodHandle handle(SwiftAnyType ty) { * Returns the dest object. */ public static MemorySegment initializeWithCopy(SwiftAnyType type, MemorySegment dest, MemorySegment src) { - var fullTypeMetadata = fullTypeMetadata(type.$memorySegment()); - var wtable = valueWitnessTable(fullTypeMetadata); - var mh = initializeWithCopy.handle(type); try { - return (MemorySegment) mh.invokeExact(dest, src, wtable); + return (MemorySegment) mh.invokeExact(dest, src, type.$memorySegment()); } catch (Throwable th) { throw new AssertionError("Failed to initializeWithCopy '" + type + "' (" + dest + ", " + src + ")", th); } From c2f683e0c890a6044fc47c6677dad4d12d06aaa5 Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Mon, 7 Jul 2025 10:08:18 -0700 Subject: [PATCH 304/426] [JExtract] Import 'Foundation.Data' if used * Introduce `KnownSwiftModules` to represent `Swift` and `Foundation` modules. * `SwiftSymbolTable.setup()` is now a factory method to create `SwiftSymbolTable`. It scans the source file for module dependency. If `import Foundation` is found, add `Foundation` from the `KnownSwiftModules` (Just `Data` for now) * In `Swift2JavaTranslator` import `Data` APIs if any of the imported APIs use `Data` * `Data` has limited hardcoded APIs `init(bytes:count:)`, `getter:count`, and `withUnsafeBytes(_:)`. * Add `import Foundation` in Swift thunk if any of the the original source files import it --- .../JExtractSwiftPlugin.swift | 7 + .../MySwiftLibrary/MySwiftLibrary.swift | 6 + .../com/example/swift/HelloJava2Swift.java | 18 + .../FFM/CDeclLowering/CRepresentation.swift | 4 +- ...Swift2JavaGenerator+FunctionLowering.swift | 28 +- ...MSwift2JavaGenerator+JavaTranslation.swift | 14 +- ...ift2JavaGenerator+SwiftThunkPrinting.swift | 16 +- .../FFM/FFMSwift2JavaGenerator.swift | 5 +- ...ISwift2JavaGenerator+JavaTranslation.swift | 8 +- .../JNI/JNISwift2JavaGenerator.swift | 3 + .../Swift2JavaTranslator.swift | 85 ++++- .../SwiftTypes/DependencyScanner.swift | 29 ++ .../SwiftTypes/SwiftKnownModules.swift | 94 +++++ .../SwiftTypes/SwiftKnownTypeDecls.swift | 61 ++++ .../SwiftTypes/SwiftKnownTypes.swift | 46 +-- .../SwiftNominalTypeDeclaration.swift | 19 +- .../SwiftParsedModuleSymbolTable.swift | 120 ------- .../SwiftParsedModuleSymbolTableBuilder.swift | 178 ++++++++++ .../SwiftStandardLibraryTypeDecls.swift | 198 ----------- .../SwiftTypes/SwiftSymbolTable.swift | 125 +++---- .../Asserts/LoweringAssertions.swift | 6 +- .../JExtractSwiftTests/DataImportTests.swift | 328 ++++++++++++++++++ .../SwiftSymbolTableTests.swift | 8 +- 23 files changed, 936 insertions(+), 470 deletions(-) create mode 100644 Sources/JExtractSwiftLib/SwiftTypes/DependencyScanner.swift create mode 100644 Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownModules.swift create mode 100644 Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownTypeDecls.swift delete mode 100644 Sources/JExtractSwiftLib/SwiftTypes/SwiftParsedModuleSymbolTable.swift create mode 100644 Sources/JExtractSwiftLib/SwiftTypes/SwiftParsedModuleSymbolTableBuilder.swift delete mode 100644 Sources/JExtractSwiftLib/SwiftTypes/SwiftStandardLibraryTypeDecls.swift create mode 100644 Tests/JExtractSwiftTests/DataImportTests.swift diff --git a/Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift b/Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift index 7bfb51cf..83c5f0d9 100644 --- a/Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift +++ b/Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift @@ -100,6 +100,13 @@ struct JExtractSwiftBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin { outputSwiftDirectory.appending(path: "\(sourceModule.name)Module+SwiftJava.swift") ] + // If the module uses 'Data' type, the thunk file is emitted as if 'Data' is declared + // in that module. Declare the thunk file as the output. + // FIXME: Make this conditional. + outputSwiftFiles += [ + outputSwiftDirectory.appending(path: "Data+SwiftJava.swift") + ] + return [ .buildCommand( displayName: "Generate Java wrappers for Swift types", diff --git a/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift b/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift index 18b6546d..ce949283 100644 --- a/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift +++ b/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift @@ -23,6 +23,8 @@ import Glibc import Darwin.C #endif +import Foundation + public func helloWorld() { p("\(#function)") } @@ -53,6 +55,10 @@ public func globalReceiveRawBuffer(buf: UnsafeRawBufferPointer) -> Int { public var globalBuffer: UnsafeRawBufferPointer = UnsafeRawBufferPointer(UnsafeMutableRawBufferPointer.allocate(byteCount: 124, alignment: 1)) +public func globalReceiveReturnData(data: Data) -> Data { + return Data(data) +} + public func withBuffer(body: (UnsafeRawBufferPointer) -> Void) { body(globalBuffer) } diff --git a/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java b/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java index 668140b2..985820b1 100644 --- a/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java +++ b/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java @@ -22,6 +22,10 @@ import org.swift.swiftkit.ffm.AllocatingSwiftArena; import org.swift.swiftkit.ffm.SwiftRuntime; +import java.lang.foreign.MemoryLayout; +import java.lang.foreign.MemorySegment; +import java.lang.foreign.ValueLayout; + public class HelloJava2Swift { public static void main(String[] args) { @@ -78,6 +82,20 @@ static void examples() { }); } + // Example of using 'Data'. + try (var arena = AllocatingSwiftArena.ofConfined()) { + var origBytes = arena.allocateFrom("foobar"); + var origDat = Data.init(origBytes, origBytes.byteSize(), arena); + SwiftRuntime.trace("origDat.count = " + origDat.getCount()); + + var retDat = MySwiftLibrary.globalReceiveReturnData(origDat, arena); + retDat.withUnsafeBytes((retBytes) -> { + var str = retBytes.getString(0); + SwiftRuntime.trace("retStr=" + str); + }); + } + + System.out.println("DONE."); } diff --git a/Sources/JExtractSwiftLib/FFM/CDeclLowering/CRepresentation.swift b/Sources/JExtractSwiftLib/FFM/CDeclLowering/CRepresentation.swift index eb27e5f6..9f4a9ac9 100644 --- a/Sources/JExtractSwiftLib/FFM/CDeclLowering/CRepresentation.swift +++ b/Sources/JExtractSwiftLib/FFM/CDeclLowering/CRepresentation.swift @@ -102,7 +102,7 @@ enum CDeclToCLoweringError: Error { case invalidFunctionConvention(SwiftFunctionType) } -extension SwiftStandardLibraryTypeKind { +extension SwiftKnownTypeDeclKind { /// Determine the primitive C type that corresponds to this C standard /// library type, if there is one. var primitiveCType: CType? { @@ -125,7 +125,7 @@ extension SwiftStandardLibraryTypeKind { .qualified(const: true, volatile: false, type: .void) ) case .void: .void - case .unsafePointer, .unsafeMutablePointer, .unsafeRawBufferPointer, .unsafeMutableRawBufferPointer, .unsafeBufferPointer, .unsafeMutableBufferPointer, .string: + case .unsafePointer, .unsafeMutablePointer, .unsafeRawBufferPointer, .unsafeMutableRawBufferPointer, .unsafeBufferPointer, .unsafeMutableBufferPointer, .string, .data: nil } } diff --git a/Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift b/Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift index db764e2e..488bd4e7 100644 --- a/Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift +++ b/Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift @@ -29,7 +29,7 @@ extension FFMSwift2JavaGenerator { enclosingType: try enclosingType.map { try SwiftType($0, symbolTable: symbolTable) }, symbolTable: symbolTable ) - return try CdeclLowering(swiftStdlibTypes: swiftStdlibTypes).lowerFunctionSignature(signature) + return try CdeclLowering(symbolTable: symbolTable).lowerFunctionSignature(signature) } /// Lower the given initializer to a C-compatible entrypoint, @@ -46,7 +46,7 @@ extension FFMSwift2JavaGenerator { symbolTable: symbolTable ) - return try CdeclLowering(swiftStdlibTypes: swiftStdlibTypes).lowerFunctionSignature(signature) + return try CdeclLowering(symbolTable: symbolTable).lowerFunctionSignature(signature) } /// Lower the given variable decl to a C-compatible entrypoint, @@ -69,7 +69,7 @@ extension FFMSwift2JavaGenerator { enclosingType: try enclosingType.map { try SwiftType($0, symbolTable: symbolTable) }, symbolTable: symbolTable ) - return try CdeclLowering(swiftStdlibTypes: swiftStdlibTypes).lowerFunctionSignature(signature) + return try CdeclLowering(symbolTable: symbolTable).lowerFunctionSignature(signature) } } @@ -77,8 +77,8 @@ extension FFMSwift2JavaGenerator { struct CdeclLowering { var knownTypes: SwiftKnownTypes - init(swiftStdlibTypes: SwiftStandardLibraryTypeDecls) { - self.knownTypes = SwiftKnownTypes(decls: swiftStdlibTypes) + init(symbolTable: SwiftSymbolTable) { + self.knownTypes = SwiftKnownTypes(symbolTable: symbolTable) } /// Lower the given Swift function signature to a Swift @_cdecl function signature, @@ -266,6 +266,9 @@ struct CdeclLowering { ) } + case .data: + break + default: // Unreachable? Should be handled by `CType(cdeclType:)` lowering above. throw LoweringError.unhandledType(type) @@ -407,6 +410,9 @@ struct CdeclLowering { ]) ) + case .data: + break + default: throw LoweringError.unhandledType(type) } @@ -509,6 +515,9 @@ struct CdeclLowering { // Returning string is not supported at this point. throw LoweringError.unhandledType(type) + case .data: + break + default: // Unreachable? Should be handled by `CType(cdeclType:)` lowering above. throw LoweringError.unhandledType(type) @@ -663,8 +672,7 @@ extension LoweredFunctionSignature { package func cdeclThunk( cName: String, swiftAPIName: String, - as apiKind: SwiftAPIKind, - stdlibTypes: SwiftStandardLibraryTypeDecls + as apiKind: SwiftAPIKind ) -> FunctionDeclSyntax { let cdeclParams = allLoweredParameters.map(\.description).joined(separator: ", ") @@ -765,7 +773,7 @@ extension LoweredFunctionSignature { } enum LoweringError: Error { - case inoutNotSupported(SwiftType) - case unhandledType(SwiftType) - case effectNotSupported(SwiftEffectSpecifier) + case inoutNotSupported(SwiftType, file: String = #file, line: Int = #line) + case unhandledType(SwiftType, file: String = #file, line: Int = #line) + case effectNotSupported(SwiftEffectSpecifier, file: String = #file, line: Int = #line) } diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift index d29f6b96..fe1806a9 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift @@ -24,7 +24,7 @@ extension FFMSwift2JavaGenerator { let translated: TranslatedFunctionDecl? do { - let translation = JavaTranslation(swiftStdlibTypes: self.swiftStdlibTypes) + let translation = JavaTranslation(symbolTable: self.symbolTable) translated = try translation.translate(decl) } catch { self.log.info("Failed to translate: '\(decl.swiftDecl.qualifiedNameForDebug)'; \(error)") @@ -113,12 +113,12 @@ extension FFMSwift2JavaGenerator { } struct JavaTranslation { - var swiftStdlibTypes: SwiftStandardLibraryTypeDecls + var symbolTable: SwiftSymbolTable func translate( _ decl: ImportedFunc ) throws -> TranslatedFunctionDecl { - let lowering = CdeclLowering(swiftStdlibTypes: self.swiftStdlibTypes) + let lowering = CdeclLowering(symbolTable: symbolTable) let loweredSignature = try lowering.lowerFunctionSignature(decl.functionSignature) // Name. @@ -353,6 +353,9 @@ extension FFMSwift2JavaGenerator { conversion: .call(.placeholder, function: "SwiftRuntime.toCString", withArena: true) ) + case .data: + break + default: throw JavaTranslationError.unhandledType(swiftType) } @@ -438,6 +441,9 @@ extension FFMSwift2JavaGenerator { ) ) + case .data: + break + case .unsafePointer, .unsafeMutablePointer: // FIXME: Implement throw JavaTranslationError.unhandledType(swiftType) @@ -629,6 +635,6 @@ extension CType { } enum JavaTranslationError: Error { - case inoutNotSupported(SwiftType) + case inoutNotSupported(SwiftType, file: String = #file, line: Int = #line) case unhandledType(SwiftType, file: String = #file, line: Int = #line) } diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+SwiftThunkPrinting.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+SwiftThunkPrinting.swift index d6b09b24..d717255d 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+SwiftThunkPrinting.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+SwiftThunkPrinting.swift @@ -87,6 +87,8 @@ extension FFMSwift2JavaGenerator { """) + printSwiftThunkImports(&printer) + for thunk in stt.renderGlobalThunks() { printer.print(thunk) printer.println() @@ -114,11 +116,22 @@ extension FFMSwift2JavaGenerator { """ ) + printSwiftThunkImports(&printer) + for thunk in stt.renderThunks(forType: ty) { printer.print("\(thunk)") printer.print("") } } + + func printSwiftThunkImports(_ printer: inout CodePrinter) { + for module in self.symbolTable.importedModules.keys.sorted() { + guard module != "Swift" else { + continue + } + printer.print("import \(module)") + } + } } struct SwiftThunkTranslator { @@ -196,8 +209,7 @@ struct SwiftThunkTranslator { let thunkFunc = translated.loweredSignature.cdeclThunk( cName: thunkName, swiftAPIName: decl.name, - as: decl.apiKind, - stdlibTypes: st.swiftStdlibTypes + as: decl.apiKind ) return [DeclSyntax(thunkFunc)] } diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift index 9a140b94..6cf80d9b 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift @@ -24,7 +24,6 @@ package class FFMSwift2JavaGenerator: Swift2JavaGenerator { let javaPackage: String let swiftOutputDirectory: String let javaOutputDirectory: String - let swiftStdlibTypes: SwiftStandardLibraryTypeDecls let symbolTable: SwiftSymbolTable var javaPackagePath: String { @@ -53,7 +52,6 @@ package class FFMSwift2JavaGenerator: Swift2JavaGenerator { self.swiftOutputDirectory = swiftOutputDirectory self.javaOutputDirectory = javaOutputDirectory self.symbolTable = translator.symbolTable - self.swiftStdlibTypes = translator.swiftStdlibTypeDecls // If we are forced to write empty files, construct the expected outputs if translator.config.writeEmptyFiles ?? false { @@ -65,6 +63,9 @@ package class FFMSwift2JavaGenerator: Swift2JavaGenerator { return String(filePathPart.replacing(".swift", with: "+SwiftJava.swift")) }) self.expectedOutputSwiftFiles.insert("\(translator.swiftModuleName)Module+SwiftJava.swift") + + // FIXME: Can we avoid this? + self.expectedOutputSwiftFiles.insert("Data+SwiftJava.swift") } else { self.expectedOutputSwiftFiles = [] } diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift index a5df702c..929a332c 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift @@ -67,7 +67,7 @@ extension JNISwift2JavaGenerator { switch swiftType { case .nominal(let nominalType): if let knownType = nominalType.nominalTypeDecl.knownStandardLibraryType { - guard let javaType = translate(standardLibraryType: knownType) else { + guard let javaType = translate(knownType: knownType) else { fatalError("unsupported known type: \(knownType)") } return javaType @@ -83,8 +83,8 @@ extension JNISwift2JavaGenerator { } } - func translate(standardLibraryType: SwiftStandardLibraryTypeKind) -> JavaType? { - switch standardLibraryType { + func translate(knownType: SwiftKnownTypeDeclKind) -> JavaType? { + switch knownType { case .bool: .boolean case .int8: .byte case .uint16: .char @@ -101,6 +101,8 @@ extension JNISwift2JavaGenerator { .unsafeRawBufferPointer, .unsafeMutableRawBufferPointer, .unsafeBufferPointer, .unsafeMutableBufferPointer: nil + case .data: + fatalError("unimplemented") } } } diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator.swift index b242cf66..0cc523b4 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator.swift @@ -58,6 +58,9 @@ package class JNISwift2JavaGenerator: Swift2JavaGenerator { return String(filePathPart.replacing(".swift", with: "+SwiftJava.swift")) }) self.expectedOutputSwiftFiles.insert("\(translator.swiftModuleName)Module+SwiftJava.swift") + + // FIXME: Can we avoid this? + self.expectedOutputSwiftFiles.insert("Data+SwiftJava.swift") } else { self.expectedOutputSwiftFiles = [] } diff --git a/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift b/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift index 89deda9a..82798c15 100644 --- a/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift +++ b/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift @@ -27,6 +27,9 @@ public final class Swift2JavaTranslator { let config: Configuration + /// The name of the Swift module being translated. + let swiftModuleName: String + // ==== Input struct Input { @@ -46,14 +49,7 @@ public final class Swift2JavaTranslator { /// type representation. package var importedTypes: [String: ImportedNominalType] = [:] - package var swiftStdlibTypeDecls: SwiftStandardLibraryTypeDecls - - package let symbolTable: SwiftSymbolTable - - /// The name of the Swift module being translated. - var swiftModuleName: String { - symbolTable.moduleName - } + package var symbolTable: SwiftSymbolTable! = nil public init( config: Configuration @@ -62,12 +58,7 @@ public final class Swift2JavaTranslator { fatalError("Missing 'swiftModule' name.") // FIXME: can we make it required in config? but we shared config for many cases } self.config = config - self.symbolTable = SwiftSymbolTable(parsedModuleName: swiftModule) - - // Create a mock of the Swift standard library. - var parsedSwiftModule = SwiftParsedModuleSymbolTable(moduleName: "Swift") - self.swiftStdlibTypeDecls = SwiftStandardLibraryTypeDecls(into: &parsedSwiftModule) - self.symbolTable.importedModules.append(parsedSwiftModule.symbolTable) + self.swiftModuleName = swiftModule } } @@ -108,11 +99,69 @@ extension Swift2JavaTranslator { log.trace("Analyzing \(input.filePath)") visitor.visit(sourceFile: input.syntax) } + + // If any API uses 'Foundation.Data', import 'Data' as if it's declared in + // this module. + if let dataDecl = self.symbolTable[.data] { + if self.isUsing(dataDecl) { + visitor.visit(nominalDecl: dataDecl.syntax!.asNominal!, in: nil) + } + } } package func prepareForTranslation() { - /// Setup the symbol table. - symbolTable.setup(inputs.map({ $0.syntax })) + self.symbolTable = SwiftSymbolTable.setup( + moduleName: self.swiftModuleName, + inputs.map({ $0.syntax }), + log: self.log + ) + } + + /// Check if any of the imported decls uses the specified nominal declaration. + func isUsing(_ decl: SwiftNominalTypeDeclaration) -> Bool { + func check(_ type: SwiftType) -> Bool { + switch type { + case .nominal(let nominal): + return nominal.nominalTypeDecl == decl + case .optional(let ty): + return check(ty) + case .tuple(let tuple): + return tuple.contains(where: check) + case .function(let fn): + return check(fn.resultType) || fn.parameters.contains(where: { check($0.type) }) + case .metatype(let ty): + return check(ty) + } + } + + func check(_ fn: ImportedFunc) -> Bool { + if check(fn.functionSignature.result.type) { + return true + } + if fn.functionSignature.parameters.contains(where: { check($0.type) }) { + return true + } + return false + } + + if self.importedGlobalFuncs.contains(where: check) { + return true + } + if self.importedGlobalVariables.contains(where: check) { + return true + } + for importedType in self.importedTypes.values { + if importedType.initializers.contains(where: check) { + return true + } + if importedType.methods.contains(where: check) { + return true + } + if importedType.variables.contains(where: check) { + return true + } + } + return false } } @@ -146,10 +195,10 @@ extension Swift2JavaTranslator { } // Whether to import this extension? - guard let nominalNode = symbolTable.parsedModule.nominalTypeSyntaxNodes[swiftNominalDecl] else { + guard swiftNominalDecl.moduleName == self.swiftModuleName else { return nil } - guard nominalNode.shouldImport(log: log) else { + guard swiftNominalDecl.syntax!.shouldImport(log: log) else { return nil } diff --git a/Sources/JExtractSwiftLib/SwiftTypes/DependencyScanner.swift b/Sources/JExtractSwiftLib/SwiftTypes/DependencyScanner.swift new file mode 100644 index 00000000..409c81a7 --- /dev/null +++ b/Sources/JExtractSwiftLib/SwiftTypes/DependencyScanner.swift @@ -0,0 +1,29 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import SwiftSyntax + +/// Scan importing modules. +func importingModuleNames(sourceFile: SourceFileSyntax) -> [String] { + var importingModuleNames: [String] = [] + for item in sourceFile.statements { + if let importDecl = item.item.as(ImportDeclSyntax.self) { + guard let moduleName = importDecl.path.first?.name.text else { + continue + } + importingModuleNames.append(moduleName) + } + } + return importingModuleNames +} diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownModules.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownModules.swift new file mode 100644 index 00000000..21862c16 --- /dev/null +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownModules.swift @@ -0,0 +1,94 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import SwiftSyntax +import SwiftSyntaxBuilder + +enum SwiftKnownModule: String { + case swift = "Swift" + case foundation = "Foundation" + + var name: String { + return self.rawValue + } + + var symbolTable: SwiftModuleSymbolTable { + return switch self { + case .swift: swiftSymbolTable + case .foundation: foundationSymbolTable + } + } + + var sourceFile: SourceFileSyntax { + return switch self { + case .swift: swiftSourceFile + case .foundation: foundationSourceFile + } + } +} + +private var swiftSymbolTable: SwiftModuleSymbolTable { + var builder = SwiftParsedModuleSymbolTableBuilder(moduleName: "Swift", importedModules: [:]) + builder.handle(sourceFile: swiftSourceFile) + return builder.finalize() +} + +private var foundationSymbolTable: SwiftModuleSymbolTable { + var builder = SwiftParsedModuleSymbolTableBuilder(moduleName: "Foundation", importedModules: ["Swift": swiftSymbolTable]) + builder.handle(sourceFile: foundationSourceFile) + return builder.finalize() +} + +private let swiftSourceFile: SourceFileSyntax = """ + public struct Bool {} + public struct Int {} + public struct UInt {} + public struct Int8 {} + public struct UInt8 {} + public struct Int16 {} + public struct UInt16 {} + public struct Int32 {} + public struct UInt32 {} + public struct Int64 {} + public struct UInt64 {} + public struct Float {} + public struct Double {} + + public struct UnsafeRawPointer {} + public struct UnsafeMutableRawPointer {} + public struct UnsafeRawBufferPointer {} + public struct UnsafeMutableRawBufferPointer {} + + public struct UnsafePointer {} + public struct UnsafeMutablePointer {} + + public struct UnsafeBufferPointer {} + public struct UnsafeMutableBufferPointer {} + + // FIXME: Support 'typealias Void = ()' + public struct Void {} + + public struct String { + public init(cString: UnsafePointer) + public func withCString(_ body: (UnsafePointer) -> Void) + } + """ + +private let foundationSourceFile: SourceFileSyntax = """ + public struct Data { + public init(bytes: UnsafeRawPointer, count: Int) + public var count: Int { get } + public func withUnsafeBytes(_ body: (UnsafeRawBufferPointer) -> Void) + } + """ diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownTypeDecls.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownTypeDecls.swift new file mode 100644 index 00000000..0ac915c7 --- /dev/null +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownTypeDecls.swift @@ -0,0 +1,61 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import SwiftSyntax + +enum SwiftKnownTypeDeclKind: String, Hashable { + case bool = "Swift.Bool" + case int = "Swift.Int" + case uint = "Swift.UInt" + case int8 = "Swift.Int8" + case uint8 = "Swift.UInt8" + case int16 = "Swift.Int16" + case uint16 = "Swift.UInt16" + case int32 = "Swift.Int32" + case uint32 = "Swift.UInt32" + case int64 = "Swift.Int64" + case uint64 = "Swift.UInt64" + case float = "Swift.Float" + case double = "Swift.Double" + case unsafeRawPointer = "Swift.UnsafeRawPointer" + case unsafeMutableRawPointer = "Swift.UnsafeMutableRawPointer" + case unsafeRawBufferPointer = "Swift.UnsafeRawBufferPointer" + case unsafeMutableRawBufferPointer = "Swift.UnsafeMutableRawBufferPointer" + case unsafePointer = "Swift.UnsafePointer" + case unsafeMutablePointer = "Swift.UnsafeMutablePointer" + case unsafeBufferPointer = "Swift.UnsafeBufferPointer" + case unsafeMutableBufferPointer = "Swift.UnsafeMutableBufferPointer" + case void = "Swift.Void" + case string = "Swift.String" + + case data = "Foundation.Data" + + var moduleAndName: (module: String, name: String) { + let qualified = self.rawValue + let period = qualified.firstIndex(of: ".")! + return ( + module: String(qualified[.. SwiftType { .nominal( SwiftNominalType( - nominalTypeDecl: decls.unsafePointerDecl, + nominalTypeDecl: symbolTable[.unsafePointer], genericArguments: [pointeeType] ) ) @@ -47,7 +47,7 @@ struct SwiftKnownTypes { func unsafeMutablePointer(_ pointeeType: SwiftType) -> SwiftType { .nominal( SwiftNominalType( - nominalTypeDecl: decls.unsafeMutablePointerDecl, + nominalTypeDecl: symbolTable[.unsafeMutablePointer], genericArguments: [pointeeType] ) ) @@ -56,7 +56,7 @@ struct SwiftKnownTypes { func unsafeBufferPointer(_ elementType: SwiftType) -> SwiftType { .nominal( SwiftNominalType( - nominalTypeDecl: decls.unsafeBufferPointerDecl, + nominalTypeDecl: symbolTable[.unsafeBufferPointer], genericArguments: [elementType] ) ) @@ -65,7 +65,7 @@ struct SwiftKnownTypes { func unsafeMutableBufferPointer(_ elementType: SwiftType) -> SwiftType { .nominal( SwiftNominalType( - nominalTypeDecl: decls.unsafeMutableBufferPointerDecl, + nominalTypeDecl: symbolTable[.unsafeMutableBufferPointer], genericArguments: [elementType] ) ) diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftNominalTypeDeclaration.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftNominalTypeDeclaration.swift index 29a287fe..b63f930c 100644 --- a/Sources/JExtractSwiftLib/SwiftTypes/SwiftNominalTypeDeclaration.swift +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftNominalTypeDeclaration.swift @@ -31,28 +31,28 @@ package class SwiftNominalTypeDeclaration { /// The syntax node this declaration is derived from. /// Can be `nil` if this is loaded from a .swiftmodule. - var syntax: NominalTypeDeclSyntaxNode? + let syntax: NominalTypeDeclSyntaxNode? /// The kind of nominal type. - var kind: Kind + let kind: Kind /// The parent nominal type when this nominal type is nested inside another type, e.g., /// MyCollection.Iterator. - var parent: SwiftNominalTypeDeclaration? + let parent: SwiftNominalTypeDeclaration? /// The module in which this nominal type is defined. If this is a nested type, the /// module might be different from that of the parent type, if this nominal type /// is defined in an extension within another module. - var moduleName: String + let moduleName: String /// The name of this nominal type, e.g., 'MyCollection'. - var name: String + let name: String // TODO: Generic parameters. /// Identify this nominal declaration as one of the known standard library /// types, like 'Swift.Int[. - lazy var knownStandardLibraryType: SwiftStandardLibraryTypeKind? = { + lazy var knownStandardLibraryType: SwiftKnownTypeDeclKind? = { self.computeKnownStandardLibraryType() }() @@ -66,6 +66,7 @@ package class SwiftNominalTypeDeclaration { self.moduleName = moduleName self.parent = parent self.name = node.name.text + self.syntax = node // Determine the kind from the syntax node. switch Syntax(node).as(SyntaxEnum.self) { @@ -80,12 +81,12 @@ package class SwiftNominalTypeDeclaration { /// Determine the known standard library type for this nominal type /// declaration. - private func computeKnownStandardLibraryType() -> SwiftStandardLibraryTypeKind? { - if parent != nil || moduleName != "Swift" { + private func computeKnownStandardLibraryType() -> SwiftKnownTypeDeclKind? { + if parent != nil { return nil } - return SwiftStandardLibraryTypeKind(typeNameInSwiftModule: name) + return SwiftKnownTypeDeclKind(rawValue: "\(moduleName).\(name)") } package var qualifiedName: String { diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftParsedModuleSymbolTable.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftParsedModuleSymbolTable.swift deleted file mode 100644 index 1eb37eac..00000000 --- a/Sources/JExtractSwiftLib/SwiftTypes/SwiftParsedModuleSymbolTable.swift +++ /dev/null @@ -1,120 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2025 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of Swift.org project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -import SwiftSyntax - -struct SwiftParsedModuleSymbolTable { - var symbolTable: SwiftModuleSymbolTable - - /// The nominal type declarations, indexed by the nominal type declaration syntax node. - var nominalTypeDeclarations: [SyntaxIdentifier: SwiftNominalTypeDeclaration] = [:] - - /// Mapping from the nominal type declarations in this module back to the syntax - /// node. This is the reverse mapping of 'nominalTypeDeclarations'. - var nominalTypeSyntaxNodes: [SwiftNominalTypeDeclaration: NominalTypeDeclSyntaxNode] = [:] - - init(moduleName: String) { - symbolTable = .init(moduleName: moduleName) - } -} - -extension SwiftParsedModuleSymbolTable: SwiftSymbolTableProtocol { - var moduleName: String { - symbolTable.moduleName - } - - func lookupTopLevelNominalType(_ name: String) -> SwiftNominalTypeDeclaration? { - symbolTable.lookupTopLevelNominalType(name) - } - - func lookupNestedType(_ name: String, parent: SwiftNominalTypeDeclaration) -> SwiftNominalTypeDeclaration? { - symbolTable.lookupNestedType(name, parent: parent) - } -} - -extension SwiftParsedModuleSymbolTable { - /// Look up a nominal type declaration based on its syntax node. - func lookup(_ node: NominalTypeDeclSyntaxNode) -> SwiftNominalTypeDeclaration? { - nominalTypeDeclarations[node.id] - } - - /// Add a nominal type declaration and all of the nested types within it to the symbol - /// table. - @discardableResult - mutating func addNominalTypeDeclaration( - _ node: NominalTypeDeclSyntaxNode, - parent: SwiftNominalTypeDeclaration? - ) -> SwiftNominalTypeDeclaration { - // If we have already recorded this nominal type declaration, we're done. - if let existingNominal = nominalTypeDeclarations[node.id] { - return existingNominal - } - - // Otherwise, create the nominal type declaration. - let nominalTypeDecl = SwiftNominalTypeDeclaration( - moduleName: moduleName, - parent: parent, - node: node - ) - - // Ensure that we can find this nominal type declaration again based on the syntax - // node, and vice versa. - nominalTypeDeclarations[node.id] = nominalTypeDecl - nominalTypeSyntaxNodes[nominalTypeDecl] = node - - if let parent { - // For nested types, make them discoverable from the parent type. - symbolTable.nestedTypes[parent, default: [:]][node.name.text] = nominalTypeDecl - } else { - // For top-level types, make them discoverable by name. - symbolTable.topLevelTypes[node.name.text] = nominalTypeDecl - } - - // Find any nested types within this nominal type and add them. - for member in node.memberBlock.members { - if let nominalMember = member.decl.asNominal { - addNominalTypeDeclaration(nominalMember, parent: nominalTypeDecl) - } - } - - return nominalTypeDecl - } - - /// Add any nested types within the given extension (with known extended nominal type - /// declaration) to the symbol table. - mutating func addExtension( - _ extensionNode: ExtensionDeclSyntax, - extending nominalTypeDecl: SwiftNominalTypeDeclaration - ) { - // Find any nested types within this extension and add them. - for member in extensionNode.memberBlock.members { - if let nominalMember = member.decl.asNominal { - addNominalTypeDeclaration(nominalMember, parent: nominalTypeDecl) - } - } - } -} - -extension DeclSyntaxProtocol { - var asNominal: NominalTypeDeclSyntaxNode? { - switch DeclSyntax(self).as(DeclSyntaxEnum.self) { - case .actorDecl(let actorDecl): actorDecl - case .classDecl(let classDecl): classDecl - case .enumDecl(let enumDecl): enumDecl - case .protocolDecl(let protocolDecl): protocolDecl - case .structDecl(let structDecl): structDecl - default: nil - } - } -} diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftParsedModuleSymbolTableBuilder.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftParsedModuleSymbolTableBuilder.swift new file mode 100644 index 00000000..4026e624 --- /dev/null +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftParsedModuleSymbolTableBuilder.swift @@ -0,0 +1,178 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import SwiftSyntax + +struct SwiftParsedModuleSymbolTableBuilder { + let log: Logger? + + /// The symbol table being built. + var symbolTable: SwiftModuleSymbolTable + + /// Imported modules to resolve type syntax. + let importedModules: [String: SwiftModuleSymbolTable] + + /// Extension decls their extended type hasn't been resolved. + var unresolvedExtensions: [ExtensionDeclSyntax] + + init(moduleName: String, importedModules: [String: SwiftModuleSymbolTable], log: Logger? = nil) { + self.log = log + self.symbolTable = .init(moduleName: moduleName) + self.importedModules = importedModules + self.unresolvedExtensions = [] + } + + var moduleName: String { + symbolTable.moduleName + } +} + +extension SwiftParsedModuleSymbolTableBuilder { + + mutating func handle( + sourceFile: SourceFileSyntax + ) { + // Find top-level type declarations. + for statement in sourceFile.statements { + // We only care about declarations. + guard case .decl(let decl) = statement.item else { + continue + } + + if let nominalTypeNode = decl.asNominal { + self.handle(nominalTypeDecl: nominalTypeNode, parent: nil) + } + if let extensionNode = decl.as(ExtensionDeclSyntax.self) { + self.handle(extensionDecl: extensionNode) + } + } + } + + /// Add a nominal type declaration and all of the nested types within it to the symbol + /// table. + mutating func handle( + nominalTypeDecl node: NominalTypeDeclSyntaxNode, + parent: SwiftNominalTypeDeclaration? + ) { + // If we have already recorded a nominal type with the name in this module, + // it's an invalid redeclaration. + if let _ = symbolTable.lookupType(node.name.text, parent: parent) { + log?.debug("Failed to add a decl into symbol table: redeclaration; " + node.nameForDebug) + return + } + + // Otherwise, create the nominal type declaration. + let nominalTypeDecl = SwiftNominalTypeDeclaration( + moduleName: moduleName, + parent: parent, + node: node + ) + + if let parent { + // For nested types, make them discoverable from the parent type. + symbolTable.nestedTypes[parent, default: [:]][nominalTypeDecl.name] = nominalTypeDecl + } else { + // For top-level types, make them discoverable by name. + symbolTable.topLevelTypes[nominalTypeDecl.name] = nominalTypeDecl + } + + self.handle(memberBlock: node.memberBlock, parent: nominalTypeDecl) + } + + mutating func handle( + memberBlock node: MemberBlockSyntax, + parent: SwiftNominalTypeDeclaration + ) { + for member in node.members { + // Find any nested types within this nominal type and add them. + if let nominalMember = member.decl.asNominal { + self.handle(nominalTypeDecl: nominalMember, parent: parent) + } + } + + } + + mutating func handle( + extensionDecl node: ExtensionDeclSyntax + ) { + if !self.tryHandle(extension: node) { + self.unresolvedExtensions.append(node) + } + } + + /// Add any nested types within the given extension to the symbol table. + /// If the extended nominal type can't be resolved, returns false. + mutating func tryHandle( + extension node: ExtensionDeclSyntax + ) -> Bool { + // Try to resolve the type referenced by this extension declaration. + // If it fails, we'll try again later. + let table = SwiftSymbolTable( + parsedModule: symbolTable, + importedModules: importedModules + ) + guard let extendedType = try? SwiftType(node.extendedType, symbolTable: table) else { + return false + } + guard let extendedNominal = extendedType.asNominalTypeDeclaration else { + // Extending type was not a nominal type. Ignore it. + return true + } + + // Find any nested types within this extension and add them. + self.handle(memberBlock: node.memberBlock, parent: extendedNominal) + return true + } + + /// Finalize the symbol table and return it. + mutating func finalize() -> SwiftModuleSymbolTable { + // Handle the unresolved extensions. + // The work queue is required because, the extending type might be declared + // in another extension that hasn't been processed. E.g.: + // + // extension Outer.Inner { struct Deeper {} } + // extension Outer { struct Inner {} } + // struct Outer {} + // + while !unresolvedExtensions.isEmpty { + var extensions = self.unresolvedExtensions + extensions.removeAll(where: { + self.tryHandle(extension: $0) + }) + + // If we didn't resolve anything, we're done. + if extensions.count == unresolvedExtensions.count { + break + } + + assert(extensions.count < unresolvedExtensions.count) + self.unresolvedExtensions = extensions + } + + return symbolTable + } +} + +extension DeclSyntaxProtocol { + var asNominal: NominalTypeDeclSyntaxNode? { + switch DeclSyntax(self).as(DeclSyntaxEnum.self) { + case .actorDecl(let actorDecl): actorDecl + case .classDecl(let classDecl): classDecl + case .enumDecl(let enumDecl): enumDecl + case .protocolDecl(let protocolDecl): protocolDecl + case .structDecl(let structDecl): structDecl + default: nil + } + } +} diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftStandardLibraryTypeDecls.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftStandardLibraryTypeDecls.swift deleted file mode 100644 index 5678b2bb..00000000 --- a/Sources/JExtractSwiftLib/SwiftTypes/SwiftStandardLibraryTypeDecls.swift +++ /dev/null @@ -1,198 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2025 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of Swift.org project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -import SwiftSyntax - -enum SwiftStandardLibraryTypeKind: String, Hashable, CaseIterable { - case bool = "Bool" - case int = "Int" - case uint = "UInt" - case int8 = "Int8" - case uint8 = "UInt8" - case int16 = "Int16" - case uint16 = "UInt16" - case int32 = "Int32" - case uint32 = "UInt32" - case int64 = "Int64" - case uint64 = "UInt64" - case float = "Float" - case double = "Double" - case unsafeRawPointer = "UnsafeRawPointer" - case unsafeMutableRawPointer = "UnsafeMutableRawPointer" - case unsafeRawBufferPointer = "UnsafeRawBufferPointer" - case unsafeMutableRawBufferPointer = "UnsafeMutableRawBufferPointer" - case unsafePointer = "UnsafePointer" - case unsafeMutablePointer = "UnsafeMutablePointer" - case unsafeBufferPointer = "UnsafeBufferPointer" - case unsafeMutableBufferPointer = "UnsafeMutableBufferPointer" - case string = "String" - case void = "Void" - - var typeName: String { rawValue } - - init?(typeNameInSwiftModule: String) { - self.init(rawValue: typeNameInSwiftModule) - } - - /// Whether this declaration is generic. - var isGeneric: Bool { - switch self { - case .bool, .double, .float, .int, .int8, .int16, .int32, .int64, - .uint, .uint8, .uint16, .uint32, .uint64, .unsafeRawPointer, - .unsafeMutableRawPointer, .unsafeRawBufferPointer, .unsafeMutableRawBufferPointer, - .string, .void: - false - - case .unsafePointer, .unsafeMutablePointer, .unsafeBufferPointer, - .unsafeMutableBufferPointer: - true - } - } - - var isPointer: Bool { - switch self { - case .unsafePointer, .unsafeMutablePointer, .unsafeRawPointer, .unsafeMutableRawPointer: - return true - default: - return false - } - } -} - -/// Captures many types from the Swift standard library in their most basic -/// forms, so that the translator can reason about them in source code. -public struct SwiftStandardLibraryTypeDecls { - // Swift.UnsafePointer - let unsafePointerDecl: SwiftNominalTypeDeclaration - - // Swift.UnsafeMutablePointer - let unsafeMutablePointerDecl: SwiftNominalTypeDeclaration - - // Swift.UnsafeBufferPointer - let unsafeBufferPointerDecl: SwiftNominalTypeDeclaration - - // Swift.UnsafeMutableBufferPointer - let unsafeMutableBufferPointerDecl: SwiftNominalTypeDeclaration - - /// Mapping from known standard library types to their nominal type declaration. - let knownTypeToNominal: [SwiftStandardLibraryTypeKind: SwiftNominalTypeDeclaration] - - /// Mapping from nominal type declarations to known types. - let nominalTypeDeclToKnownType: [SwiftNominalTypeDeclaration: SwiftStandardLibraryTypeKind] - - private static func recordKnownType( - _ type: SwiftStandardLibraryTypeKind, - _ syntax: NominalTypeDeclSyntaxNode, - knownTypeToNominal: inout [SwiftStandardLibraryTypeKind: SwiftNominalTypeDeclaration], - nominalTypeDeclToKnownType: inout [SwiftNominalTypeDeclaration: SwiftStandardLibraryTypeKind], - parsedModule: inout SwiftParsedModuleSymbolTable - ) { - let nominalDecl = parsedModule.addNominalTypeDeclaration(syntax, parent: nil) - knownTypeToNominal[type] = nominalDecl - nominalTypeDeclToKnownType[nominalDecl] = type - } - - private static func recordKnownNonGenericStruct( - _ type: SwiftStandardLibraryTypeKind, - knownTypeToNominal: inout [SwiftStandardLibraryTypeKind: SwiftNominalTypeDeclaration], - nominalTypeDeclToKnownType: inout [SwiftNominalTypeDeclaration: SwiftStandardLibraryTypeKind], - parsedModule: inout SwiftParsedModuleSymbolTable - ) { - recordKnownType( - type, - StructDeclSyntax( - name: .identifier(type.typeName), - memberBlock: .init(members: []) - ), - knownTypeToNominal: &knownTypeToNominal, - nominalTypeDeclToKnownType: &nominalTypeDeclToKnownType, - parsedModule: &parsedModule - ) - } - - init(into parsedModule: inout SwiftParsedModuleSymbolTable) { - // Pointer types - self.unsafePointerDecl = parsedModule.addNominalTypeDeclaration( - StructDeclSyntax( - name: .identifier("UnsafePointer"), - genericParameterClause: .init( - parameters: [GenericParameterSyntax(name: .identifier("Element"))] - ), - memberBlock: .init(members: []) - ), - parent: nil - ) - - self.unsafeMutablePointerDecl = parsedModule.addNominalTypeDeclaration( - StructDeclSyntax( - name: .identifier("UnsafeMutablePointer"), - genericParameterClause: .init( - parameters: [GenericParameterSyntax(name: .identifier("Element"))] - ), - memberBlock: .init(members: []) - ), - parent: nil - ) - - self.unsafeBufferPointerDecl = parsedModule.addNominalTypeDeclaration( - StructDeclSyntax( - name: .identifier("UnsafeBufferPointer"), - genericParameterClause: .init( - parameters: [GenericParameterSyntax(name: .identifier("Element"))] - ), - memberBlock: .init(members: []) - ), - parent: nil - ) - - self.unsafeMutableBufferPointerDecl = parsedModule.addNominalTypeDeclaration( - StructDeclSyntax( - name: .identifier("UnsafeMutableBufferPointer"), - genericParameterClause: .init( - parameters: [GenericParameterSyntax(name: .identifier("Element"))] - ), - memberBlock: .init(members: []) - ), - parent: nil - ) - - var knownTypeToNominal: [SwiftStandardLibraryTypeKind: SwiftNominalTypeDeclaration] = [:] - var nominalTypeDeclToKnownType: [SwiftNominalTypeDeclaration: SwiftStandardLibraryTypeKind] = [:] - - // Handle all of the non-generic types at once. - for knownType in SwiftStandardLibraryTypeKind.allCases { - guard !knownType.isGeneric else { - continue - } - - Self.recordKnownNonGenericStruct( - knownType, - knownTypeToNominal: &knownTypeToNominal, - nominalTypeDeclToKnownType: &nominalTypeDeclToKnownType, - parsedModule: &parsedModule - ) - } - - self.knownTypeToNominal = knownTypeToNominal - self.nominalTypeDeclToKnownType = nominalTypeDeclToKnownType - } - - subscript(knownType: SwiftStandardLibraryTypeKind) -> SwiftNominalTypeDeclaration { - knownTypeToNominal[knownType]! - } - - subscript(nominalType: SwiftNominalTypeDeclaration) -> SwiftStandardLibraryTypeKind? { - nominalTypeDeclToKnownType[nominalType] - } -} diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftSymbolTable.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftSymbolTable.swift index 87c2c80f..239d38c4 100644 --- a/Sources/JExtractSwiftLib/SwiftTypes/SwiftSymbolTable.swift +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftSymbolTable.swift @@ -38,89 +38,50 @@ extension SwiftSymbolTableProtocol { } package class SwiftSymbolTable { - var importedModules: [SwiftModuleSymbolTable] = [] - var parsedModule: SwiftParsedModuleSymbolTable + let importedModules: [String: SwiftModuleSymbolTable] + let parsedModule:SwiftModuleSymbolTable - package init(parsedModuleName: String) { - self.parsedModule = SwiftParsedModuleSymbolTable(moduleName: parsedModuleName) - } + private var knownTypeToNominal: [SwiftKnownTypeDeclKind: SwiftNominalTypeDeclaration] = [:] - func addImportedModule(symbolTable: SwiftModuleSymbolTable) { - importedModules.append(symbolTable) + init(parsedModule: SwiftModuleSymbolTable, importedModules: [String: SwiftModuleSymbolTable]) { + self.parsedModule = parsedModule + self.importedModules = importedModules } } extension SwiftSymbolTable { - package func setup(_ sourceFiles: some Collection) { - // First, register top-level and nested nominal types to the symbol table. + package static func setup( + moduleName: String, + _ sourceFiles: some Collection, + log: Logger + ) -> SwiftSymbolTable { + + // Prepare imported modules. + // FIXME: Support arbitrary dependencies. + var moduleNames: Set = [] for sourceFile in sourceFiles { - self.addNominalTypeDeclarations(sourceFile) - } - - // Next bind the extensions. - - // The work queue is required because, the extending type might be declared - // in another extension that hasn't been processed. E.g.: - // - // extension Outer.Inner { struct Deeper {} } - // extension Outer { struct Inner {} } - // struct Outer {} - // - var unresolvedExtensions: [ExtensionDeclSyntax] = [] - for sourceFile in sourceFiles { - // Find extensions. - for statement in sourceFile.statements { - // We only care about extensions at top-level. - if case .decl(let decl) = statement.item, let extNode = decl.as(ExtensionDeclSyntax.self) { - let resolved = handleExtension(extNode) - if !resolved { - unresolvedExtensions.append(extNode) - } - } - } + moduleNames.formUnion(importingModuleNames(sourceFile: sourceFile)) } - - while !unresolvedExtensions.isEmpty { - let numExtensionsBefore = unresolvedExtensions.count - unresolvedExtensions.removeAll(where: handleExtension(_:)) - - // If we didn't resolve anything, we're done. - if numExtensionsBefore == unresolvedExtensions.count { - break + var importedModules: [String: SwiftModuleSymbolTable] = [:] + importedModules[SwiftKnownModule.swift.name] = SwiftKnownModule.swift.symbolTable + for moduleName in moduleNames.sorted() { + if + importedModules[moduleName] == nil, + let knownModule = SwiftKnownModule(rawValue: moduleName) + { + importedModules[moduleName] = knownModule.symbolTable } - assert(numExtensionsBefore > unresolvedExtensions.count) } - } - private func addNominalTypeDeclarations(_ sourceFile: SourceFileSyntax) { - // Find top-level nominal type declarations. - for statement in sourceFile.statements { - // We only care about declarations. - guard case .decl(let decl) = statement.item, - let nominalTypeNode = decl.asNominal else { - continue - } - - parsedModule.addNominalTypeDeclaration(nominalTypeNode, parent: nil) - } - } + // FIXME: Support granular lookup context (file, type context). - private func handleExtension(_ extensionDecl: ExtensionDeclSyntax) -> Bool { - // Try to resolve the type referenced by this extension declaration. - // If it fails, we'll try again later. - guard let extendedType = try? SwiftType(extensionDecl.extendedType, symbolTable: self) else { - return false - } - guard let extendedNominal = extendedType.asNominalTypeDeclaration else { - // Extending type was not a nominal type. Ignore it. - return true + var builder = SwiftParsedModuleSymbolTableBuilder(moduleName: moduleName, importedModules: importedModules, log: log) + // First, register top-level and nested nominal types to the symbol table. + for sourceFile in sourceFiles { + builder.handle(sourceFile: sourceFile) } - - // Register nested nominals in extensions to the symbol table. - parsedModule.addExtension(extensionDecl, extending: extendedNominal) - - // We have successfully resolved the extended type. Record it. - return true + let parsedModule = builder.finalize() + return SwiftSymbolTable(parsedModule: parsedModule, importedModules: importedModules) } } @@ -134,12 +95,14 @@ extension SwiftSymbolTable: SwiftSymbolTableProtocol { return parsedResult } - for importedModule in importedModules { + for importedModule in importedModules.values { if let result = importedModule.lookupTopLevelNominalType(name) { return result } } + // FIXME: Implement module qualified name lookups. E.g. 'Swift.String' + return nil } @@ -149,7 +112,7 @@ extension SwiftSymbolTable: SwiftSymbolTableProtocol { return parsedResult } - for importedModule in importedModules { + for importedModule in importedModules.values { if let result = importedModule.lookupNestedType(name, parent: parent) { return result } @@ -158,3 +121,21 @@ extension SwiftSymbolTable: SwiftSymbolTableProtocol { return nil } } + +extension SwiftSymbolTable { + /// Map 'SwiftKnownTypeDeclKind' to the declaration. + subscript(knownType: SwiftKnownTypeDeclKind) -> SwiftNominalTypeDeclaration! { + if let known = knownTypeToNominal[knownType] { + return known + } + + let (module, name) = knownType.moduleAndName + guard let moduleTable = importedModules[module] else { + return nil + } + + let found = moduleTable.lookupTopLevelNominalType(name) + knownTypeToNominal[knownType] = found + return found + } +} diff --git a/Tests/JExtractSwiftTests/Asserts/LoweringAssertions.swift b/Tests/JExtractSwiftTests/Asserts/LoweringAssertions.swift index 05323630..eebfdf4a 100644 --- a/Tests/JExtractSwiftTests/Asserts/LoweringAssertions.swift +++ b/Tests/JExtractSwiftTests/Asserts/LoweringAssertions.swift @@ -73,8 +73,7 @@ func assertLoweredFunction( let loweredCDecl = loweredFunction.cdeclThunk( cName: "c_\(swiftFunctionName)", swiftAPIName: swiftFunctionName, - as: apiKind, - stdlibTypes: translator.swiftStdlibTypeDecls + as: apiKind ) #expect( @@ -141,8 +140,7 @@ func assertLoweredVariableAccessor( let loweredCDecl = loweredFunction?.cdeclThunk( cName: "c_\(swiftVariableName)", swiftAPIName: swiftVariableName, - as: isSet ? .setter : .getter, - stdlibTypes: translator.swiftStdlibTypeDecls + as: isSet ? .setter : .getter ) #expect( diff --git a/Tests/JExtractSwiftTests/DataImportTests.swift b/Tests/JExtractSwiftTests/DataImportTests.swift new file mode 100644 index 00000000..75613407 --- /dev/null +++ b/Tests/JExtractSwiftTests/DataImportTests.swift @@ -0,0 +1,328 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import JExtractSwiftLib +import Testing + +final class DataImportTests { + let class_interfaceFile = + """ + import Foundation + + public func receiveData(dat: Data) + public func returnData() -> Data + """ + + @Test("Import Data: Swift thunks") + func swiftThunk() throws { + + try assertOutput( + input: class_interfaceFile, .ffm, .swift, + expectedChunks: [ + """ + import Foundation + """, + """ + @_cdecl("swiftjava_SwiftModule_receiveData_dat") + public func swiftjava_SwiftModule_receiveData_dat(_ dat: UnsafeRawPointer) { + receiveData(dat: dat.assumingMemoryBound(to: Data.self).pointee) + } + """, + """ + @_cdecl("swiftjava_SwiftModule_returnData") + public func swiftjava_SwiftModule_returnData(_ _result: UnsafeMutableRawPointer) { + _result.assumingMemoryBound(to: Data.self).initialize(to: returnData()) + } + """, + + """ + @_cdecl("swiftjava_getType_SwiftModule_Data") + public func swiftjava_getType_SwiftModule_Data() -> UnsafeMutableRawPointer /* Any.Type */ { + return unsafeBitCast(Data.self, to: UnsafeMutableRawPointer.self) + } + """, + + """ + @_cdecl("swiftjava_SwiftModule_Data_init_bytes_count") + public func swiftjava_SwiftModule_Data_init_bytes_count(_ bytes: UnsafeRawPointer, _ count: Int, _ _result: UnsafeMutableRawPointer) { + _result.assumingMemoryBound(to: Data.self).initialize(to: Data(bytes: bytes, count: count)) + } + """, + + """ + @_cdecl("swiftjava_SwiftModule_Data_count$get") + public func swiftjava_SwiftModule_Data_count$get(_ self: UnsafeRawPointer) -> Int { + return self.assumingMemoryBound(to: Data.self).pointee.count + } + """, + + """ + @_cdecl("swiftjava_SwiftModule_Data_withUnsafeBytes__") + public func swiftjava_SwiftModule_Data_withUnsafeBytes__(_ body: @convention(c) (UnsafeRawPointer?, Int) -> Void, _ self: UnsafeRawPointer) { + self.assumingMemoryBound(to: Data.self).pointee.withUnsafeBytes({ (_0) in + return body(_0.baseAddress, _0.count) + }) + } + """, + ] + ) + } + + @Test("Import Data: JavaBindings") + func javaBindings() throws { + + try assertOutput( + input: class_interfaceFile, .ffm, .java, + expectedChunks: [ + """ + /** + * {@snippet lang=c : + * void swiftjava_SwiftModule_receiveData_dat(const void *dat) + * } + */ + private static class swiftjava_SwiftModule_receiveData_dat { + private static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( + /* dat: */SwiftValueLayout.SWIFT_POINTER + ); + private static final MemorySegment ADDR = + SwiftModule.findOrThrow("swiftjava_SwiftModule_receiveData_dat"); + private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + public static void call(java.lang.foreign.MemorySegment dat) { + try { + if (SwiftRuntime.TRACE_DOWNCALLS) { + SwiftRuntime.traceDowncall(dat); + } + HANDLE.invokeExact(dat); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + } + """, + + """ + /** + * Downcall to Swift: + * {@snippet lang=swift : + * public func receiveData(dat: Data) + * } + */ + public static void receiveData(Data dat) { + swiftjava_SwiftModule_receiveData_dat.call(dat.$memorySegment()); + } + """, + + """ + /** + * {@snippet lang=c : + * void swiftjava_SwiftModule_returnData(void *_result) + * } + */ + private static class swiftjava_SwiftModule_returnData { + private static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( + /* _result: */SwiftValueLayout.SWIFT_POINTER + ); + private static final MemorySegment ADDR = + SwiftModule.findOrThrow("swiftjava_SwiftModule_returnData"); + private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + public static void call(java.lang.foreign.MemorySegment _result) { + try { + if (SwiftRuntime.TRACE_DOWNCALLS) { + SwiftRuntime.traceDowncall(_result); + } + HANDLE.invokeExact(_result); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + } + """, + + """ + /** + * Downcall to Swift: + * {@snippet lang=swift : + * public func returnData() -> Data + * } + */ + public static Data returnData(AllocatingSwiftArena swiftArena$) { + MemorySegment _result = swiftArena$.allocate(Data.$LAYOUT); + swiftjava_SwiftModule_returnData.call(_result); + return new Data(_result, swiftArena$); + } + """, + + + """ + /** + * {@snippet lang=c : + * void swiftjava_SwiftModule_Data_init_bytes_count(const void *bytes, ptrdiff_t count, void *_result) + * } + */ + private static class swiftjava_SwiftModule_Data_init_bytes_count { + private static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( + /* bytes: */SwiftValueLayout.SWIFT_POINTER, + /* count: */SwiftValueLayout.SWIFT_INT, + /* _result: */SwiftValueLayout.SWIFT_POINTER + ); + private static final MemorySegment ADDR = + SwiftModule.findOrThrow("swiftjava_SwiftModule_Data_init_bytes_count"); + private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + public static void call(java.lang.foreign.MemorySegment bytes, long count, java.lang.foreign.MemorySegment _result) { + try { + if (SwiftRuntime.TRACE_DOWNCALLS) { + SwiftRuntime.traceDowncall(bytes, count, _result); + } + HANDLE.invokeExact(bytes, count, _result); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + } + """, + + """ + /** + * Downcall to Swift: + * {@snippet lang=swift : + * public init(bytes: UnsafeRawPointer, count: Int) + * } + */ + public static Data init(java.lang.foreign.MemorySegment bytes, long count, AllocatingSwiftArena swiftArena$) { + MemorySegment _result = swiftArena$.allocate(Data.$LAYOUT); + swiftjava_SwiftModule_Data_init_bytes_count.call(bytes, count, _result); + return new Data(_result, swiftArena$); + } + """, + + """ + /** + * {@snippet lang=c : + * ptrdiff_t swiftjava_SwiftModule_Data_count$get(const void *self) + * } + */ + private static class swiftjava_SwiftModule_Data_count$get { + private static final FunctionDescriptor DESC = FunctionDescriptor.of( + /* -> */SwiftValueLayout.SWIFT_INT, + /* self: */SwiftValueLayout.SWIFT_POINTER + ); + private static final MemorySegment ADDR = + SwiftModule.findOrThrow("swiftjava_SwiftModule_Data_count$get"); + private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + public static long call(java.lang.foreign.MemorySegment self) { + try { + if (SwiftRuntime.TRACE_DOWNCALLS) { + SwiftRuntime.traceDowncall(self); + } + return (long) HANDLE.invokeExact(self); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + } + """, + + """ + /** + * Downcall to Swift: + * {@snippet lang=swift : + * public var count: Int + * } + */ + public long getCount() { + $ensureAlive(); + return swiftjava_SwiftModule_Data_count$get.call(this.$memorySegment()); + } + """, + + """ + /** + * {@snippet lang=c : + * void swiftjava_SwiftModule_Data_withUnsafeBytes__(void (*body)(const void *, ptrdiff_t), const void *self) + * } + */ + private static class swiftjava_SwiftModule_Data_withUnsafeBytes__ { + private static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( + /* body: */SwiftValueLayout.SWIFT_POINTER, + /* self: */SwiftValueLayout.SWIFT_POINTER + ); + private static final MemorySegment ADDR = + SwiftModule.findOrThrow("swiftjava_SwiftModule_Data_withUnsafeBytes__"); + private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + public static void call(java.lang.foreign.MemorySegment body, java.lang.foreign.MemorySegment self) { + try { + if (SwiftRuntime.TRACE_DOWNCALLS) { + SwiftRuntime.traceDowncall(body, self); + } + HANDLE.invokeExact(body, self); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + /** + * {snippet lang=c : + * void (*)(const void *, ptrdiff_t) + * } + */ + private static class $body { + @FunctionalInterface + public interface Function { + void apply(java.lang.foreign.MemorySegment _0, long _1); + } + private static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( + /* _0: */SwiftValueLayout.SWIFT_POINTER, + /* _1: */SwiftValueLayout.SWIFT_INT + ); + private static final MethodHandle HANDLE = SwiftRuntime.upcallHandle(Function.class, "apply", DESC); + private static MemorySegment toUpcallStub(Function fi, Arena arena) { + return Linker.nativeLinker().upcallStub(HANDLE.bindTo(fi), DESC, arena); + } + } + } + """, + + """ + public static class withUnsafeBytes { + @FunctionalInterface + public interface body { + void apply(java.lang.foreign.MemorySegment _0); + } + private static MemorySegment $toUpcallStub(body fi, Arena arena) { + return swiftjava_SwiftModule_Data_withUnsafeBytes__.$body.toUpcallStub((_0_pointer, _0_count) -> { + fi.apply(_0_pointer.reinterpret(_0_count)); + }, arena); + } + } + """, + + + """ + /** + * Downcall to Swift: + * {@snippet lang=swift : + * public func withUnsafeBytes(_ body: (UnsafeRawBufferPointer) -> Void) + * } + */ + public void withUnsafeBytes(withUnsafeBytes.body body) { + $ensureAlive(); + try(var arena$ = Arena.ofConfined()) { + swiftjava_SwiftModule_Data_withUnsafeBytes__.call(withUnsafeBytes.$toUpcallStub(body, arena$), this.$memorySegment()); + } + } + """ + ] + ) + } + +} diff --git a/Tests/JExtractSwiftTests/SwiftSymbolTableTests.swift b/Tests/JExtractSwiftTests/SwiftSymbolTableTests.swift index 2bbaa913..fdbf2d5f 100644 --- a/Tests/JExtractSwiftTests/SwiftSymbolTableTests.swift +++ b/Tests/JExtractSwiftTests/SwiftSymbolTableTests.swift @@ -21,7 +21,6 @@ import Testing struct SwiftSymbolTableSuite { @Test func lookupBindingTests() throws { - let symbolTable = SwiftSymbolTable(parsedModuleName: "MyModule") let sourceFile1: SourceFileSyntax = """ extension X.Y { struct Z { } @@ -33,8 +32,11 @@ struct SwiftSymbolTableSuite { let sourceFile2: SourceFileSyntax = """ struct X {} """ - - symbolTable.setup([sourceFile1, sourceFile2]) + let symbolTable = SwiftSymbolTable.setup( + moduleName: "MyModule", + [sourceFile1, sourceFile2], + log: Logger(label: "swift-java", logLevel: .critical) + ) let x = try #require(symbolTable.lookupType("X", parent: nil)) let xy = try #require(symbolTable.lookupType("Y", parent: x)) From 21cff45bc012712bf93113ebc2eff791ede77ac2 Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Thu, 10 Jul 2025 15:17:57 -0700 Subject: [PATCH 305/426] [JExtract/FFM] Translate 'some DataProtocol' parameters to 'Data' * Introduce `SwiftType.opaque(SwiftType)` and `.existential(SwiftType)` to represent `some` and `any` types respectively. * Introduce `SwiftKnownTypes.representativeType(of:)` to the hardcoded `DataProtocol` -> `Data` translation mapping. --- .../MySwiftLibrary/MySwiftLibrary.swift | 4 + .../com/example/swift/HelloJava2Swift.java | 10 +- .../FFM/CDeclLowering/CRepresentation.swift | 6 +- ...Swift2JavaGenerator+FunctionLowering.swift | 26 +++++- ...MSwift2JavaGenerator+JavaTranslation.swift | 66 +++++++++---- ...ISwift2JavaGenerator+JavaTranslation.swift | 8 +- .../Swift2JavaTranslator.swift | 12 ++- .../SwiftTypes/SwiftKnownModules.swift | 4 +- .../SwiftTypes/SwiftKnownTypeDecls.swift | 1 + .../SwiftTypes/SwiftKnownTypes.swift | 12 +++ .../SwiftNominalTypeDeclaration.swift | 2 +- .../SwiftTypes/SwiftType.swift | 37 ++++++-- .../JExtractSwiftTests/DataImportTests.swift | 92 ++++++++++++++++++- 13 files changed, 225 insertions(+), 55 deletions(-) diff --git a/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift b/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift index ce949283..c9291c80 100644 --- a/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift +++ b/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift @@ -63,6 +63,10 @@ public func withBuffer(body: (UnsafeRawBufferPointer) -> Void) { body(globalBuffer) } +public func globalReceiveSomeDataProtocol(data: some DataProtocol) { + p(Array(data).description) +} + // ==== Internal helpers func p(_ msg: String, file: String = #fileID, line: UInt = #line, function: String = #function) { diff --git a/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java b/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java index 985820b1..821b228e 100644 --- a/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java +++ b/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java @@ -22,10 +22,6 @@ import org.swift.swiftkit.ffm.AllocatingSwiftArena; import org.swift.swiftkit.ffm.SwiftRuntime; -import java.lang.foreign.MemoryLayout; -import java.lang.foreign.MemorySegment; -import java.lang.foreign.ValueLayout; - public class HelloJava2Swift { public static void main(String[] args) { @@ -95,6 +91,12 @@ static void examples() { }); } + try (var arena = AllocatingSwiftArena.ofConfined()) { + var bytes = arena.allocateFrom("hello"); + var dat = Data.init(bytes, bytes.byteSize(), arena); + MySwiftLibrary.globalReceiveSomeDataProtocol(dat); + } + System.out.println("DONE."); } diff --git a/Sources/JExtractSwiftLib/FFM/CDeclLowering/CRepresentation.swift b/Sources/JExtractSwiftLib/FFM/CDeclLowering/CRepresentation.swift index 9f4a9ac9..4e44e74b 100644 --- a/Sources/JExtractSwiftLib/FFM/CDeclLowering/CRepresentation.swift +++ b/Sources/JExtractSwiftLib/FFM/CDeclLowering/CRepresentation.swift @@ -24,7 +24,7 @@ extension CType { init(cdeclType: SwiftType) throws { switch cdeclType { case .nominal(let nominalType): - if let knownType = nominalType.nominalTypeDecl.knownStandardLibraryType { + if let knownType = nominalType.nominalTypeDecl.knownTypeKind { if let primitiveCType = knownType.primitiveCType { self = primitiveCType return @@ -68,7 +68,7 @@ extension CType { case .optional(let wrapped) where wrapped.isPointer: try self.init(cdeclType: wrapped) - case .metatype, .optional, .tuple: + case .metatype, .optional, .tuple, .opaque, .existential: throw CDeclToCLoweringError.invalidCDeclType(cdeclType) } } @@ -125,7 +125,7 @@ extension SwiftKnownTypeDeclKind { .qualified(const: true, volatile: false, type: .void) ) case .void: .void - case .unsafePointer, .unsafeMutablePointer, .unsafeRawBufferPointer, .unsafeMutableRawBufferPointer, .unsafeBufferPointer, .unsafeMutableBufferPointer, .string, .data: + case .unsafePointer, .unsafeMutablePointer, .unsafeRawBufferPointer, .unsafeMutableRawBufferPointer, .unsafeBufferPointer, .unsafeMutableBufferPointer, .string, .data, .dataProtocol: nil } } diff --git a/Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift b/Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift index 488bd4e7..0c6c707c 100644 --- a/Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift +++ b/Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift @@ -77,6 +77,10 @@ extension FFMSwift2JavaGenerator { struct CdeclLowering { var knownTypes: SwiftKnownTypes + init(knownTypes: SwiftKnownTypes) { + self.knownTypes = knownTypes + } + init(symbolTable: SwiftSymbolTable) { self.knownTypes = SwiftKnownTypes(symbolTable: symbolTable) } @@ -165,7 +169,7 @@ struct CdeclLowering { ) case .nominal(let nominal): - if let knownType = nominal.nominalTypeDecl.knownStandardLibraryType { + if let knownType = nominal.nominalTypeDecl.knownTypeKind { if convention == .inout { // FIXME: Support non-trivial 'inout' for builtin types. throw LoweringError.inoutNotSupported(type) @@ -320,6 +324,18 @@ struct CdeclLowering { conversion: conversion ) + case .opaque(let proto), .existential(let proto): + // If the protocol has a known representative implementation, e.g. `String` for `StringProtocol` + // Translate it as the concrete type. + // NOTE: This is a temporary workaround until we add support for generics. + if + let knownProtocol = proto.asNominalTypeDeclaration?.knownTypeKind, + let concreteTy = knownTypes.representativeType(of: knownProtocol) + { + return try lowerParameter(concreteTy, convention: convention, parameterName: parameterName) + } + throw LoweringError.unhandledType(type) + case .optional: throw LoweringError.unhandledType(type) } @@ -386,7 +402,7 @@ struct CdeclLowering { switch type { case .nominal(let nominal): - if let knownType = nominal.nominalTypeDecl.knownStandardLibraryType { + if let knownType = nominal.nominalTypeDecl.knownTypeKind { switch knownType { case .unsafeRawBufferPointer, .unsafeMutableRawBufferPointer: // pointer buffers are lowered to (raw-pointer, count) pair. @@ -421,7 +437,7 @@ struct CdeclLowering { // Custom types are not supported yet. throw LoweringError.unhandledType(type) - case .function, .metatype, .optional, .tuple: + case .function, .metatype, .optional, .tuple, .existential, .opaque: // TODO: Implement throw LoweringError.unhandledType(type) } @@ -454,7 +470,7 @@ struct CdeclLowering { case .nominal(let nominal): // Types from the Swift standard library that we know about. - if let knownType = nominal.nominalTypeDecl.knownStandardLibraryType { + if let knownType = nominal.nominalTypeDecl.knownTypeKind { switch knownType { case .unsafePointer, .unsafeMutablePointer: // Typed pointers are lowered to corresponding raw forms. @@ -575,7 +591,7 @@ struct CdeclLowering { conversion: .tupleExplode(conversions, name: outParameterName) ) - case .function(_), .optional(_): + case .function, .optional, .existential, .opaque: throw LoweringError.unhandledType(type) } } diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift index fe1806a9..db706a91 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift @@ -113,12 +113,16 @@ extension FFMSwift2JavaGenerator { } struct JavaTranslation { - var symbolTable: SwiftSymbolTable + var knownTypes: SwiftKnownTypes + + init(symbolTable: SwiftSymbolTable) { + self.knownTypes = SwiftKnownTypes(symbolTable: symbolTable) + } func translate( _ decl: ImportedFunc ) throws -> TranslatedFunctionDecl { - let lowering = CdeclLowering(symbolTable: symbolTable) + let lowering = CdeclLowering(knownTypes: knownTypes) let loweredSignature = try lowering.lowerFunctionSignature(decl.functionSignature) // Name. @@ -208,7 +212,7 @@ extension FFMSwift2JavaGenerator { switch type { case .nominal(let nominal): - if let knownType = nominal.nominalTypeDecl.knownStandardLibraryType { + if let knownType = nominal.nominalTypeDecl.knownTypeKind { switch knownType { case .unsafeRawBufferPointer, .unsafeMutableRawBufferPointer: return TranslatedParameter( @@ -248,11 +252,12 @@ extension FFMSwift2JavaGenerator { // 'self' let selfParameter: TranslatedParameter? if case .instance(let swiftSelf) = swiftSignature.selfParameter { - selfParameter = try self.translate( - swiftParam: swiftSelf, + selfParameter = try self.translateParameter( + type: swiftSelf.type, + convention: swiftSelf.convention, + parameterName: swiftSelf.parameterName ?? "self", loweredParam: loweredFunctionSignature.selfParameter!, - methodName: methodName, - parameterName: swiftSelf.parameterName ?? "self" + methodName: methodName ) } else { selfParameter = nil @@ -263,11 +268,12 @@ extension FFMSwift2JavaGenerator { .map { (idx, swiftParam) in let loweredParam = loweredFunctionSignature.parameters[idx] let parameterName = swiftParam.parameterName ?? "_\(idx)" - return try self.translate( - swiftParam: swiftParam, + return try self.translateParameter( + type: swiftParam.type, + convention: swiftParam.convention, + parameterName: parameterName, loweredParam: loweredParam, - methodName: methodName, - parameterName: parameterName + methodName: methodName ) } @@ -285,13 +291,13 @@ extension FFMSwift2JavaGenerator { } /// Translate a Swift API parameter to the user-facing Java API parameter. - func translate( - swiftParam: SwiftParameter, + func translateParameter( + type swiftType: SwiftType, + convention: SwiftParameterConvention, + parameterName: String, loweredParam: LoweredParameter, - methodName: String, - parameterName: String + methodName: String ) throws -> TranslatedParameter { - let swiftType = swiftParam.type // If there is a 1:1 mapping between this Swift type and a C type, that can // be expressed as a Java primitive type. @@ -319,8 +325,8 @@ extension FFMSwift2JavaGenerator { ) case .nominal(let swiftNominalType): - if let knownType = swiftNominalType.nominalTypeDecl.knownStandardLibraryType { - if swiftParam.convention == .inout { + if let knownType = swiftNominalType.nominalTypeDecl.knownTypeKind { + if convention == .inout { // FIXME: Support non-trivial 'inout' for builtin types. throw JavaTranslationError.inoutNotSupported(swiftType) } @@ -388,6 +394,26 @@ extension FFMSwift2JavaGenerator { conversion: .call(.placeholder, function: "\(methodName).$toUpcallStub", withArena: true) ) + case .existential(let proto), .opaque(let proto): + // If the protocol has a known representative implementation, e.g. `String` for `StringProtocol` + // Translate it as the concrete type. + // NOTE: This is a temporary workaround until we add support for generics. + if + let knownProtocol = proto.asNominalTypeDeclaration?.knownTypeKind, + let concreteTy = knownTypes.representativeType(of: knownProtocol) + { + return try translateParameter( + type: concreteTy, + convention: convention, + parameterName: parameterName, + loweredParam: loweredParam, + methodName: methodName + ) + } + + // Otherwise, not supported yet. + throw JavaTranslationError.unhandledType(swiftType) + case .optional: throw JavaTranslationError.unhandledType(swiftType) } @@ -422,7 +448,7 @@ extension FFMSwift2JavaGenerator { ) case .nominal(let swiftNominalType): - if let knownType = swiftNominalType.nominalTypeDecl.knownStandardLibraryType { + if let knownType = swiftNominalType.nominalTypeDecl.knownTypeKind { switch knownType { case .unsafeRawBufferPointer, .unsafeMutableRawBufferPointer: return TranslatedResult( @@ -476,7 +502,7 @@ extension FFMSwift2JavaGenerator { // TODO: Implement. throw JavaTranslationError.unhandledType(swiftType) - case .optional, .function: + case .optional, .function, .existential, .opaque: throw JavaTranslationError.unhandledType(swiftType) } diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift index 929a332c..f006b4a8 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift @@ -66,7 +66,7 @@ extension JNISwift2JavaGenerator { func translate(swiftType: SwiftType) -> JavaType { switch swiftType { case .nominal(let nominalType): - if let knownType = nominalType.nominalTypeDecl.knownStandardLibraryType { + if let knownType = nominalType.nominalTypeDecl.knownTypeKind { guard let javaType = translate(knownType: knownType) else { fatalError("unsupported known type: \(knownType)") } @@ -78,7 +78,7 @@ extension JNISwift2JavaGenerator { case .tuple([]): return .void - case .metatype, .optional, .tuple, .function: + case .metatype, .optional, .tuple, .function, .existential, .opaque: fatalError("unsupported type: \(self)") } } @@ -99,10 +99,8 @@ extension JNISwift2JavaGenerator { .unsafeRawPointer, .unsafeMutableRawPointer, .unsafePointer, .unsafeMutablePointer, .unsafeRawBufferPointer, .unsafeMutableRawBufferPointer, - .unsafeBufferPointer, .unsafeMutableBufferPointer: + .unsafeBufferPointer, .unsafeMutableBufferPointer, .data, .dataProtocol: nil - case .data: - fatalError("unimplemented") } } } diff --git a/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift b/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift index 82798c15..07023b09 100644 --- a/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift +++ b/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift @@ -103,7 +103,8 @@ extension Swift2JavaTranslator { // If any API uses 'Foundation.Data', import 'Data' as if it's declared in // this module. if let dataDecl = self.symbolTable[.data] { - if self.isUsing(dataDecl) { + let dataProtocolDecl = self.symbolTable[.dataProtocol]! + if self.isUsing(where: { $0 == dataDecl || $0 == dataProtocolDecl }) { visitor.visit(nominalDecl: dataDecl.syntax!.asNominal!, in: nil) } } @@ -117,12 +118,13 @@ extension Swift2JavaTranslator { ) } - /// Check if any of the imported decls uses the specified nominal declaration. - func isUsing(_ decl: SwiftNominalTypeDeclaration) -> Bool { + /// Check if any of the imported decls uses a nominal declaration that satisfies + /// the given predicate. + func isUsing(where predicate: (SwiftNominalTypeDeclaration) -> Bool) -> Bool { func check(_ type: SwiftType) -> Bool { switch type { case .nominal(let nominal): - return nominal.nominalTypeDecl == decl + return predicate(nominal.nominalTypeDecl) case .optional(let ty): return check(ty) case .tuple(let tuple): @@ -131,6 +133,8 @@ extension Swift2JavaTranslator { return check(fn.resultType) || fn.parameters.contains(where: { check($0.type) }) case .metatype(let ty): return check(ty) + case .existential(let ty), .opaque(let ty): + return check(ty) } } diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownModules.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownModules.swift index 21862c16..47abb7f0 100644 --- a/Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownModules.swift +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownModules.swift @@ -86,7 +86,9 @@ private let swiftSourceFile: SourceFileSyntax = """ """ private let foundationSourceFile: SourceFileSyntax = """ - public struct Data { + public protocol DataProtocol {} + + public struct Data: DataProtocol { public init(bytes: UnsafeRawPointer, count: Int) public var count: Int { get } public func withUnsafeBytes(_ body: (UnsafeRawBufferPointer) -> Void) diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownTypeDecls.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownTypeDecls.swift index 0ac915c7..d6af5920 100644 --- a/Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownTypeDecls.swift +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownTypeDecls.swift @@ -39,6 +39,7 @@ enum SwiftKnownTypeDeclKind: String, Hashable { case void = "Swift.Void" case string = "Swift.String" + case dataProtocol = "Foundation.DataProtocol" case data = "Foundation.Data" var moduleAndName: (module: String, name: String) { diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownTypes.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownTypes.swift index ea4371a3..8c70f7e2 100644 --- a/Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownTypes.swift +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownTypes.swift @@ -35,6 +35,9 @@ struct SwiftKnownTypes { var unsafeRawPointer: SwiftType { .nominal(SwiftNominalType(nominalTypeDecl: symbolTable[.unsafeRawPointer])) } var unsafeMutableRawPointer: SwiftType { .nominal(SwiftNominalType(nominalTypeDecl: symbolTable[.unsafeMutableRawPointer])) } + var dataProtocol: SwiftType { .nominal(SwiftNominalType(nominalTypeDecl: symbolTable[.dataProtocol])) } + var data: SwiftType { .nominal(SwiftNominalType(nominalTypeDecl: symbolTable[.data])) } + func unsafePointer(_ pointeeType: SwiftType) -> SwiftType { .nominal( SwiftNominalType( @@ -70,4 +73,13 @@ struct SwiftKnownTypes { ) ) } + + /// Returns the known representative concrete type if there is one for the + /// given protocol kind. E.g. `String` for `StringProtocol` + func representativeType(of knownProtocol: SwiftKnownTypeDeclKind) -> SwiftType? { + switch knownProtocol { + case .dataProtocol: return self.data + default: return nil + } + } } diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftNominalTypeDeclaration.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftNominalTypeDeclaration.swift index b63f930c..8be645c8 100644 --- a/Sources/JExtractSwiftLib/SwiftTypes/SwiftNominalTypeDeclaration.swift +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftNominalTypeDeclaration.swift @@ -52,7 +52,7 @@ package class SwiftNominalTypeDeclaration { /// Identify this nominal declaration as one of the known standard library /// types, like 'Swift.Int[. - lazy var knownStandardLibraryType: SwiftKnownTypeDeclKind? = { + lazy var knownTypeKind: SwiftKnownTypeDeclKind? = { self.computeKnownStandardLibraryType() }() diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftType.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftType.swift index c2ddd2a5..531ab45c 100644 --- a/Sources/JExtractSwiftLib/SwiftTypes/SwiftType.swift +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftType.swift @@ -16,12 +16,25 @@ import SwiftSyntax /// Describes a type in the Swift type system. enum SwiftType: Equatable { + case nominal(SwiftNominalType) + indirect case function(SwiftFunctionType) + + /// `.Type` indirect case metatype(SwiftType) - case nominal(SwiftNominalType) + + /// `?` indirect case optional(SwiftType) + + /// `(, )` case tuple([SwiftType]) + /// `any ` + indirect case existential(SwiftType) + + /// `some ` + indirect case opaque(SwiftType) + static var void: Self { return .tuple([]) } @@ -30,7 +43,7 @@ enum SwiftType: Equatable { switch self { case .nominal(let nominal): nominal case .tuple(let elements): elements.count == 1 ? elements[0].asNominalType : nil - case .function, .metatype, .optional: nil + case .function, .metatype, .optional, .existential, .opaque: nil } } @@ -54,7 +67,7 @@ enum SwiftType: Equatable { var isPointer: Bool { switch self { case .nominal(let nominal): - if let knownType = nominal.nominalTypeDecl.knownStandardLibraryType { + if let knownType = nominal.nominalTypeDecl.knownTypeKind { return knownType.isPointer } default: @@ -73,7 +86,7 @@ enum SwiftType: Equatable { return nominal.nominalTypeDecl.isReferenceType case .metatype, .function: return true - case .optional, .tuple: + case .optional, .tuple, .existential, .opaque: return false } } @@ -84,7 +97,7 @@ extension SwiftType: CustomStringConvertible { /// requires parentheses. private var postfixRequiresParentheses: Bool { switch self { - case .function: true + case .function, .existential, .opaque: true case .metatype, .nominal, .optional, .tuple: false } } @@ -103,6 +116,10 @@ extension SwiftType: CustomStringConvertible { return "\(wrappedType.description)?" case .tuple(let elements): return "(\(elements.map(\.description).joined(separator: ", ")))" + case .existential(let constraintType): + return "any \(constraintType)" + case .opaque(let constraintType): + return "some \(constraintType)" } } } @@ -159,8 +176,7 @@ extension SwiftType { switch type.as(TypeSyntaxEnum.self) { case .arrayType, .classRestrictionType, .compositionType, .dictionaryType, .missingType, .namedOpaqueReturnType, - .packElementType, .packExpansionType, .someOrAnyType, - .suppressedType: + .packElementType, .packExpansionType, .suppressedType: throw TypeTranslationError.unimplementedType(type) case .attributedType(let attributedType): @@ -254,6 +270,13 @@ extension SwiftType { self = try .tuple(tupleType.elements.map { element in try SwiftType(element.type, symbolTable: symbolTable) }) + + case .someOrAnyType(let someOrAntType): + if someOrAntType.someOrAnySpecifier.tokenKind == .keyword(.some) { + self = .opaque(try SwiftType(someOrAntType.constraint, symbolTable: symbolTable)) + } else { + self = .opaque(try SwiftType(someOrAntType.constraint, symbolTable: symbolTable)) + } } } diff --git a/Tests/JExtractSwiftTests/DataImportTests.swift b/Tests/JExtractSwiftTests/DataImportTests.swift index 75613407..104f7f0e 100644 --- a/Tests/JExtractSwiftTests/DataImportTests.swift +++ b/Tests/JExtractSwiftTests/DataImportTests.swift @@ -16,7 +16,7 @@ import JExtractSwiftLib import Testing final class DataImportTests { - let class_interfaceFile = + let data_interfaceFile = """ import Foundation @@ -24,11 +24,19 @@ final class DataImportTests { public func returnData() -> Data """ + let dataProtocol_interfaceFile = + """ + import Foundation + + public func receiveDataProtocol(dat: some DataProtocol) + """ + + @Test("Import Data: Swift thunks") - func swiftThunk() throws { + func data_swiftThunk() throws { try assertOutput( - input: class_interfaceFile, .ffm, .swift, + input: data_interfaceFile, .ffm, .swift, expectedChunks: [ """ import Foundation @@ -80,10 +88,10 @@ final class DataImportTests { } @Test("Import Data: JavaBindings") - func javaBindings() throws { + func data_javaBindings() throws { try assertOutput( - input: class_interfaceFile, .ffm, .java, + input: data_interfaceFile, .ffm, .java, expectedChunks: [ """ /** @@ -325,4 +333,78 @@ final class DataImportTests { ) } + @Test("Import DataProtocol: Swift thunks") + func dataProtocol_swiftThunk() throws { + try assertOutput( + input: dataProtocol_interfaceFile, .ffm, .swift, + expectedChunks: [ + """ + import Foundation + """, + """ + @_cdecl("swiftjava_SwiftModule_receiveDataProtocol_dat") + public func swiftjava_SwiftModule_receiveDataProtocol_dat(_ dat: UnsafeRawPointer) { + receiveDataProtocol(dat: dat.assumingMemoryBound(to: Data.self).pointee) + } + """, + + // Just to make sure 'Data' is imported. + """ + @_cdecl("swiftjava_getType_SwiftModule_Data") + """ + ] + ) + } + + @Test("Import DataProtocol: JavaBindings") + func dataProtocol_javaBindings() throws { + + try assertOutput( + input: dataProtocol_interfaceFile, .ffm, .java, + expectedChunks: [ + """ + /** + * {@snippet lang=c : + * void swiftjava_SwiftModule_receiveDataProtocol_dat(const void *dat) + * } + */ + private static class swiftjava_SwiftModule_receiveDataProtocol_dat { + private static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( + /* dat: */SwiftValueLayout.SWIFT_POINTER + ); + private static final MemorySegment ADDR = + SwiftModule.findOrThrow("swiftjava_SwiftModule_receiveDataProtocol_dat"); + private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + public static void call(java.lang.foreign.MemorySegment dat) { + try { + if (SwiftRuntime.TRACE_DOWNCALLS) { + SwiftRuntime.traceDowncall(dat); + } + HANDLE.invokeExact(dat); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + } + """, + + """ + /** + * Downcall to Swift: + * {@snippet lang=swift : + * public func receiveDataProtocol(dat: some DataProtocol) + * } + */ + public static void receiveDataProtocol(Data dat) { + swiftjava_SwiftModule_receiveDataProtocol_dat.call(dat.$memorySegment()); + } + """, + + // Just to make sure 'Data' is imported. + """ + public final class Data + """ + ] + ) + } } From 36d05c76f352b076ff1552c704b8d24cacae35d6 Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Thu, 10 Jul 2025 16:30:29 -0700 Subject: [PATCH 306/426] [JExtract/FFM] Add Data and DataProtocol tests Also, run Samples:SwiftKitSampleApp:test in CI --- .../MySwiftLibrary/MySwiftLibrary.swift | 3 +- Samples/SwiftKitSampleApp/ci-validate.sh | 3 +- .../com/example/swift/DataImportTest.java | 49 +++++++++++++++++++ 3 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 Samples/SwiftKitSampleApp/src/test/java/com/example/swift/DataImportTest.java diff --git a/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift b/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift index c9291c80..1bcca4fd 100644 --- a/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift +++ b/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift @@ -63,8 +63,9 @@ public func withBuffer(body: (UnsafeRawBufferPointer) -> Void) { body(globalBuffer) } -public func globalReceiveSomeDataProtocol(data: some DataProtocol) { +public func globalReceiveSomeDataProtocol(data: some DataProtocol) -> Int { p(Array(data).description) + return data.count } // ==== Internal helpers diff --git a/Samples/SwiftKitSampleApp/ci-validate.sh b/Samples/SwiftKitSampleApp/ci-validate.sh index 07b42627..c7a68d22 100755 --- a/Samples/SwiftKitSampleApp/ci-validate.sh +++ b/Samples/SwiftKitSampleApp/ci-validate.sh @@ -3,4 +3,5 @@ set -x set -e -./gradlew run \ No newline at end of file +./gradlew run +./gradlew test \ No newline at end of file diff --git a/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/DataImportTest.java b/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/DataImportTest.java new file mode 100644 index 00000000..52a63f81 --- /dev/null +++ b/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/DataImportTest.java @@ -0,0 +1,49 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package com.example.swift; + +import org.junit.jupiter.api.Test; +import org.swift.swiftkit.ffm.AllocatingSwiftArena; + +import static org.junit.jupiter.api.Assertions.*; + +public class DataImportTest { + @Test + void test_Data_receiveAndReturn() { + try (var arena = AllocatingSwiftArena.ofConfined()) { + var origBytes = arena.allocateFrom("foobar"); + var origDat = Data.init(origBytes, origBytes.byteSize(), arena); + assertEquals(7, origDat.getCount()); + + var retDat = MySwiftLibrary.globalReceiveReturnData(origDat, arena); + assertEquals(7, retDat.getCount()); + retDat.withUnsafeBytes((retBytes) -> { + assertEquals(7, retBytes.byteSize()); + var str = retBytes.getString(0); + assertEquals("foobar", str); + }); + } + } + + @Test + void test_DataProtocol_receive() { + try (var arena = AllocatingSwiftArena.ofConfined()) { + var bytes = arena.allocateFrom("hello"); + var dat = Data.init(bytes, bytes.byteSize(), arena); + var result = MySwiftLibrary.globalReceiveSomeDataProtocol(dat); + assertEquals(6, result); + } + } +} From f69d84a5ae5a4420949d524f60d9852db523a2da Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Fri, 11 Jul 2025 20:58:09 +0900 Subject: [PATCH 307/426] Drop the java.toolchain version to 17, which has a Corretto LTS release (#304) --- .github/actions/prepare_env/action.yml | 2 +- SwiftKitCore/build.gradle | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/actions/prepare_env/action.yml b/.github/actions/prepare_env/action.yml index c63b87cf..8fc986e0 100644 --- a/.github/actions/prepare_env/action.yml +++ b/.github/actions/prepare_env/action.yml @@ -11,7 +11,7 @@ runs: java-version: | 24 21 - 19 + 17 cache: 'gradle' - name: Set JAVA_HOME_{N} shell: bash diff --git a/SwiftKitCore/build.gradle b/SwiftKitCore/build.gradle index 3d5907f2..78cdbeb2 100644 --- a/SwiftKitCore/build.gradle +++ b/SwiftKitCore/build.gradle @@ -25,11 +25,11 @@ repositories { java { toolchain { - // JDK 19 is the last JDK to support Java 7 - languageVersion.set(JavaLanguageVersion.of(19)) + languageVersion.set(JavaLanguageVersion.of(17)) } // Support Android 6+ (Java 7) sourceCompatibility = JavaVersion.VERSION_1_7 + targetCompatibility = JavaVersion.VERSION_1_7 } dependencies { From 17210b73ab357d118eb565a98a64ad0fb3df8650 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Fri, 11 Jul 2025 21:09:23 +0900 Subject: [PATCH 308/426] WIP: Update readme to reflect latest work Work in progress, but it's time to update the readme --- README.md | 51 ++++++++++++++++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index b7ad4def..f9f4ca3f 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,8 @@ This repository contains two approaches to Swift/Java interoperability. -- A Swift library (`JavaKit`) and bindings generator that allows a Swift program to make use of Java libraries by wrapping Java classes in corresponding Swift types, allowing Swift to directly call any wrapped Java API. -- The `jextract-swift` tool which is similar to the JDK's `jextract` which allows to extract Java sources which are used - to efficiently call into Swift _from Java_. +- Swift library (`JavaKit`) and bindings generator that allows a Swift program to make use of Java libraries by wrapping Java classes in corresponding Swift types, allowing Swift to directly call any wrapped Java API. +- The `swift-java` tool which which offers automated ways to import or "extract" bindings to sources or libraries in either language. The results are bindings for Swift or Java. ## :construction: :construction: :construction: Early Development :construction: :construction: :construction: @@ -16,34 +15,48 @@ The primary purpose of this repository is to create an environment for collabora ## Dependencies -### Required Swift Development Toolchains +### Required JDK versions -To build and use this project, currently, you will need to download a custom toolchain which includes some improvements in Swift that this project relies on: +This project consists of different modules which have different Swift and Java runtime requirements. -**Required toolchain download:** +## JavaKit macros -Currently this project supports Swift `6.0.x` and we are working on supporting later releases. +JavaKit is a Swift library offering macros which simplify writing JNI code "by hand" but also calling Java code from Swift. -You can use Swiftly ([macOS](https://www.swift.org/install/macos/swiftly/) / [linux](https://www.swift.org/install/linux/swiftly/)) the Swift toolchain installer to install the necessary Swift versions. +It is possible to generate Swift bindings to Java libraries using JavaKit by using the `swift-java wrap-java` command. -### Required JDK versions +Required language/runtime versions: +- **JDK 17+**, any recent JDK installation should be sufficient, as only general reflection and JNI APIs are used by this integration +- **Swift 6.0.x**, because the library uses modern Swift macros -This project consists of different modules which have different Swift and Java runtime requirements. +**swift-java jextract** -**JavaKit** – the Swift macros allowing the invocation of Java libraries from Swift +Is a source generator which will **generate Java bindings to existing Swift libraries**. +Its inputs are Swift sources or packages, and outputs are generated Swift and Java code necessary to call these functions efficiently from Java. -- **JDK 17+**, any recent JDK installation should be sufficient, as only general reflection and JNI APIs are used by this integration -- **Swift 6.0.x**, because the library uses modern Swift macros +## swift-java jextract --mode=ffm (default) + +This mode provides the most flexibility and performance, and allows to decrease the amount of data being copied between Swift and Java. +This does require the use of the relatively recent [JEP-454: Foreign Function & Memory API](https://openjdk.org/jeps/454), which is only available since JDK22, and will become part of JDK LTS releases with JDK 25 (depending on your JDK vendor). + +This is the primary way we envision calling Swift code from server-side Java libraries and applications. + +Required language/runtime versions: +- **Swift 6.1**, because of dependence on rich swift interface files +- **JDK 24+** + - We are validating the implementation using the currently supported non-LTE release, which at present means JDK-24. + +## swift-java jextract --mode=jni -**jextract-swift** – the source generator that ingests .swiftinterface files and makes them available to be called from generated Java sources +In this mode, the generated sources will use the legacy JNI approach to calling native code. -- **Swift 6.0.x development snapshots**, because of dependence on rich swift interface files -- **JDK 22+** because of dependence on [JEP-454: Foreign Function & Memory API](https://openjdk.org/jeps/454) - - We are validating the implementation using the currently supported non-LTE release, which at present means JDK-23. +This mode is more limited in some performance and flexibility that it can offer, however it is the most compatible, since even very old JVM's as well as even Android systems can be supported by this mode. +We recommend this mode when FFM is not available, or wide ranging deployment compatibility is your priority. When performance is paramaunt, we recommend the FFM mode instead. -The extract tool may become able to generate legacy compatible sources, which would not require JEP-454 and would instead rely on existing JNI facilities. Currently though, efforts are focused on the forward-looking implementation using modern foreign function and memory APIs. +Required language/runtime versions: +- **Swift 6.1**, because of dependence on rich swift interface files +- **Java 7+**, including -Support for more recent Swift versions will be provided, for now please stick to 6.0 while evaluating this early version of swift-java. ## Development and Testing From ac8040060e71162f6d184789da3e3ca64523d918 Mon Sep 17 00:00:00 2001 From: Mads Odgaard Date: Fri, 11 Jul 2025 23:58:34 +0200 Subject: [PATCH 309/426] [JExtract] Generate JNI code for memory management with `SwiftKitCore` (#302) --- .../com/example/swift/HelloJava2SwiftJNI.java | 7 +- .../com/example/swift/MySwiftClassTest.java | 17 +++-- ...t2JavaGenerator+JavaBindingsPrinting.swift | 62 +++++++++++++--- ...ift2JavaGenerator+SwiftThunkPrinting.swift | 73 ++++++++++++++++--- .../swift/swiftkit/core/JNISwiftInstance.java | 2 +- .../JNI/JNIClassTests.swift | 54 +++++++++++--- 6 files changed, 175 insertions(+), 40 deletions(-) diff --git a/Samples/JExtractJNISampleApp/src/main/java/com/example/swift/HelloJava2SwiftJNI.java b/Samples/JExtractJNISampleApp/src/main/java/com/example/swift/HelloJava2SwiftJNI.java index 66366a19..38860c06 100644 --- a/Samples/JExtractJNISampleApp/src/main/java/com/example/swift/HelloJava2SwiftJNI.java +++ b/Samples/JExtractJNISampleApp/src/main/java/com/example/swift/HelloJava2SwiftJNI.java @@ -19,6 +19,7 @@ // Import javakit/swiftkit support libraries import org.swift.swiftkit.core.SwiftLibraries; +import org.swift.swiftkit.core.ConfinedSwiftMemorySession; public class HelloJava2SwiftJNI { @@ -40,8 +41,10 @@ static void examples() { MySwiftClass.method(); - MySwiftClass myClass = MySwiftClass.init(10, 5); - MySwiftClass myClass2 = MySwiftClass.init(); + try (var arena = new ConfinedSwiftMemorySession(Thread.currentThread())) { + MySwiftClass myClass = MySwiftClass.init(10, 5, arena); + MySwiftClass myClass2 = MySwiftClass.init(arena); + } System.out.println("DONE."); } diff --git a/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/MySwiftClassTest.java b/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/MySwiftClassTest.java index 994240cb..ec0e31dd 100644 --- a/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/MySwiftClassTest.java +++ b/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/MySwiftClassTest.java @@ -14,24 +14,25 @@ package com.example.swift; -import com.example.swift.MySwiftLibrary; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; +import org.swift.swiftkit.core.ConfinedSwiftMemorySession; import static org.junit.jupiter.api.Assertions.*; public class MySwiftClassTest { @Test void init_noParameters() { - MySwiftClass c = MySwiftClass.init(); - assertNotNull(c); + try (var arena = new ConfinedSwiftMemorySession(Thread.currentThread())) { + MySwiftClass c = MySwiftClass.init(arena); + assertNotNull(c); + } } @Test void init_withParameters() { - MySwiftClass c = MySwiftClass.init(1337, 42); - assertNotNull(c); + try (var arena = new ConfinedSwiftMemorySession(Thread.currentThread())) { + MySwiftClass c = MySwiftClass.init(1337, 42, arena); + assertNotNull(c); + } } - } \ No newline at end of file diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift index ac775638..6a1c549a 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift @@ -12,6 +12,19 @@ // //===----------------------------------------------------------------------===// + +// MARK: Defaults + +extension JNISwift2JavaGenerator { + /// Default set Java imports for every generated file + static let defaultJavaImports: Array = [ + "org.swift.swiftkit.core.*", + "org.swift.swiftkit.core.util.*", + ] +} + +// MARK: Printing + extension JNISwift2JavaGenerator { func writeExportedJavaSources() throws { var printer = CodePrinter() @@ -72,6 +85,7 @@ extension JNISwift2JavaGenerator { private func printImportedNominal(_ printer: inout CodePrinter, _ decl: ImportedNominalType) { printHeader(&printer) printPackage(&printer) + printImports(&printer) printNominal(&printer, decl) { printer in printer.print( @@ -87,14 +101,10 @@ extension JNISwift2JavaGenerator { """ ) - printer.println() - printer.print( """ - private long selfPointer; - - private \(decl.swiftNominal.name)(long selfPointer) { - this.selfPointer = selfPointer; + public \(decl.swiftNominal.name)(long selfPointer, SwiftArena swiftArena) { + super(selfPointer, swiftArena); } """ ) @@ -108,6 +118,8 @@ extension JNISwift2JavaGenerator { for method in decl.methods { printFunctionBinding(&printer, method) } + + printDestroyFunction(&printer, decl) } } @@ -130,10 +142,17 @@ extension JNISwift2JavaGenerator { ) } + private func printImports(_ printer: inout CodePrinter) { + for i in JNISwift2JavaGenerator.defaultJavaImports { + printer.print("import \(i);") + } + printer.print("") + } + private func printNominal( _ printer: inout CodePrinter, _ decl: ImportedNominalType, body: (inout CodePrinter) -> Void ) { - printer.printBraceBlock("public final class \(decl.swiftNominal.name)") { printer in + printer.printBraceBlock("public final class \(decl.swiftNominal.name) extends JNISwiftInstance") { printer in body(&printer) } } @@ -160,7 +179,7 @@ extension JNISwift2JavaGenerator { printer.print( """ long selfPointer = \(type.qualifiedName).allocatingInit(\(initArguments.joined(separator: ", "))); - return new \(type.qualifiedName)(selfPointer); + return new \(type.qualifiedName)(selfPointer, swiftArena$); """ ) } @@ -182,6 +201,26 @@ extension JNISwift2JavaGenerator { ) } + /// Prints the destroy function for a `JNISwiftInstance` + private func printDestroyFunction(_ printer: inout CodePrinter, _ type: ImportedNominalType) { + printer.print("private static native void $destroy(long selfPointer);") + + printer.print("@Override") + printer.printBraceBlock("protected Runnable $createDestroyFunction()") { printer in + printer.print( + """ + long $selfPointer = this.pointer(); + return new Runnable() { + @Override + public void run() { + \(type.swiftNominal.name).$destroy($selfPointer); + } + }; + """ + ) + } + } + /// Renders a Java function signature /// /// `func method(x: Int, y: Int) -> Int` becomes @@ -189,7 +228,12 @@ extension JNISwift2JavaGenerator { private func renderFunctionSignature(_ decl: ImportedFunc) -> String { let translatedDecl = translatedDecl(for: decl) let resultType = translatedDecl.translatedFunctionSignature.resultType - let parameters = translatedDecl.translatedFunctionSignature.parameters.map(\.asParameter) + var parameters = translatedDecl.translatedFunctionSignature.parameters.map(\.asParameter) + + if decl.isInitializer { + parameters.append("SwiftArena swiftArena$") + } + let throwsClause = decl.isThrowing ? " throws Exception" : "" return "\(resultType) \(translatedDecl.name)(\(parameters.joined(separator: ", ")))\(throwsClause)" diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift index b4d73873..a14c2078 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift @@ -13,6 +13,11 @@ //===----------------------------------------------------------------------===// import JavaTypes +#if canImport(FoundationEssentials) +import FoundationEssentials +#else +import Foundation +#endif extension JNISwift2JavaGenerator { func writeSwiftThunkSources() throws { @@ -96,6 +101,8 @@ extension JNISwift2JavaGenerator { printSwiftFunctionThunk(&printer, method) printer.println() } + + printDestroyFunctionThunk(&printer, type) } private func printInitializerThunk(_ printer: inout CodePrinter, _ decl: ImportedFunc) { @@ -199,24 +206,18 @@ extension JNISwift2JavaGenerator { resultType: JavaType, _ body: (inout CodePrinter) -> Void ) { - var jniSignature = parameters.reduce(into: "") { signature, parameter in + let jniSignature = parameters.reduce(into: "") { signature, parameter in signature += parameter.type.jniTypeSignature } - // Escape signature characters - jniSignature = jniSignature - .replacingOccurrences(of: "_", with: "_1") - .replacingOccurrences(of: "/", with: "_") - .replacingOccurrences(of: ";", with: "_2") - .replacingOccurrences(of: "[", with: "_3") - let cName = "Java_" + self.javaPackage.replacingOccurrences(of: ".", with: "_") - + "_\(parentName)_" - + javaMethodName + + "_\(parentName.escapedJNIIdentifier)_" + + javaMethodName.escapedJNIIdentifier + "__" - + jniSignature + + jniSignature.escapedJNIIdentifier + let translatedParameters = parameters.map { "\($0.name): \($0.type.jniTypeName)" } @@ -251,6 +252,30 @@ extension JNISwift2JavaGenerator { ) } + /// Prints the implementation of the destroy function. + private func printDestroyFunctionThunk(_ printer: inout CodePrinter, _ type: ImportedNominalType) { + printCDecl( + &printer, + javaMethodName: "$destroy", + parentName: type.swiftNominal.name, + parameters: [ + JavaParameter(name: "selfPointer", type: .long) + ], + isStatic: true, + resultType: .void + ) { printer in + // Deinitialize the pointer allocated (which will call the VWT destroy method) + // then deallocate the memory. + printer.print( + """ + let pointer = UnsafeMutablePointer<\(type.qualifiedName)>(bitPattern: Int(Int64(fromJNI: selfPointer, in: environment!)))! + pointer.deinitialize(count: 1) + pointer.deallocate() + """ + ) + } + } + /// Renders the arguments for making a downcall private func renderDowncallArguments( swiftFunctionSignature: SwiftFunctionSignature, @@ -266,3 +291,29 @@ extension JNISwift2JavaGenerator { .joined(separator: ", ") } } + +extension String { + /// Returns a version of the string correctly escaped for a JNI + var escapedJNIIdentifier: String { + self.map { + if $0 == "_" { + return "_1" + } else if $0 == "/" { + return "_" + } else if $0 == ";" { + return "_2" + } else if $0 == "[" { + return "_3" + } else if $0.isASCII && ($0.isLetter || $0.isNumber) { + return String($0) + } else if let utf16 = $0.utf16.first { + // Escape any non-alphanumeric to their UTF16 hex encoding + let utf16Hex = String(format: "%04x", utf16) + return "_0\(utf16Hex)" + } else { + fatalError("Invalid JNI character: \($0)") + } + } + .joined() + } +} diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/JNISwiftInstance.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/JNISwiftInstance.java index 891745a2..f9966793 100644 --- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/JNISwiftInstance.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/JNISwiftInstance.java @@ -39,7 +39,7 @@ protected JNISwiftInstance(long pointer, SwiftArena arena) { * * @return a function that is called when the value should be destroyed. */ - abstract Runnable $createDestroyFunction(); + protected abstract Runnable $createDestroyFunction(); @Override public SwiftInstanceCleanup createCleanupAction() { diff --git a/Tests/JExtractSwiftTests/JNI/JNIClassTests.swift b/Tests/JExtractSwiftTests/JNI/JNIClassTests.swift index c39d5815..0c0f4f02 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIClassTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIClassTests.swift @@ -44,8 +44,11 @@ struct JNIClassTests { // Swift module: SwiftModule package com.example.swift; + + import org.swift.swiftkit.core.*; + import org.swift.swiftkit.core.util.*; - public final class MyClass { + public final class MyClass extends JNISwiftInstance { static final String LIB_NAME = "SwiftModule"; @SuppressWarnings("unused") @@ -55,12 +58,25 @@ struct JNIClassTests { return true; } - private long selfPointer; - - private MyClass(long selfPointer) { - this.selfPointer = selfPointer; + public MyClass(long selfPointer, SwiftArena swiftArena) { + super(selfPointer, swiftArena); } """, + """ + private static native void $destroy(long selfPointer); + """, + """ + @Override + protected Runnable $createDestroyFunction() { + long $selfPointer = this.pointer(); + return new Runnable() { + @Override + public void run() { + MyClass.$destroy($selfPointer); + } + }; + } + """ ]) } @@ -116,9 +132,9 @@ struct JNIClassTests { * public init(x: Int64, y: Int64) * } */ - public static MyClass init(long x, long y) { + public static MyClass init(long x, long y, SwiftArena swiftArena$) { long selfPointer = MyClass.allocatingInit(x, y); - return new MyClass(selfPointer); + return new MyClass(selfPointer, swiftArena$); } """, """ @@ -128,9 +144,9 @@ struct JNIClassTests { * public init() * } */ - public static MyClass init() { + public static MyClass init(SwiftArena swiftArena$) { long selfPointer = MyClass.allocatingInit(); - return new MyClass(selfPointer); + return new MyClass(selfPointer, swiftArena$); } """, """ @@ -170,4 +186,24 @@ struct JNIClassTests { ] ) } + + @Test + func destroyFunction_swiftThunks() throws { + try assertOutput( + input: source, + .jni, + .swift, + detectChunkByInitialLines: 1, + expectedChunks: [ + """ + @_cdecl("Java_com_example_swift_MyClass__00024destroy__J") + func Java_com_example_swift_MyClass__00024destroy__J(environment: UnsafeMutablePointer!, thisClass: jclass, selfPointer: jlong) { + let pointer = UnsafeMutablePointer(bitPattern: Int(Int64(fromJNI: selfPointer, in: environment!)))! + pointer.deinitialize(count: 1) + pointer.deallocate() + } + """ + ] + ) + } } From 7bec68559498cbdfc18abd288988b737f5b5d69e Mon Sep 17 00:00:00 2001 From: Mads Odgaard Date: Sat, 12 Jul 2025 13:08:53 +0200 Subject: [PATCH 310/426] [JExtract] Add support for JNI member methods (#305) --- .../Sources/MySwiftLibrary/MySwiftClass.swift | 16 +++ .../com/example/swift/HelloJava2SwiftJNI.java | 6 + .../com/example/swift/MySwiftClassTest.java | 26 ++++ ...t2JavaGenerator+JavaBindingsPrinting.swift | 37 ++++++ ...ift2JavaGenerator+SwiftThunkPrinting.swift | 124 +++++++++++------- .../Exceptions/ExceptionHandling.swift | 2 +- .../JNI/JNIClassTests.swift | 47 +++++++ 7 files changed, 210 insertions(+), 48 deletions(-) diff --git a/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftClass.swift b/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftClass.swift index fca6236f..82958464 100644 --- a/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftClass.swift +++ b/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftClass.swift @@ -34,4 +34,20 @@ public class MySwiftClass { deinit { p("deinit called!") } + + public func sum() -> Int64 { + return x + y + } + + public func xMultiplied(by z: Int64) -> Int64 { + return x * z; + } + + enum MySwiftClassError: Error { + case swiftError + } + + public func throwingFunction() throws { + throw MySwiftClassError.swiftError + } } diff --git a/Samples/JExtractJNISampleApp/src/main/java/com/example/swift/HelloJava2SwiftJNI.java b/Samples/JExtractJNISampleApp/src/main/java/com/example/swift/HelloJava2SwiftJNI.java index 38860c06..575859ec 100644 --- a/Samples/JExtractJNISampleApp/src/main/java/com/example/swift/HelloJava2SwiftJNI.java +++ b/Samples/JExtractJNISampleApp/src/main/java/com/example/swift/HelloJava2SwiftJNI.java @@ -44,6 +44,12 @@ static void examples() { try (var arena = new ConfinedSwiftMemorySession(Thread.currentThread())) { MySwiftClass myClass = MySwiftClass.init(10, 5, arena); MySwiftClass myClass2 = MySwiftClass.init(arena); + + try { + myClass.throwingFunction(); + } catch (Exception e) { + System.out.println("Caught exception: " + e.getMessage()); + } } System.out.println("DONE."); diff --git a/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/MySwiftClassTest.java b/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/MySwiftClassTest.java index ec0e31dd..3982b480 100644 --- a/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/MySwiftClassTest.java +++ b/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/MySwiftClassTest.java @@ -35,4 +35,30 @@ void init_withParameters() { assertNotNull(c); } } + + @Test + void sum() { + try (var arena = new ConfinedSwiftMemorySession(Thread.currentThread())) { + MySwiftClass c = MySwiftClass.init(20, 10, arena); + assertEquals(30, c.sum()); + } + } + + @Test + void xMultiplied() { + try (var arena = new ConfinedSwiftMemorySession(Thread.currentThread())) { + MySwiftClass c = MySwiftClass.init(20, 10, arena); + assertEquals(200, c.xMultiplied(10)); + } + } + + @Test + void throwingFunction() { + try (var arena = new ConfinedSwiftMemorySession(Thread.currentThread())) { + MySwiftClass c = MySwiftClass.init(20, 10, arena); + Exception exception = assertThrows(Exception.class, () -> c.throwingFunction()); + + assertEquals("swiftError", exception.getMessage()); + } + } } \ No newline at end of file diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift index 6a1c549a..dce399a9 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift @@ -164,12 +164,49 @@ extension JNISwift2JavaGenerator { } private func printFunctionBinding(_ printer: inout CodePrinter, _ decl: ImportedFunc) { + if decl.isStatic || decl.isInitializer || !decl.hasParent { + printStaticFunctionBinding(&printer, decl) + } else { + printMemberMethodBindings(&printer, decl) + } + } + + private func printStaticFunctionBinding(_ printer: inout CodePrinter, _ decl: ImportedFunc) { printDeclDocumentation(&printer, decl) printer.print( "public static native \(renderFunctionSignature(decl));" ) } + /// Renders Java bindings for member methods + /// + /// Member methods are generated as a function that extracts the `selfPointer` + /// and passes it down to another native function along with the arguments + /// to call the Swift implementation. + private func printMemberMethodBindings(_ printer: inout CodePrinter, _ decl: ImportedFunc) { + let translatedDecl = translatedDecl(for: decl) + + printDeclDocumentation(&printer, decl) + printer.printBraceBlock("public \(renderFunctionSignature(decl))") { printer in + var arguments = translatedDecl.translatedFunctionSignature.parameters.map(\.name) + arguments.append("selfPointer") + + let returnKeyword = translatedDecl.translatedFunctionSignature.resultType.isVoid ? "" : "return " + + printer.print( + """ + long selfPointer = this.pointer(); + \(returnKeyword)\(translatedDecl.parentName).$\(translatedDecl.name)(\(arguments.joined(separator: ", "))); + """ + ) + } + + let returnType = translatedDecl.translatedFunctionSignature.resultType + var parameters = translatedDecl.translatedFunctionSignature.parameters.map(\.asParameter) + parameters.append("long selfPointer") + printer.print("private static native \(returnType) $\(translatedDecl.name)(\(parameters.joined(separator: ", ")));") + } + private func printInitializerBindings(_ printer: inout CodePrinter, _ decl: ImportedFunc, type: ImportedNominalType) { let translatedDecl = translatedDecl(for: decl) diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift index a14c2078..24532ca1 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift @@ -136,67 +136,97 @@ extension JNISwift2JavaGenerator { _ printer: inout CodePrinter, _ decl: ImportedFunc ) { + // Free functions does not have a parent + if decl.isStatic || !decl.hasParent { + self.printSwiftStaticFunctionThunk(&printer, decl) + } else { + self.printSwiftMemberFunctionThunk(&printer, decl) + } + } + + private func printSwiftStaticFunctionThunk(_ printer: inout CodePrinter, _ decl: ImportedFunc) { let translatedDecl = self.translatedDecl(for: decl) - let parentName = translatedDecl.parentName - let swiftReturnType = decl.functionSignature.result.type - printCDecl(&printer, decl) { printer in - let downcallParameters = renderDowncallArguments( - swiftFunctionSignature: decl.functionSignature, - translatedFunctionSignature: translatedDecl.translatedFunctionSignature + printCDecl( + &printer, + javaMethodName: translatedDecl.name, + parentName: translatedDecl.parentName, + parameters: translatedDecl.translatedFunctionSignature.parameters, + isStatic: true, + resultType: translatedDecl.translatedFunctionSignature.resultType + ) { printer in + // For free functions the parent is the Swift module + let parentName = decl.parentType?.asNominalTypeDeclaration?.qualifiedName ?? swiftModuleName + self.printFunctionDowncall(&printer, decl, calleeName: parentName) + } + } + + private func printSwiftMemberFunctionThunk(_ printer: inout CodePrinter, _ decl: ImportedFunc) { + let translatedDecl = self.translatedDecl(for: decl) + let swiftParentName = decl.parentType!.asNominalTypeDeclaration!.qualifiedName + + printCDecl( + &printer, + javaMethodName: "$\(translatedDecl.name)", + parentName: translatedDecl.parentName, + parameters: translatedDecl.translatedFunctionSignature.parameters + [ + JavaParameter(name: "selfPointer", type: .long) + ], + isStatic: true, + resultType: translatedDecl.translatedFunctionSignature.resultType + ) { printer in + printer.print( + """ + let self$ = UnsafeMutablePointer<\(swiftParentName)>(bitPattern: Int(Int64(fromJNI: selfPointer, in: environment!)))! + """ ) - let tryClause: String = decl.isThrowing ? "try " : "" - let functionDowncall = - "\(tryClause)\(parentName).\(decl.name)(\(downcallParameters))" - - let innerBody = - if swiftReturnType.isVoid { - functionDowncall - } else { - """ - let result = \(functionDowncall) - return result.getJNIValue(in: environment) - """ - } + self.printFunctionDowncall(&printer, decl, calleeName: "self$.pointee") + } + } + + private func printFunctionDowncall( + _ printer: inout CodePrinter, + _ decl: ImportedFunc, + calleeName: String + ) { + let translatedDecl = self.translatedDecl(for: decl) + let swiftReturnType = decl.functionSignature.result.type + + let downcallParameters = renderDowncallArguments( + swiftFunctionSignature: decl.functionSignature, + translatedFunctionSignature: translatedDecl.translatedFunctionSignature + ) + let tryClause: String = decl.isThrowing ? "try " : "" + let functionDowncall = "\(tryClause)\(calleeName).\(decl.name)(\(downcallParameters))" + + let returnStatement = + if swiftReturnType.isVoid { + functionDowncall + } else { + """ + let result = \(functionDowncall) + return result.getJNIValue(in: environment) + """ + } - if decl.isThrowing { - let dummyReturn = - !swiftReturnType.isVoid ? "return \(swiftReturnType).jniPlaceholderValue" : "" - printer.print( + if decl.isThrowing { + let dummyReturn = + !swiftReturnType.isVoid ? "return \(swiftReturnType).jniPlaceholderValue" : "" + printer.print( """ do { - \(innerBody) + \(returnStatement) } catch { environment.throwAsException(error) \(dummyReturn) } """ - ) - } else { - printer.print(innerBody) - } + ) + } else { + printer.print(returnStatement) } } - private func printCDecl( - _ printer: inout CodePrinter, - _ decl: ImportedFunc, - _ body: (inout CodePrinter) -> Void - ) { - let translatedDecl = translatedDecl(for: decl) - let parentName = translatedDecl.parentName - - printCDecl( - &printer, - javaMethodName: translatedDecl.name, - parentName: parentName, - parameters: translatedDecl.translatedFunctionSignature.parameters, - isStatic: decl.isStatic || decl.isInitializer || !decl.hasParent, - resultType: translatedDecl.translatedFunctionSignature.resultType, - body - ) - } - private func printCDecl( _ printer: inout CodePrinter, javaMethodName: String, diff --git a/Sources/JavaKit/Exceptions/ExceptionHandling.swift b/Sources/JavaKit/Exceptions/ExceptionHandling.swift index 02537281..d5ca1107 100644 --- a/Sources/JavaKit/Exceptions/ExceptionHandling.swift +++ b/Sources/JavaKit/Exceptions/ExceptionHandling.swift @@ -39,7 +39,7 @@ extension JNIEnvironment { } // Otherwise, create a exception with a message. - _ = try! JavaClass.withJNIClass(in: self) { exceptionClass in + _ = try! Exception.withJNIClass(in: self) { exceptionClass in interface.ThrowNew(self, exceptionClass, String(describing: error)) } } diff --git a/Tests/JExtractSwiftTests/JNI/JNIClassTests.swift b/Tests/JExtractSwiftTests/JNI/JNIClassTests.swift index 0c0f4f02..41802e55 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIClassTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIClassTests.swift @@ -33,6 +33,8 @@ struct JNIClassTests { self.x = 0 self.y = 0 } + + public func doSomething(x: Int64) {} } """ @@ -206,4 +208,49 @@ struct JNIClassTests { ] ) } + + @Test + func memberMethod_javaBindings() throws { + try assertOutput( + input: source, + .jni, + .java, + expectedChunks: [ + """ + /** + * Downcall to Swift: + * {@snippet lang=swift : + * public func doSomething(x: Int64) + * } + */ + public void doSomething(long x) { + long selfPointer = this.pointer(); + MyClass.$doSomething(x, selfPointer); + } + """, + """ + private static native void $doSomething(long x, long selfPointer); + """ + ] + ) + } + + @Test + func memberMethod_swiftThunks() throws { + try assertOutput( + input: source, + .jni, + .swift, + detectChunkByInitialLines: 1, + expectedChunks: [ + """ + @_cdecl("Java_com_example_swift_MyClass__00024doSomething__JJ") + func Java_com_example_swift_MyClass__00024doSomething__JJ(environment: UnsafeMutablePointer!, thisClass: jclass, x: jlong, selfPointer: jlong) { + let self$ = UnsafeMutablePointer(bitPattern: Int(Int64(fromJNI: selfPointer, in: environment!)))! + self$.pointee.doSomething(x: Int64(fromJNI: x, in: environment!)) + } + """, + ] + ) + } } From 94d5f345335062bbe9833e3c84d701c5101c7d8e Mon Sep 17 00:00:00 2001 From: Mads Odgaard Date: Sun, 13 Jul 2025 09:45:50 +0200 Subject: [PATCH 311/426] [JExtract/JNI] Add support for variables (#306) * add support for variables * prefix boolean variables with `is` to match Java conventions * add confined arena constructor with current thread * add variable tests * PR feedback * add test for isWarm --- .../Sources/MySwiftLibrary/MySwiftClass.swift | 25 ++ .../MySwiftLibrary/MySwiftLibrary.swift | 2 + .../Sources/MySwiftLibrary/swift-java.config | 2 +- .../com/example/swift/HelloJava2SwiftJNI.java | 4 +- .../com/example/swift/MySwiftClassTest.java | 67 ++- .../com/example/swift/MySwiftLibraryTest.java | 7 + .../Convenience/String+Extensions.swift | 12 +- ...MSwift2JavaGenerator+JavaTranslation.swift | 4 +- Sources/JExtractSwiftLib/ImportedDecls.swift | 18 + ...t2JavaGenerator+JavaBindingsPrinting.swift | 12 + ...ISwift2JavaGenerator+JavaTranslation.swift | 9 +- ...ift2JavaGenerator+SwiftThunkPrinting.swift | 43 +- .../SwiftTypes/SwiftFunctionSignature.swift | 11 +- .../core/ConfinedSwiftMemorySession.java | 4 + .../JNI/JNIVariablesTests.swift | 386 ++++++++++++++++++ 15 files changed, 584 insertions(+), 22 deletions(-) create mode 100644 Tests/JExtractSwiftTests/JNI/JNIVariablesTests.swift diff --git a/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftClass.swift b/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftClass.swift index 82958464..386a7227 100644 --- a/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftClass.swift +++ b/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftClass.swift @@ -16,6 +16,31 @@ public class MySwiftClass { let x: Int64 let y: Int64 + public let constant: Int64 = 100 + public var mutable: Int64 = 0 + public var product: Int64 { + return x * y + } + public var throwingVariable: Int64 { + get throws { + throw MySwiftClassError.swiftError + } + } + public var mutableDividedByTwo: Int64 { + get { + return mutable / 2 + } + set { + mutable = newValue * 2 + } + } + public let warm: Bool = false + public var getAsync: Int64 { + get async { + return 42 + } + } + public static func method() { p("Hello from static method in a class!") } diff --git a/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift b/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift index be04bc08..1dd84547 100644 --- a/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift +++ b/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift @@ -23,6 +23,8 @@ import Darwin.C #endif +public var globalVariable: Int64 = 0 + public func helloWorld() { p("\(#function)") } diff --git a/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/swift-java.config b/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/swift-java.config index 46bf1f1c..bb637f34 100644 --- a/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/swift-java.config +++ b/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/swift-java.config @@ -1,4 +1,4 @@ { "javaPackage": "com.example.swift", - "mode": "jni" + "mode": "jni", } diff --git a/Samples/JExtractJNISampleApp/src/main/java/com/example/swift/HelloJava2SwiftJNI.java b/Samples/JExtractJNISampleApp/src/main/java/com/example/swift/HelloJava2SwiftJNI.java index 575859ec..8e7ca284 100644 --- a/Samples/JExtractJNISampleApp/src/main/java/com/example/swift/HelloJava2SwiftJNI.java +++ b/Samples/JExtractJNISampleApp/src/main/java/com/example/swift/HelloJava2SwiftJNI.java @@ -41,10 +41,12 @@ static void examples() { MySwiftClass.method(); - try (var arena = new ConfinedSwiftMemorySession(Thread.currentThread())) { + try (var arena = new ConfinedSwiftMemorySession()) { MySwiftClass myClass = MySwiftClass.init(10, 5, arena); MySwiftClass myClass2 = MySwiftClass.init(arena); + System.out.println("myClass.isWarm: " + myClass.isWarm()); + try { myClass.throwingFunction(); } catch (Exception e) { diff --git a/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/MySwiftClassTest.java b/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/MySwiftClassTest.java index 3982b480..bf244416 100644 --- a/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/MySwiftClassTest.java +++ b/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/MySwiftClassTest.java @@ -22,7 +22,7 @@ public class MySwiftClassTest { @Test void init_noParameters() { - try (var arena = new ConfinedSwiftMemorySession(Thread.currentThread())) { + try (var arena = new ConfinedSwiftMemorySession()) { MySwiftClass c = MySwiftClass.init(arena); assertNotNull(c); } @@ -30,7 +30,7 @@ void init_noParameters() { @Test void init_withParameters() { - try (var arena = new ConfinedSwiftMemorySession(Thread.currentThread())) { + try (var arena = new ConfinedSwiftMemorySession()) { MySwiftClass c = MySwiftClass.init(1337, 42, arena); assertNotNull(c); } @@ -38,7 +38,7 @@ void init_withParameters() { @Test void sum() { - try (var arena = new ConfinedSwiftMemorySession(Thread.currentThread())) { + try (var arena = new ConfinedSwiftMemorySession()) { MySwiftClass c = MySwiftClass.init(20, 10, arena); assertEquals(30, c.sum()); } @@ -46,7 +46,7 @@ void sum() { @Test void xMultiplied() { - try (var arena = new ConfinedSwiftMemorySession(Thread.currentThread())) { + try (var arena = new ConfinedSwiftMemorySession()) { MySwiftClass c = MySwiftClass.init(20, 10, arena); assertEquals(200, c.xMultiplied(10)); } @@ -54,11 +54,68 @@ void xMultiplied() { @Test void throwingFunction() { - try (var arena = new ConfinedSwiftMemorySession(Thread.currentThread())) { + try (var arena = new ConfinedSwiftMemorySession()) { MySwiftClass c = MySwiftClass.init(20, 10, arena); Exception exception = assertThrows(Exception.class, () -> c.throwingFunction()); assertEquals("swiftError", exception.getMessage()); } } + + @Test + void constant() { + try (var arena = new ConfinedSwiftMemorySession()) { + MySwiftClass c = MySwiftClass.init(20, 10, arena); + assertEquals(100, c.getConstant()); + } + } + + @Test + void mutable() { + try (var arena = new ConfinedSwiftMemorySession()) { + MySwiftClass c = MySwiftClass.init(20, 10, arena); + assertEquals(0, c.getMutable()); + c.setMutable(42); + assertEquals(42, c.getMutable()); + } + } + + @Test + void product() { + try (var arena = new ConfinedSwiftMemorySession()) { + MySwiftClass c = MySwiftClass.init(20, 10, arena); + assertEquals(200, c.getProduct()); + } + } + + @Test + void throwingVariable() { + try (var arena = new ConfinedSwiftMemorySession()) { + MySwiftClass c = MySwiftClass.init(20, 10, arena); + + Exception exception = assertThrows(Exception.class, () -> c.getThrowingVariable()); + + assertEquals("swiftError", exception.getMessage()); + } + } + + @Test + void mutableDividedByTwo() { + try (var arena = new ConfinedSwiftMemorySession()) { + MySwiftClass c = MySwiftClass.init(20, 10, arena); + assertEquals(0, c.getMutableDividedByTwo()); + c.setMutable(20); + assertEquals(10, c.getMutableDividedByTwo()); + c.setMutableDividedByTwo(5); + assertEquals(10, c.getMutable()); + } + } + + @Test + void isWarm() { + try (var arena = new ConfinedSwiftMemorySession()) { + MySwiftClass c = MySwiftClass.init(20, 10, arena); + assertFalse(c.isWarm()); + } + } } \ No newline at end of file diff --git a/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/MySwiftLibraryTest.java b/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/MySwiftLibraryTest.java index f1cefd19..5c9c2358 100644 --- a/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/MySwiftLibraryTest.java +++ b/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/MySwiftLibraryTest.java @@ -54,4 +54,11 @@ void call_writeString_jextract() { assertEquals(string.length(), reply); } + + @Test + void globalVariable() { + assertEquals(0, MySwiftLibrary.getGlobalVariable()); + MySwiftLibrary.setGlobalVariable(100); + assertEquals(100, MySwiftLibrary.getGlobalVariable()); + } } \ No newline at end of file diff --git a/Sources/JExtractSwiftLib/Convenience/String+Extensions.swift b/Sources/JExtractSwiftLib/Convenience/String+Extensions.swift index 53781cef..1878ba2f 100644 --- a/Sources/JExtractSwiftLib/Convenience/String+Extensions.swift +++ b/Sources/JExtractSwiftLib/Convenience/String+Extensions.swift @@ -22,4 +22,14 @@ extension String { return "\(f.uppercased())\(String(dropFirst()))" } -} \ No newline at end of file + + /// Returns whether the string is of the format `isX` + var hasJavaBooleanNamingConvention: Bool { + guard self.hasPrefix("is"), self.count > 2 else { + return false + } + + let thirdCharacterIndex = self.index(self.startIndex, offsetBy: 2) + return self[thirdCharacterIndex].isUppercase + } +} diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift index db706a91..e548db5c 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift @@ -127,8 +127,8 @@ extension FFMSwift2JavaGenerator { // Name. let javaName = switch decl.apiKind { - case .getter: "get\(decl.name.toCamelCase)" - case .setter: "set\(decl.name.toCamelCase)" + case .getter: decl.javaGetterName + case .setter: decl.javaSetterName case .function, .initializer: decl.name } diff --git a/Sources/JExtractSwiftLib/ImportedDecls.swift b/Sources/JExtractSwiftLib/ImportedDecls.swift index 76d53d88..4b8a478a 100644 --- a/Sources/JExtractSwiftLib/ImportedDecls.swift +++ b/Sources/JExtractSwiftLib/ImportedDecls.swift @@ -154,3 +154,21 @@ extension ImportedFunc: Hashable { return lhs === rhs } } + +extension ImportedFunc { + var javaGetterName: String { + let returnsBoolean = self.functionSignature.result.type.asNominalTypeDeclaration?.knownTypeKind == .bool + + if !returnsBoolean { + return "get\(self.name.toCamelCase)" + } else if !self.name.hasJavaBooleanNamingConvention { + return "is\(self.name.toCamelCase)" + } else { + return self.name.toCamelCase + } + } + + var javaSetterName: String { + "set\(self.name.toCamelCase)" + } +} diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift index dce399a9..ec0fa9c4 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift @@ -79,6 +79,11 @@ extension JNISwift2JavaGenerator { printFunctionBinding(&printer, decl) printer.println() } + + for decl in analysis.importedGlobalVariables { + printFunctionBinding(&printer, decl) + printer.println() + } } } @@ -113,10 +118,17 @@ extension JNISwift2JavaGenerator { for initializer in decl.initializers { printInitializerBindings(&printer, initializer, type: decl) + printer.println() } for method in decl.methods { printFunctionBinding(&printer, method) + printer.println() + } + + for variable in decl.variables { + printFunctionBinding(&printer, variable) + printer.println() } printDestroyFunction(&printer, decl) diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift index f006b4a8..179991df 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift @@ -37,8 +37,15 @@ extension JNISwift2JavaGenerator { // Types with no parent will be outputted inside a "module" class. let parentName = decl.parentType?.asNominalType?.nominalTypeDecl.qualifiedName ?? swiftModuleName + // Name. + let javaName = switch decl.apiKind { + case .getter: decl.javaGetterName + case .setter: decl.javaSetterName + case .function, .initializer: decl.name + } + return TranslatedFunctionDecl( - name: decl.name, + name: javaName, parentName: parentName, translatedFunctionSignature: translatedFunctionSignature ) diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift index 24532ca1..c32e0e27 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift @@ -87,6 +87,11 @@ extension JNISwift2JavaGenerator { printSwiftFunctionThunk(&printer, decl) printer.println() } + + for decl in analysis.importedGlobalVariables { + printSwiftFunctionThunk(&printer, decl) + printer.println() + } } private func printNominalTypeThunks(_ printer: inout CodePrinter, _ type: ImportedNominalType) throws { @@ -102,6 +107,11 @@ extension JNISwift2JavaGenerator { printer.println() } + for variable in type.variables { + printSwiftFunctionThunk(&printer, variable) + printer.println() + } + printDestroyFunctionThunk(&printer, type) } @@ -192,19 +202,34 @@ extension JNISwift2JavaGenerator { let translatedDecl = self.translatedDecl(for: decl) let swiftReturnType = decl.functionSignature.result.type - let downcallParameters = renderDowncallArguments( - swiftFunctionSignature: decl.functionSignature, - translatedFunctionSignature: translatedDecl.translatedFunctionSignature - ) let tryClause: String = decl.isThrowing ? "try " : "" - let functionDowncall = "\(tryClause)\(calleeName).\(decl.name)(\(downcallParameters))" + + let result: String + switch decl.apiKind { + case .function, .initializer: + let downcallParameters = renderDowncallArguments( + swiftFunctionSignature: decl.functionSignature, + translatedFunctionSignature: translatedDecl.translatedFunctionSignature + ) + result = "\(tryClause)\(calleeName).\(decl.name)(\(downcallParameters))" + + case .getter: + result = "\(tryClause)\(calleeName).\(decl.name)" + + case .setter: + guard let newValueParameter = decl.functionSignature.parameters.first else { + fatalError("Setter did not contain newValue parameter: \(decl)") + } + + result = "\(calleeName).\(decl.name) = \(renderJNIToSwiftConversion("newValue", type: newValueParameter.type))" + } let returnStatement = if swiftReturnType.isVoid { - functionDowncall + result } else { """ - let result = \(functionDowncall) + let result = \(result) return result.getJNIValue(in: environment) """ } @@ -320,6 +345,10 @@ extension JNISwift2JavaGenerator { } .joined(separator: ", ") } + + private func renderJNIToSwiftConversion(_ variableName: String, type: SwiftType) -> String { + "\(type)(fromJNI: \(variableName), in: environment!)" + } } extension String { diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftFunctionSignature.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftFunctionSignature.swift index 8f0b3128..5cca79bf 100644 --- a/Sources/JExtractSwiftLib/SwiftTypes/SwiftFunctionSignature.swift +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftFunctionSignature.swift @@ -211,11 +211,11 @@ extension SwiftFunctionSignature { switch binding.accessorBlock?.accessors { case .getter(let getter): if let getter = getter.as(AccessorDeclSyntax.self) { - effectSpecifiers = Self.effectSpecifiers(from: getter) + effectSpecifiers = try Self.effectSpecifiers(from: getter) } case .accessors(let accessors): if let getter = accessors.first(where: { $0.accessorSpecifier.tokenKind == .keyword(.get) }) { - effectSpecifiers = Self.effectSpecifiers(from: getter) + effectSpecifiers = try Self.effectSpecifiers(from: getter) } default: break @@ -232,11 +232,14 @@ extension SwiftFunctionSignature { } } - private static func effectSpecifiers(from decl: AccessorDeclSyntax) -> [SwiftEffectSpecifier] { + private static func effectSpecifiers(from decl: AccessorDeclSyntax) throws -> [SwiftEffectSpecifier] { var effectSpecifiers = [SwiftEffectSpecifier]() if decl.effectSpecifiers?.throwsClause != nil { effectSpecifiers.append(.throws) } + if let asyncSpecifier = decl.effectSpecifiers?.asyncSpecifier { + throw SwiftFunctionTranslationError.async(asyncSpecifier) + } return effectSpecifiers } } @@ -254,7 +257,7 @@ extension VariableDeclSyntax { /// - Parameters: /// - binding the pattern binding in this declaration. func supportedAccessorKinds(binding: PatternBindingSyntax) -> SupportedAccessorKinds { - if self.bindingSpecifier == .keyword(.let) { + if self.bindingSpecifier.tokenKind == .keyword(.let) { return [.get] } diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/ConfinedSwiftMemorySession.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/ConfinedSwiftMemorySession.java index cd8f2dd1..1b6821ca 100644 --- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/ConfinedSwiftMemorySession.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/ConfinedSwiftMemorySession.java @@ -28,6 +28,10 @@ public class ConfinedSwiftMemorySession implements ClosableSwiftArena { final ConfinedResourceList resources; + public ConfinedSwiftMemorySession() { + this(Thread.currentThread()); + } + public ConfinedSwiftMemorySession(Thread owner) { this.owner = owner; this.state = new AtomicInteger(ACTIVE); diff --git a/Tests/JExtractSwiftTests/JNI/JNIVariablesTests.swift b/Tests/JExtractSwiftTests/JNI/JNIVariablesTests.swift new file mode 100644 index 00000000..f09789d4 --- /dev/null +++ b/Tests/JExtractSwiftTests/JNI/JNIVariablesTests.swift @@ -0,0 +1,386 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import JExtractSwiftLib +import Testing + +@Suite +struct JNIVariablesTests { + let membersSource = + """ + public class MyClass { + public let constant: Int64 + public var mutable: Int64 + public var computed: Int64 { + return 0 + } + public var computedThrowing: Int64 { + get throws { return 0 } + } + public var getterAndSetter: Int64 { + get { return 0 } + set { } + } + public var someBoolean: Bool + public let isBoolean: Bool + } + """ + + @Test + func constant_javaBindings() throws { + try assertOutput(input: membersSource, .jni, .java, expectedChunks: [ + """ + /** + * Downcall to Swift: + * {@snippet lang=swift : + * public let constant: Int64 + * } + */ + public long getConstant() { + long selfPointer = this.pointer(); + return MyClass.$getConstant(selfPointer); + } + """, + """ + private static native long $getConstant(long selfPointer); + """ + ]) + } + + @Test + func constant_swiftThunks() throws { + try assertOutput( + input: membersSource, + .jni, + .swift, + detectChunkByInitialLines: 1, + expectedChunks: [ + """ + @_cdecl("Java_com_example_swift_MyClass__00024getConstant__J") + func Java_com_example_swift_MyClass__00024getConstant__J(environment: UnsafeMutablePointer!, thisClass: jclass, selfPointer: jlong) -> jlong { + let self$ = UnsafeMutablePointer(bitPattern: Int(Int64(fromJNI: selfPointer, in: environment!)))! + let result = self$.pointee.constant + return result.getJNIValue(in: environment) + } + """ + ] + ) + } + + @Test + func mutable_javaBindings() throws { + try assertOutput( + input: membersSource, + .jni, + .java, + detectChunkByInitialLines: 8, + expectedChunks: [ + """ + /** + * Downcall to Swift: + * {@snippet lang=swift : + * public var mutable: Int64 + * } + */ + public long getMutable() { + long selfPointer = this.pointer(); + return MyClass.$getMutable(selfPointer); + } + """, + """ + /** + * Downcall to Swift: + * {@snippet lang=swift : + * public var mutable: Int64 + * } + */ + public void setMutable(long newValue) { + long selfPointer = this.pointer(); + MyClass.$setMutable(newValue, selfPointer); + } + """, + """ + private static native long $getMutable(long selfPointer); + """, + """ + private static native void $setMutable(long newValue, long selfPointer); + """ + ] + ) + } + + @Test + func mutable_swiftThunks() throws { + try assertOutput( + input: membersSource, + .jni, + .swift, + detectChunkByInitialLines: 1, + expectedChunks: [ + """ + @_cdecl("Java_com_example_swift_MyClass__00024getMutable__J") + func Java_com_example_swift_MyClass__00024getMutable__J(environment: UnsafeMutablePointer!, thisClass: jclass, selfPointer: jlong) -> jlong { + let self$ = UnsafeMutablePointer(bitPattern: Int(Int64(fromJNI: selfPointer, in: environment!)))! + let result = self$.pointee.mutable + return result.getJNIValue(in: environment) + } + """, + """ + @_cdecl("Java_com_example_swift_MyClass__00024setMutable__JJ") + func Java_com_example_swift_MyClass__00024setMutable__JJ(environment: UnsafeMutablePointer!, thisClass: jclass, newValue: jlong, selfPointer: jlong) { + let self$ = UnsafeMutablePointer(bitPattern: Int(Int64(fromJNI: selfPointer, in: environment!)))! + self$.pointee.mutable = Int64(fromJNI: newValue, in: environment!) + } + """ + ] + ) + } + + @Test + func computed_javaBindings() throws { + try assertOutput( + input: membersSource, + .jni, + .java, + detectChunkByInitialLines: 8, + expectedChunks: [ + """ + /** + * Downcall to Swift: + * {@snippet lang=swift : + * public var computed: Int64 + * } + */ + public long getComputed() { + long selfPointer = this.pointer(); + return MyClass.$getComputed(selfPointer); + } + """, + """ + private static native long $getComputed(long selfPointer); + """, + ] + ) + } + + @Test + func computed_swiftThunks() throws { + try assertOutput( + input: membersSource, + .jni, + .swift, + detectChunkByInitialLines: 1, + expectedChunks: [ + """ + @_cdecl("Java_com_example_swift_MyClass__00024getComputed__J") + func Java_com_example_swift_MyClass__00024getComputed__J(environment: UnsafeMutablePointer!, thisClass: jclass, selfPointer: jlong) -> jlong { + let self$ = UnsafeMutablePointer(bitPattern: Int(Int64(fromJNI: selfPointer, in: environment!)))! + let result = self$.pointee.computed + return result.getJNIValue(in: environment) + } + """, + ] + ) + } + + @Test + func computedThrowing_javaBindings() throws { + try assertOutput( + input: membersSource, + .jni, + .java, + detectChunkByInitialLines: 8, + expectedChunks: [ + """ + /** + * Downcall to Swift: + * {@snippet lang=swift : + * public var computedThrowing: Int64 + * } + */ + public long getComputedThrowing() throws Exception { + long selfPointer = this.pointer(); + return MyClass.$getComputedThrowing(selfPointer); + } + """, + """ + private static native long $getComputedThrowing(long selfPointer); + """, + ] + ) + } + + @Test + func computedThrowing_swiftThunks() throws { + try assertOutput( + input: membersSource, + .jni, + .swift, + detectChunkByInitialLines: 1, + expectedChunks: [ + """ + @_cdecl("Java_com_example_swift_MyClass__00024getComputedThrowing__J") + func Java_com_example_swift_MyClass__00024getComputedThrowing__J(environment: UnsafeMutablePointer!, thisClass: jclass, selfPointer: jlong) -> jlong { + let self$ = UnsafeMutablePointer(bitPattern: Int(Int64(fromJNI: selfPointer, in: environment!)))! + do { + let result = try self$.pointee.computedThrowing + return result.getJNIValue(in: environment) + } catch { + environment.throwAsException(error) + return Int64.jniPlaceholderValue + } + } + """, + ] + ) + } + + @Test + func getterAndSetter_javaBindings() throws { + try assertOutput( + input: membersSource, + .jni, + .java, + detectChunkByInitialLines: 8, + expectedChunks: [ + """ + /** + * Downcall to Swift: + * {@snippet lang=swift : + * public var getterAndSetter: Int64 + * } + */ + public long getGetterAndSetter() { + long selfPointer = this.pointer(); + return MyClass.$getGetterAndSetter(selfPointer); + } + """, + """ + /** + * Downcall to Swift: + * {@snippet lang=swift : + * public var getterAndSetter: Int64 + * } + */ + public void setGetterAndSetter(long newValue) { + long selfPointer = this.pointer(); + MyClass.$setGetterAndSetter(newValue, selfPointer); + } + """, + """ + private static native long $getGetterAndSetter(long selfPointer); + """, + """ + private static native void $setGetterAndSetter(long newValue, long selfPointer); + """ + ] + ) + } + + @Test + func getterAndSetter_swiftThunks() throws { + try assertOutput( + input: membersSource, + .jni, + .swift, + detectChunkByInitialLines: 1, + expectedChunks: [ + """ + @_cdecl("Java_com_example_swift_MyClass__00024getGetterAndSetter__J") + func Java_com_example_swift_MyClass__00024getGetterAndSetter__J(environment: UnsafeMutablePointer!, thisClass: jclass, selfPointer: jlong) -> jlong { + let self$ = UnsafeMutablePointer(bitPattern: Int(Int64(fromJNI: selfPointer, in: environment!)))! + let result = self$.pointee.getterAndSetter + return result.getJNIValue(in: environment) + } + """, + """ + @_cdecl("Java_com_example_swift_MyClass__00024setGetterAndSetter__JJ") + func Java_com_example_swift_MyClass__00024setGetterAndSetter__JJ(environment: UnsafeMutablePointer!, thisClass: jclass, newValue: jlong, selfPointer: jlong) { + let self$ = UnsafeMutablePointer(bitPattern: Int(Int64(fromJNI: selfPointer, in: environment!)))! + self$.pointee.getterAndSetter = Int64(fromJNI: newValue, in: environment!) + } + """ + ] + ) + } + + @Test + func someBoolean_javaBindings() throws { + try assertOutput( + input: membersSource, + .jni, + .java, + detectChunkByInitialLines: 8, + expectedChunks: [ + """ + /** + * Downcall to Swift: + * {@snippet lang=swift : + * public var someBoolean: Bool + * } + */ + public boolean isSomeBoolean() { + long selfPointer = this.pointer(); + return MyClass.$isSomeBoolean(selfPointer); + } + """, + """ + /** + * Downcall to Swift: + * {@snippet lang=swift : + * public var someBoolean: Bool + * } + */ + public void setSomeBoolean(boolean newValue) { + long selfPointer = this.pointer(); + MyClass.$setSomeBoolean(newValue, selfPointer); + } + """, + """ + private static native boolean $isSomeBoolean(long selfPointer); + """, + """ + private static native void $setSomeBoolean(boolean newValue, long selfPointer); + """ + ] + ) + } + + @Test + func boolean_swiftThunks() throws { + try assertOutput( + input: membersSource, + .jni, + .swift, + detectChunkByInitialLines: 1, + expectedChunks: [ + """ + @_cdecl("Java_com_example_swift_MyClass__00024isSomeBoolean__J") + func Java_com_example_swift_MyClass__00024isSomeBoolean__J(environment: UnsafeMutablePointer!, thisClass: jclass, selfPointer: jlong) -> jboolean { + let self$ = UnsafeMutablePointer(bitPattern: Int(Int64(fromJNI: selfPointer, in: environment!)))! + let result = self$.pointee.someBoolean + return result.getJNIValue(in: environment) + } + """, + """ + @_cdecl("Java_com_example_swift_MyClass__00024setSomeBoolean__ZJ") + func Java_com_example_swift_MyClass__00024setSomeBoolean__ZJ(environment: UnsafeMutablePointer!, thisClass: jclass, newValue: jboolean, selfPointer: jlong) { + let self$ = UnsafeMutablePointer(bitPattern: Int(Int64(fromJNI: selfPointer, in: environment!)))! + self$.pointee.someBoolean = Bool(fromJNI: newValue, in: environment!) + } + """ + ] + ) + } +} From 9c0d7ebe061ae3da75bcbd9e7208bb28f9d92507 Mon Sep 17 00:00:00 2001 From: Mads Odgaard Date: Mon, 14 Jul 2025 04:53:31 +0200 Subject: [PATCH 312/426] [JExtract/JNI] Omit unsupported types instead of crashing (#313) --- .../Sources/MySwiftLibrary/MySwiftClass.swift | 1 + .../Sources/MySwiftLibrary/MySwiftClass.swift | 1 + ...t2JavaGenerator+JavaBindingsPrinting.swift | 16 ++++++-- ...ISwift2JavaGenerator+JavaTranslation.swift | 38 ++++++++++++------- ...ift2JavaGenerator+SwiftThunkPrinting.swift | 19 ++++++++-- 5 files changed, 54 insertions(+), 21 deletions(-) diff --git a/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftClass.swift b/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftClass.swift index 386a7227..fd0ce488 100644 --- a/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftClass.swift +++ b/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftClass.swift @@ -16,6 +16,7 @@ public class MySwiftClass { let x: Int64 let y: Int64 + public let byte: UInt8 = 0 public let constant: Int64 = 100 public var mutable: Int64 = 0 public var product: Int64 { diff --git a/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftClass.swift b/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftClass.swift index 97f5149e..30661045 100644 --- a/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftClass.swift +++ b/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftClass.swift @@ -14,6 +14,7 @@ public class MySwiftClass { + public let byte: UInt8 = 0 public var len: Int public var cap: Int diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift index ec0fa9c4..80b47760 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift @@ -176,6 +176,11 @@ extension JNISwift2JavaGenerator { } private func printFunctionBinding(_ printer: inout CodePrinter, _ decl: ImportedFunc) { + guard let _ = translatedDecl(for: decl) else { + // Failed to translate. Skip. + return + } + if decl.isStatic || decl.isInitializer || !decl.hasParent { printStaticFunctionBinding(&printer, decl) } else { @@ -196,7 +201,7 @@ extension JNISwift2JavaGenerator { /// and passes it down to another native function along with the arguments /// to call the Swift implementation. private func printMemberMethodBindings(_ printer: inout CodePrinter, _ decl: ImportedFunc) { - let translatedDecl = translatedDecl(for: decl) + let translatedDecl = translatedDecl(for: decl)! // We will only call this method if we can translate the decl. printDeclDocumentation(&printer, decl) printer.printBraceBlock("public \(renderFunctionSignature(decl))") { printer in @@ -220,7 +225,10 @@ extension JNISwift2JavaGenerator { } private func printInitializerBindings(_ printer: inout CodePrinter, _ decl: ImportedFunc, type: ImportedNominalType) { - let translatedDecl = translatedDecl(for: decl) + guard let translatedDecl = translatedDecl(for: decl) else { + // Failed to translate. Skip. + return + } printDeclDocumentation(&printer, decl) printer.printBraceBlock("public static \(renderFunctionSignature(decl))") { printer in @@ -275,7 +283,9 @@ extension JNISwift2JavaGenerator { /// `func method(x: Int, y: Int) -> Int` becomes /// `long method(long x, long y)` private func renderFunctionSignature(_ decl: ImportedFunc) -> String { - let translatedDecl = translatedDecl(for: decl) + guard let translatedDecl = translatedDecl(for: decl) else { + fatalError("Unable to render function signature for a function that cannot be translated: \(decl)") + } let resultType = translatedDecl.translatedFunctionSignature.resultType var parameters = translatedDecl.translatedFunctionSignature.parameters.map(\.asParameter) diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift index 179991df..9dc433d4 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift @@ -17,13 +17,19 @@ import JavaTypes extension JNISwift2JavaGenerator { func translatedDecl( for decl: ImportedFunc - ) -> TranslatedFunctionDecl { + ) -> TranslatedFunctionDecl? { if let cached = translatedDecls[decl] { return cached } - let translation = JavaTranslation(swiftModuleName: self.swiftModuleName) - let translated = translation.translate(decl) + let translated: TranslatedFunctionDecl? + do { + let translation = JavaTranslation(swiftModuleName: swiftModuleName) + translated = try translation.translate(decl) + } catch { + self.logger.debug("Failed to translate: '\(decl.swiftDecl.qualifiedNameForDebug)'; \(error)") + translated = nil + } translatedDecls[decl] = translated return translated @@ -32,8 +38,8 @@ extension JNISwift2JavaGenerator { struct JavaTranslation { let swiftModuleName: String - func translate(_ decl: ImportedFunc) -> TranslatedFunctionDecl { - let translatedFunctionSignature = translate(functionSignature: decl.functionSignature) + func translate(_ decl: ImportedFunc) throws -> TranslatedFunctionDecl { + let translatedFunctionSignature = try translate(functionSignature: decl.functionSignature) // Types with no parent will be outputted inside a "module" class. let parentName = decl.parentType?.asNominalType?.nominalTypeDecl.qualifiedName ?? swiftModuleName @@ -51,31 +57,31 @@ extension JNISwift2JavaGenerator { ) } - func translate(functionSignature: SwiftFunctionSignature, isInitializer: Bool = false) -> TranslatedFunctionSignature { - let parameters = functionSignature.parameters.enumerated().map { idx, param in + func translate(functionSignature: SwiftFunctionSignature, isInitializer: Bool = false) throws -> TranslatedFunctionSignature { + let parameters = try functionSignature.parameters.enumerated().map { idx, param in let parameterName = param.parameterName ?? "arg\(idx))" - return translate(swiftParam: param, parameterName: parameterName) + return try translate(swiftParam: param, parameterName: parameterName) } - return TranslatedFunctionSignature( + return try TranslatedFunctionSignature( parameters: parameters, resultType: translate(swiftType: functionSignature.result.type) ) } - func translate(swiftParam: SwiftParameter, parameterName: String) -> JavaParameter { - return JavaParameter( + func translate(swiftParam: SwiftParameter, parameterName: String) throws -> JavaParameter { + return try JavaParameter( name: parameterName, type: translate(swiftType: swiftParam.type) ) } - func translate(swiftType: SwiftType) -> JavaType { + func translate(swiftType: SwiftType) throws -> JavaType { switch swiftType { case .nominal(let nominalType): if let knownType = nominalType.nominalTypeDecl.knownTypeKind { guard let javaType = translate(knownType: knownType) else { - fatalError("unsupported known type: \(knownType)") + throw JavaTranslationError.unsupportedSwiftType(swiftType) } return javaType } @@ -86,7 +92,7 @@ extension JNISwift2JavaGenerator { return .void case .metatype, .optional, .tuple, .function, .existential, .opaque: - fatalError("unsupported type: \(self)") + throw JavaTranslationError.unsupportedSwiftType(swiftType) } } @@ -127,4 +133,8 @@ extension JNISwift2JavaGenerator { let parameters: [JavaParameter] let resultType: JavaType } + + enum JavaTranslationError: Error { + case unsupportedSwiftType(SwiftType) + } } diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift index c32e0e27..30db69d1 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift @@ -116,7 +116,11 @@ extension JNISwift2JavaGenerator { } private func printInitializerThunk(_ printer: inout CodePrinter, _ decl: ImportedFunc) { - let translatedDecl = translatedDecl(for: decl) + guard let translatedDecl = translatedDecl(for: decl) else { + // Failed to translate. Skip. + return + } + let typeName = translatedDecl.parentName printCDecl( @@ -146,6 +150,11 @@ extension JNISwift2JavaGenerator { _ printer: inout CodePrinter, _ decl: ImportedFunc ) { + guard let _ = translatedDecl(for: decl) else { + // Failed to translate. Skip. + return + } + // Free functions does not have a parent if decl.isStatic || !decl.hasParent { self.printSwiftStaticFunctionThunk(&printer, decl) @@ -155,7 +164,7 @@ extension JNISwift2JavaGenerator { } private func printSwiftStaticFunctionThunk(_ printer: inout CodePrinter, _ decl: ImportedFunc) { - let translatedDecl = self.translatedDecl(for: decl) + let translatedDecl = self.translatedDecl(for: decl)! // We will only call this method if we can translate the decl. printCDecl( &printer, @@ -172,7 +181,7 @@ extension JNISwift2JavaGenerator { } private func printSwiftMemberFunctionThunk(_ printer: inout CodePrinter, _ decl: ImportedFunc) { - let translatedDecl = self.translatedDecl(for: decl) + let translatedDecl = self.translatedDecl(for: decl)! // We will only call this method if can translate the decl. let swiftParentName = decl.parentType!.asNominalTypeDeclaration!.qualifiedName printCDecl( @@ -199,7 +208,9 @@ extension JNISwift2JavaGenerator { _ decl: ImportedFunc, calleeName: String ) { - let translatedDecl = self.translatedDecl(for: decl) + guard let translatedDecl = self.translatedDecl(for: decl) else { + fatalError("Cannot print function downcall for a function that can't be translated: \(decl)") + } let swiftReturnType = decl.functionSignature.result.type let tryClause: String = decl.isThrowing ? "try " : "" From 5ed029daa1a3567b662a769edf18aa74f8631822 Mon Sep 17 00:00:00 2001 From: Alsey Coleman Miller Date: Mon, 14 Jul 2025 02:35:22 -0400 Subject: [PATCH 313/426] [JavaKit] Don't include JVM path for Android (#309) --- Package.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Package.swift b/Package.swift index 403617da..81d53b1d 100644 --- a/Package.swift +++ b/Package.swift @@ -226,7 +226,7 @@ let package = Package( exclude: ["swift-java.config"], swiftSettings: [ .swiftLanguageMode(.v5), - .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) + .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"], .when(platforms: [.macOS, .linux, .windows])) ], linkerSettings: [ .unsafeFlags( From 3b63202effbb2fdc4a1705dc20b1369c2d235791 Mon Sep 17 00:00:00 2001 From: Mads Odgaard Date: Tue, 15 Jul 2025 08:49:47 +0200 Subject: [PATCH 314/426] add struct tests (#316) --- .../MySwiftLibrary/MySwiftStruct.swift | 33 +++ .../com/example/swift/HelloJava2SwiftJNI.java | 6 + .../com/example/swift/MySwiftStructTest.java | 50 +++++ .../JNI/JNIStructTests.swift | 188 ++++++++++++++++++ 4 files changed, 277 insertions(+) create mode 100644 Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftStruct.swift create mode 100644 Samples/JExtractJNISampleApp/src/test/java/com/example/swift/MySwiftStructTest.java create mode 100644 Tests/JExtractSwiftTests/JNI/JNIStructTests.swift diff --git a/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftStruct.swift b/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftStruct.swift new file mode 100644 index 00000000..00e2533c --- /dev/null +++ b/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftStruct.swift @@ -0,0 +1,33 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +public struct MySwiftStruct { + private var cap: Int64 + public var len: Int64 + + public init(cap: Int64, len: Int64) { + self.cap = cap + self.len = len + } + + public func getCapacity() -> Int64 { + self.cap + } + + public mutating func increaseCap(by value: Int64) -> Int64 { + precondition(value > 0) + self.cap += value + return self.cap + } +} diff --git a/Samples/JExtractJNISampleApp/src/main/java/com/example/swift/HelloJava2SwiftJNI.java b/Samples/JExtractJNISampleApp/src/main/java/com/example/swift/HelloJava2SwiftJNI.java index 8e7ca284..21cad317 100644 --- a/Samples/JExtractJNISampleApp/src/main/java/com/example/swift/HelloJava2SwiftJNI.java +++ b/Samples/JExtractJNISampleApp/src/main/java/com/example/swift/HelloJava2SwiftJNI.java @@ -52,6 +52,12 @@ static void examples() { } catch (Exception e) { System.out.println("Caught exception: " + e.getMessage()); } + + MySwiftStruct myStruct = MySwiftStruct.init(12, 34, arena); + System.out.println("myStruct.cap: " + myStruct.getCapacity()); + System.out.println("myStruct.len: " + myStruct.getLen()); + myStruct.increaseCap(10); + System.out.println("myStruct.cap after increase: " + myStruct.getCapacity()); } System.out.println("DONE."); diff --git a/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/MySwiftStructTest.java b/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/MySwiftStructTest.java new file mode 100644 index 00000000..9eeaf029 --- /dev/null +++ b/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/MySwiftStructTest.java @@ -0,0 +1,50 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package com.example.swift; + +import org.junit.jupiter.api.Test; +import org.swift.swiftkit.core.ConfinedSwiftMemorySession; + +import static org.junit.jupiter.api.Assertions.*; + +public class MySwiftStructTest { + @Test + void init() { + try (var arena = new ConfinedSwiftMemorySession()) { + MySwiftStruct s = MySwiftStruct.init(1337, 42, arena); + assertEquals(1337, s.getCapacity()); + assertEquals(42, s.getLen()); + } + } + + @Test + void getAndSetLen() { + try (var arena = new ConfinedSwiftMemorySession()) { + MySwiftStruct s = MySwiftStruct.init(1337, 42, arena); + s.setLen(100); + assertEquals(100, s.getLen()); + } + } + + @Test + void increaseCap() { + try (var arena = new ConfinedSwiftMemorySession()) { + MySwiftStruct s = MySwiftStruct.init(1337, 42, arena); + long newCap = s.increaseCap(10); + assertEquals(1347, newCap); + assertEquals(1347, s.getCapacity()); + } + } +} \ No newline at end of file diff --git a/Tests/JExtractSwiftTests/JNI/JNIStructTests.swift b/Tests/JExtractSwiftTests/JNI/JNIStructTests.swift new file mode 100644 index 00000000..0a883ed1 --- /dev/null +++ b/Tests/JExtractSwiftTests/JNI/JNIStructTests.swift @@ -0,0 +1,188 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import JExtractSwiftLib +import Testing + +@Suite +struct JNIStructTests { + let source = """ + public struct MyStruct { + let x: Int64 + let y: Int64 + + public init(x: Int64, y: Int64) { + self.x = y + self.y = y + } + + public func doSomething(x: Int64) {} + } + """ + + @Test + func generatesJavaClass() throws { + try assertOutput(input: source, .jni, .java, expectedChunks: [ + """ + // Generated by jextract-swift + // Swift module: SwiftModule + + package com.example.swift; + + import org.swift.swiftkit.core.*; + import org.swift.swiftkit.core.util.*; + + public final class MyStruct extends JNISwiftInstance { + static final String LIB_NAME = "SwiftModule"; + + @SuppressWarnings("unused") + private static final boolean INITIALIZED_LIBS = initializeLibs(); + static boolean initializeLibs() { + System.loadLibrary(LIB_NAME); + return true; + } + + public MyStruct(long selfPointer, SwiftArena swiftArena) { + super(selfPointer, swiftArena); + } + """, + """ + private static native void $destroy(long selfPointer); + """, + """ + @Override + protected Runnable $createDestroyFunction() { + long $selfPointer = this.pointer(); + return new Runnable() { + @Override + public void run() { + MyStruct.$destroy($selfPointer); + } + }; + } + """ + ]) + } + + @Test + func initializer_javaBindings() throws { + try assertOutput( + input: source, + .jni, + .java, + expectedChunks: [ + """ + /** + * Downcall to Swift: + * {@snippet lang=swift : + * public init(x: Int64, y: Int64) + * } + */ + public static MyStruct init(long x, long y, SwiftArena swiftArena$) { + long selfPointer = MyStruct.allocatingInit(x, y); + return new MyStruct(selfPointer, swiftArena$); + } + """, + """ + private static native long allocatingInit(long x, long y); + """, + ] + ) + } + + @Test + func initializer_swiftThunks() throws { + try assertOutput( + input: source, + .jni, + .swift, + detectChunkByInitialLines: 1, + expectedChunks: [ + """ + @_cdecl("Java_com_example_swift_MyStruct_allocatingInit__JJ") + func Java_com_example_swift_MyStruct_allocatingInit__JJ(environment: UnsafeMutablePointer!, thisClass: jclass, x: jlong, y: jlong) -> jlong { + let selfPointer = UnsafeMutablePointer.allocate(capacity: 1) + selfPointer.initialize(to: MyStruct(x: Int64(fromJNI: x, in: environment!), y: Int64(fromJNI: y, in: environment!))) + return Int64(Int(bitPattern: selfPointer)).getJNIValue(in: environment) + } + """ + ] + ) + } + + @Test + func destroyFunction_swiftThunks() throws { + try assertOutput( + input: source, + .jni, + .swift, + detectChunkByInitialLines: 1, + expectedChunks: [ + """ + @_cdecl("Java_com_example_swift_MyStruct__00024destroy__J") + func Java_com_example_swift_MyStruct__00024destroy__J(environment: UnsafeMutablePointer!, thisClass: jclass, selfPointer: jlong) { + let pointer = UnsafeMutablePointer(bitPattern: Int(Int64(fromJNI: selfPointer, in: environment!)))! + pointer.deinitialize(count: 1) + pointer.deallocate() + } + """ + ] + ) + } + + @Test + func memberMethod_javaBindings() throws { + try assertOutput( + input: source, + .jni, + .java, + expectedChunks: [ + """ + /** + * Downcall to Swift: + * {@snippet lang=swift : + * public func doSomething(x: Int64) + * } + */ + public void doSomething(long x) { + long selfPointer = this.pointer(); + MyStruct.$doSomething(x, selfPointer); + } + """, + """ + private static native void $doSomething(long x, long selfPointer); + """ + ] + ) + } + + @Test + func memberMethod_swiftThunks() throws { + try assertOutput( + input: source, + .jni, + .swift, + detectChunkByInitialLines: 1, + expectedChunks: [ + """ + @_cdecl("Java_com_example_swift_MyStruct__00024doSomething__JJ") + func Java_com_example_swift_MyStruct__00024doSomething__JJ(environment: UnsafeMutablePointer!, thisClass: jclass, x: jlong, selfPointer: jlong) { + let self$ = UnsafeMutablePointer(bitPattern: Int(Int64(fromJNI: selfPointer, in: environment!)))! + self$.pointee.doSomething(x: Int64(fromJNI: x, in: environment!)) + } + """, + ] + ) + } +} From 78b3e200e2946d70c840a38353c505f92fcfc960 Mon Sep 17 00:00:00 2001 From: Mads Odgaard Date: Tue, 15 Jul 2025 08:52:03 +0200 Subject: [PATCH 315/426] conform `Int` to `JavaValue` (#317) --- .../BridgedValues/JavaValue+Integers.swift | 119 ++++++++++++++++++ 1 file changed, 119 insertions(+) diff --git a/Sources/JavaKit/BridgedValues/JavaValue+Integers.swift b/Sources/JavaKit/BridgedValues/JavaValue+Integers.swift index 01a7bdba..1af1b549 100644 --- a/Sources/JavaKit/BridgedValues/JavaValue+Integers.swift +++ b/Sources/JavaKit/BridgedValues/JavaValue+Integers.swift @@ -285,3 +285,122 @@ extension Int64: JavaValue { 0 } } + +#if _pointerBitWidth(_32) +extension Int: JavaValue { + + public typealias JNIType = jint + + public static var jvalueKeyPath: WritableKeyPath { \.i } + + public func getJNIValue(in environment: JNIEnvironment) -> JNIType { JNIType(self) } + + public init(fromJNI value: JNIType, in environment: JNIEnvironment) { + self = Int(value) + } + + public static var javaType: JavaType { .int } + + public static func jniMethodCall( + in environment: JNIEnvironment + ) -> ((JNIEnvironment, jobject, jmethodID, UnsafePointer?) -> JNIType) { + environment.interface.CallIntMethodA + } + + public static func jniFieldGet(in environment: JNIEnvironment) -> JNIFieldGet { + environment.interface.GetIntField + } + + public static func jniFieldSet(in environment: JNIEnvironment) -> JNIFieldSet { + environment.interface.SetIntField + } + + public static func jniStaticMethodCall( + in environment: JNIEnvironment + ) -> ((JNIEnvironment, jobject, jmethodID, UnsafePointer?) -> JNIType) { + environment.interface.CallStaticIntMethodA + } + + public static func jniStaticFieldGet(in environment: JNIEnvironment) -> JNIStaticFieldGet { + environment.interface.GetStaticIntField + } + + public static func jniStaticFieldSet(in environment: JNIEnvironment) -> JNIStaticFieldSet { + environment.interface.SetStaticIntField + } + + public static func jniNewArray(in environment: JNIEnvironment) -> JNINewArray { + environment.interface.NewIntArray + } + + public static func jniGetArrayRegion(in environment: JNIEnvironment) -> JNIGetArrayRegion { + environment.interface.GetIntArrayRegion + } + + public static func jniSetArrayRegion(in environment: JNIEnvironment) -> JNISetArrayRegion { + environment.interface.SetIntArrayRegion + } + + public static var jniPlaceholderValue: jint { + 0 + } +} +#elseif _pointerBitWidth(_64) +extension Int: JavaValue { + public typealias JNIType = jlong + + public static var jvalueKeyPath: WritableKeyPath { \.j } + + public func getJNIValue(in environment: JNIEnvironment) -> JNIType { JNIType(self) } + + public init(fromJNI value: JNIType, in environment: JNIEnvironment) { + self = Int(value) + } + + public static var javaType: JavaType { .long } + + public static func jniMethodCall( + in environment: JNIEnvironment + ) -> ((JNIEnvironment, jobject, jmethodID, UnsafePointer?) -> JNIType) { + environment.interface.CallLongMethodA + } + + public static func jniFieldGet(in environment: JNIEnvironment) -> JNIFieldGet { + environment.interface.GetLongField + } + + public static func jniFieldSet(in environment: JNIEnvironment) -> JNIFieldSet { + environment.interface.SetLongField + } + + public static func jniStaticMethodCall( + in environment: JNIEnvironment + ) -> ((JNIEnvironment, jobject, jmethodID, UnsafePointer?) -> JNIType) { + environment.interface.CallStaticLongMethodA + } + + public static func jniStaticFieldGet(in environment: JNIEnvironment) -> JNIStaticFieldGet { + environment.interface.GetStaticLongField + } + + public static func jniStaticFieldSet(in environment: JNIEnvironment) -> JNIStaticFieldSet { + environment.interface.SetStaticLongField + } + + public static func jniNewArray(in environment: JNIEnvironment) -> JNINewArray { + environment.interface.NewLongArray + } + + public static func jniGetArrayRegion(in environment: JNIEnvironment) -> JNIGetArrayRegion { + environment.interface.GetLongArrayRegion + } + + public static func jniSetArrayRegion(in environment: JNIEnvironment) -> JNISetArrayRegion { + environment.interface.SetLongArrayRegion + } + + public static var jniPlaceholderValue: jlong { + 0 + } +} +#endif From 19a67851589ea61e46768e90b4ec878c28052eed Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Tue, 15 Jul 2025 17:33:07 -0700 Subject: [PATCH 316/426] [JExtract/FFM] Bridge Optional parameters (#320) --- .../MySwiftLibrary/MySwiftLibrary.swift | 17 ++ .../com/example/swift/HelloJava2Swift.java | 4 + .../com/example/swift/OptionalImportTest.java | 35 ++++ .../FFM/CDeclLowering/CRepresentation.swift | 2 +- ...Swift2JavaGenerator+FunctionLowering.swift | 91 +++++++++- .../JExtractSwiftLib/FFM/ConversionStep.swift | 8 +- ...MSwift2JavaGenerator+JavaTranslation.swift | 85 +++++++++- .../FFM/FFMSwift2JavaGenerator.swift | 4 +- ...ISwift2JavaGenerator+JavaTranslation.swift | 2 +- .../SwiftTypes/SwiftKnownModules.swift | 2 + .../SwiftTypes/SwiftKnownTypeDecls.swift | 1 + .../org/swift/swiftkit/ffm/SwiftRuntime.java | 40 ++++- .../FunctionLoweringTests.swift | 21 +++ .../OptionalImportTests.swift | 156 ++++++++++++++++++ 14 files changed, 449 insertions(+), 19 deletions(-) create mode 100644 Samples/SwiftKitSampleApp/src/test/java/com/example/swift/OptionalImportTest.java create mode 100644 Tests/JExtractSwiftTests/OptionalImportTests.swift diff --git a/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift b/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift index 1bcca4fd..cdd61c12 100644 --- a/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift +++ b/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift @@ -68,6 +68,23 @@ public func globalReceiveSomeDataProtocol(data: some DataProtocol) -> Int { return data.count } +public func globalReceiveOptional(o1: Int?, o2: (some DataProtocol)?) -> Int { + switch (o1, o2) { + case (nil, nil): + p(", ") + return 0 + case (let v1?, nil): + p("\(v1), ") + return 1 + case (nil, let v2?): + p(", \(v2)") + return 2 + case (let v1?, let v2?): + p("\(v1), \(v2)") + return 3 + } +} + // ==== Internal helpers func p(_ msg: String, file: String = #fileID, line: UInt = #line, function: String = #function) { diff --git a/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java b/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java index 821b228e..3b083cc0 100644 --- a/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java +++ b/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java @@ -22,6 +22,9 @@ import org.swift.swiftkit.ffm.AllocatingSwiftArena; import org.swift.swiftkit.ffm.SwiftRuntime; +import java.util.Optional; +import java.util.OptionalLong; + public class HelloJava2Swift { public static void main(String[] args) { @@ -95,6 +98,7 @@ static void examples() { var bytes = arena.allocateFrom("hello"); var dat = Data.init(bytes, bytes.byteSize(), arena); MySwiftLibrary.globalReceiveSomeDataProtocol(dat); + MySwiftLibrary.globalReceiveOptional(OptionalLong.of(12), Optional.of(dat)); } diff --git a/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/OptionalImportTest.java b/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/OptionalImportTest.java new file mode 100644 index 00000000..57e8dba6 --- /dev/null +++ b/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/OptionalImportTest.java @@ -0,0 +1,35 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package com.example.swift; + +import org.junit.jupiter.api.Test; +import org.swift.swiftkit.ffm.AllocatingSwiftArena; + +import java.util.Optional; +import java.util.OptionalLong; + +import static org.junit.jupiter.api.Assertions.*; + +public class OptionalImportTest { + @Test + void test_Optional_receive() { + try (var arena = AllocatingSwiftArena.ofConfined()) { + var origBytes = arena.allocateFrom("foobar"); + var data = Data.init(origBytes, origBytes.byteSize(), arena); + assertEquals(0, MySwiftLibrary.globalReceiveOptional(OptionalLong.empty(), Optional.empty())); + assertEquals(3, MySwiftLibrary.globalReceiveOptional(OptionalLong.of(12), Optional.of(data))); + } + } +} diff --git a/Sources/JExtractSwiftLib/FFM/CDeclLowering/CRepresentation.swift b/Sources/JExtractSwiftLib/FFM/CDeclLowering/CRepresentation.swift index 4e44e74b..c2bb53ab 100644 --- a/Sources/JExtractSwiftLib/FFM/CDeclLowering/CRepresentation.swift +++ b/Sources/JExtractSwiftLib/FFM/CDeclLowering/CRepresentation.swift @@ -125,7 +125,7 @@ extension SwiftKnownTypeDeclKind { .qualified(const: true, volatile: false, type: .void) ) case .void: .void - case .unsafePointer, .unsafeMutablePointer, .unsafeRawBufferPointer, .unsafeMutableRawBufferPointer, .unsafeBufferPointer, .unsafeMutableBufferPointer, .string, .data, .dataProtocol: + case .unsafePointer, .unsafeMutablePointer, .unsafeRawBufferPointer, .unsafeMutableRawBufferPointer, .unsafeBufferPointer, .unsafeMutableBufferPointer, .string, .data, .dataProtocol, .optional: nil } } diff --git a/Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift b/Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift index 0c6c707c..bb994164 100644 --- a/Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift +++ b/Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift @@ -194,7 +194,7 @@ struct CdeclLowering { ) case .unsafeBufferPointer, .unsafeMutableBufferPointer: - guard let genericArgs = type.asNominalType?.genericArguments, genericArgs.count == 1 else { + guard let genericArgs = nominal.genericArguments, genericArgs.count == 1 else { throw LoweringError.unhandledType(type) } // Typed pointers are lowered to (raw-pointer, count) pair. @@ -253,6 +253,12 @@ struct CdeclLowering { ] )) + case .optional: + guard let genericArgs = nominal.genericArguments, genericArgs.count == 1 else { + throw LoweringError.unhandledType(type) + } + return try lowerOptionalParameter(genericArgs[0], convention: convention, parameterName: parameterName) + case .string: // 'String' is passed in by C string. i.e. 'UnsafePointer' ('const uint8_t *') if knownType == .string { @@ -336,8 +342,79 @@ struct CdeclLowering { } throw LoweringError.unhandledType(type) - case .optional: - throw LoweringError.unhandledType(type) + case .optional(let wrapped): + return try lowerOptionalParameter(wrapped, convention: convention, parameterName: parameterName) + } + } + + /// Lower a Swift Optional to cdecl function type. + /// + /// - Parameters: + /// - fn: the Swift function type to lower. + func lowerOptionalParameter( + _ wrappedType: SwiftType, + convention: SwiftParameterConvention, + parameterName: String + ) throws -> LoweredParameter { + // If there is a 1:1 mapping between this Swift type and a C type, lower it to 'UnsafePointer?' + if let _ = try? CType(cdeclType: wrappedType) { + return LoweredParameter( + cdeclParameters: [ + SwiftParameter(convention: .byValue, parameterName: parameterName, type: .optional(knownTypes.unsafePointer(wrappedType))) + ], + conversion: .pointee(.optionalChain(.placeholder)) + ) + } + + switch wrappedType { + case .nominal(let nominal): + if let knownType = nominal.nominalTypeDecl.knownTypeKind { + switch knownType { + case .data: + break + case .unsafeRawPointer, .unsafeMutableRawPointer: + throw LoweringError.unhandledType(.optional(wrappedType)) + case .unsafeRawBufferPointer, .unsafeMutableRawBufferPointer: + throw LoweringError.unhandledType(.optional(wrappedType)) + case .unsafePointer, .unsafeMutablePointer: + throw LoweringError.unhandledType(.optional(wrappedType)) + case .unsafeBufferPointer, .unsafeMutableBufferPointer: + throw LoweringError.unhandledType(.optional(wrappedType)) + case .void, .string: + throw LoweringError.unhandledType(.optional(wrappedType)) + case .dataProtocol: + throw LoweringError.unhandledType(.optional(wrappedType)) + default: + // Unreachable? Should be handled by `CType(cdeclType:)` lowering above. + throw LoweringError.unhandledType(.optional(wrappedType)) + } + } + + // Lower arbitrary nominal to `UnsafeRawPointer?` + return LoweredParameter( + cdeclParameters: [ + SwiftParameter(convention: .byValue, parameterName: parameterName, type: .optional(knownTypes.unsafeRawPointer)) + ], + conversion: .pointee(.typedPointer(.optionalChain(.placeholder), swiftType: wrappedType)) + ) + + case .existential(let proto), .opaque(let proto): + if + let knownProtocol = proto.asNominalTypeDeclaration?.knownTypeKind, + let concreteTy = knownTypes.representativeType(of: knownProtocol) + { + return try lowerOptionalParameter(concreteTy, convention: convention, parameterName: parameterName) + } + throw LoweringError.unhandledType(.optional(wrappedType)) + + case .tuple(let tuple): + if tuple.count == 1 { + return try lowerOptionalParameter(tuple[0], convention: convention, parameterName: parameterName) + } + throw LoweringError.unhandledType(.optional(wrappedType)) + + case .function, .metatype, .optional: + throw LoweringError.unhandledType(.optional(wrappedType)) } } @@ -527,13 +604,13 @@ struct CdeclLowering { case .void: return LoweredResult(cdeclResultType: .void, cdeclOutParameters: [], conversion: .placeholder) - case .string: - // Returning string is not supported at this point. - throw LoweringError.unhandledType(type) - case .data: break + case .string, .optional: + // Not supported at this point. + throw LoweringError.unhandledType(type) + default: // Unreachable? Should be handled by `CType(cdeclType:)` lowering above. throw LoweringError.unhandledType(type) diff --git a/Sources/JExtractSwiftLib/FFM/ConversionStep.swift b/Sources/JExtractSwiftLib/FFM/ConversionStep.swift index c7fa53e3..656d9dd9 100644 --- a/Sources/JExtractSwiftLib/FFM/ConversionStep.swift +++ b/Sources/JExtractSwiftLib/FFM/ConversionStep.swift @@ -62,6 +62,8 @@ enum ConversionStep: Equatable { indirect case member(ConversionStep, member: String) + indirect case optionalChain(ConversionStep) + /// Count the number of times that the placeholder occurs within this /// conversion step. var placeholderCount: Int { @@ -71,7 +73,7 @@ enum ConversionStep: Equatable { .typedPointer(let inner, swiftType: _), .unsafeCastPointer(let inner, swiftType: _), .populatePointer(name: _, assumingType: _, to: let inner), - .member(let inner, member: _): + .member(let inner, member: _), .optionalChain(let inner): inner.placeholderCount case .initialize(_, arguments: let arguments): arguments.reduce(0) { $0 + $1.argument.placeholderCount } @@ -175,6 +177,10 @@ enum ConversionStep: Equatable { } return nil + case .optionalChain(let step): + let inner = step.asExprSyntax(placeholder: placeholder, bodyItems: &bodyItems) + return ExprSyntax(OptionalChainingExprSyntax(expression: inner!)) + case .closureLowering(let parameterSteps, let resultStep): var body: [CodeBlockItemSyntax] = [] diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift index e548db5c..9f658188 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift @@ -238,7 +238,6 @@ extension FFMSwift2JavaGenerator { throw JavaTranslationError.unhandledType(type) } - /// Translate a Swift API signature to the user-facing Java API signature. /// /// Note that the result signature is for the high-level Java API, not the @@ -349,6 +348,12 @@ extension FFMSwift2JavaGenerator { ]) ) + case .optional: + guard let genericArgs = swiftNominalType.genericArguments, genericArgs.count == 1 else { + throw JavaTranslationError.unhandledType(swiftType) + } + return try translateOptionalParameter(wrappedType: genericArgs[0], convention: convention, parameterName: parameterName, loweredParam: loweredParam, methodName: methodName) + case .string: return TranslatedParameter( javaParameters: [ @@ -414,8 +419,81 @@ extension FFMSwift2JavaGenerator { // Otherwise, not supported yet. throw JavaTranslationError.unhandledType(swiftType) - case .optional: - throw JavaTranslationError.unhandledType(swiftType) + case .optional(let wrapped): + return try translateOptionalParameter(wrappedType: wrapped, convention: convention, parameterName: parameterName, loweredParam: loweredParam, methodName: methodName) + } + } + + /// Translate an Optional Swift API parameter to the user-facing Java API parameter. + func translateOptionalParameter( + wrappedType swiftType: SwiftType, + convention: SwiftParameterConvention, + parameterName: String, + loweredParam: LoweredParameter, + methodName: String + ) throws -> TranslatedParameter { + // If there is a 1:1 mapping between this Swift type and a C type, that can + // be expressed as a Java primitive type. + if let cType = try? CType(cdeclType: swiftType) { + var (translatedClass, lowerFunc) = switch cType.javaType { + case .int: ("OptionalInt", "toOptionalSegmentInt") + case .long: ("OptionalLong", "toOptionalSegmentLong") + case .double: ("OptionalDouble", "toOptionalSegmentDouble") + case .boolean: ("Optional", "toOptionalSegmentBoolean") + case .byte: ("Optional", "toOptionalSegmentByte") + case .char: ("Optional", "toOptionalSegmentCharacter") + case .short: ("Optional", "toOptionalSegmentShort") + case .float: ("Optional", "toOptionalSegmentFloat") + default: + throw JavaTranslationError.unhandledType(.optional(swiftType)) + } + return TranslatedParameter( + javaParameters: [ + JavaParameter(name: parameterName, type: JavaType(className: translatedClass)) + ], + conversion: .call(.placeholder, function: "SwiftRuntime.\(lowerFunc)", withArena: true) + ) + } + + switch swiftType { + case .nominal(let nominal): + if let knownType = nominal.nominalTypeDecl.knownTypeKind { + switch knownType { + case .data, .dataProtocol: + break + default: + throw JavaTranslationError.unhandledType(.optional(swiftType)) + } + } + + let translatedTy = try self.translate(swiftType: swiftType) + return TranslatedParameter( + javaParameters: [ + JavaParameter(name: parameterName, type: JavaType(className: "Optional<\(translatedTy.description)>")) + ], + conversion: .call(.placeholder, function: "SwiftRuntime.toOptionalSegmentInstance", withArena: false) + ) + case .existential(let proto), .opaque(let proto): + if + let knownProtocol = proto.asNominalTypeDeclaration?.knownTypeKind, + let concreteTy = knownTypes.representativeType(of: knownProtocol) + { + return try translateOptionalParameter( + wrappedType: concreteTy, + convention: convention, + parameterName: parameterName, + loweredParam: loweredParam, + methodName: methodName + ) + } + throw JavaTranslationError.unhandledType(.optional(swiftType)) + case .tuple(let tuple): + if tuple.count == 1 { + return try translateOptionalParameter(wrappedType: tuple[0], convention: convention, parameterName: parameterName, loweredParam: loweredParam, methodName: methodName) + } + throw JavaTranslationError.unhandledType(.optional(swiftType)) + default: + throw JavaTranslationError.unhandledType(.optional(swiftType)) } } @@ -585,7 +663,6 @@ extension FFMSwift2JavaGenerator.TranslatedFunctionSignature { } } - extension CType { /// Map lowered C type to Java type for FFM binding. var javaType: JavaType { diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift index 6cf80d9b..a24dabb1 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift @@ -101,9 +101,7 @@ extension FFMSwift2JavaGenerator { // Necessary for native calls and type mapping "java.lang.foreign.*", "java.lang.invoke.*", - "java.util.Arrays", - "java.util.stream.Collectors", - "java.util.concurrent.atomic.*", + "java.util.*", "java.nio.charset.StandardCharsets", ] } diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift index 9dc433d4..2e3ffff8 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift @@ -112,7 +112,7 @@ extension JNISwift2JavaGenerator { .unsafeRawPointer, .unsafeMutableRawPointer, .unsafePointer, .unsafeMutablePointer, .unsafeRawBufferPointer, .unsafeMutableRawBufferPointer, - .unsafeBufferPointer, .unsafeMutableBufferPointer, .data, .dataProtocol: + .unsafeBufferPointer, .unsafeMutableBufferPointer, .optional, .data, .dataProtocol: nil } } diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownModules.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownModules.swift index 47abb7f0..938d0c4a 100644 --- a/Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownModules.swift +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownModules.swift @@ -76,6 +76,8 @@ private let swiftSourceFile: SourceFileSyntax = """ public struct UnsafeBufferPointer {} public struct UnsafeMutableBufferPointer {} + public struct Optional {} + // FIXME: Support 'typealias Void = ()' public struct Void {} diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownTypeDecls.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownTypeDecls.swift index d6af5920..11ff25c4 100644 --- a/Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownTypeDecls.swift +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownTypeDecls.swift @@ -36,6 +36,7 @@ enum SwiftKnownTypeDeclKind: String, Hashable { case unsafeMutablePointer = "Swift.UnsafeMutablePointer" case unsafeBufferPointer = "Swift.UnsafeBufferPointer" case unsafeMutableBufferPointer = "Swift.UnsafeMutableBufferPointer" + case optional = "Swift.Optional" case void = "Swift.Void" case string = "Swift.String" diff --git a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/SwiftRuntime.java b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/SwiftRuntime.java index f734bbef..dc18b445 100644 --- a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/SwiftRuntime.java +++ b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/SwiftRuntime.java @@ -14,14 +14,14 @@ package org.swift.swiftkit.ffm; +import org.swift.swiftkit.core.SwiftInstance; import org.swift.swiftkit.core.util.PlatformUtils; import java.lang.foreign.*; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.VarHandle; -import java.util.Arrays; -import java.util.Optional; +import java.util.*; import java.util.stream.Collectors; import static org.swift.swiftkit.core.util.StringUtils.stripPrefix; @@ -425,6 +425,42 @@ public static MemorySegment toCString(String str, Arena arena) { return arena.allocateFrom(str); } + public static MemorySegment toOptionalSegmentInt(OptionalInt opt, Arena arena) { + return opt.isPresent() ? arena.allocateFrom(ValueLayout.JAVA_INT, opt.getAsInt()) : MemorySegment.NULL; + } + + public static MemorySegment toOptionalSegmentLong(OptionalLong opt, Arena arena) { + return opt.isPresent() ? arena.allocateFrom(ValueLayout.JAVA_LONG, opt.getAsLong()) : MemorySegment.NULL; + } + + public static MemorySegment toOptionalSegmentDouble(OptionalDouble opt, Arena arena) { + return opt.isPresent() ? arena.allocateFrom(ValueLayout.JAVA_DOUBLE, opt.getAsDouble()) : MemorySegment.NULL; + } + + public static MemorySegment toOptionalSegmentBoolean(Optional opt, Arena arena) { + return opt.map(val -> arena.allocateFrom(ValueLayout.JAVA_BYTE, (byte) (val ? 1 : 0))).orElse(MemorySegment.NULL); + } + + public static MemorySegment toOptionalSegmentByte(Optional opt, Arena arena) { + return opt.map(val -> arena.allocateFrom(ValueLayout.JAVA_BYTE, val)).orElse(MemorySegment.NULL); + } + + public static MemorySegment toOptionalSegmentCharacter(Optional opt, Arena arena) { + return opt.map(val -> arena.allocateFrom(ValueLayout.JAVA_CHAR, val)).orElse(MemorySegment.NULL); + } + + public static MemorySegment toOptionalSegmentShort(Optional opt, Arena arena) { + return opt.map(val -> arena.allocateFrom(ValueLayout.JAVA_SHORT, val)).orElse(MemorySegment.NULL); + } + + public static MemorySegment toOptionalSegmentFloat(Optional opt, Arena arena) { + return opt.map(val -> arena.allocateFrom(ValueLayout.JAVA_FLOAT, val)).orElse(MemorySegment.NULL); + } + + public static MemorySegment toOptionalSegmentInstance(Optional opt) { + return opt.map(instance -> instance.$memorySegment()).orElse(MemorySegment.NULL); + } + private static class swift_getTypeName { /** diff --git a/Tests/JExtractSwiftTests/FunctionLoweringTests.swift b/Tests/JExtractSwiftTests/FunctionLoweringTests.swift index 9422bbdb..8419ec61 100644 --- a/Tests/JExtractSwiftTests/FunctionLoweringTests.swift +++ b/Tests/JExtractSwiftTests/FunctionLoweringTests.swift @@ -383,6 +383,27 @@ final class FunctionLoweringTests { ) } + @Test("Lowering optional primitives") + func lowerOptionalParameters() throws { + try assertLoweredFunction( + """ + func fn(a1: Optional, a2: Int?, a3: Point?, a4: (some DataProtocol)?) + """, + sourceFile: """ + import Foundation + struct Point {} + """, + expectedCDecl:""" + @_cdecl("c_fn") + public func c_fn(_ a1: UnsafePointer?, _ a2: UnsafePointer?, _ a3: UnsafeRawPointer?, _ a4: UnsafeRawPointer?) { + fn(a1: a1?.pointee, a2: a2?.pointee, a3: a3?.assumingMemoryBound(to: Point.self).pointee, a4: a4?.assumingMemoryBound(to: Data.self).pointee) + } + """, + expectedCFunction: """ + void c_fn(const ptrdiff_t *a1, const ptrdiff_t *a2, const void *a3, const void *a4) + """) + } + @Test("Lowering read accessor") func lowerGlobalReadAccessor() throws { try assertLoweredVariableAccessor( diff --git a/Tests/JExtractSwiftTests/OptionalImportTests.swift b/Tests/JExtractSwiftTests/OptionalImportTests.swift new file mode 100644 index 00000000..756bb3d9 --- /dev/null +++ b/Tests/JExtractSwiftTests/OptionalImportTests.swift @@ -0,0 +1,156 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import JExtractSwiftLib +import Testing + +final class OptionalImportTests { + let interfaceFile = + """ + import Foundation + + public func receiveOptionalIntSugar(_ arg: Int?) + public func receiveOptionalIntExplicit(_ arg: Optional) + public func receiveOptionalDataProto(_ arg: (some DataProtocol)?)) + """ + + + @Test("Import Optionals: JavaBindings") + func data_javaBindings() throws { + + try assertOutput( + input: interfaceFile, .ffm, .java, + expectedChunks: [ + """ + /** + * {@snippet lang=c : + * void swiftjava_SwiftModule_receiveOptionalIntSugar__(const ptrdiff_t *arg) + * } + */ + private static class swiftjava_SwiftModule_receiveOptionalIntSugar__ { + private static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( + /* arg: */SwiftValueLayout.SWIFT_POINTER + ); + private static final MemorySegment ADDR = + SwiftModule.findOrThrow("swiftjava_SwiftModule_receiveOptionalIntSugar__"); + private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + public static void call(java.lang.foreign.MemorySegment arg) { + try { + if (SwiftRuntime.TRACE_DOWNCALLS) { + SwiftRuntime.traceDowncall(arg); + } + HANDLE.invokeExact(arg); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + } + """, + + """ + /** + * Downcall to Swift: + * {@snippet lang=swift : + * public func receiveOptionalIntSugar(_ arg: Int?) + * } + */ + public static void receiveOptionalIntSugar(OptionalLong arg) { + try(var arena$ = Arena.ofConfined()) { + swiftjava_SwiftModule_receiveOptionalIntSugar__.call(SwiftRuntime.toOptionalSegmentLong(arg, arena$)); + } + } + """, + + """ + /** + * {@snippet lang=c : + * void swiftjava_SwiftModule_receiveOptionalIntExplicit__(const ptrdiff_t *arg) + * } + */ + private static class swiftjava_SwiftModule_receiveOptionalIntExplicit__ { + private static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( + /* arg: */SwiftValueLayout.SWIFT_POINTER + ); + private static final MemorySegment ADDR = + SwiftModule.findOrThrow("swiftjava_SwiftModule_receiveOptionalIntExplicit__"); + private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + public static void call(java.lang.foreign.MemorySegment arg) { + try { + if (SwiftRuntime.TRACE_DOWNCALLS) { + SwiftRuntime.traceDowncall(arg); + } + HANDLE.invokeExact(arg); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + } + """, + + """ + /** + * Downcall to Swift: + * {@snippet lang=swift : + * public func receiveOptionalIntExplicit(_ arg: Optional) + * } + */ + public static void receiveOptionalIntExplicit(OptionalLong arg) { + try(var arena$ = Arena.ofConfined()) { + swiftjava_SwiftModule_receiveOptionalIntExplicit__.call(SwiftRuntime.toOptionalSegmentLong(arg, arena$)); + } + } + """, + + + """ + /** + * {@snippet lang=c : + * void swiftjava_SwiftModule_receiveOptionalDataProto__(const void *arg) + * } + */ + private static class swiftjava_SwiftModule_receiveOptionalDataProto__ { + private static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( + /* arg: */SwiftValueLayout.SWIFT_POINTER + ); + private static final MemorySegment ADDR = + SwiftModule.findOrThrow("swiftjava_SwiftModule_receiveOptionalDataProto__"); + private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + public static void call(java.lang.foreign.MemorySegment arg) { + try { + if (SwiftRuntime.TRACE_DOWNCALLS) { + SwiftRuntime.traceDowncall(arg); + } + HANDLE.invokeExact(arg); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + } + """, + + """ + /** + * Downcall to Swift: + * {@snippet lang=swift : + * public func receiveOptionalDataProto(_ arg: (some DataProtocol)?) + * } + */ + public static void receiveOptionalDataProto(Optional arg) { + swiftjava_SwiftModule_receiveOptionalDataProto__.call(SwiftRuntime.toOptionalSegmentInstance(arg)); + } + """, + ] + ) + } +} From c0f166d9e1effafe850a098d56ebdd288e82e69e Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Thu, 17 Jul 2025 13:53:45 +0900 Subject: [PATCH 317/426] [SwiftKit] Move 'selfPointer' to 'JNISwiftInstance' & downcall trace logs (#322) Co-authored-by: Rintaro Ishizaki --- .../com/example/swift/HelloJava2Swift.java | 25 ++-- ...t2JavaGenerator+JavaBindingsPrinting.swift | 4 +- ...ift2JavaGenerator+SwiftThunkPrinting.swift | 1 + ...t2JavaGenerator+JavaBindingsPrinting.swift | 25 +++- ...ift2JavaGenerator+SwiftThunkPrinting.swift | 51 ++++++-- .../org/swift/swiftkit/core/CallTraces.java | 61 +++++++++ .../core/ConfinedSwiftMemorySession.java | 2 +- .../swift/swiftkit/core/JNISwiftInstance.java | 21 ++- .../swift/swiftkit/core/SwiftInstance.java | 35 ++--- .../swift/swiftkit/core/SwiftLibraries.java | 3 +- .../org/swift/swiftkit/core/SwiftObjects.java | 26 ++++ .../ffm/AllocatingAutoSwiftMemorySession.java | 2 +- .../swift/swiftkit/ffm/FFMSwiftInstance.java | 30 +++-- .../swiftkit/ffm/FFMSwiftInstanceCleanup.java | 16 +-- .../org/swift/swiftkit/ffm/SwiftRuntime.java | 40 +----- .../Asserts/TextAssertions.swift | 20 +-- .../JExtractSwiftTests/DataImportTests.swift | 26 ++-- .../FuncCallbackImportTests.swift | 12 +- .../FunctionDescriptorImportTests.swift | 20 +-- .../JNI/JNIClassTests.swift | 69 ++++++---- .../JNI/JNIStructTests.swift | 49 +++++-- .../JNI/JNIVariablesTests.swift | 121 ++++++++++++++---- .../MethodImportTests.swift | 3 - .../OptionalImportTests.swift | 12 +- .../StringPassingTests.swift | 4 +- .../VariableImportTests.swift | 8 +- 26 files changed, 451 insertions(+), 235 deletions(-) create mode 100644 SwiftKitCore/src/main/java/org/swift/swiftkit/core/CallTraces.java create mode 100644 SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftObjects.java diff --git a/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java b/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java index 3b083cc0..cecb1231 100644 --- a/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java +++ b/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java @@ -18,6 +18,7 @@ // Import javakit/swiftkit support libraries +import org.swift.swiftkit.core.CallTraces; import org.swift.swiftkit.core.SwiftLibraries; import org.swift.swiftkit.ffm.AllocatingSwiftArena; import org.swift.swiftkit.ffm.SwiftRuntime; @@ -43,30 +44,30 @@ static void examples() { long cnt = MySwiftLibrary.globalWriteString("String from Java"); - SwiftRuntime.trace("count = " + cnt); + CallTraces.trace("count = " + cnt); MySwiftLibrary.globalCallMeRunnable(() -> { - SwiftRuntime.trace("running runnable"); + CallTraces.trace("running runnable"); }); - SwiftRuntime.trace("getGlobalBuffer().byteSize()=" + MySwiftLibrary.getGlobalBuffer().byteSize()); + CallTraces.trace("getGlobalBuffer().byteSize()=" + MySwiftLibrary.getGlobalBuffer().byteSize()); MySwiftLibrary.withBuffer((buf) -> { - SwiftRuntime.trace("withBuffer{$0.byteSize()}=" + buf.byteSize()); + CallTraces.trace("withBuffer{$0.byteSize()}=" + buf.byteSize()); }); // Example of using an arena; MyClass.deinit is run at end of scope try (var arena = AllocatingSwiftArena.ofConfined()) { MySwiftClass obj = MySwiftClass.init(2222, 7777, arena); // just checking retains/releases work - SwiftRuntime.trace("retainCount = " + SwiftRuntime.retainCount(obj)); + CallTraces.trace("retainCount = " + SwiftRuntime.retainCount(obj)); SwiftRuntime.retain(obj); - SwiftRuntime.trace("retainCount = " + SwiftRuntime.retainCount(obj)); + CallTraces.trace("retainCount = " + SwiftRuntime.retainCount(obj)); SwiftRuntime.release(obj); - SwiftRuntime.trace("retainCount = " + SwiftRuntime.retainCount(obj)); + CallTraces.trace("retainCount = " + SwiftRuntime.retainCount(obj)); obj.setCounter(12); - SwiftRuntime.trace("obj.counter = " + obj.getCounter()); + CallTraces.trace("obj.counter = " + obj.getCounter()); obj.voidMethod(); obj.takeIntMethod(42); @@ -75,9 +76,9 @@ static void examples() { otherObj.voidMethod(); MySwiftStruct swiftValue = MySwiftStruct.init(2222, 1111, arena); - SwiftRuntime.trace("swiftValue.capacity = " + swiftValue.getCapacity()); + CallTraces.trace("swiftValue.capacity = " + swiftValue.getCapacity()); swiftValue.withCapLen((cap, len) -> { - SwiftRuntime.trace("withCapLenCallback: cap=" + cap + ", len=" + len); + CallTraces.trace("withCapLenCallback: cap=" + cap + ", len=" + len); }); } @@ -85,12 +86,12 @@ static void examples() { try (var arena = AllocatingSwiftArena.ofConfined()) { var origBytes = arena.allocateFrom("foobar"); var origDat = Data.init(origBytes, origBytes.byteSize(), arena); - SwiftRuntime.trace("origDat.count = " + origDat.getCount()); + CallTraces.trace("origDat.count = " + origDat.getCount()); var retDat = MySwiftLibrary.globalReceiveReturnData(origDat, arena); retDat.withUnsafeBytes((retBytes) -> { var str = retBytes.getString(0); - SwiftRuntime.trace("retStr=" + str); + CallTraces.trace("retStr=" + str); }); } diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift index 13230a32..28b3aba1 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift @@ -116,8 +116,8 @@ extension FFMSwift2JavaGenerator { """ public static \(returnTy) call(\(paramsStr)) { try { - if (SwiftRuntime.TRACE_DOWNCALLS) { - SwiftRuntime.traceDowncall(\(argsStr)); + if (CallTraces.TRACE_DOWNCALLS) { + CallTraces.traceDowncall(\(argsStr)); } \(maybeReturn)HANDLE.invokeExact(\(argsStr)); } catch (Throwable ex$) { diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+SwiftThunkPrinting.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+SwiftThunkPrinting.swift index d717255d..10dab4b9 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+SwiftThunkPrinting.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+SwiftThunkPrinting.swift @@ -131,6 +131,7 @@ extension FFMSwift2JavaGenerator { } printer.print("import \(module)") } + printer.println() } } diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift index 80b47760..4f4ad4d8 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift @@ -206,13 +206,15 @@ extension JNISwift2JavaGenerator { printDeclDocumentation(&printer, decl) printer.printBraceBlock("public \(renderFunctionSignature(decl))") { printer in var arguments = translatedDecl.translatedFunctionSignature.parameters.map(\.name) - arguments.append("selfPointer") + + let selfVarName = "self$" + arguments.append(selfVarName) let returnKeyword = translatedDecl.translatedFunctionSignature.resultType.isVoid ? "" : "return " printer.print( """ - long selfPointer = this.pointer(); + long \(selfVarName) = this.$memoryAddress(); \(returnKeyword)\(translatedDecl.parentName).$\(translatedDecl.name)(\(arguments.joined(separator: ", "))); """ ) @@ -235,8 +237,8 @@ extension JNISwift2JavaGenerator { let initArguments = translatedDecl.translatedFunctionSignature.parameters.map(\.name) printer.print( """ - long selfPointer = \(type.qualifiedName).allocatingInit(\(initArguments.joined(separator: ", "))); - return new \(type.qualifiedName)(selfPointer, swiftArena$); + long self$ = \(type.qualifiedName).allocatingInit(\(initArguments.joined(separator: ", "))); + return new \(type.qualifiedName)(self$, swiftArena$); """ ) } @@ -262,15 +264,24 @@ extension JNISwift2JavaGenerator { private func printDestroyFunction(_ printer: inout CodePrinter, _ type: ImportedNominalType) { printer.print("private static native void $destroy(long selfPointer);") + let funcName = "$createDestroyFunction" printer.print("@Override") - printer.printBraceBlock("protected Runnable $createDestroyFunction()") { printer in + printer.printBraceBlock("protected Runnable \(funcName)()") { printer in printer.print( """ - long $selfPointer = this.pointer(); + long self$ = this.$memoryAddress(); + if (CallTraces.TRACE_DOWNCALLS) { + CallTraces.traceDowncall("\(type.swiftNominal.name).\(funcName)", + "this", this, + "self", self$); + } return new Runnable() { @Override public void run() { - \(type.swiftNominal.name).$destroy($selfPointer); + if (CallTraces.TRACE_DOWNCALLS) { + CallTraces.traceDowncall("\(type.swiftNominal.name).$destroy", "self", self$); + } + \(type.swiftNominal.name).$destroy(self$); } }; """ diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift index 30db69d1..38d4ff79 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift @@ -138,9 +138,9 @@ extension JNISwift2JavaGenerator { // TODO: Throwing initializers printer.print( """ - let selfPointer = UnsafeMutablePointer<\(typeName)>.allocate(capacity: 1) - selfPointer.initialize(to: \(typeName)(\(downcallArguments))) - return Int64(Int(bitPattern: selfPointer)).getJNIValue(in: environment) + let self$ = UnsafeMutablePointer<\(typeName)>.allocate(capacity: 1) + self$.initialize(to: \(typeName)(\(downcallArguments))) + return Int64(Int(bitPattern: self$)).getJNIValue(in: environment) """ ) } @@ -184,22 +184,20 @@ extension JNISwift2JavaGenerator { let translatedDecl = self.translatedDecl(for: decl)! // We will only call this method if can translate the decl. let swiftParentName = decl.parentType!.asNominalTypeDeclaration!.qualifiedName + let selfPointerParam = JavaParameter(name: "selfPointer", type: .long) printCDecl( &printer, javaMethodName: "$\(translatedDecl.name)", parentName: translatedDecl.parentName, parameters: translatedDecl.translatedFunctionSignature.parameters + [ - JavaParameter(name: "selfPointer", type: .long) + selfPointerParam ], isStatic: true, resultType: translatedDecl.translatedFunctionSignature.resultType ) { printer in - printer.print( - """ - let self$ = UnsafeMutablePointer<\(swiftParentName)>(bitPattern: Int(Int64(fromJNI: selfPointer, in: environment!)))! - """ - ) - self.printFunctionDowncall(&printer, decl, calleeName: "self$.pointee") + let selfVar = self.printSelfJLongToUnsafeMutablePointer(&printer, + swiftParentName: swiftParentName, selfPointerParam) + self.printFunctionDowncall(&printer, decl, calleeName: "\(selfVar).pointee") } } @@ -320,28 +318,53 @@ extension JNISwift2JavaGenerator { /// Prints the implementation of the destroy function. private func printDestroyFunctionThunk(_ printer: inout CodePrinter, _ type: ImportedNominalType) { + let selfPointerParam = JavaParameter(name: "selfPointer", type: .long) printCDecl( &printer, javaMethodName: "$destroy", parentName: type.swiftNominal.name, parameters: [ - JavaParameter(name: "selfPointer", type: .long) + selfPointerParam ], isStatic: true, resultType: .void ) { printer in + let parentName = type.qualifiedName + let selfVar = self.printSelfJLongToUnsafeMutablePointer(&printer, swiftParentName: parentName, selfPointerParam) // Deinitialize the pointer allocated (which will call the VWT destroy method) // then deallocate the memory. printer.print( """ - let pointer = UnsafeMutablePointer<\(type.qualifiedName)>(bitPattern: Int(Int64(fromJNI: selfPointer, in: environment!)))! - pointer.deinitialize(count: 1) - pointer.deallocate() + \(selfVar).deinitialize(count: 1) + \(selfVar).deallocate() """ ) } } + /// Print the necessary conversion logic to go from a `jlong` to a `UnsafeMutablePointer` + /// + /// - Returns: name of the created "self" variable + private func printSelfJLongToUnsafeMutablePointer( + _ printer: inout CodePrinter, + swiftParentName: String, _ selfPointerParam: JavaParameter) -> String { + let newSelfParamName = "self$" + printer.print( + """ + guard let env$ = environment else { + fatalError("Missing JNIEnv in downcall to \\(#function)") + } + assert(\(selfPointerParam.name) != 0, "\(selfPointerParam.name) memory address was null") + let selfBits$ = Int(Int64(fromJNI: \(selfPointerParam.name), in: env$)) + guard let \(newSelfParamName) = UnsafeMutablePointer<\(swiftParentName)>(bitPattern: selfBits$) else { + fatalError("self memory address was null in call to \\(#function)!") + } + """ + ) + return newSelfParamName + } + + /// Renders the arguments for making a downcall private func renderDowncallArguments( swiftFunctionSignature: SwiftFunctionSignature, diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/CallTraces.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/CallTraces.java new file mode 100644 index 00000000..358205ff --- /dev/null +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/CallTraces.java @@ -0,0 +1,61 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package org.swift.swiftkit.core; + +public class CallTraces { + public static final boolean TRACE_DOWNCALLS = + Boolean.getBoolean("jextract.trace.downcalls"); + + // Used to manually debug with complete backtraces on every traceDowncall + public static final boolean TRACE_DOWNCALLS_FULL = false; + + public static void traceDowncall(Object... args) { + RuntimeException ex = new RuntimeException(); + + String traceArgs = joinArgs(args); + System.err.printf("[java][%s:%d] Downcall: %s.%s(%s)\n", + ex.getStackTrace()[1].getFileName(), + ex.getStackTrace()[1].getLineNumber(), + ex.getStackTrace()[1].getClassName(), + ex.getStackTrace()[1].getMethodName(), + traceArgs); + if (TRACE_DOWNCALLS_FULL) { + ex.printStackTrace(); + } + } + + public static void trace(Object... args) { + RuntimeException ex = new RuntimeException(); + + String traceArgs = joinArgs(args); + System.err.printf("[java][%s:%d] %s: %s\n", + ex.getStackTrace()[1].getFileName(), + ex.getStackTrace()[1].getLineNumber(), + ex.getStackTrace()[1].getMethodName(), + traceArgs); + } + + private static String joinArgs(Object[] args) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < args.length; i++) { + if (i > 0) { + sb.append(", "); + } + sb.append(args[i].toString()); + } + return sb.toString(); + } + +} diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/ConfinedSwiftMemorySession.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/ConfinedSwiftMemorySession.java index 1b6821ca..7c6e80fb 100644 --- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/ConfinedSwiftMemorySession.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/ConfinedSwiftMemorySession.java @@ -60,7 +60,7 @@ public void close() { public void register(SwiftInstance instance) { checkValid(); - SwiftInstanceCleanup cleanup = instance.createCleanupAction(); + SwiftInstanceCleanup cleanup = instance.$createCleanup(); this.resources.add(cleanup); } diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/JNISwiftInstance.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/JNISwiftInstance.java index f9966793..6b30ed2f 100644 --- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/JNISwiftInstance.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/JNISwiftInstance.java @@ -14,17 +14,30 @@ package org.swift.swiftkit.core; +import java.util.Objects; import java.util.concurrent.atomic.AtomicBoolean; public abstract class JNISwiftInstance extends SwiftInstance { + // Pointer to the "self". + protected final long selfPointer; + /** * The designated constructor of any imported Swift types. * - * @param pointer a pointer to the memory containing the value + * @param selfPointer a pointer to the memory containing the value * @param arena the arena this object belongs to. When the arena goes out of scope, this value is destroyed. */ - protected JNISwiftInstance(long pointer, SwiftArena arena) { - super(pointer, arena); + protected JNISwiftInstance(long selfPointer, SwiftArena arena) { + SwiftObjects.requireNonZero(selfPointer, "selfPointer"); + this.selfPointer = selfPointer; + + // Only register once we have fully initialized the object since this will need the object pointer. + arena.register(this); + } + + @Override + public long $memoryAddress() { + return this.selfPointer; } /** @@ -42,7 +55,7 @@ protected JNISwiftInstance(long pointer, SwiftArena arena) { protected abstract Runnable $createDestroyFunction(); @Override - public SwiftInstanceCleanup createCleanupAction() { + public SwiftInstanceCleanup $createCleanup() { final AtomicBoolean statusDestroyedFlag = $statusDestroyedFlag(); Runnable markAsDestroyed = new Runnable() { @Override diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftInstance.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftInstance.java index 638cb8be..44955cc6 100644 --- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftInstance.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftInstance.java @@ -17,49 +17,38 @@ import java.util.concurrent.atomic.AtomicBoolean; public abstract class SwiftInstance { - /// Pointer to the "self". - private final long selfPointer; + + // TODO: make this a flagset integer and/or use a field updater + /** Used to track additional state of the underlying object, e.g. if it was explicitly destroyed. */ + private final AtomicBoolean $state$destroyed = new AtomicBoolean(false); /** - * The pointer to the instance in memory. I.e. the {@code self} of the Swift object or value. + * Pointer to the {@code self} of the underlying Swift object or value. + * + * @apiNote When using this pointer one must ensure that the underlying object + * is kept alive using some means (e.g. a class remains retained), as + * this function does not ensure safety of the address in any way. */ - public final long pointer() { - return this.selfPointer; - } + public abstract long $memoryAddress(); /** * Called when the arena has decided the value should be destroyed. *

* Warning: The cleanup action must not capture {@code this}. */ - public abstract SwiftInstanceCleanup createCleanupAction(); - - // TODO: make this a flagset integer and/or use a field updater - /** Used to track additional state of the underlying object, e.g. if it was explicitly destroyed. */ - private final AtomicBoolean $state$destroyed = new AtomicBoolean(false); + public abstract SwiftInstanceCleanup $createCleanup(); /** * Exposes a boolean value which can be used to indicate if the object was destroyed. *

* This is exposing the object, rather than performing the action because we don't want to accidentally * form a strong reference to the {@code SwiftInstance} which could prevent the cleanup from running, - * if using an GC managed instance (e.g. using an {@link AutoSwiftMemorySession}. + * if using an GC managed instance (e.g. using an {@code AutoSwiftMemorySession}. */ public final AtomicBoolean $statusDestroyedFlag() { return this.$state$destroyed; } - /** - * The designated constructor of any imported Swift types. - * - * @param pointer a pointer to the memory containing the value - * @param arena the arena this object belongs to. When the arena goes out of scope, this value is destroyed. - */ - protected SwiftInstance(long pointer, SwiftArena arena) { - this.selfPointer = pointer; - arena.register(this); - } - /** * Ensures that this instance has not been destroyed. *

diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftLibraries.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftLibraries.java index 2abdaff5..3230e52a 100644 --- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftLibraries.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftLibraries.java @@ -26,7 +26,6 @@ public final class SwiftLibraries { public static final String STDLIB_DYLIB_NAME = "swiftCore"; public static final String SWIFTKITSWIFT_DYLIB_NAME = "SwiftKitSwift"; - public static final boolean TRACE_DOWNCALLS = Boolean.getBoolean("jextract.trace.downcalls"); private static final String STDLIB_MACOS_DYLIB_PATH = "/usr/lib/swift/libswiftCore.dylib"; @@ -57,7 +56,7 @@ public static void loadLibrary(String libname) { public static void loadResourceLibrary(String libname) { String resourceName = PlatformUtils.dynamicLibraryName(libname); - if (SwiftLibraries.TRACE_DOWNCALLS) { + if (CallTraces.TRACE_DOWNCALLS) { System.out.println("[swift-java] Loading resource library: " + resourceName); } diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftObjects.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftObjects.java new file mode 100644 index 00000000..c508e90e --- /dev/null +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftObjects.java @@ -0,0 +1,26 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package org.swift.swiftkit.core; + +/** + * Utility functions, similar to @{link java.util.Objects} + */ +public class SwiftObjects { + public static void requireNonZero(long number, String name) { + if (number == 0) { + throw new IllegalArgumentException(String.format("'%s' must not be zero!", name)); + } + } +} diff --git a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/AllocatingAutoSwiftMemorySession.java b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/AllocatingAutoSwiftMemorySession.java index fecd5202..7063fefb 100644 --- a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/AllocatingAutoSwiftMemorySession.java +++ b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/AllocatingAutoSwiftMemorySession.java @@ -56,7 +56,7 @@ public void register(SwiftInstance instance) { // We make sure we don't capture `instance` in the // cleanup action, so we can ignore the warning below. - var cleanupAction = instance.createCleanupAction(); + var cleanupAction = instance.$createCleanup(); cleaner.register(instance, cleanupAction); } diff --git a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMSwiftInstance.java b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMSwiftInstance.java index f4a01aa4..1236bad2 100644 --- a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMSwiftInstance.java +++ b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMSwiftInstance.java @@ -22,6 +22,19 @@ public abstract class FFMSwiftInstance extends SwiftInstance { private final MemorySegment memorySegment; + /** + * The designated constructor of any imported Swift types. + * + * @param segment the memory segment. + * @param arena the arena this object belongs to. When the arena goes out of scope, this value is destroyed. + */ + protected FFMSwiftInstance(MemorySegment segment, AllocatingSwiftArena arena) { + this.memorySegment = segment; + + // Only register once we have fully initialized the object since this will need the object pointer. + arena.register(this); + } + /** * The pointer to the instance in memory. I.e. the {@code self} of the Swift object or value. */ @@ -29,24 +42,19 @@ public abstract class FFMSwiftInstance extends SwiftInstance { return this.memorySegment; } + @Override + public long $memoryAddress() { + return $memorySegment().address(); + } + /** * The Swift type metadata of this type. */ public abstract SwiftAnyType $swiftType(); - /** - * The designated constructor of any imported Swift types. - * - * @param segment the memory segment. - * @param arena the arena this object belongs to. When the arena goes out of scope, this value is destroyed. - */ - protected FFMSwiftInstance(MemorySegment segment, AllocatingSwiftArena arena) { - super(segment.address(), arena); - this.memorySegment = segment; - } @Override - public SwiftInstanceCleanup createCleanupAction() { + public SwiftInstanceCleanup $createCleanup() { var statusDestroyedFlag = $statusDestroyedFlag(); Runnable markAsDestroyed = () -> statusDestroyedFlag.set(true); diff --git a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMSwiftInstanceCleanup.java b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMSwiftInstanceCleanup.java index a5d0829a..c3a9beb6 100644 --- a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMSwiftInstanceCleanup.java +++ b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMSwiftInstanceCleanup.java @@ -19,13 +19,13 @@ import java.lang.foreign.MemorySegment; public class FFMSwiftInstanceCleanup implements SwiftInstanceCleanup { - private final MemorySegment selfPointer; - private final SwiftAnyType selfType; + private final MemorySegment memoryAddress; + private final SwiftAnyType type; private final Runnable markAsDestroyed; - public FFMSwiftInstanceCleanup(MemorySegment selfPointer, SwiftAnyType selfType, Runnable markAsDestroyed) { - this.selfPointer = selfPointer; - this.selfType = selfType; + public FFMSwiftInstanceCleanup(MemorySegment memoryAddress, SwiftAnyType type, Runnable markAsDestroyed) { + this.memoryAddress = memoryAddress; + this.type = type; this.markAsDestroyed = markAsDestroyed; } @@ -34,9 +34,9 @@ public void run() { markAsDestroyed.run(); // Allow null pointers just for AutoArena tests. - if (selfType != null && selfPointer != null) { - System.out.println("[debug] Destroy swift value [" + selfType.getSwiftName() + "]: " + selfPointer); - SwiftValueWitnessTable.destroy(selfType, selfPointer); + if (type != null && memoryAddress != null) { + System.out.println("[debug] Destroy swift value [" + type.getSwiftName() + "]: " + memoryAddress); + SwiftValueWitnessTable.destroy(type, memoryAddress); } } } diff --git a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/SwiftRuntime.java b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/SwiftRuntime.java index dc18b445..eca6be82 100644 --- a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/SwiftRuntime.java +++ b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/SwiftRuntime.java @@ -15,6 +15,7 @@ package org.swift.swiftkit.ffm; import org.swift.swiftkit.core.SwiftInstance; +import org.swift.swiftkit.core.CallTraces; import org.swift.swiftkit.core.util.PlatformUtils; import java.lang.foreign.*; @@ -24,6 +25,7 @@ import java.util.*; import java.util.stream.Collectors; +import static org.swift.swiftkit.core.CallTraces.traceDowncall; import static org.swift.swiftkit.core.util.StringUtils.stripPrefix; import static org.swift.swiftkit.core.util.StringUtils.stripSuffix; @@ -31,7 +33,6 @@ public class SwiftRuntime { public static final String STDLIB_DYLIB_NAME = "swiftCore"; public static final String SWIFTKITSWIFT_DYLIB_NAME = "SwiftKitSwift"; - public static final boolean TRACE_DOWNCALLS = Boolean.getBoolean("jextract.trace.downcalls"); private static final String STDLIB_MACOS_DYLIB_PATH = "/usr/lib/swift/libswiftCore.dylib"; @@ -65,33 +66,6 @@ private static SymbolLookup getSymbolLookup() { public SwiftRuntime() { } - public static void traceDowncall(Object... args) { - var ex = new RuntimeException(); - - String traceArgs = Arrays.stream(args) - .map(Object::toString) - .collect(Collectors.joining(", ")); - System.out.printf("[java][%s:%d] Downcall: %s.%s(%s)\n", - ex.getStackTrace()[1].getFileName(), - ex.getStackTrace()[1].getLineNumber(), - ex.getStackTrace()[1].getClassName(), - ex.getStackTrace()[1].getMethodName(), - traceArgs); - } - - public static void trace(Object... args) { - var ex = new RuntimeException(); - - String traceArgs = Arrays.stream(args) - .map(Object::toString) - .collect(Collectors.joining(", ")); - System.out.printf("[java][%s:%d] %s: %s\n", - ex.getStackTrace()[1].getFileName(), - ex.getStackTrace()[1].getLineNumber(), - ex.getStackTrace()[1].getMethodName(), - traceArgs); - } - static MemorySegment findOrThrow(String symbol) { return SYMBOL_LOOKUP.find(symbol) .orElseThrow(() -> new UnsatisfiedLinkError("unresolved symbol: %s".formatted(symbol))); @@ -152,7 +126,7 @@ private static class swift_retainCount { public static long retainCount(MemorySegment object) { var mh$ = swift_retainCount.HANDLE; try { - if (TRACE_DOWNCALLS) { + if (CallTraces.TRACE_DOWNCALLS) { traceDowncall("swift_retainCount", object); } return (long) mh$.invokeExact(object); @@ -182,7 +156,7 @@ private static class swift_retain { public static void retain(MemorySegment object) { var mh$ = swift_retain.HANDLE; try { - if (TRACE_DOWNCALLS) { + if (CallTraces.TRACE_DOWNCALLS) { traceDowncall("swift_retain", object); } mh$.invokeExact(object); @@ -212,7 +186,7 @@ private static class swift_release { public static void release(MemorySegment object) { var mh$ = swift_release.HANDLE; try { - if (TRACE_DOWNCALLS) { + if (CallTraces.TRACE_DOWNCALLS) { traceDowncall("swift_release", object); } mh$.invokeExact(object); @@ -248,7 +222,7 @@ private static class swift_getTypeByName { public static MemorySegment getTypeByName(String string) { var mh$ = swift_getTypeByName.HANDLE; try { - if (TRACE_DOWNCALLS) { + if (CallTraces.TRACE_DOWNCALLS) { traceDowncall("_typeByName"); } // TODO: A bit annoying to generate, we need an arena for the conversion... @@ -303,7 +277,7 @@ public static Optional getTypeByMangledNameInEnvironment(String ma // contain this, but we don't need it for type lookup mangledName = stripSuffix(mangledName, "Ma"); mangledName = stripSuffix(mangledName, "CN"); - if (TRACE_DOWNCALLS) { + if (CallTraces.TRACE_DOWNCALLS) { traceDowncall("swift_getTypeByMangledNameInEnvironment", mangledName); } try (Arena arena = Arena.ofConfined()) { diff --git a/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift b/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift index 3c4ad56a..5b70f68a 100644 --- a/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift +++ b/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift @@ -28,7 +28,7 @@ func assertOutput( _ mode: JExtractGenerationMode, _ renderKind: RenderKind, swiftModuleName: String = "SwiftModule", - detectChunkByInitialLines: Int = 4, + detectChunkByInitialLines _detectChunkByInitialLines: Int = 4, expectedChunks: [String], fileID: String = #fileID, filePath: String = #filePath, @@ -79,19 +79,22 @@ func assertOutput( let gotLines = output.split(separator: "\n").filter { l in l.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines).count > 0 } - for expected in expectedChunks { - let expectedLines = expected.split(separator: "\n") + for expectedChunk in expectedChunks { + let expectedLines = expectedChunk.split(separator: "\n") + let detectChunkByInitialLines = min(expectedLines.count, _detectChunkByInitialLines) + precondition(detectChunkByInitialLines > 0, "Chunk size to detect cannot be zero lines!") var matchingOutputOffset: Int? = nil let expectedInitialMatchingLines = expectedLines[0.. (offset+detectChunkByInitialLines) { - let textLinesAtOffset = gotLines[offset.. (lineOffset+detectChunkByInitialLines) { + let textLinesAtOffset = gotLines[lineOffset..!, thisClass: jclass) -> jlong { - let selfPointer = UnsafeMutablePointer.allocate(capacity: 1) - selfPointer.initialize(to: MyClass()) - return Int64(Int(bitPattern: selfPointer)).getJNIValue(in: environment) + let self$ = UnsafeMutablePointer.allocate(capacity: 1) + self$.initialize(to: MyClass()) + return Int64(Int(bitPattern: self$)).getJNIValue(in: environment) } """, """ @_cdecl("Java_com_example_swift_MyClass_allocatingInit__JJ") func Java_com_example_swift_MyClass_allocatingInit__JJ(environment: UnsafeMutablePointer!, thisClass: jclass, x: jlong, y: jlong) -> jlong { - let selfPointer = UnsafeMutablePointer.allocate(capacity: 1) - selfPointer.initialize(to: MyClass(x: Int64(fromJNI: x, in: environment!), y: Int64(fromJNI: y, in: environment!))) - return Int64(Int(bitPattern: selfPointer)).getJNIValue(in: environment) + let self$ = UnsafeMutablePointer.allocate(capacity: 1) + self$.initialize(to: MyClass(x: Int64(fromJNI: x, in: environment!), y: Int64(fromJNI: y, in: environment!))) + return Int64(Int(bitPattern: self$)).getJNIValue(in: environment) } """ ] @@ -200,9 +207,16 @@ struct JNIClassTests { """ @_cdecl("Java_com_example_swift_MyClass__00024destroy__J") func Java_com_example_swift_MyClass__00024destroy__J(environment: UnsafeMutablePointer!, thisClass: jclass, selfPointer: jlong) { - let pointer = UnsafeMutablePointer(bitPattern: Int(Int64(fromJNI: selfPointer, in: environment!)))! - pointer.deinitialize(count: 1) - pointer.deallocate() + guard let env$ = environment else { + fatalError("Missing JNIEnv in downcall to \\(#function)") + } + assert(selfPointer != 0, "selfPointer memory address was null") + let selfBits$ = Int(Int64(fromJNI: selfPointer, in: env$)) + guard let self$ = UnsafeMutablePointer(bitPattern: selfBits$) else { + fatalError("self memory address was null in call to \\(#function)!") + } + self$.deinitialize(count: 1) + self$.deallocate() } """ ] @@ -218,14 +232,14 @@ struct JNIClassTests { expectedChunks: [ """ /** - * Downcall to Swift: - * {@snippet lang=swift : - * public func doSomething(x: Int64) - * } - */ + * Downcall to Swift: + * {@snippet lang=swift : + * public func doSomething(x: Int64) + * } + */ public void doSomething(long x) { - long selfPointer = this.pointer(); - MyClass.$doSomething(x, selfPointer); + long self$ = this.$memoryAddress(); + MyClass.$doSomething(x, self$); } """, """ @@ -246,7 +260,14 @@ struct JNIClassTests { """ @_cdecl("Java_com_example_swift_MyClass__00024doSomething__JJ") func Java_com_example_swift_MyClass__00024doSomething__JJ(environment: UnsafeMutablePointer!, thisClass: jclass, x: jlong, selfPointer: jlong) { - let self$ = UnsafeMutablePointer(bitPattern: Int(Int64(fromJNI: selfPointer, in: environment!)))! + guard let env$ = environment else { + fatalError("Missing JNIEnv in downcall to \\(#function)") + } + assert(selfPointer != 0, "selfPointer memory address was null") + let selfBits$ = Int(Int64(fromJNI: selfPointer, in: env$)) + guard let self$ = UnsafeMutablePointer(bitPattern: selfBits$) else { + fatalError("self memory address was null in call to \\(#function)!") + } self$.pointee.doSomething(x: Int64(fromJNI: x, in: environment!)) } """, diff --git a/Tests/JExtractSwiftTests/JNI/JNIStructTests.swift b/Tests/JExtractSwiftTests/JNI/JNIStructTests.swift index 0a883ed1..47b1c4dc 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIStructTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIStructTests.swift @@ -63,11 +63,19 @@ struct JNIStructTests { """ @Override protected Runnable $createDestroyFunction() { - long $selfPointer = this.pointer(); + long self$ = this.$memoryAddress(); + if (CallTraces.TRACE_DOWNCALLS) { + CallTraces.traceDowncall("MyStruct.$createDestroyFunction", + "this", this, + "self", self$); + } return new Runnable() { @Override public void run() { - MyStruct.$destroy($selfPointer); + if (CallTraces.TRACE_DOWNCALLS) { + CallTraces.traceDowncall("MyStruct.$destroy", "self", self$); + } + MyStruct.$destroy(self$); } }; } @@ -90,8 +98,8 @@ struct JNIStructTests { * } */ public static MyStruct init(long x, long y, SwiftArena swiftArena$) { - long selfPointer = MyStruct.allocatingInit(x, y); - return new MyStruct(selfPointer, swiftArena$); + long self$ = MyStruct.allocatingInit(x, y); + return new MyStruct(self$, swiftArena$); } """, """ @@ -112,9 +120,9 @@ struct JNIStructTests { """ @_cdecl("Java_com_example_swift_MyStruct_allocatingInit__JJ") func Java_com_example_swift_MyStruct_allocatingInit__JJ(environment: UnsafeMutablePointer!, thisClass: jclass, x: jlong, y: jlong) -> jlong { - let selfPointer = UnsafeMutablePointer.allocate(capacity: 1) - selfPointer.initialize(to: MyStruct(x: Int64(fromJNI: x, in: environment!), y: Int64(fromJNI: y, in: environment!))) - return Int64(Int(bitPattern: selfPointer)).getJNIValue(in: environment) + let self$ = UnsafeMutablePointer.allocate(capacity: 1) + self$.initialize(to: MyStruct(x: Int64(fromJNI: x, in: environment!), y: Int64(fromJNI: y, in: environment!))) + return Int64(Int(bitPattern: self$)).getJNIValue(in: environment) } """ ] @@ -127,14 +135,20 @@ struct JNIStructTests { input: source, .jni, .swift, - detectChunkByInitialLines: 1, expectedChunks: [ """ @_cdecl("Java_com_example_swift_MyStruct__00024destroy__J") func Java_com_example_swift_MyStruct__00024destroy__J(environment: UnsafeMutablePointer!, thisClass: jclass, selfPointer: jlong) { - let pointer = UnsafeMutablePointer(bitPattern: Int(Int64(fromJNI: selfPointer, in: environment!)))! - pointer.deinitialize(count: 1) - pointer.deallocate() + guard let env$ = environment else { + fatalError("Missing JNIEnv in downcall to \\(#function)") + } + assert(selfPointer != 0, "selfPointer memory address was null") + let selfBits$ = Int(Int64(fromJNI: selfPointer, in: env$)) + guard let self$ = UnsafeMutablePointer(bitPattern: selfBits$) else { + fatalError("self memory address was null in call to \\(#function)!") + } + self$.deinitialize(count: 1) + self$.deallocate() } """ ] @@ -156,8 +170,8 @@ struct JNIStructTests { * } */ public void doSomething(long x) { - long selfPointer = this.pointer(); - MyStruct.$doSomething(x, selfPointer); + long self$ = this.$memoryAddress(); + MyStruct.$doSomething(x, self$); } """, """ @@ -178,7 +192,14 @@ struct JNIStructTests { """ @_cdecl("Java_com_example_swift_MyStruct__00024doSomething__JJ") func Java_com_example_swift_MyStruct__00024doSomething__JJ(environment: UnsafeMutablePointer!, thisClass: jclass, x: jlong, selfPointer: jlong) { - let self$ = UnsafeMutablePointer(bitPattern: Int(Int64(fromJNI: selfPointer, in: environment!)))! + guard let env$ = environment else { + fatalError("Missing JNIEnv in downcall to \\(#function)") + } + assert(selfPointer != 0, "selfPointer memory address was null") + let selfBits$ = Int(Int64(fromJNI: selfPointer, in: env$)) + guard let self$ = UnsafeMutablePointer(bitPattern: selfBits$) else { + fatalError("self memory address was null in call to \\(#function)!") + } self$.pointee.doSomething(x: Int64(fromJNI: x, in: environment!)) } """, diff --git a/Tests/JExtractSwiftTests/JNI/JNIVariablesTests.swift b/Tests/JExtractSwiftTests/JNI/JNIVariablesTests.swift index f09789d4..3f65bd97 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIVariablesTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIVariablesTests.swift @@ -48,8 +48,8 @@ struct JNIVariablesTests { * } */ public long getConstant() { - long selfPointer = this.pointer(); - return MyClass.$getConstant(selfPointer); + long self$ = this.$memoryAddress(); + return MyClass.$getConstant(self$); } """, """ @@ -69,7 +69,14 @@ struct JNIVariablesTests { """ @_cdecl("Java_com_example_swift_MyClass__00024getConstant__J") func Java_com_example_swift_MyClass__00024getConstant__J(environment: UnsafeMutablePointer!, thisClass: jclass, selfPointer: jlong) -> jlong { - let self$ = UnsafeMutablePointer(bitPattern: Int(Int64(fromJNI: selfPointer, in: environment!)))! + guard let env$ = environment else { + fatalError("Missing JNIEnv in downcall to \\(#function)") + } + assert(selfPointer != 0, "selfPointer memory address was null") + let selfBits$ = Int(Int64(fromJNI: selfPointer, in: env$)) + guard let self$ = UnsafeMutablePointer(bitPattern: selfBits$) else { + fatalError("self memory address was null in call to \\(#function)!") + } let result = self$.pointee.constant return result.getJNIValue(in: environment) } @@ -94,8 +101,8 @@ struct JNIVariablesTests { * } */ public long getMutable() { - long selfPointer = this.pointer(); - return MyClass.$getMutable(selfPointer); + long self$ = this.$memoryAddress(); + return MyClass.$getMutable(self$); } """, """ @@ -106,8 +113,8 @@ struct JNIVariablesTests { * } */ public void setMutable(long newValue) { - long selfPointer = this.pointer(); - MyClass.$setMutable(newValue, selfPointer); + long self$ = this.$memoryAddress(); + MyClass.$setMutable(newValue, self$); } """, """ @@ -131,7 +138,14 @@ struct JNIVariablesTests { """ @_cdecl("Java_com_example_swift_MyClass__00024getMutable__J") func Java_com_example_swift_MyClass__00024getMutable__J(environment: UnsafeMutablePointer!, thisClass: jclass, selfPointer: jlong) -> jlong { - let self$ = UnsafeMutablePointer(bitPattern: Int(Int64(fromJNI: selfPointer, in: environment!)))! + guard let env$ = environment else { + fatalError("Missing JNIEnv in downcall to \\(#function)") + } + assert(selfPointer != 0, "selfPointer memory address was null") + let selfBits$ = Int(Int64(fromJNI: selfPointer, in: env$)) + guard let self$ = UnsafeMutablePointer(bitPattern: selfBits$) else { + fatalError("self memory address was null in call to \\(#function)!") + } let result = self$.pointee.mutable return result.getJNIValue(in: environment) } @@ -139,7 +153,14 @@ struct JNIVariablesTests { """ @_cdecl("Java_com_example_swift_MyClass__00024setMutable__JJ") func Java_com_example_swift_MyClass__00024setMutable__JJ(environment: UnsafeMutablePointer!, thisClass: jclass, newValue: jlong, selfPointer: jlong) { - let self$ = UnsafeMutablePointer(bitPattern: Int(Int64(fromJNI: selfPointer, in: environment!)))! + guard let env$ = environment else { + fatalError("Missing JNIEnv in downcall to \\(#function)") + } + assert(selfPointer != 0, "selfPointer memory address was null") + let selfBits$ = Int(Int64(fromJNI: selfPointer, in: env$)) + guard let self$ = UnsafeMutablePointer(bitPattern: selfBits$) else { + fatalError("self memory address was null in call to \\(#function)!") + } self$.pointee.mutable = Int64(fromJNI: newValue, in: environment!) } """ @@ -163,8 +184,8 @@ struct JNIVariablesTests { * } */ public long getComputed() { - long selfPointer = this.pointer(); - return MyClass.$getComputed(selfPointer); + long self$ = this.$memoryAddress(); + return MyClass.$getComputed(self$); } """, """ @@ -185,7 +206,15 @@ struct JNIVariablesTests { """ @_cdecl("Java_com_example_swift_MyClass__00024getComputed__J") func Java_com_example_swift_MyClass__00024getComputed__J(environment: UnsafeMutablePointer!, thisClass: jclass, selfPointer: jlong) -> jlong { - let self$ = UnsafeMutablePointer(bitPattern: Int(Int64(fromJNI: selfPointer, in: environment!)))! + guard let env$ = environment else { + fatalError("Missing JNIEnv in downcall to \\(#function)") + } + assert(selfPointer != 0, "selfPointer memory address was null") + let selfBits$ = Int(Int64(fromJNI: selfPointer, in: env$)) + guard let self$ = UnsafeMutablePointer(bitPattern: selfBits$) else { + fatalError("self memory address was null in call to \\(#function)!") + } + let result = self$.pointee.computed return result.getJNIValue(in: environment) } @@ -210,8 +239,8 @@ struct JNIVariablesTests { * } */ public long getComputedThrowing() throws Exception { - long selfPointer = this.pointer(); - return MyClass.$getComputedThrowing(selfPointer); + long self$ = this.$memoryAddress(); + return MyClass.$getComputedThrowing(self$); } """, """ @@ -232,7 +261,15 @@ struct JNIVariablesTests { """ @_cdecl("Java_com_example_swift_MyClass__00024getComputedThrowing__J") func Java_com_example_swift_MyClass__00024getComputedThrowing__J(environment: UnsafeMutablePointer!, thisClass: jclass, selfPointer: jlong) -> jlong { - let self$ = UnsafeMutablePointer(bitPattern: Int(Int64(fromJNI: selfPointer, in: environment!)))! + guard let env$ = environment else { + fatalError("Missing JNIEnv in downcall to \\(#function)") + } + assert(selfPointer != 0, "selfPointer memory address was null") + let selfBits$ = Int(Int64(fromJNI: selfPointer, in: env$)) + guard let self$ = UnsafeMutablePointer(bitPattern: selfBits$) else { + fatalError("self memory address was null in call to \\(#function)!") + } + do { let result = try self$.pointee.computedThrowing return result.getJNIValue(in: environment) @@ -262,8 +299,8 @@ struct JNIVariablesTests { * } */ public long getGetterAndSetter() { - long selfPointer = this.pointer(); - return MyClass.$getGetterAndSetter(selfPointer); + long self$ = this.$memoryAddress(); + return MyClass.$getGetterAndSetter(self$); } """, """ @@ -274,8 +311,8 @@ struct JNIVariablesTests { * } */ public void setGetterAndSetter(long newValue) { - long selfPointer = this.pointer(); - MyClass.$setGetterAndSetter(newValue, selfPointer); + long self$ = this.$memoryAddress(); + MyClass.$setGetterAndSetter(newValue, self$); } """, """ @@ -299,7 +336,15 @@ struct JNIVariablesTests { """ @_cdecl("Java_com_example_swift_MyClass__00024getGetterAndSetter__J") func Java_com_example_swift_MyClass__00024getGetterAndSetter__J(environment: UnsafeMutablePointer!, thisClass: jclass, selfPointer: jlong) -> jlong { - let self$ = UnsafeMutablePointer(bitPattern: Int(Int64(fromJNI: selfPointer, in: environment!)))! + guard let env$ = environment else { + fatalError("Missing JNIEnv in downcall to \\(#function)") + } + assert(selfPointer != 0, "selfPointer memory address was null") + let selfBits$ = Int(Int64(fromJNI: selfPointer, in: env$)) + guard let self$ = UnsafeMutablePointer(bitPattern: selfBits$) else { + fatalError("self memory address was null in call to \\(#function)!") + } + let result = self$.pointee.getterAndSetter return result.getJNIValue(in: environment) } @@ -307,7 +352,15 @@ struct JNIVariablesTests { """ @_cdecl("Java_com_example_swift_MyClass__00024setGetterAndSetter__JJ") func Java_com_example_swift_MyClass__00024setGetterAndSetter__JJ(environment: UnsafeMutablePointer!, thisClass: jclass, newValue: jlong, selfPointer: jlong) { - let self$ = UnsafeMutablePointer(bitPattern: Int(Int64(fromJNI: selfPointer, in: environment!)))! + guard let env$ = environment else { + fatalError("Missing JNIEnv in downcall to \\(#function)") + } + assert(selfPointer != 0, "selfPointer memory address was null") + let selfBits$ = Int(Int64(fromJNI: selfPointer, in: env$)) + guard let self$ = UnsafeMutablePointer(bitPattern: selfBits$) else { + fatalError("self memory address was null in call to \\(#function)!") + } + self$.pointee.getterAndSetter = Int64(fromJNI: newValue, in: environment!) } """ @@ -331,8 +384,8 @@ struct JNIVariablesTests { * } */ public boolean isSomeBoolean() { - long selfPointer = this.pointer(); - return MyClass.$isSomeBoolean(selfPointer); + long self$ = this.$memoryAddress(); + return MyClass.$isSomeBoolean(self$); } """, """ @@ -343,8 +396,8 @@ struct JNIVariablesTests { * } */ public void setSomeBoolean(boolean newValue) { - long selfPointer = this.pointer(); - MyClass.$setSomeBoolean(newValue, selfPointer); + long self$ = this.$memoryAddress(); + MyClass.$setSomeBoolean(newValue, self$); } """, """ @@ -368,7 +421,14 @@ struct JNIVariablesTests { """ @_cdecl("Java_com_example_swift_MyClass__00024isSomeBoolean__J") func Java_com_example_swift_MyClass__00024isSomeBoolean__J(environment: UnsafeMutablePointer!, thisClass: jclass, selfPointer: jlong) -> jboolean { - let self$ = UnsafeMutablePointer(bitPattern: Int(Int64(fromJNI: selfPointer, in: environment!)))! + guard let env$ = environment else { + fatalError("Missing JNIEnv in downcall to \\(#function)") + } + assert(selfPointer != 0, "selfPointer memory address was null") + let selfBits$ = Int(Int64(fromJNI: selfPointer, in: env$)) + guard let self$ = UnsafeMutablePointer(bitPattern: selfBits$) else { + fatalError("self memory address was null in call to \\(#function)!") + } let result = self$.pointee.someBoolean return result.getJNIValue(in: environment) } @@ -376,7 +436,14 @@ struct JNIVariablesTests { """ @_cdecl("Java_com_example_swift_MyClass__00024setSomeBoolean__ZJ") func Java_com_example_swift_MyClass__00024setSomeBoolean__ZJ(environment: UnsafeMutablePointer!, thisClass: jclass, newValue: jboolean, selfPointer: jlong) { - let self$ = UnsafeMutablePointer(bitPattern: Int(Int64(fromJNI: selfPointer, in: environment!)))! + guard let env$ = environment else { + fatalError("Missing JNIEnv in downcall to \\(#function)") + } + assert(selfPointer != 0, "selfPointer memory address was null") + let selfBits$ = Int(Int64(fromJNI: selfPointer, in: env$)) + guard let self$ = UnsafeMutablePointer(bitPattern: selfBits$) else { + fatalError("self memory address was null in call to \\(#function)!") + } self$.pointee.someBoolean = Bool(fromJNI: newValue, in: environment!) } """ diff --git a/Tests/JExtractSwiftTests/MethodImportTests.swift b/Tests/JExtractSwiftTests/MethodImportTests.swift index 118ca789..73357d6b 100644 --- a/Tests/JExtractSwiftTests/MethodImportTests.swift +++ b/Tests/JExtractSwiftTests/MethodImportTests.swift @@ -168,7 +168,6 @@ final class MethodImportTests { } assertOutput( - dump: true, output, expected: """ @@ -212,7 +211,6 @@ final class MethodImportTests { } assertOutput( - dump: true, output, expected: """ @@ -256,7 +254,6 @@ final class MethodImportTests { } assertOutput( - dump: true, output, expected: """ diff --git a/Tests/JExtractSwiftTests/OptionalImportTests.swift b/Tests/JExtractSwiftTests/OptionalImportTests.swift index 756bb3d9..daa9fe66 100644 --- a/Tests/JExtractSwiftTests/OptionalImportTests.swift +++ b/Tests/JExtractSwiftTests/OptionalImportTests.swift @@ -47,8 +47,8 @@ final class OptionalImportTests { private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); public static void call(java.lang.foreign.MemorySegment arg) { try { - if (SwiftRuntime.TRACE_DOWNCALLS) { - SwiftRuntime.traceDowncall(arg); + if (CallTraces.TRACE_DOWNCALLS) { + CallTraces.traceDowncall(arg); } HANDLE.invokeExact(arg); } catch (Throwable ex$) { @@ -87,8 +87,8 @@ final class OptionalImportTests { private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); public static void call(java.lang.foreign.MemorySegment arg) { try { - if (SwiftRuntime.TRACE_DOWNCALLS) { - SwiftRuntime.traceDowncall(arg); + if (CallTraces.TRACE_DOWNCALLS) { + CallTraces.traceDowncall(arg); } HANDLE.invokeExact(arg); } catch (Throwable ex$) { @@ -128,8 +128,8 @@ final class OptionalImportTests { private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); public static void call(java.lang.foreign.MemorySegment arg) { try { - if (SwiftRuntime.TRACE_DOWNCALLS) { - SwiftRuntime.traceDowncall(arg); + if (CallTraces.TRACE_DOWNCALLS) { + CallTraces.traceDowncall(arg); } HANDLE.invokeExact(arg); } catch (Throwable ex$) { diff --git a/Tests/JExtractSwiftTests/StringPassingTests.swift b/Tests/JExtractSwiftTests/StringPassingTests.swift index 6a5c1c80..ea81ac84 100644 --- a/Tests/JExtractSwiftTests/StringPassingTests.swift +++ b/Tests/JExtractSwiftTests/StringPassingTests.swift @@ -45,8 +45,8 @@ final class StringPassingTests { private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); public static long call(java.lang.foreign.MemorySegment string) { try { - if (SwiftRuntime.TRACE_DOWNCALLS) { - SwiftRuntime.traceDowncall(string); + if (CallTraces.TRACE_DOWNCALLS) { + CallTraces.traceDowncall(string); } return (long) HANDLE.invokeExact(string); } catch (Throwable ex$) { diff --git a/Tests/JExtractSwiftTests/VariableImportTests.swift b/Tests/JExtractSwiftTests/VariableImportTests.swift index e0a6678c..da0c1afa 100644 --- a/Tests/JExtractSwiftTests/VariableImportTests.swift +++ b/Tests/JExtractSwiftTests/VariableImportTests.swift @@ -51,8 +51,8 @@ final class VariableImportTests { private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); public static long call(java.lang.foreign.MemorySegment self) { try { - if (SwiftRuntime.TRACE_DOWNCALLS) { - SwiftRuntime.traceDowncall(self); + if (CallTraces.TRACE_DOWNCALLS) { + CallTraces.traceDowncall(self); } return (long) HANDLE.invokeExact(self); } catch (Throwable ex$) { @@ -84,8 +84,8 @@ final class VariableImportTests { private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); public static void call(long newValue, java.lang.foreign.MemorySegment self) { try { - if (SwiftRuntime.TRACE_DOWNCALLS) { - SwiftRuntime.traceDowncall(newValue, self); + if (CallTraces.TRACE_DOWNCALLS) { + CallTraces.traceDowncall(newValue, self); } HANDLE.invokeExact(newValue, self); } catch (Throwable ex$) { From a82196e91377f09a7919a27809acffa25b217695 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Thu, 17 Jul 2025 15:51:01 +0900 Subject: [PATCH 318/426] Build: simple local maven publishing (#324) --- SwiftKitCore/build.gradle | 17 +++++++++++++++++ SwiftKitFFM/build.gradle | 17 +++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/SwiftKitCore/build.gradle b/SwiftKitCore/build.gradle index 78cdbeb2..7bab76e0 100644 --- a/SwiftKitCore/build.gradle +++ b/SwiftKitCore/build.gradle @@ -14,15 +14,32 @@ plugins { id("build-logic.java-application-conventions") + id("maven-publish") } group = "org.swift.swiftkit" version = "1.0-SNAPSHOT" +base { + archivesName = "swiftkit-core" +} repositories { + mavenLocal() mavenCentral() } +publishing { + publications { + maven(MavenPublication) { + groupId = group + artifactId = 'swiftkit-core' + version = '1.0-SNAPSHOT' + + from components.java + } + } +} + java { toolchain { languageVersion.set(JavaLanguageVersion.of(17)) diff --git a/SwiftKitFFM/build.gradle b/SwiftKitFFM/build.gradle index 22f88001..d818586d 100644 --- a/SwiftKitFFM/build.gradle +++ b/SwiftKitFFM/build.gradle @@ -14,15 +14,32 @@ plugins { id("build-logic.java-application-conventions") + id("maven-publish") } group = "org.swift.swiftkit" version = "1.0-SNAPSHOT" +base { + archivesName = "swiftkit-ffm" +} repositories { + mavenLocal() mavenCentral() } +publishing { + publications { + maven(MavenPublication) { + groupId = group + artifactId = 'swiftkit-ffm' + version = '1.0-SNAPSHOT' + + from components.java + } + } +} + java { toolchain { languageVersion.set(JavaLanguageVersion.of(24)) From 86da9eec8711415f142e5967d4352bb1352c77e1 Mon Sep 17 00:00:00 2001 From: Mads Odgaard Date: Tue, 22 Jul 2025 10:31:20 +0200 Subject: [PATCH 319/426] [JExtract/JNI] Fix boolean naming for variables already called `isX` (#325) --- .../Convenience/String+Extensions.swift | 3 +- Sources/JExtractSwiftLib/ImportedDecls.swift | 18 +++- .../Asserts/TextAssertions.swift | 1 - .../JNI/JNIVariablesTests.swift | 87 ++++++++++++++++++- 4 files changed, 100 insertions(+), 9 deletions(-) diff --git a/Sources/JExtractSwiftLib/Convenience/String+Extensions.swift b/Sources/JExtractSwiftLib/Convenience/String+Extensions.swift index 1878ba2f..1851e154 100644 --- a/Sources/JExtractSwiftLib/Convenience/String+Extensions.swift +++ b/Sources/JExtractSwiftLib/Convenience/String+Extensions.swift @@ -14,8 +14,7 @@ extension String { - // TODO: naive implementation good enough for our simple case `methodMethodSomething` -> `MethodSomething` - var toCamelCase: String { + var firstCharacterUppercased: String { guard let f = first else { return self } diff --git a/Sources/JExtractSwiftLib/ImportedDecls.swift b/Sources/JExtractSwiftLib/ImportedDecls.swift index 4b8a478a..dd7e9c10 100644 --- a/Sources/JExtractSwiftLib/ImportedDecls.swift +++ b/Sources/JExtractSwiftLib/ImportedDecls.swift @@ -160,15 +160,25 @@ extension ImportedFunc { let returnsBoolean = self.functionSignature.result.type.asNominalTypeDeclaration?.knownTypeKind == .bool if !returnsBoolean { - return "get\(self.name.toCamelCase)" + return "get\(self.name.firstCharacterUppercased)" } else if !self.name.hasJavaBooleanNamingConvention { - return "is\(self.name.toCamelCase)" + return "is\(self.name.firstCharacterUppercased)" } else { - return self.name.toCamelCase + return self.name } } var javaSetterName: String { - "set\(self.name.toCamelCase)" + let isBooleanSetter = self.functionSignature.parameters.first?.type.asNominalTypeDeclaration?.knownTypeKind == .bool + + // If the variable is already named "isX", then we make + // the setter "setX" to match beans spec. + if isBooleanSetter && self.name.hasJavaBooleanNamingConvention { + // Safe to force unwrap due to `hasJavaBooleanNamingConvention` check. + let propertyName = self.name.split(separator: "is", maxSplits: 1).last! + return "set\(propertyName)" + } else { + return "set\(self.name.firstCharacterUppercased)" + } } } diff --git a/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift b/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift index 5b70f68a..47397c63 100644 --- a/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift +++ b/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift @@ -115,7 +115,6 @@ func assertOutput( print("==== ---------------------------------------------------------------") #expect(output.contains(expectedChunk), sourceLocation: sourceLocation) - fatalError("Failed: \(filePath):\(line)") continue } diff --git a/Tests/JExtractSwiftTests/JNI/JNIVariablesTests.swift b/Tests/JExtractSwiftTests/JNI/JNIVariablesTests.swift index 3f65bd97..272d27b5 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIVariablesTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIVariablesTests.swift @@ -33,7 +33,7 @@ struct JNIVariablesTests { set { } } public var someBoolean: Bool - public let isBoolean: Bool + public var isBoolean: Bool } """ @@ -411,7 +411,7 @@ struct JNIVariablesTests { } @Test - func boolean_swiftThunks() throws { + func someBoolean_swiftThunks() throws { try assertOutput( input: membersSource, .jni, @@ -450,4 +450,87 @@ struct JNIVariablesTests { ] ) } + + @Test + func isBoolean_javaBindings() throws { + try assertOutput( + input: membersSource, + .jni, + .java, + detectChunkByInitialLines: 8, + expectedChunks: [ + """ + /** + * Downcall to Swift: + * {@snippet lang=swift : + * public var isBoolean: Bool + * } + */ + public boolean isBoolean() { + long self$ = this.$memoryAddress(); + return MyClass.$isBoolean(self$); + } + """, + """ + /** + * Downcall to Swift: + * {@snippet lang=swift : + * public var isBoolean: Bool + * } + */ + public void setBoolean(boolean newValue) { + long self$ = this.$memoryAddress(); + MyClass.$setBoolean(newValue, self$); + } + """, + """ + private static native boolean $isBoolean(long selfPointer); + """, + """ + private static native void $setBoolean(boolean newValue, long selfPointer); + """ + ] + ) + } + + @Test + func isBoolean_swiftThunks() throws { + try assertOutput( + input: membersSource, + .jni, + .swift, + detectChunkByInitialLines: 1, + expectedChunks: [ + """ + @_cdecl("Java_com_example_swift_MyClass__00024isBoolean__J") + func Java_com_example_swift_MyClass__00024isBoolean__J(environment: UnsafeMutablePointer!, thisClass: jclass, selfPointer: jlong) -> jboolean { + guard let env$ = environment else { + fatalError("Missing JNIEnv in downcall to \\(#function)") + } + assert(selfPointer != 0, "selfPointer memory address was null") + let selfBits$ = Int(Int64(fromJNI: selfPointer, in: env$)) + guard let self$ = UnsafeMutablePointer(bitPattern: selfBits$) else { + fatalError("self memory address was null in call to \\(#function)!") + } + let result = self$.pointee.isBoolean + return result.getJNIValue(in: environment) + } + """, + """ + @_cdecl("Java_com_example_swift_MyClass__00024setBoolean__ZJ") + func Java_com_example_swift_MyClass__00024setBoolean__ZJ(environment: UnsafeMutablePointer!, thisClass: jclass, newValue: jboolean, selfPointer: jlong) { + guard let env$ = environment else { + fatalError("Missing JNIEnv in downcall to \\(#function)") + } + assert(selfPointer != 0, "selfPointer memory address was null") + let selfBits$ = Int(Int64(fromJNI: selfPointer, in: env$)) + guard let self$ = UnsafeMutablePointer(bitPattern: selfBits$) else { + fatalError("self memory address was null in call to \\(#function)!") + } + self$.pointee.isBoolean = Bool(fromJNI: newValue, in: environment!) + } + """ + ] + ) + } } From a25d2166c2d9d21638166ae997aec60542d9d6ee Mon Sep 17 00:00:00 2001 From: Mads Odgaard Date: Tue, 22 Jul 2025 12:40:04 +0200 Subject: [PATCH 320/426] [JExtract/JNI] Add support for classes/structs as parameters and return values (#326) --- .../Sources/MySwiftLibrary/MySwiftClass.swift | 12 +- .../com/example/swift/MySwiftClassTest.java | 21 ++ ...t2JavaGenerator+JavaBindingsPrinting.swift | 127 +++++------ ...ISwift2JavaGenerator+JavaTranslation.swift | 204 +++++++++++++---- ...wift2JavaGenerator+NativeTranslation.swift | 209 ++++++++++++++++++ ...ift2JavaGenerator+SwiftThunkPrinting.swift | 181 ++++++--------- Sources/JExtractSwiftLib/JNI/JNIType.swift | 82 +++++++ .../JavaConstants/JavaTypes.swift | 10 + .../JNI/JNIClassTests.swift | 164 +++++++++++--- .../JNI/JNIModuleTests.swift | 81 ++++--- .../JNI/JNIStructTests.swift | 30 ++- .../JNI/JNIVariablesTests.swift | 179 ++++++--------- 12 files changed, 883 insertions(+), 417 deletions(-) create mode 100644 Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift create mode 100644 Sources/JExtractSwiftLib/JNI/JNIType.swift diff --git a/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftClass.swift b/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftClass.swift index fd0ce488..b4447f4f 100644 --- a/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftClass.swift +++ b/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftClass.swift @@ -13,8 +13,8 @@ //===----------------------------------------------------------------------===// public class MySwiftClass { - let x: Int64 - let y: Int64 + public let x: Int64 + public let y: Int64 public let byte: UInt8 = 0 public let constant: Int64 = 100 @@ -76,4 +76,12 @@ public class MySwiftClass { public func throwingFunction() throws { throw MySwiftClassError.swiftError } + + public func sumX(with other: MySwiftClass) -> Int64 { + return self.x + other.x + } + + public func copy() -> MySwiftClass { + return MySwiftClass(x: self.x, y: self.y) + } } diff --git a/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/MySwiftClassTest.java b/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/MySwiftClassTest.java index bf244416..4425d6b2 100644 --- a/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/MySwiftClassTest.java +++ b/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/MySwiftClassTest.java @@ -118,4 +118,25 @@ void isWarm() { assertFalse(c.isWarm()); } } + + @Test + void sumWithX() { + try (var arena = new ConfinedSwiftMemorySession()) { + MySwiftClass c1 = MySwiftClass.init(20, 10, arena); + MySwiftClass c2 = MySwiftClass.init(50, 10, arena); + assertEquals(70, c1.sumX(c2)); + } + } + + @Test + void copy() { + try (var arena = new ConfinedSwiftMemorySession()) { + MySwiftClass c1 = MySwiftClass.init(20, 10, arena); + MySwiftClass c2 = c1.copy(arena); + + assertEquals(20, c2.getX()); + assertEquals(10, c2.getY()); + assertNotEquals(c1.$memoryAddress(), c2.$memoryAddress()); + } + } } \ No newline at end of file diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift index 4f4ad4d8..9c3d14b8 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift @@ -117,7 +117,7 @@ extension JNISwift2JavaGenerator { printer.println() for initializer in decl.initializers { - printInitializerBindings(&printer, initializer, type: decl) + printFunctionBinding(&printer, initializer) printer.println() } @@ -176,75 +176,82 @@ extension JNISwift2JavaGenerator { } private func printFunctionBinding(_ printer: inout CodePrinter, _ decl: ImportedFunc) { - guard let _ = translatedDecl(for: decl) else { + guard let translatedDecl = translatedDecl(for: decl) else { // Failed to translate. Skip. return } + var modifiers = ["public"] if decl.isStatic || decl.isInitializer || !decl.hasParent { - printStaticFunctionBinding(&printer, decl) - } else { - printMemberMethodBindings(&printer, decl) + modifiers.append("static") } - } - private func printStaticFunctionBinding(_ printer: inout CodePrinter, _ decl: ImportedFunc) { - printDeclDocumentation(&printer, decl) - printer.print( - "public static native \(renderFunctionSignature(decl));" - ) - } + let translatedSignature = translatedDecl.translatedFunctionSignature + let resultType = translatedSignature.resultType.javaType + var parameters = translatedDecl.translatedFunctionSignature.parameters.map(\.parameter.asParameter) + if translatedSignature.requiresSwiftArena { + parameters.append("SwiftArena swiftArena$") + } + let throwsClause = decl.isThrowing ? " throws Exception" : "" - /// Renders Java bindings for member methods - /// - /// Member methods are generated as a function that extracts the `selfPointer` - /// and passes it down to another native function along with the arguments - /// to call the Swift implementation. - private func printMemberMethodBindings(_ printer: inout CodePrinter, _ decl: ImportedFunc) { - let translatedDecl = translatedDecl(for: decl)! // We will only call this method if we can translate the decl. + let modifiersStr = modifiers.joined(separator: " ") + let parametersStr = parameters.joined(separator: ", ") printDeclDocumentation(&printer, decl) - printer.printBraceBlock("public \(renderFunctionSignature(decl))") { printer in - var arguments = translatedDecl.translatedFunctionSignature.parameters.map(\.name) - - let selfVarName = "self$" - arguments.append(selfVarName) + printer.printBraceBlock( + "\(modifiersStr) \(resultType) \(translatedDecl.name)(\(parametersStr))\(throwsClause)" + ) { printer in + printDowncall(&printer, decl) + } - let returnKeyword = translatedDecl.translatedFunctionSignature.resultType.isVoid ? "" : "return " + printNativeFunction(&printer, decl) + } - printer.print( - """ - long \(selfVarName) = this.$memoryAddress(); - \(returnKeyword)\(translatedDecl.parentName).$\(translatedDecl.name)(\(arguments.joined(separator: ", "))); - """ - ) + private func printNativeFunction(_ printer: inout CodePrinter, _ decl: ImportedFunc) { + let translatedDecl = translatedDecl(for: decl)! // Will always call with valid decl + let nativeSignature = translatedDecl.nativeFunctionSignature + let resultType = nativeSignature.result.javaType + var parameters = nativeSignature.parameters + if let selfParameter = nativeSignature.selfParameter { + parameters.append(selfParameter) } + let renderedParameters = parameters.map { "\($0.javaParameter.type) \($0.javaParameter.name)"}.joined(separator: ", ") - let returnType = translatedDecl.translatedFunctionSignature.resultType - var parameters = translatedDecl.translatedFunctionSignature.parameters.map(\.asParameter) - parameters.append("long selfPointer") - printer.print("private static native \(returnType) $\(translatedDecl.name)(\(parameters.joined(separator: ", ")));") + printer.print("private static native \(resultType) \(translatedDecl.nativeFunctionName)(\(renderedParameters));") } - private func printInitializerBindings(_ printer: inout CodePrinter, _ decl: ImportedFunc, type: ImportedNominalType) { - guard let translatedDecl = translatedDecl(for: decl) else { - // Failed to translate. Skip. - return + private func printDowncall( + _ printer: inout CodePrinter, + _ decl: ImportedFunc + ) { + let translatedDecl = translatedDecl(for: decl)! // We will only call this method if we can translate the decl. + let translatedFunctionSignature = translatedDecl.translatedFunctionSignature + + // Regular parameters. + var arguments = [String]() + for parameter in translatedFunctionSignature.parameters { + let lowered = parameter.conversion.render(&printer, parameter.parameter.name) + arguments.append(lowered) } - printDeclDocumentation(&printer, decl) - printer.printBraceBlock("public static \(renderFunctionSignature(decl))") { printer in - let initArguments = translatedDecl.translatedFunctionSignature.parameters.map(\.name) - printer.print( - """ - long self$ = \(type.qualifiedName).allocatingInit(\(initArguments.joined(separator: ", "))); - return new \(type.qualifiedName)(self$, swiftArena$); - """ - ) + // 'self' parameter. + if let selfParameter = translatedFunctionSignature.selfParameter { + let lowered = selfParameter.conversion.render(&printer, "this") + arguments.append(lowered) } - let parameters = translatedDecl.translatedFunctionSignature.parameters.map(\.asParameter) - printer.print("private static native long allocatingInit(\(parameters.joined(separator: ", ")));") + //=== Part 3: Downcall. + // TODO: If we always generate a native method and a "public" method, we can actually choose our own thunk names + // using the registry? + let downcall = "\(translatedDecl.parentName).\(translatedDecl.nativeFunctionName)(\(arguments.joined(separator: ", ")))" + + //=== Part 4: Convert the return value. + if translatedFunctionSignature.resultType.javaType.isVoid { + printer.print("\(downcall);") + } else { + let result = translatedFunctionSignature.resultType.conversion.render(&printer, downcall) + printer.print("return \(result);") + } } private func printDeclDocumentation(_ printer: inout CodePrinter, _ decl: ImportedFunc) { @@ -288,24 +295,4 @@ extension JNISwift2JavaGenerator { ) } } - - /// Renders a Java function signature - /// - /// `func method(x: Int, y: Int) -> Int` becomes - /// `long method(long x, long y)` - private func renderFunctionSignature(_ decl: ImportedFunc) -> String { - guard let translatedDecl = translatedDecl(for: decl) else { - fatalError("Unable to render function signature for a function that cannot be translated: \(decl)") - } - let resultType = translatedDecl.translatedFunctionSignature.resultType - var parameters = translatedDecl.translatedFunctionSignature.parameters.map(\.asParameter) - - if decl.isInitializer { - parameters.append("SwiftArena swiftArena$") - } - - let throwsClause = decl.isThrowing ? " throws Exception" : "" - - return "\(resultType) \(translatedDecl.name)(\(parameters.joined(separator: ", ")))\(throwsClause)" - } } diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift index 2e3ffff8..e0253624 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift @@ -39,7 +39,16 @@ extension JNISwift2JavaGenerator { let swiftModuleName: String func translate(_ decl: ImportedFunc) throws -> TranslatedFunctionDecl { + let nativeTranslation = NativeJavaTranslation() + + // Swift -> Java let translatedFunctionSignature = try translate(functionSignature: decl.functionSignature) + // Java -> Java (native) + let nativeFunctionSignature = try nativeTranslation.translate( + functionSignature: decl.functionSignature, + translatedFunctionSignature: translatedFunctionSignature + ) + // Types with no parent will be outputted inside a "module" class. let parentName = decl.parentType?.asNominalType?.nominalTypeDecl.qualifiedName ?? swiftModuleName @@ -52,68 +61,99 @@ extension JNISwift2JavaGenerator { return TranslatedFunctionDecl( name: javaName, + nativeFunctionName: "$\(javaName)", parentName: parentName, - translatedFunctionSignature: translatedFunctionSignature + translatedFunctionSignature: translatedFunctionSignature, + nativeFunctionSignature: nativeFunctionSignature ) } - func translate(functionSignature: SwiftFunctionSignature, isInitializer: Bool = false) throws -> TranslatedFunctionSignature { + func translate(functionSignature: SwiftFunctionSignature) throws -> TranslatedFunctionSignature { let parameters = try functionSignature.parameters.enumerated().map { idx, param in let parameterName = param.parameterName ?? "arg\(idx))" - return try translate(swiftParam: param, parameterName: parameterName) + return try translateParameter(swiftType: param.type, parameterName: parameterName) + } + + // 'self' + let selfParameter: TranslatedParameter? + if case .instance(let swiftSelf) = functionSignature.selfParameter { + selfParameter = try self.translateParameter( + swiftType: swiftSelf.type, + parameterName: swiftSelf.parameterName ?? "self" + ) + } else { + selfParameter = nil } return try TranslatedFunctionSignature( + selfParameter: selfParameter, parameters: parameters, - resultType: translate(swiftType: functionSignature.result.type) - ) - } - - func translate(swiftParam: SwiftParameter, parameterName: String) throws -> JavaParameter { - return try JavaParameter( - name: parameterName, - type: translate(swiftType: swiftParam.type) + resultType: translate(swiftResult: functionSignature.result) ) } - func translate(swiftType: SwiftType) throws -> JavaType { + func translateParameter(swiftType: SwiftType, parameterName: String) throws -> TranslatedParameter { switch swiftType { case .nominal(let nominalType): if let knownType = nominalType.nominalTypeDecl.knownTypeKind { - guard let javaType = translate(knownType: knownType) else { + guard let javaType = JNISwift2JavaGenerator.translate(knownType: knownType) else { throw JavaTranslationError.unsupportedSwiftType(swiftType) } - return javaType + + return TranslatedParameter( + parameter: JavaParameter(name: parameterName, type: javaType), + conversion: .placeholder + ) } - return .class(package: nil, name: nominalType.nominalTypeDecl.name) + // For now, we assume this is a JExtract class. + return TranslatedParameter( + parameter: JavaParameter( + name: parameterName, + type: .class(package: nil, name: nominalType.nominalTypeDecl.name) + ), + conversion: .valueMemoryAddress(.placeholder) + ) case .tuple([]): - return .void + return TranslatedParameter( + parameter: JavaParameter(name: parameterName, type: .void), + conversion: .placeholder + ) case .metatype, .optional, .tuple, .function, .existential, .opaque: throw JavaTranslationError.unsupportedSwiftType(swiftType) } } - func translate(knownType: SwiftKnownTypeDeclKind) -> JavaType? { - switch knownType { - case .bool: .boolean - case .int8: .byte - case .uint16: .char - case .int16: .short - case .int32: .int - case .int64: .long - case .float: .float - case .double: .double - case .void: .void - case .string: .javaLangString - case .int, .uint, .uint8, .uint32, .uint64, - .unsafeRawPointer, .unsafeMutableRawPointer, - .unsafePointer, .unsafeMutablePointer, - .unsafeRawBufferPointer, .unsafeMutableRawBufferPointer, - .unsafeBufferPointer, .unsafeMutableBufferPointer, .optional, .data, .dataProtocol: - nil + func translate( + swiftResult: SwiftResult + ) throws -> TranslatedResult { + switch swiftResult.type { + case .nominal(let nominalType): + if let knownType = nominalType.nominalTypeDecl.knownTypeKind { + guard let javaType = JNISwift2JavaGenerator.translate(knownType: knownType) else { + throw JavaTranslationError.unsupportedSwiftType(swiftResult.type) + } + + return TranslatedResult( + javaType: javaType, + conversion: .placeholder + ) + } + + // For now, we assume this is a JExtract class. + let javaType = JavaType.class(package: nil, name: nominalType.nominalTypeDecl.name) + return TranslatedResult( + javaType: javaType, + conversion: .constructSwiftValue(.placeholder, javaType) + ) + + case .tuple([]): + return TranslatedResult(javaType: .void, conversion: .placeholder) + + case .metatype, .optional, .tuple, .function, .existential, .opaque: + throw JavaTranslationError.unsupportedSwiftType(swiftResult.type) } } } @@ -122,16 +162,106 @@ extension JNISwift2JavaGenerator { /// Java function name let name: String + /// The name of the native function + let nativeFunctionName: String + /// The name of the Java parent scope this function is declared in let parentName: String - /// Function signature + /// Function signature of the Java function the user will call let translatedFunctionSignature: TranslatedFunctionSignature + + /// Function signature of the native function that will be implemented by Swift + let nativeFunctionSignature: NativeFunctionSignature + } + + static func translate(knownType: SwiftKnownTypeDeclKind) -> JavaType? { + switch knownType { + case .bool: .boolean + case .int8: .byte + case .uint16: .char + case .int16: .short + case .int32: .int + case .int64: .long + case .float: .float + case .double: .double + case .void: .void + case .string: .javaLangString + case .int, .uint, .uint8, .uint32, .uint64, + .unsafeRawPointer, .unsafeMutableRawPointer, + .unsafePointer, .unsafeMutablePointer, + .unsafeRawBufferPointer, .unsafeMutableRawBufferPointer, + .unsafeBufferPointer, .unsafeMutableBufferPointer, .optional, .data, .dataProtocol: + nil + } } struct TranslatedFunctionSignature { - let parameters: [JavaParameter] - let resultType: JavaType + let selfParameter: TranslatedParameter? + let parameters: [TranslatedParameter] + let resultType: TranslatedResult + + var requiresSwiftArena: Bool { + return self.resultType.conversion.requiresSwiftArena + } + } + + /// Represent a Swift API parameter translated to Java. + struct TranslatedParameter { + let parameter: JavaParameter + let conversion: JavaNativeConversionStep + } + + /// Represent a Swift API result translated to Java. + struct TranslatedResult { + let javaType: JavaType + + /// Represents how to convert the Java native result into a user-facing result. + let conversion: JavaNativeConversionStep + } + + /// Describes how to convert values between Java types and the native Java function + enum JavaNativeConversionStep { + /// The value being converted + case placeholder + + /// `value.$memoryAddress()` + indirect case valueMemoryAddress(JavaNativeConversionStep) + + /// Call `new \(Type)(\(placeholder), swiftArena$)` + indirect case constructSwiftValue(JavaNativeConversionStep, JavaType) + + /// Returns the conversion string applied to the placeholder. + func render(_ printer: inout CodePrinter, _ placeholder: String) -> String { + // NOTE: 'printer' is used if the conversion wants to cause side-effects. + // E.g. storing a temporary values into a variable. + switch self { + case .placeholder: + return placeholder + + case .valueMemoryAddress: + return "\(placeholder).$memoryAddress()" + + case .constructSwiftValue(let inner, let javaType): + let inner = inner.render(&printer, placeholder) + return "new \(javaType.className!)(\(inner), swiftArena$)" + + } + } + + /// Whether the conversion uses SwiftArena. + var requiresSwiftArena: Bool { + switch self { + case .placeholder: + return false + + case .constructSwiftValue: + return true + + case .valueMemoryAddress(let inner): + return inner.requiresSwiftArena + } + } } enum JavaTranslationError: Error { diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift new file mode 100644 index 00000000..461c7301 --- /dev/null +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift @@ -0,0 +1,209 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import JavaTypes + +extension JNISwift2JavaGenerator { + + struct NativeJavaTranslation { + /// Translates a Swift function into the native JNI method signature. + func translate( + functionSignature: SwiftFunctionSignature, + translatedFunctionSignature: TranslatedFunctionSignature + ) throws -> NativeFunctionSignature { + let parameters = try zip(translatedFunctionSignature.parameters, functionSignature.parameters).map { translatedParameter, swiftParameter in + let parameterName = translatedParameter.parameter.name + return try translate(swiftParameter: swiftParameter, parameterName: parameterName) + } + + // Lower the self parameter. + let nativeSelf: NativeParameter? = switch functionSignature.selfParameter { + case .instance(let selfParameter): + try translate( + swiftParameter: selfParameter, + parameterName: selfParameter.parameterName ?? "self" + ) + case nil, .initializer(_), .staticMethod(_): + nil + } + + return try NativeFunctionSignature( + selfParameter: nativeSelf, + parameters: parameters, + result: translate(swiftResult: functionSignature.result) + ) + } + + func translate( + swiftParameter: SwiftParameter, + parameterName: String + ) throws -> NativeParameter { + switch swiftParameter.type { + case .nominal(let nominalType): + if let knownType = nominalType.nominalTypeDecl.knownTypeKind { + guard let javaType = JNISwift2JavaGenerator.translate(knownType: knownType), javaType.implementsJavaValue else { + throw JavaTranslationError.unsupportedSwiftType(swiftParameter.type) + } + + return NativeParameter( + javaParameter: JavaParameter(name: parameterName, type: javaType), + conversion: .initFromJNI(.placeholder, swiftType: swiftParameter.type) + ) + } + + case .tuple([]): + return NativeParameter( + javaParameter: JavaParameter(name: parameterName, type: .void), + conversion: .placeholder + ) + + case .metatype, .optional, .tuple, .function, .existential, .opaque: + throw JavaTranslationError.unsupportedSwiftType(swiftParameter.type) + } + + // Classes are passed as the pointer. + return NativeParameter( + javaParameter: JavaParameter(name: parameterName, type: .long), + conversion: .pointee(.extractSwiftValue(.placeholder, swiftType: swiftParameter.type)) + ) + } + + func translate( + swiftResult: SwiftResult + ) throws -> NativeResult { + switch swiftResult.type { + case .nominal(let nominalType): + if let knownType = nominalType.nominalTypeDecl.knownTypeKind { + guard let javaType = JNISwift2JavaGenerator.translate(knownType: knownType), javaType.implementsJavaValue else { + throw JavaTranslationError.unsupportedSwiftType(swiftResult.type) + } + + return NativeResult( + javaType: javaType, + conversion: .getJNIValue(.placeholder) + ) + } + + case .tuple([]): + return NativeResult( + javaType: .void, + conversion: .placeholder + ) + + case .metatype, .optional, .tuple, .function, .existential, .opaque: + throw JavaTranslationError.unsupportedSwiftType(swiftResult.type) + } + + // TODO: Handle other classes, for example from JavaKit macros. + // for now we assume all passed in classes are JExtract generated + // so we pass the pointer. + return NativeResult( + javaType: .long, + conversion: .getJNIValue(.allocateSwiftValue(name: "result", swiftType: swiftResult.type)) + ) + } + } + + struct NativeFunctionSignature { + let selfParameter: NativeParameter? + let parameters: [NativeParameter] + let result: NativeResult + } + + struct NativeParameter { + let javaParameter: JavaParameter + + var jniType: JNIType { + javaParameter.type.jniType + } + + /// Represents how to convert the JNI parameter to a Swift parameter + let conversion: NativeSwiftConversionStep + } + + struct NativeResult { + let javaType: JavaType + let conversion: NativeSwiftConversionStep + } + + /// Describes how to convert values between Java types and Swift through JNI + enum NativeSwiftConversionStep { + /// The value being converted + case placeholder + + /// `value.getJNIValue(in:)` + indirect case getJNIValue(NativeSwiftConversionStep) + + /// `SwiftType(from: value, in: environment!)` + indirect case initFromJNI(NativeSwiftConversionStep, swiftType: SwiftType) + + /// Extracts a swift type at a pointer given by a long. + indirect case extractSwiftValue(NativeSwiftConversionStep, swiftType: SwiftType) + + /// Allocate memory for a Swift value and outputs the pointer + indirect case allocateSwiftValue(name: String, swiftType: SwiftType) + + /// The thing to which the pointer typed, which is the `pointee` property + /// of the `Unsafe(Mutable)Pointer` types in Swift. + indirect case pointee(NativeSwiftConversionStep) + + + /// Returns the conversion string applied to the placeholder. + func render(_ printer: inout CodePrinter, _ placeholder: String) -> String { + // NOTE: 'printer' is used if the conversion wants to cause side-effects. + // E.g. storing a temporary values into a variable. + switch self { + case .placeholder: + return placeholder + + case .getJNIValue(let inner): + let inner = inner.render(&printer, placeholder) + return "\(inner).getJNIValue(in: environment!)" + + case .initFromJNI(let inner, let swiftType): + let inner = inner.render(&printer, placeholder) + return "\(swiftType)(fromJNI: \(inner), in: environment!)" + + case .extractSwiftValue(let inner, let swiftType): + let inner = inner.render(&printer, placeholder) + printer.print( + """ + assert(\(inner) != 0, "\(inner) memory address was null") + let \(inner)Bits$ = Int(Int64(fromJNI: \(inner), in: environment!)) + guard let \(inner)$ = UnsafeMutablePointer<\(swiftType)>(bitPattern: \(inner)Bits$) else { + fatalError("\(inner) memory address was null in call to \\(#function)!") + } + """ + ) + return "\(inner)$" + + case .allocateSwiftValue(let name, let swiftType): + let pointerName = "\(name)$" + let bitsName = "\(name)Bits$" + printer.print( + """ + let \(pointerName) = UnsafeMutablePointer<\(swiftType)>.allocate(capacity: 1) + \(pointerName).initialize(to: \(placeholder)) + let \(bitsName) = Int64(Int(bitPattern: \(pointerName))) + """ + ) + return bitsName + + case .pointee(let inner): + let inner = inner.render(&printer, placeholder) + return "\(inner).pointee" + } + } + } +} diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift index 38d4ff79..d8b6b275 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift @@ -98,7 +98,7 @@ extension JNISwift2JavaGenerator { printHeader(&printer) for initializer in type.initializers { - printInitializerThunk(&printer, initializer) + printSwiftFunctionThunk(&printer, initializer) printer.println() } @@ -115,141 +115,105 @@ extension JNISwift2JavaGenerator { printDestroyFunctionThunk(&printer, type) } - private func printInitializerThunk(_ printer: inout CodePrinter, _ decl: ImportedFunc) { - guard let translatedDecl = translatedDecl(for: decl) else { - // Failed to translate. Skip. - return - } - - let typeName = translatedDecl.parentName - - printCDecl( - &printer, - javaMethodName: "allocatingInit", - parentName: translatedDecl.parentName, - parameters: translatedDecl.translatedFunctionSignature.parameters, - isStatic: true, - resultType: .long - ) { printer in - let downcallArguments = renderDowncallArguments( - swiftFunctionSignature: decl.functionSignature, - translatedFunctionSignature: translatedDecl.translatedFunctionSignature - ) - // TODO: Throwing initializers - printer.print( - """ - let self$ = UnsafeMutablePointer<\(typeName)>.allocate(capacity: 1) - self$.initialize(to: \(typeName)(\(downcallArguments))) - return Int64(Int(bitPattern: self$)).getJNIValue(in: environment) - """ - ) - } - } - private func printSwiftFunctionThunk( _ printer: inout CodePrinter, _ decl: ImportedFunc ) { - guard let _ = translatedDecl(for: decl) else { + guard let translatedDecl = translatedDecl(for: decl) else { // Failed to translate. Skip. return } - // Free functions does not have a parent - if decl.isStatic || !decl.hasParent { - self.printSwiftStaticFunctionThunk(&printer, decl) - } else { - self.printSwiftMemberFunctionThunk(&printer, decl) - } - } + let nativeSignature = translatedDecl.nativeFunctionSignature + var parameters = nativeSignature.parameters - private func printSwiftStaticFunctionThunk(_ printer: inout CodePrinter, _ decl: ImportedFunc) { - let translatedDecl = self.translatedDecl(for: decl)! // We will only call this method if we can translate the decl. - - printCDecl( - &printer, - javaMethodName: translatedDecl.name, - parentName: translatedDecl.parentName, - parameters: translatedDecl.translatedFunctionSignature.parameters, - isStatic: true, - resultType: translatedDecl.translatedFunctionSignature.resultType - ) { printer in - // For free functions the parent is the Swift module - let parentName = decl.parentType?.asNominalTypeDeclaration?.qualifiedName ?? swiftModuleName - self.printFunctionDowncall(&printer, decl, calleeName: parentName) + if let selfParameter = nativeSignature.selfParameter { + parameters.append(selfParameter) } - } - - private func printSwiftMemberFunctionThunk(_ printer: inout CodePrinter, _ decl: ImportedFunc) { - let translatedDecl = self.translatedDecl(for: decl)! // We will only call this method if can translate the decl. - let swiftParentName = decl.parentType!.asNominalTypeDeclaration!.qualifiedName - let selfPointerParam = JavaParameter(name: "selfPointer", type: .long) printCDecl( &printer, - javaMethodName: "$\(translatedDecl.name)", + javaMethodName: translatedDecl.nativeFunctionName, parentName: translatedDecl.parentName, - parameters: translatedDecl.translatedFunctionSignature.parameters + [ - selfPointerParam - ], - isStatic: true, - resultType: translatedDecl.translatedFunctionSignature.resultType + parameters: parameters.map(\.javaParameter), + resultType: nativeSignature.result.javaType.jniType ) { printer in - let selfVar = self.printSelfJLongToUnsafeMutablePointer(&printer, - swiftParentName: swiftParentName, selfPointerParam) - self.printFunctionDowncall(&printer, decl, calleeName: "\(selfVar).pointee") + self.printFunctionDowncall(&printer, decl) } } private func printFunctionDowncall( _ printer: inout CodePrinter, - _ decl: ImportedFunc, - calleeName: String + _ decl: ImportedFunc ) { guard let translatedDecl = self.translatedDecl(for: decl) else { fatalError("Cannot print function downcall for a function that can't be translated: \(decl)") } - let swiftReturnType = decl.functionSignature.result.type + let nativeSignature = translatedDecl.nativeFunctionSignature let tryClause: String = decl.isThrowing ? "try " : "" + // Regular parameters. + var arguments = [String]() + for parameter in nativeSignature.parameters { + let lowered = parameter.conversion.render(&printer, parameter.javaParameter.name) + arguments.append(lowered) + } + + // Callee + let callee: String = switch decl.functionSignature.selfParameter { + case .instance(let swiftSelf): + nativeSignature.selfParameter!.conversion.render( + &printer, + swiftSelf.parameterName ?? "self" + ) + case .staticMethod(let selfType), .initializer(let selfType): + "\(selfType)" + case .none: + swiftModuleName + } + + // Build the result let result: String switch decl.apiKind { case .function, .initializer: - let downcallParameters = renderDowncallArguments( - swiftFunctionSignature: decl.functionSignature, - translatedFunctionSignature: translatedDecl.translatedFunctionSignature - ) - result = "\(tryClause)\(calleeName).\(decl.name)(\(downcallParameters))" + let downcallArguments = zip( + decl.functionSignature.parameters, + arguments + ).map { originalParam, argument in + let label = originalParam.argumentLabel.map { "\($0): " } ?? "" + return "\(label)\(argument)" + } + .joined(separator: ", ") + result = "\(tryClause)\(callee).\(decl.name)(\(downcallArguments))" case .getter: - result = "\(tryClause)\(calleeName).\(decl.name)" + result = "\(tryClause)\(callee).\(decl.name)" case .setter: - guard let newValueParameter = decl.functionSignature.parameters.first else { + guard let newValueArgument = arguments.first else { fatalError("Setter did not contain newValue parameter: \(decl)") } - result = "\(calleeName).\(decl.name) = \(renderJNIToSwiftConversion("newValue", type: newValueParameter.type))" + result = "\(callee).\(decl.name) = \(newValueArgument)" } - let returnStatement = - if swiftReturnType.isVoid { - result + // Lower the result. + let innerBody: String + if !decl.functionSignature.result.type.isVoid { + let loweredResult = nativeSignature.result.conversion.render(&printer, result) + innerBody = "return \(loweredResult)" } else { - """ - let result = \(result) - return result.getJNIValue(in: environment) - """ + innerBody = result } if decl.isThrowing { - let dummyReturn = - !swiftReturnType.isVoid ? "return \(swiftReturnType).jniPlaceholderValue" : "" + // TODO: Handle classes for dummy value + let dummyReturn = !nativeSignature.result.javaType.isVoid ? "return \(decl.functionSignature.result.type).jniPlaceholderValue" : "" printer.print( """ do { - \(returnStatement) + \(innerBody) } catch { environment.throwAsException(error) \(dummyReturn) @@ -257,7 +221,7 @@ extension JNISwift2JavaGenerator { """ ) } else { - printer.print(returnStatement) + printer.print(innerBody) } } @@ -266,8 +230,7 @@ extension JNISwift2JavaGenerator { javaMethodName: String, parentName: String, parameters: [JavaParameter], - isStatic: Bool, - resultType: JavaType, + resultType: JNIType, _ body: (inout CodePrinter) -> Void ) { let jniSignature = parameters.reduce(into: "") { signature, parameter in @@ -283,16 +246,15 @@ extension JNISwift2JavaGenerator { + jniSignature.escapedJNIIdentifier let translatedParameters = parameters.map { - "\($0.name): \($0.type.jniTypeName)" + "\($0.name): \($0.type.jniType)" } - let thisParameter = isStatic ? "thisClass: jclass" : "thisObject: jobject" let thunkParameters = [ "environment: UnsafeMutablePointer!", - thisParameter + "thisClass: jclass" ] + translatedParameters - let thunkReturnType = !resultType.isVoid ? " -> \(resultType.jniTypeName)" : "" + let thunkReturnType = resultType != .void ? " -> \(resultType)" : "" // TODO: Think about function overloads printer.printBraceBlock( @@ -326,7 +288,6 @@ extension JNISwift2JavaGenerator { parameters: [ selfPointerParam ], - isStatic: true, resultType: .void ) { printer in let parentName = type.qualifiedName @@ -347,7 +308,9 @@ extension JNISwift2JavaGenerator { /// - Returns: name of the created "self" variable private func printSelfJLongToUnsafeMutablePointer( _ printer: inout CodePrinter, - swiftParentName: String, _ selfPointerParam: JavaParameter) -> String { + swiftParentName: String, + _ selfPointerParam: JavaParameter + ) -> String { let newSelfParamName = "self$" printer.print( """ @@ -363,26 +326,6 @@ extension JNISwift2JavaGenerator { ) return newSelfParamName } - - - /// Renders the arguments for making a downcall - private func renderDowncallArguments( - swiftFunctionSignature: SwiftFunctionSignature, - translatedFunctionSignature: TranslatedFunctionSignature - ) -> String { - zip( - swiftFunctionSignature.parameters, - translatedFunctionSignature.parameters - ).map { originalParam, translatedParam in - let label = originalParam.argumentLabel.map { "\($0): " } ?? "" - return "\(label)\(originalParam.type)(fromJNI: \(translatedParam.name), in: environment!)" - } - .joined(separator: ", ") - } - - private func renderJNIToSwiftConversion(_ variableName: String, type: SwiftType) -> String { - "\(type)(fromJNI: \(variableName), in: environment!)" - } } extension String { diff --git a/Sources/JExtractSwiftLib/JNI/JNIType.swift b/Sources/JExtractSwiftLib/JNI/JNIType.swift new file mode 100644 index 00000000..d152942a --- /dev/null +++ b/Sources/JExtractSwiftLib/JNI/JNIType.swift @@ -0,0 +1,82 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import JavaTypes + +/// Represents types that are able to be passed over a JNI boundary. +/// +/// - SeeAlso: https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/types.html +enum JNIType { + case jboolean + case jfloat + case jdouble + case jbyte + case jchar + case jshort + case jint + case jlong + case void + case jstring + case jclass + case jthrowable + case jobject + case jbooleanArray + case jbyteArray + case jcharArray + case jshortArray + case jintArray + case jlongArray + case jfloatArray + case jdoubleArray + case jobjectArray +} + +extension JavaType { + var jniType: JNIType { + switch self { + case .boolean: .jboolean + case .byte: .jbyte + case .char: .jchar + case .short: .jshort + case .int: .jint + case .long: .jlong + case .float: .jfloat + case .double: .jdouble + case .void: .void + case .array(.boolean): .jbooleanArray + case .array(.byte): .jbyteArray + case .array(.char): .jcharArray + case .array(.short): .jshortArray + case .array(.int): .jintArray + case .array(.long): .jlongArray + case .array(.float): .jfloatArray + case .array(.double): .jdoubleArray + case .array: .jobjectArray + case .javaLangString: .jstring + case .javaLangClass: .jclass + case .javaLangThrowable: .jthrowable + case .class: .jobject + } + } + + /// Returns whether this type returns `JavaValue` from JavaKit + var implementsJavaValue: Bool { + switch self { + case .boolean, .byte, .char, .short, .int, .long, .float, .double, .void, .javaLangString: + true + default: + false + } + } +} diff --git a/Sources/JExtractSwiftLib/JavaConstants/JavaTypes.swift b/Sources/JExtractSwiftLib/JavaConstants/JavaTypes.swift index 633943ef..02850801 100644 --- a/Sources/JExtractSwiftLib/JavaConstants/JavaTypes.swift +++ b/Sources/JExtractSwiftLib/JavaConstants/JavaTypes.swift @@ -29,4 +29,14 @@ extension JavaType { static var javaLangRunnable: JavaType { .class(package: "java.lang", name: "Runnable") } + + /// The description of the type java.lang.Class. + static var javaLangClass: JavaType { + .class(package: "java.lang", name: "Class") + } + + /// The description of the type java.lang.Throwable. + static var javaLangThrowable: JavaType { + .class(package: "java.lang", name: "Throwable") + } } diff --git a/Tests/JExtractSwiftTests/JNI/JNIClassTests.swift b/Tests/JExtractSwiftTests/JNI/JNIClassTests.swift index 5970e7a0..cfe78fbd 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIClassTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIClassTests.swift @@ -35,6 +35,9 @@ struct JNIClassTests { } public func doSomething(x: Int64) {} + + public func copy() -> MyClass {} + public func isEqual(to other: MyClass) -> Bool {} } """ @@ -103,7 +106,12 @@ struct JNIClassTests { * public static func method() * } */ - public static native void method(); + public static void method() { + MyClass.$method(); + } + """, + """ + private static native void $method(); """ ] ) @@ -118,8 +126,8 @@ struct JNIClassTests { detectChunkByInitialLines: 1, expectedChunks: [ """ - @_cdecl("Java_com_example_swift_MyClass_method__") - func Java_com_example_swift_MyClass_method__(environment: UnsafeMutablePointer!, thisClass: jclass) { + @_cdecl("Java_com_example_swift_MyClass__00024method__") + func Java_com_example_swift_MyClass__00024method__(environment: UnsafeMutablePointer!, thisClass: jclass) { MyClass.method() } """ @@ -142,8 +150,7 @@ struct JNIClassTests { * } */ public static MyClass init(long x, long y, SwiftArena swiftArena$) { - long self$ = MyClass.allocatingInit(x, y); - return new MyClass(self$, swiftArena$); + return new MyClass(MyClass.$init(x, y), swiftArena$); } """, """ @@ -154,15 +161,14 @@ struct JNIClassTests { * } */ public static MyClass init(SwiftArena swiftArena$) { - long self$ = MyClass.allocatingInit(); - return new MyClass(self$, swiftArena$); + return new MyClass(MyClass.$init(), swiftArena$); } """, """ - private static native long allocatingInit(long x, long y); + private static native long $init(long x, long y); """, """ - private static native long allocatingInit(); + private static native long $init(); """ ] ) @@ -177,19 +183,21 @@ struct JNIClassTests { detectChunkByInitialLines: 1, expectedChunks: [ """ - @_cdecl("Java_com_example_swift_MyClass_allocatingInit__") - func Java_com_example_swift_MyClass_allocatingInit__(environment: UnsafeMutablePointer!, thisClass: jclass) -> jlong { - let self$ = UnsafeMutablePointer.allocate(capacity: 1) - self$.initialize(to: MyClass()) - return Int64(Int(bitPattern: self$)).getJNIValue(in: environment) + @_cdecl("Java_com_example_swift_MyClass__00024init__JJ") + func Java_com_example_swift_MyClass__00024init__JJ(environment: UnsafeMutablePointer!, thisClass: jclass, x: jlong, y: jlong) -> jlong { + let result$ = UnsafeMutablePointer.allocate(capacity: 1) + result$.initialize(to: MyClass.init(x: Int64(fromJNI: x, in: environment!), y: Int64(fromJNI: y, in: environment!))) + let resultBits$ = Int64(Int(bitPattern: result$)) + return resultBits$.getJNIValue(in: environment!) } """, """ - @_cdecl("Java_com_example_swift_MyClass_allocatingInit__JJ") - func Java_com_example_swift_MyClass_allocatingInit__JJ(environment: UnsafeMutablePointer!, thisClass: jclass, x: jlong, y: jlong) -> jlong { - let self$ = UnsafeMutablePointer.allocate(capacity: 1) - self$.initialize(to: MyClass(x: Int64(fromJNI: x, in: environment!), y: Int64(fromJNI: y, in: environment!))) - return Int64(Int(bitPattern: self$)).getJNIValue(in: environment) + @_cdecl("Java_com_example_swift_MyClass__00024init__") + func Java_com_example_swift_MyClass__00024init__(environment: UnsafeMutablePointer!, thisClass: jclass) -> jlong { + let result$ = UnsafeMutablePointer.allocate(capacity: 1) + result$.initialize(to: MyClass.init()) + let resultBits$ = Int64(Int(bitPattern: result$)) + return resultBits$.getJNIValue(in: environment!) } """ ] @@ -238,12 +246,11 @@ struct JNIClassTests { * } */ public void doSomething(long x) { - long self$ = this.$memoryAddress(); - MyClass.$doSomething(x, self$); + MyClass.$doSomething(x, this.$memoryAddress()); } """, """ - private static native void $doSomething(long x, long selfPointer); + private static native void $doSomething(long x, long self); """ ] ) @@ -259,12 +266,9 @@ struct JNIClassTests { expectedChunks: [ """ @_cdecl("Java_com_example_swift_MyClass__00024doSomething__JJ") - func Java_com_example_swift_MyClass__00024doSomething__JJ(environment: UnsafeMutablePointer!, thisClass: jclass, x: jlong, selfPointer: jlong) { - guard let env$ = environment else { - fatalError("Missing JNIEnv in downcall to \\(#function)") - } - assert(selfPointer != 0, "selfPointer memory address was null") - let selfBits$ = Int(Int64(fromJNI: selfPointer, in: env$)) + func Java_com_example_swift_MyClass__00024doSomething__JJ(environment: UnsafeMutablePointer!, thisClass: jclass, x: jlong, self: jlong) { + assert(self != 0, "self memory address was null") + let selfBits$ = Int(Int64(fromJNI: self, in: environment!)) guard let self$ = UnsafeMutablePointer(bitPattern: selfBits$) else { fatalError("self memory address was null in call to \\(#function)!") } @@ -274,4 +278,108 @@ struct JNIClassTests { ] ) } + + @Test + func methodReturningClass_javaBindings() throws { + try assertOutput( + input: source, + .jni, + .java, + expectedChunks: [ + """ + /** + * Downcall to Swift: + * {@snippet lang=swift : + * public func copy() -> MyClass + * } + */ + public MyClass copy(SwiftArena swiftArena$) { + return new MyClass(MyClass.$copy(this.$memoryAddress()), swiftArena$); + } + """, + """ + private static native long $copy(long self); + """ + ] + ) + } + + @Test + func methodReturningClass_swiftThunks() throws { + try assertOutput( + input: source, + .jni, + .swift, + detectChunkByInitialLines: 1, + expectedChunks: [ + """ + @_cdecl("Java_com_example_swift_MyClass__00024copy__J") + func Java_com_example_swift_MyClass__00024copy__J(environment: UnsafeMutablePointer!, thisClass: jclass, self: jlong) -> jlong { + assert(self != 0, "self memory address was null") + let selfBits$ = Int(Int64(fromJNI: self, in: environment!)) + guard let self$ = UnsafeMutablePointer(bitPattern: selfBits$) else { + fatalError("self memory address was null in call to \\(#function)!") + } + let result$ = UnsafeMutablePointer.allocate(capacity: 1) + result$.initialize(to: self$.pointee.copy()) + let resultBits$ = Int64(Int(bitPattern: result$)) + return resultBits$.getJNIValue(in: environment!) + } + """, + ] + ) + } + + @Test + func classAsParameter_javaBindings() throws { + try assertOutput( + input: source, + .jni, + .java, + expectedChunks: [ + """ + /** + * Downcall to Swift: + * {@snippet lang=swift : + * public func isEqual(to other: MyClass) -> Bool + * } + */ + public boolean isEqual(MyClass other) { + return MyClass.$isEqual(other.$memoryAddress(), this.$memoryAddress()); + } + """, + """ + private static native boolean $isEqual(long other, long self); + """ + ] + ) + } + + @Test + func classAsParameter_swiftThunks() throws { + try assertOutput( + input: source, + .jni, + .swift, + detectChunkByInitialLines: 1, + expectedChunks: [ + """ + @_cdecl("Java_com_example_swift_MyClass__00024isEqual__JJ") + func Java_com_example_swift_MyClass__00024isEqual__JJ(environment: UnsafeMutablePointer!, thisClass: jclass, other: jlong, self: jlong) -> jboolean { + assert(other != 0, "other memory address was null") + let otherBits$ = Int(Int64(fromJNI: other, in: environment!)) + guard let other$ = UnsafeMutablePointer(bitPattern: otherBits$) else { + fatalError("other memory address was null in call to \\(#function)!") + } + assert(self != 0, "self memory address was null") + let selfBits$ = Int(Int64(fromJNI: self, in: environment!)) + guard let self$ = UnsafeMutablePointer(bitPattern: selfBits$) else { + fatalError("self memory address was null in call to \\(#function)!") + } + return self$.pointee.isEqual(to: other$.pointee).getJNIValue(in: environment!) + } + """, + ] + ) + } } diff --git a/Tests/JExtractSwiftTests/JNI/JNIModuleTests.swift b/Tests/JExtractSwiftTests/JNI/JNIModuleTests.swift index d6a030a8..4696253c 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIModuleTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIModuleTests.swift @@ -67,7 +67,12 @@ struct JNIModuleTests { * public func helloWorld() * } */ - public static native void helloWorld(); + public static void helloWorld() { + SwiftModule.$helloWorld(); + } + """, + """ + private static native void $helloWorld(); """, """ /** @@ -76,7 +81,12 @@ struct JNIModuleTests { * public func takeIntegers(i1: Int8, i2: Int16, i3: Int32, i4: Int64) -> UInt16 * } */ - public static native char takeIntegers(byte i1, short i2, int i3, long i4); + public static char takeIntegers(byte i1, short i2, int i3, long i4) { + return SwiftModule.$takeIntegers(i1, i2, i3, i4); + } + """, + """ + private static native char $takeIntegers(byte i1, short i2, int i3, long i4); """, """ /** @@ -85,7 +95,12 @@ struct JNIModuleTests { * public func otherPrimitives(b: Bool, f: Float, d: Double) * } */ - public static native void otherPrimitives(boolean b, float f, double d); + public static void otherPrimitives(boolean b, float f, double d) { + SwiftModule.$otherPrimitives(b, f, d); + } + """, + """ + private static native void $otherPrimitives(boolean b, float f, double d); """ ] ) @@ -100,21 +115,20 @@ struct JNIModuleTests { detectChunkByInitialLines: 1, expectedChunks: [ """ - @_cdecl("Java_com_example_swift_SwiftModule_helloWorld__") - func Java_com_example_swift_SwiftModule_helloWorld__(environment: UnsafeMutablePointer!, thisClass: jclass) { + @_cdecl("Java_com_example_swift_SwiftModule__00024helloWorld__") + func Java_com_example_swift_SwiftModule__00024helloWorld__(environment: UnsafeMutablePointer!, thisClass: jclass) { SwiftModule.helloWorld() } """, """ - @_cdecl("Java_com_example_swift_SwiftModule_takeIntegers__BSIJ") - func Java_com_example_swift_SwiftModule_takeIntegers__BSIJ(environment: UnsafeMutablePointer!, thisClass: jclass, i1: jbyte, i2: jshort, i3: jint, i4: jlong) -> jchar { - let result = SwiftModule.takeIntegers(i1: Int8(fromJNI: i1, in: environment!), i2: Int16(fromJNI: i2, in: environment!), i3: Int32(fromJNI: i3, in: environment!), i4: Int64(fromJNI: i4, in: environment!)) - return result.getJNIValue(in: environment) - } + @_cdecl("Java_com_example_swift_SwiftModule__00024takeIntegers__BSIJ") + func Java_com_example_swift_SwiftModule__00024takeIntegers__BSIJ(environment: UnsafeMutablePointer!, thisClass: jclass, i1: jbyte, i2: jshort, i3: jint, i4: jlong) -> jchar { + return SwiftModule.takeIntegers(i1: Int8(fromJNI: i1, in: environment!), i2: Int16(fromJNI: i2, in: environment!), i3: Int32(fromJNI: i3, in: environment!), i4: Int64(fromJNI: i4, in: environment!)).getJNIValue(in: environment!) + } """, """ - @_cdecl("Java_com_example_swift_SwiftModule_otherPrimitives__ZFD") - func Java_com_example_swift_SwiftModule_otherPrimitives__ZFD(environment: UnsafeMutablePointer!, thisClass: jclass, b: jboolean, f: jfloat, d: jdouble) { + @_cdecl("Java_com_example_swift_SwiftModule__00024otherPrimitives__ZFD") + func Java_com_example_swift_SwiftModule__00024otherPrimitives__ZFD(environment: UnsafeMutablePointer!, thisClass: jclass, b: jboolean, f: jfloat, d: jdouble) { SwiftModule.otherPrimitives(b: Bool(fromJNI: b, in: environment!), f: Float(fromJNI: f, in: environment!), d: Double(fromJNI: d, in: environment!)) } """ @@ -136,8 +150,13 @@ struct JNIModuleTests { * public func copy(_ string: String) -> String * } */ - public static native java.lang.String copy(java.lang.String string); + public static java.lang.String copy(java.lang.String string) { + return SwiftModule.$copy(string); + } """, + """ + private static native java.lang.String $copy(java.lang.String string); + """ ] ) } @@ -151,10 +170,9 @@ struct JNIModuleTests { detectChunkByInitialLines: 1, expectedChunks: [ """ - @_cdecl("Java_com_example_swift_SwiftModule_copy__Ljava_lang_String_2") - func Java_com_example_swift_SwiftModule_copy__Ljava_lang_String_2(environment: UnsafeMutablePointer!, thisClass: jclass, string: jstring?) -> jstring? { - let result = SwiftModule.copy(String(fromJNI: string, in: environment!)) - return result.getJNIValue(in: environment) + @_cdecl("Java_com_example_swift_SwiftModule__00024copy__Ljava_lang_String_2") + func Java_com_example_swift_SwiftModule__00024copy__Ljava_lang_String_2(environment: UnsafeMutablePointer!, thisClass: jclass, string: jstring) -> jstring { + return SwiftModule.copy(String(fromJNI: string, in: environment!)).getJNIValue(in: environment!) } """, ] @@ -175,7 +193,12 @@ struct JNIModuleTests { * public func methodA() throws * } */ - public static native void methodA() throws Exception; + public static void methodA() throws Exception { + SwiftModule.$methodA(); + } + """, + """ + private static native void $methodA(); """, """ /** @@ -184,8 +207,13 @@ struct JNIModuleTests { * public func methodB() throws -> Int64 * } */ - public static native long methodB() throws Exception; + public static long methodB() throws Exception { + return SwiftModule.$methodB(); + } """, + """ + private static native long $methodB(); + """ ] ) } @@ -199,9 +227,9 @@ struct JNIModuleTests { detectChunkByInitialLines: 1, expectedChunks: [ """ - @_cdecl("Java_com_example_swift_SwiftModule_methodA__") - func Java_com_example_swift_SwiftModule_methodA__(environment: UnsafeMutablePointer!, thisClass: jclass) { - do { + @_cdecl("Java_com_example_swift_SwiftModule__00024methodA__") + func Java_com_example_swift_SwiftModule__00024methodA__(environment: UnsafeMutablePointer!, thisClass: jclass) { + do { try SwiftModule.methodA() } catch { environment.throwAsException(error) @@ -209,11 +237,10 @@ struct JNIModuleTests { } """, """ - @_cdecl("Java_com_example_swift_SwiftModule_methodB__") - func Java_com_example_swift_SwiftModule_methodB__(environment: UnsafeMutablePointer!, thisClass: jclass) -> jlong { - do { - let result = try SwiftModule.methodB() - return result.getJNIValue(in: environment) + @_cdecl("Java_com_example_swift_SwiftModule__00024methodB__") + func Java_com_example_swift_SwiftModule__00024methodB__(environment: UnsafeMutablePointer!, thisClass: jclass) -> jlong { + do { + return try SwiftModule.methodB().getJNIValue(in: environment!) } catch { environment.throwAsException(error) return Int64.jniPlaceholderValue diff --git a/Tests/JExtractSwiftTests/JNI/JNIStructTests.swift b/Tests/JExtractSwiftTests/JNI/JNIStructTests.swift index 47b1c4dc..a4084654 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIStructTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIStructTests.swift @@ -98,12 +98,11 @@ struct JNIStructTests { * } */ public static MyStruct init(long x, long y, SwiftArena swiftArena$) { - long self$ = MyStruct.allocatingInit(x, y); - return new MyStruct(self$, swiftArena$); + return new MyStruct(MyStruct.$init(x, y), swiftArena$); } """, """ - private static native long allocatingInit(long x, long y); + private static native long $init(long x, long y); """, ] ) @@ -118,11 +117,12 @@ struct JNIStructTests { detectChunkByInitialLines: 1, expectedChunks: [ """ - @_cdecl("Java_com_example_swift_MyStruct_allocatingInit__JJ") - func Java_com_example_swift_MyStruct_allocatingInit__JJ(environment: UnsafeMutablePointer!, thisClass: jclass, x: jlong, y: jlong) -> jlong { - let self$ = UnsafeMutablePointer.allocate(capacity: 1) - self$.initialize(to: MyStruct(x: Int64(fromJNI: x, in: environment!), y: Int64(fromJNI: y, in: environment!))) - return Int64(Int(bitPattern: self$)).getJNIValue(in: environment) + @_cdecl("Java_com_example_swift_MyStruct__00024init__JJ") + func Java_com_example_swift_MyStruct__00024init__JJ(environment: UnsafeMutablePointer!, thisClass: jclass, x: jlong, y: jlong) -> jlong { + let result$ = UnsafeMutablePointer.allocate(capacity: 1) + result$.initialize(to: MyStruct.init(x: Int64(fromJNI: x, in: environment!), y: Int64(fromJNI: y, in: environment!))) + let resultBits$ = Int64(Int(bitPattern: result$)) + return resultBits$.getJNIValue(in: environment!) } """ ] @@ -170,12 +170,11 @@ struct JNIStructTests { * } */ public void doSomething(long x) { - long self$ = this.$memoryAddress(); - MyStruct.$doSomething(x, self$); + MyStruct.$doSomething(x, this.$memoryAddress()); } """, """ - private static native void $doSomething(long x, long selfPointer); + private static native void $doSomething(long x, long self); """ ] ) @@ -191,12 +190,9 @@ struct JNIStructTests { expectedChunks: [ """ @_cdecl("Java_com_example_swift_MyStruct__00024doSomething__JJ") - func Java_com_example_swift_MyStruct__00024doSomething__JJ(environment: UnsafeMutablePointer!, thisClass: jclass, x: jlong, selfPointer: jlong) { - guard let env$ = environment else { - fatalError("Missing JNIEnv in downcall to \\(#function)") - } - assert(selfPointer != 0, "selfPointer memory address was null") - let selfBits$ = Int(Int64(fromJNI: selfPointer, in: env$)) + func Java_com_example_swift_MyStruct__00024doSomething__JJ(environment: UnsafeMutablePointer!, thisClass: jclass, x: jlong, self: jlong) { + assert(self != 0, "self memory address was null") + let selfBits$ = Int(Int64(fromJNI: self, in: environment!)) guard let self$ = UnsafeMutablePointer(bitPattern: selfBits$) else { fatalError("self memory address was null in call to \\(#function)!") } diff --git a/Tests/JExtractSwiftTests/JNI/JNIVariablesTests.swift b/Tests/JExtractSwiftTests/JNI/JNIVariablesTests.swift index 272d27b5..5757e8da 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIVariablesTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIVariablesTests.swift @@ -48,12 +48,11 @@ struct JNIVariablesTests { * } */ public long getConstant() { - long self$ = this.$memoryAddress(); - return MyClass.$getConstant(self$); + return MyClass.$getConstant(this.$memoryAddress()); } """, """ - private static native long $getConstant(long selfPointer); + private static native long $getConstant(long self); """ ]) } @@ -68,17 +67,13 @@ struct JNIVariablesTests { expectedChunks: [ """ @_cdecl("Java_com_example_swift_MyClass__00024getConstant__J") - func Java_com_example_swift_MyClass__00024getConstant__J(environment: UnsafeMutablePointer!, thisClass: jclass, selfPointer: jlong) -> jlong { - guard let env$ = environment else { - fatalError("Missing JNIEnv in downcall to \\(#function)") - } - assert(selfPointer != 0, "selfPointer memory address was null") - let selfBits$ = Int(Int64(fromJNI: selfPointer, in: env$)) + func Java_com_example_swift_MyClass__00024getConstant__J(environment: UnsafeMutablePointer!, thisClass: jclass, self: jlong) -> jlong { + assert(self != 0, "self memory address was null") + let selfBits$ = Int(Int64(fromJNI: self, in: environment!)) guard let self$ = UnsafeMutablePointer(bitPattern: selfBits$) else { fatalError("self memory address was null in call to \\(#function)!") } - let result = self$.pointee.constant - return result.getJNIValue(in: environment) + return self$.pointee.constant.getJNIValue(in: environment!) } """ ] @@ -101,8 +96,7 @@ struct JNIVariablesTests { * } */ public long getMutable() { - long self$ = this.$memoryAddress(); - return MyClass.$getMutable(self$); + return MyClass.$getMutable(this.$memoryAddress()); } """, """ @@ -113,15 +107,14 @@ struct JNIVariablesTests { * } */ public void setMutable(long newValue) { - long self$ = this.$memoryAddress(); - MyClass.$setMutable(newValue, self$); + MyClass.$setMutable(newValue, this.$memoryAddress()); } """, """ - private static native long $getMutable(long selfPointer); + private static native long $getMutable(long self); """, """ - private static native void $setMutable(long newValue, long selfPointer); + private static native void $setMutable(long newValue, long self); """ ] ) @@ -137,27 +130,20 @@ struct JNIVariablesTests { expectedChunks: [ """ @_cdecl("Java_com_example_swift_MyClass__00024getMutable__J") - func Java_com_example_swift_MyClass__00024getMutable__J(environment: UnsafeMutablePointer!, thisClass: jclass, selfPointer: jlong) -> jlong { - guard let env$ = environment else { - fatalError("Missing JNIEnv in downcall to \\(#function)") - } - assert(selfPointer != 0, "selfPointer memory address was null") - let selfBits$ = Int(Int64(fromJNI: selfPointer, in: env$)) + func Java_com_example_swift_MyClass__00024getMutable__J(environment: UnsafeMutablePointer!, thisClass: jclass, self: jlong) -> jlong { + assert(self != 0, "self memory address was null") + let selfBits$ = Int(Int64(fromJNI: self, in: environment!)) guard let self$ = UnsafeMutablePointer(bitPattern: selfBits$) else { fatalError("self memory address was null in call to \\(#function)!") } - let result = self$.pointee.mutable - return result.getJNIValue(in: environment) + return self$.pointee.mutable.getJNIValue(in: environment!) } """, """ @_cdecl("Java_com_example_swift_MyClass__00024setMutable__JJ") - func Java_com_example_swift_MyClass__00024setMutable__JJ(environment: UnsafeMutablePointer!, thisClass: jclass, newValue: jlong, selfPointer: jlong) { - guard let env$ = environment else { - fatalError("Missing JNIEnv in downcall to \\(#function)") - } - assert(selfPointer != 0, "selfPointer memory address was null") - let selfBits$ = Int(Int64(fromJNI: selfPointer, in: env$)) + func Java_com_example_swift_MyClass__00024setMutable__JJ(environment: UnsafeMutablePointer!, thisClass: jclass, newValue: jlong, self: jlong) { + assert(self != 0, "self memory address was null") + let selfBits$ = Int(Int64(fromJNI: self, in: environment!)) guard let self$ = UnsafeMutablePointer(bitPattern: selfBits$) else { fatalError("self memory address was null in call to \\(#function)!") } @@ -184,12 +170,11 @@ struct JNIVariablesTests { * } */ public long getComputed() { - long self$ = this.$memoryAddress(); - return MyClass.$getComputed(self$); + return MyClass.$getComputed(this.$memoryAddress()); } """, """ - private static native long $getComputed(long selfPointer); + private static native long $getComputed(long self); """, ] ) @@ -205,18 +190,13 @@ struct JNIVariablesTests { expectedChunks: [ """ @_cdecl("Java_com_example_swift_MyClass__00024getComputed__J") - func Java_com_example_swift_MyClass__00024getComputed__J(environment: UnsafeMutablePointer!, thisClass: jclass, selfPointer: jlong) -> jlong { - guard let env$ = environment else { - fatalError("Missing JNIEnv in downcall to \\(#function)") - } - assert(selfPointer != 0, "selfPointer memory address was null") - let selfBits$ = Int(Int64(fromJNI: selfPointer, in: env$)) + func Java_com_example_swift_MyClass__00024getComputed__J(environment: UnsafeMutablePointer!, thisClass: jclass, self: jlong) -> jlong { + assert(self != 0, "self memory address was null") + let selfBits$ = Int(Int64(fromJNI: self, in: environment!)) guard let self$ = UnsafeMutablePointer(bitPattern: selfBits$) else { fatalError("self memory address was null in call to \\(#function)!") } - - let result = self$.pointee.computed - return result.getJNIValue(in: environment) + return self$.pointee.computed.getJNIValue(in: environment!) } """, ] @@ -239,12 +219,11 @@ struct JNIVariablesTests { * } */ public long getComputedThrowing() throws Exception { - long self$ = this.$memoryAddress(); - return MyClass.$getComputedThrowing(self$); + return MyClass.$getComputedThrowing(this.$memoryAddress()); } """, """ - private static native long $getComputedThrowing(long selfPointer); + private static native long $getComputedThrowing(long self); """, ] ) @@ -260,19 +239,14 @@ struct JNIVariablesTests { expectedChunks: [ """ @_cdecl("Java_com_example_swift_MyClass__00024getComputedThrowing__J") - func Java_com_example_swift_MyClass__00024getComputedThrowing__J(environment: UnsafeMutablePointer!, thisClass: jclass, selfPointer: jlong) -> jlong { - guard let env$ = environment else { - fatalError("Missing JNIEnv in downcall to \\(#function)") - } - assert(selfPointer != 0, "selfPointer memory address was null") - let selfBits$ = Int(Int64(fromJNI: selfPointer, in: env$)) + func Java_com_example_swift_MyClass__00024getComputedThrowing__J(environment: UnsafeMutablePointer!, thisClass: jclass, self: jlong) -> jlong { + assert(self != 0, "self memory address was null") + let selfBits$ = Int(Int64(fromJNI: self, in: environment!)) guard let self$ = UnsafeMutablePointer(bitPattern: selfBits$) else { fatalError("self memory address was null in call to \\(#function)!") } - do { - let result = try self$.pointee.computedThrowing - return result.getJNIValue(in: environment) + return try self$.pointee.computedThrowing.getJNIValue(in: environment!) } catch { environment.throwAsException(error) return Int64.jniPlaceholderValue @@ -299,8 +273,7 @@ struct JNIVariablesTests { * } */ public long getGetterAndSetter() { - long self$ = this.$memoryAddress(); - return MyClass.$getGetterAndSetter(self$); + return MyClass.$getGetterAndSetter(this.$memoryAddress()); } """, """ @@ -311,15 +284,14 @@ struct JNIVariablesTests { * } */ public void setGetterAndSetter(long newValue) { - long self$ = this.$memoryAddress(); - MyClass.$setGetterAndSetter(newValue, self$); + MyClass.$setGetterAndSetter(newValue, this.$memoryAddress()); } """, """ - private static native long $getGetterAndSetter(long selfPointer); + private static native long $getGetterAndSetter(long self); """, """ - private static native void $setGetterAndSetter(long newValue, long selfPointer); + private static native void $setGetterAndSetter(long newValue, long self); """ ] ) @@ -335,32 +307,23 @@ struct JNIVariablesTests { expectedChunks: [ """ @_cdecl("Java_com_example_swift_MyClass__00024getGetterAndSetter__J") - func Java_com_example_swift_MyClass__00024getGetterAndSetter__J(environment: UnsafeMutablePointer!, thisClass: jclass, selfPointer: jlong) -> jlong { - guard let env$ = environment else { - fatalError("Missing JNIEnv in downcall to \\(#function)") - } - assert(selfPointer != 0, "selfPointer memory address was null") - let selfBits$ = Int(Int64(fromJNI: selfPointer, in: env$)) + func Java_com_example_swift_MyClass__00024getGetterAndSetter__J(environment: UnsafeMutablePointer!, thisClass: jclass, self: jlong) -> jlong { + assert(self != 0, "self memory address was null") + let selfBits$ = Int(Int64(fromJNI: self, in: environment!)) guard let self$ = UnsafeMutablePointer(bitPattern: selfBits$) else { fatalError("self memory address was null in call to \\(#function)!") } - - let result = self$.pointee.getterAndSetter - return result.getJNIValue(in: environment) + return self$.pointee.getterAndSetter.getJNIValue(in: environment!) } """, """ @_cdecl("Java_com_example_swift_MyClass__00024setGetterAndSetter__JJ") - func Java_com_example_swift_MyClass__00024setGetterAndSetter__JJ(environment: UnsafeMutablePointer!, thisClass: jclass, newValue: jlong, selfPointer: jlong) { - guard let env$ = environment else { - fatalError("Missing JNIEnv in downcall to \\(#function)") - } - assert(selfPointer != 0, "selfPointer memory address was null") - let selfBits$ = Int(Int64(fromJNI: selfPointer, in: env$)) + func Java_com_example_swift_MyClass__00024setGetterAndSetter__JJ(environment: UnsafeMutablePointer!, thisClass: jclass, newValue: jlong, self: jlong) { + assert(self != 0, "self memory address was null") + let selfBits$ = Int(Int64(fromJNI: self, in: environment!)) guard let self$ = UnsafeMutablePointer(bitPattern: selfBits$) else { fatalError("self memory address was null in call to \\(#function)!") } - self$.pointee.getterAndSetter = Int64(fromJNI: newValue, in: environment!) } """ @@ -384,8 +347,7 @@ struct JNIVariablesTests { * } */ public boolean isSomeBoolean() { - long self$ = this.$memoryAddress(); - return MyClass.$isSomeBoolean(self$); + return MyClass.$isSomeBoolean(this.$memoryAddress()); } """, """ @@ -396,15 +358,14 @@ struct JNIVariablesTests { * } */ public void setSomeBoolean(boolean newValue) { - long self$ = this.$memoryAddress(); - MyClass.$setSomeBoolean(newValue, self$); + MyClass.$setSomeBoolean(newValue, this.$memoryAddress()); } """, """ - private static native boolean $isSomeBoolean(long selfPointer); + private static native boolean $isSomeBoolean(long self); """, """ - private static native void $setSomeBoolean(boolean newValue, long selfPointer); + private static native void $setSomeBoolean(boolean newValue, long self); """ ] ) @@ -420,27 +381,20 @@ struct JNIVariablesTests { expectedChunks: [ """ @_cdecl("Java_com_example_swift_MyClass__00024isSomeBoolean__J") - func Java_com_example_swift_MyClass__00024isSomeBoolean__J(environment: UnsafeMutablePointer!, thisClass: jclass, selfPointer: jlong) -> jboolean { - guard let env$ = environment else { - fatalError("Missing JNIEnv in downcall to \\(#function)") - } - assert(selfPointer != 0, "selfPointer memory address was null") - let selfBits$ = Int(Int64(fromJNI: selfPointer, in: env$)) + func Java_com_example_swift_MyClass__00024isSomeBoolean__J(environment: UnsafeMutablePointer!, thisClass: jclass, self: jlong) -> jboolean { + assert(self != 0, "self memory address was null") + let selfBits$ = Int(Int64(fromJNI: self, in: environment!)) guard let self$ = UnsafeMutablePointer(bitPattern: selfBits$) else { fatalError("self memory address was null in call to \\(#function)!") } - let result = self$.pointee.someBoolean - return result.getJNIValue(in: environment) + return self$.pointee.someBoolean.getJNIValue(in: environment!) } """, """ @_cdecl("Java_com_example_swift_MyClass__00024setSomeBoolean__ZJ") - func Java_com_example_swift_MyClass__00024setSomeBoolean__ZJ(environment: UnsafeMutablePointer!, thisClass: jclass, newValue: jboolean, selfPointer: jlong) { - guard let env$ = environment else { - fatalError("Missing JNIEnv in downcall to \\(#function)") - } - assert(selfPointer != 0, "selfPointer memory address was null") - let selfBits$ = Int(Int64(fromJNI: selfPointer, in: env$)) + func Java_com_example_swift_MyClass__00024setSomeBoolean__ZJ(environment: UnsafeMutablePointer!, thisClass: jclass, newValue: jboolean, self: jlong) { + assert(self != 0, "self memory address was null") + let selfBits$ = Int(Int64(fromJNI: self, in: environment!)) guard let self$ = UnsafeMutablePointer(bitPattern: selfBits$) else { fatalError("self memory address was null in call to \\(#function)!") } @@ -467,8 +421,7 @@ struct JNIVariablesTests { * } */ public boolean isBoolean() { - long self$ = this.$memoryAddress(); - return MyClass.$isBoolean(self$); + return MyClass.$isBoolean(this.$memoryAddress()); } """, """ @@ -479,15 +432,14 @@ struct JNIVariablesTests { * } */ public void setBoolean(boolean newValue) { - long self$ = this.$memoryAddress(); - MyClass.$setBoolean(newValue, self$); + MyClass.$setBoolean(newValue, this.$memoryAddress()); } """, """ - private static native boolean $isBoolean(long selfPointer); + private static native boolean $isBoolean(long self); """, """ - private static native void $setBoolean(boolean newValue, long selfPointer); + private static native void $setBoolean(boolean newValue, long self); """ ] ) @@ -503,27 +455,20 @@ struct JNIVariablesTests { expectedChunks: [ """ @_cdecl("Java_com_example_swift_MyClass__00024isBoolean__J") - func Java_com_example_swift_MyClass__00024isBoolean__J(environment: UnsafeMutablePointer!, thisClass: jclass, selfPointer: jlong) -> jboolean { - guard let env$ = environment else { - fatalError("Missing JNIEnv in downcall to \\(#function)") - } - assert(selfPointer != 0, "selfPointer memory address was null") - let selfBits$ = Int(Int64(fromJNI: selfPointer, in: env$)) + func Java_com_example_swift_MyClass__00024isBoolean__J(environment: UnsafeMutablePointer!, thisClass: jclass, self: jlong) -> jboolean { + assert(self != 0, "self memory address was null") + let selfBits$ = Int(Int64(fromJNI: self, in: environment!)) guard let self$ = UnsafeMutablePointer(bitPattern: selfBits$) else { fatalError("self memory address was null in call to \\(#function)!") } - let result = self$.pointee.isBoolean - return result.getJNIValue(in: environment) + return self$.pointee.isBoolean.getJNIValue(in: environment!) } """, """ @_cdecl("Java_com_example_swift_MyClass__00024setBoolean__ZJ") - func Java_com_example_swift_MyClass__00024setBoolean__ZJ(environment: UnsafeMutablePointer!, thisClass: jclass, newValue: jboolean, selfPointer: jlong) { - guard let env$ = environment else { - fatalError("Missing JNIEnv in downcall to \\(#function)") - } - assert(selfPointer != 0, "selfPointer memory address was null") - let selfBits$ = Int(Int64(fromJNI: selfPointer, in: env$)) + func Java_com_example_swift_MyClass__00024setBoolean__ZJ(environment: UnsafeMutablePointer!, thisClass: jclass, newValue: jboolean, self: jlong) { + assert(self != 0, "self memory address was null") + let selfBits$ = Int(Int64(fromJNI: self, in: environment!)) guard let self$ = UnsafeMutablePointer(bitPattern: selfBits$) else { fatalError("self memory address was null in call to \\(#function)!") } From f62a31752f9840f2fb3fa78b9720e179404000e7 Mon Sep 17 00:00:00 2001 From: Mads Odgaard Date: Tue, 22 Jul 2025 13:38:15 +0200 Subject: [PATCH 321/426] [JExtract/JNI] Add support for primitive non-escaping closures. (#327) --- .../Sources/MySwiftLibrary/Closures.swift | 31 ++++ .../java/com/example/swift/ClosuresTest.java | 44 +++++ .../Convenience/JavaType+Extensions.swift | 23 +-- ...t2JavaGenerator+JavaBindingsPrinting.swift | 71 +++++++- ...ISwift2JavaGenerator+JavaTranslation.swift | 114 ++++++++++-- ...wift2JavaGenerator+NativeTranslation.swift | 169 ++++++++++++++++-- ...ift2JavaGenerator+SwiftThunkPrinting.swift | 5 +- Sources/JExtractSwiftLib/JNI/JNIType.swift | 16 ++ Sources/JavaKit/JavaEnvironment.swift | 2 +- Sources/JavaKit/JavaValue.swift | 2 +- .../JNI/JNIClosureTests.swift | 129 +++++++++++++ 11 files changed, 556 insertions(+), 50 deletions(-) create mode 100644 Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/Closures.swift create mode 100644 Samples/JExtractJNISampleApp/src/test/java/com/example/swift/ClosuresTest.java create mode 100644 Tests/JExtractSwiftTests/JNI/JNIClosureTests.swift diff --git a/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/Closures.swift b/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/Closures.swift new file mode 100644 index 00000000..00d1f4b0 --- /dev/null +++ b/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/Closures.swift @@ -0,0 +1,31 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +public func emptyClosure(closure: () -> ()) { + closure() +} + +public func closureWithInt(input: Int64, closure: (Int64) -> Int64) -> Int64 { + return closure(input) +} + +public func closureMultipleArguments( + input1: Int64, + input2: Int64, + closure: (Int64, Int64) -> Int64 +) -> Int64 { + return closure(input1, input2) +} + + diff --git a/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/ClosuresTest.java b/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/ClosuresTest.java new file mode 100644 index 00000000..b8389d41 --- /dev/null +++ b/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/ClosuresTest.java @@ -0,0 +1,44 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package com.example.swift; + +import org.junit.jupiter.api.Test; + +import java.util.concurrent.atomic.AtomicBoolean; + +import static org.junit.jupiter.api.Assertions.*; + +public class ClosuresTest { + @Test + void emptyClosure() { + AtomicBoolean closureCalled = new AtomicBoolean(false); + MySwiftLibrary.emptyClosure(() -> { + closureCalled.set(true); + }); + assertTrue(closureCalled.get()); + } + + @Test + void closureWithInt() { + long result = MySwiftLibrary.closureWithInt(10, (value) -> value * 2); + assertEquals(20, result); + } + + @Test + void closureMultipleArguments() { + long result = MySwiftLibrary.closureMultipleArguments(5, 10, (a, b) -> a + b); + assertEquals(15, result); + } +} \ No newline at end of file diff --git a/Sources/JExtractSwiftLib/Convenience/JavaType+Extensions.swift b/Sources/JExtractSwiftLib/Convenience/JavaType+Extensions.swift index 9da3ae5b..f9a67419 100644 --- a/Sources/JExtractSwiftLib/Convenience/JavaType+Extensions.swift +++ b/Sources/JExtractSwiftLib/Convenience/JavaType+Extensions.swift @@ -17,21 +17,22 @@ import JavaTypes extension JavaType { var jniTypeSignature: String { switch self { - case .boolean: "Z" - case .byte: "B" - case .char: "C" - case .short: "S" - case .int: "I" - case .long: "J" - case .float: "F" - case .double: "D" + case .boolean: return "Z" + case .byte: return "B" + case .char: return "C" + case .short: return "S" + case .int: return "I" + case .long: return "J" + case .float: return "F" + case .double: return "D" case .class(let package, let name): + let nameWithInnerClasses = name.replacingOccurrences(of: ".", with: "$") if let package { - "L\(package.replacingOccurrences(of: ".", with: "/"))/\(name);" + return "L\(package.replacingOccurrences(of: ".", with: "/"))/\(nameWithInnerClasses);" } else { - "L\(name);" + return "L\(nameWithInnerClasses);" } - case .array(let javaType): "[\(javaType.jniTypeSignature)" + case .array(let javaType): return "[\(javaType.jniTypeSignature)" case .void: fatalError("There is no type signature for 'void'") } } diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift index 9c3d14b8..e0e5cb70 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift @@ -76,12 +76,12 @@ extension JNISwift2JavaGenerator { for decl in analysis.importedGlobalFuncs { self.logger.trace("Print global function: \(decl)") - printFunctionBinding(&printer, decl) + printFunctionDowncallMethods(&printer, decl) printer.println() } for decl in analysis.importedGlobalVariables { - printFunctionBinding(&printer, decl) + printFunctionDowncallMethods(&printer, decl) printer.println() } } @@ -117,17 +117,17 @@ extension JNISwift2JavaGenerator { printer.println() for initializer in decl.initializers { - printFunctionBinding(&printer, initializer) + printFunctionDowncallMethods(&printer, initializer) printer.println() } for method in decl.methods { - printFunctionBinding(&printer, method) + printFunctionDowncallMethods(&printer, method) printer.println() } for variable in decl.variables { - printFunctionBinding(&printer, variable) + printFunctionDowncallMethods(&printer, variable) printer.println() } @@ -175,12 +175,67 @@ extension JNISwift2JavaGenerator { } } - private func printFunctionBinding(_ printer: inout CodePrinter, _ decl: ImportedFunc) { - guard let translatedDecl = translatedDecl(for: decl) else { + private func printFunctionDowncallMethods( + _ printer: inout CodePrinter, + _ decl: ImportedFunc + ) { + guard translatedDecl(for: decl) != nil else { // Failed to translate. Skip. return } + printer.printSeparator(decl.displayName) + + printJavaBindingWrapperHelperClass(&printer, decl) + + printJavaBindingWrapperMethod(&printer, decl) + } + + /// Print the helper type container for a user-facing Java API. + /// + /// * User-facing functional interfaces. + private func printJavaBindingWrapperHelperClass( + _ printer: inout CodePrinter, + _ decl: ImportedFunc + ) { + let translated = self.translatedDecl(for: decl)! + if translated.functionTypes.isEmpty { + return + } + + printer.printBraceBlock( + """ + public static class \(translated.name) + """ + ) { printer in + for functionType in translated.functionTypes { + printJavaBindingWrapperFunctionTypeHelper(&printer, functionType) + } + } + } + + /// Print "wrapper" functional interface representing a Swift closure type. + func printJavaBindingWrapperFunctionTypeHelper( + _ printer: inout CodePrinter, + _ functionType: TranslatedFunctionType + ) { + let apiParams = functionType.parameters.map(\.parameter.asParameter) + + printer.print( + """ + @FunctionalInterface + public interface \(functionType.name) { + \(functionType.result.javaType) apply(\(apiParams.joined(separator: ", "))); + } + """ + ) + } + + private func printJavaBindingWrapperMethod(_ printer: inout CodePrinter, _ decl: ImportedFunc) { + guard let translatedDecl = translatedDecl(for: decl) else { + fatalError("Decl was not translated, \(decl)") + } + var modifiers = ["public"] if decl.isStatic || decl.isInitializer || !decl.hasParent { modifiers.append("static") @@ -215,7 +270,7 @@ extension JNISwift2JavaGenerator { if let selfParameter = nativeSignature.selfParameter { parameters.append(selfParameter) } - let renderedParameters = parameters.map { "\($0.javaParameter.type) \($0.javaParameter.name)"}.joined(separator: ", ") + let renderedParameters = parameters.map { "\($0.javaType) \($0.name)"}.joined(separator: ", ") printer.print("private static native \(resultType) \(translatedDecl.nativeFunctionName)(\(renderedParameters));") } diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift index e0253624..e704739c 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift @@ -24,7 +24,7 @@ extension JNISwift2JavaGenerator { let translated: TranslatedFunctionDecl? do { - let translation = JavaTranslation(swiftModuleName: swiftModuleName) + let translation = JavaTranslation(swiftModuleName: swiftModuleName, javaPackage: self.javaPackage) translated = try translation.translate(decl) } catch { self.logger.debug("Failed to translate: '\(decl.swiftDecl.qualifiedNameForDebug)'; \(error)") @@ -37,17 +37,10 @@ extension JNISwift2JavaGenerator { struct JavaTranslation { let swiftModuleName: String + let javaPackage: String func translate(_ decl: ImportedFunc) throws -> TranslatedFunctionDecl { - let nativeTranslation = NativeJavaTranslation() - - // Swift -> Java - let translatedFunctionSignature = try translate(functionSignature: decl.functionSignature) - // Java -> Java (native) - let nativeFunctionSignature = try nativeTranslation.translate( - functionSignature: decl.functionSignature, - translatedFunctionSignature: translatedFunctionSignature - ) + let nativeTranslation = NativeJavaTranslation(javaPackage: self.javaPackage) // Types with no parent will be outputted inside a "module" class. let parentName = decl.parentType?.asNominalType?.nominalTypeDecl.qualifiedName ?? swiftModuleName @@ -59,19 +52,81 @@ extension JNISwift2JavaGenerator { case .function, .initializer: decl.name } + // Swift -> Java + let translatedFunctionSignature = try translate( + functionSignature: decl.functionSignature, + methodName: javaName, + parentName: parentName + ) + // Java -> Java (native) + let nativeFunctionSignature = try nativeTranslation.translate( + functionSignature: decl.functionSignature, + translatedFunctionSignature: translatedFunctionSignature, + methodName: javaName, + parentName: parentName + ) + + // Closures. + var funcTypes: [TranslatedFunctionType] = [] + for (idx, param) in decl.functionSignature.parameters.enumerated() { + let parameterName = param.parameterName ?? "_\(idx)" + + switch param.type { + case .function(let funcTy): + let translatedClosure = try translateFunctionType( + name: parameterName, + swiftType: funcTy, + parentName: parentName + ) + funcTypes.append(translatedClosure) + default: + break + } + } + return TranslatedFunctionDecl( name: javaName, nativeFunctionName: "$\(javaName)", parentName: parentName, + functionTypes: funcTypes, translatedFunctionSignature: translatedFunctionSignature, nativeFunctionSignature: nativeFunctionSignature ) } - func translate(functionSignature: SwiftFunctionSignature) throws -> TranslatedFunctionSignature { + /// Translate Swift closure type to Java functional interface. + func translateFunctionType( + name: String, + swiftType: SwiftFunctionType, + parentName: String + ) throws -> TranslatedFunctionType { + var translatedParams: [TranslatedParameter] = [] + + for (i, param) in swiftType.parameters.enumerated() { + let paramName = param.parameterName ?? "_\(i)" + translatedParams.append( + try translateParameter(swiftType: param.type, parameterName: paramName, methodName: name, parentName: parentName) + ) + } + + let transltedResult = try translate(swiftResult: SwiftResult(convention: .direct, type: swiftType.resultType)) + + return TranslatedFunctionType( + name: name, + parameters: translatedParams, + result: transltedResult, + swiftType: swiftType + ) + } + + func translate( + functionSignature: SwiftFunctionSignature, + methodName: String, + parentName: String + ) throws -> TranslatedFunctionSignature { let parameters = try functionSignature.parameters.enumerated().map { idx, param in let parameterName = param.parameterName ?? "arg\(idx))" - return try translateParameter(swiftType: param.type, parameterName: parameterName) + return try translateParameter(swiftType: param.type, parameterName: parameterName, methodName: methodName, parentName: parentName) } // 'self' @@ -79,7 +134,9 @@ extension JNISwift2JavaGenerator { if case .instance(let swiftSelf) = functionSignature.selfParameter { selfParameter = try self.translateParameter( swiftType: swiftSelf.type, - parameterName: swiftSelf.parameterName ?? "self" + parameterName: swiftSelf.parameterName ?? "self", + methodName: methodName, + parentName: parentName ) } else { selfParameter = nil @@ -92,7 +149,12 @@ extension JNISwift2JavaGenerator { ) } - func translateParameter(swiftType: SwiftType, parameterName: String) throws -> TranslatedParameter { + func translateParameter( + swiftType: SwiftType, + parameterName: String, + methodName: String, + parentName: String + ) throws -> TranslatedParameter { switch swiftType { case .nominal(let nominalType): if let knownType = nominalType.nominalTypeDecl.knownTypeKind { @@ -121,7 +183,16 @@ extension JNISwift2JavaGenerator { conversion: .placeholder ) - case .metatype, .optional, .tuple, .function, .existential, .opaque: + case .function: + return TranslatedParameter( + parameter: JavaParameter( + name: parameterName, + type: .class(package: javaPackage, name: "\(parentName).\(methodName).\(parameterName)") + ), + conversion: .placeholder + ) + + case .metatype, .optional, .tuple, .existential, .opaque: throw JavaTranslationError.unsupportedSwiftType(swiftType) } } @@ -168,6 +239,9 @@ extension JNISwift2JavaGenerator { /// The name of the Java parent scope this function is declared in let parentName: String + /// Functional interfaces required for the Java method. + let functionTypes: [TranslatedFunctionType] + /// Function signature of the Java function the user will call let translatedFunctionSignature: TranslatedFunctionSignature @@ -220,6 +294,16 @@ extension JNISwift2JavaGenerator { let conversion: JavaNativeConversionStep } + /// Represent a Swift closure type in the user facing Java API. + /// + /// Closures are translated to named functional interfaces in Java. + struct TranslatedFunctionType { + var name: String + var parameters: [TranslatedParameter] + var result: TranslatedResult + var swiftType: SwiftFunctionType + } + /// Describes how to convert values between Java types and the native Java function enum JavaNativeConversionStep { /// The value being converted diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift index 461c7301..cae6010d 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift @@ -17,14 +17,25 @@ import JavaTypes extension JNISwift2JavaGenerator { struct NativeJavaTranslation { + let javaPackage: String + /// Translates a Swift function into the native JNI method signature. func translate( functionSignature: SwiftFunctionSignature, - translatedFunctionSignature: TranslatedFunctionSignature + translatedFunctionSignature: TranslatedFunctionSignature, + methodName: String, + parentName: String ) throws -> NativeFunctionSignature { - let parameters = try zip(translatedFunctionSignature.parameters, functionSignature.parameters).map { translatedParameter, swiftParameter in + let parameters = try zip(translatedFunctionSignature.parameters, functionSignature.parameters).map { + translatedParameter, + swiftParameter in let parameterName = translatedParameter.parameter.name - return try translate(swiftParameter: swiftParameter, parameterName: parameterName) + return try translate( + swiftParameter: swiftParameter, + parameterName: parameterName, + methodName: methodName, + parentName: parentName + ) } // Lower the self parameter. @@ -32,7 +43,9 @@ extension JNISwift2JavaGenerator { case .instance(let selfParameter): try translate( swiftParameter: selfParameter, - parameterName: selfParameter.parameterName ?? "self" + parameterName: selfParameter.parameterName ?? "self", + methodName: methodName, + parentName: parentName ) case nil, .initializer(_), .staticMethod(_): nil @@ -47,7 +60,9 @@ extension JNISwift2JavaGenerator { func translate( swiftParameter: SwiftParameter, - parameterName: String + parameterName: String, + methodName: String, + parentName: String, ) throws -> NativeParameter { switch swiftParameter.type { case .nominal(let nominalType): @@ -57,28 +72,111 @@ extension JNISwift2JavaGenerator { } return NativeParameter( - javaParameter: JavaParameter(name: parameterName, type: javaType), + name: parameterName, + javaType: javaType, conversion: .initFromJNI(.placeholder, swiftType: swiftParameter.type) ) } case .tuple([]): return NativeParameter( - javaParameter: JavaParameter(name: parameterName, type: .void), + name: parameterName, + javaType: .void, conversion: .placeholder ) - case .metatype, .optional, .tuple, .function, .existential, .opaque: + case .function(let fn): + var parameters = [NativeParameter]() + for (i, parameter) in fn.parameters.enumerated() { + let parameterName = parameter.parameterName ?? "_\(i)" + let closureParameter = try translateClosureParameter( + parameter.type, + parameterName: parameterName + ) + parameters.append(closureParameter) + } + + let result = try translateClosureResult(fn.resultType) + + return NativeParameter( + name: parameterName, + javaType: .class(package: javaPackage, name: "\(parentName).\(methodName).\(parameterName)"), + conversion: .closureLowering( + parameters: parameters, + result: result + ) + ) + + case .metatype, .optional, .tuple, .existential, .opaque: throw JavaTranslationError.unsupportedSwiftType(swiftParameter.type) } // Classes are passed as the pointer. return NativeParameter( - javaParameter: JavaParameter(name: parameterName, type: .long), + name: parameterName, + javaType: .long, conversion: .pointee(.extractSwiftValue(.placeholder, swiftType: swiftParameter.type)) ) } + func translateClosureResult( + _ type: SwiftType + ) throws -> NativeResult { + switch type { + case .nominal(let nominal): + if let knownType = nominal.nominalTypeDecl.knownTypeKind { + guard let javaType = JNISwift2JavaGenerator.translate(knownType: knownType), javaType.implementsJavaValue else { + throw JavaTranslationError.unsupportedSwiftType(type) + } + + // Only support primitives for now. + return NativeResult( + javaType: javaType, + conversion: .initFromJNI(.placeholder, swiftType: type) + ) + } + + // Custom types are not supported yet. + throw JavaTranslationError.unsupportedSwiftType(type) + + case .tuple([]): + return NativeResult( + javaType: .void, + conversion: .placeholder + ) + + case .function, .metatype, .optional, .tuple, .existential, .opaque: + throw JavaTranslationError.unsupportedSwiftType(type) + } + } + + func translateClosureParameter( + _ type: SwiftType, + parameterName: String + ) throws -> NativeParameter { + switch type { + case .nominal(let nominal): + if let knownType = nominal.nominalTypeDecl.knownTypeKind { + guard let javaType = JNISwift2JavaGenerator.translate(knownType: knownType), javaType.implementsJavaValue else { + throw JavaTranslationError.unsupportedSwiftType(type) + } + + // Only support primitives for now. + return NativeParameter( + name: parameterName, + javaType: javaType, + conversion: .getJValue(.placeholder) + ) + } + + // Custom types are not supported yet. + throw JavaTranslationError.unsupportedSwiftType(type) + + case .function, .metatype, .optional, .tuple, .existential, .opaque: + throw JavaTranslationError.unsupportedSwiftType(type) + } + } + func translate( swiftResult: SwiftResult ) throws -> NativeResult { @@ -122,10 +220,11 @@ extension JNISwift2JavaGenerator { } struct NativeParameter { - let javaParameter: JavaParameter + let name: String + let javaType: JavaType var jniType: JNIType { - javaParameter.type.jniType + javaType.jniType } /// Represents how to convert the JNI parameter to a Swift parameter @@ -145,6 +244,9 @@ extension JNISwift2JavaGenerator { /// `value.getJNIValue(in:)` indirect case getJNIValue(NativeSwiftConversionStep) + /// `value.getJValue(in:)` + indirect case getJValue(NativeSwiftConversionStep) + /// `SwiftType(from: value, in: environment!)` indirect case initFromJNI(NativeSwiftConversionStep, swiftType: SwiftType) @@ -152,12 +254,13 @@ extension JNISwift2JavaGenerator { indirect case extractSwiftValue(NativeSwiftConversionStep, swiftType: SwiftType) /// Allocate memory for a Swift value and outputs the pointer - indirect case allocateSwiftValue(name: String, swiftType: SwiftType) + case allocateSwiftValue(name: String, swiftType: SwiftType) /// The thing to which the pointer typed, which is the `pointee` property /// of the `Unsafe(Mutable)Pointer` types in Swift. indirect case pointee(NativeSwiftConversionStep) + indirect case closureLowering(parameters: [NativeParameter], result: NativeResult) /// Returns the conversion string applied to the placeholder. func render(_ printer: inout CodePrinter, _ placeholder: String) -> String { @@ -171,6 +274,10 @@ extension JNISwift2JavaGenerator { let inner = inner.render(&printer, placeholder) return "\(inner).getJNIValue(in: environment!)" + case .getJValue(let inner): + let inner = inner.render(&printer, placeholder) + return "\(inner).getJValue(in: environment!)" + case .initFromJNI(let inner, let swiftType): let inner = inner.render(&printer, placeholder) return "\(swiftType)(fromJNI: \(inner), in: environment!)" @@ -203,6 +310,44 @@ extension JNISwift2JavaGenerator { case .pointee(let inner): let inner = inner.render(&printer, placeholder) return "\(inner).pointee" + + case .closureLowering(let parameters, let nativeResult): + var printer = CodePrinter() + + let methodSignature = MethodSignature( + resultType: nativeResult.javaType, + parameterTypes: parameters.map(\.javaType) + ) + + let closureParameters = !parameters.isEmpty ? "\(parameters.map(\.name).joined(separator: ", ")) in" : "" + printer.print("{ \(closureParameters)") + printer.indent() + + let arguments = parameters.map { + $0.conversion.render(&printer, $0.name) + } + + printer.print( + """ + let class$ = environment!.interface.GetObjectClass(environment, \(placeholder)) + let methodID$ = environment!.interface.GetMethodID(environment, class$, "apply", "\(methodSignature.mangledName)")! + let arguments$: [jvalue] = [\(arguments.joined(separator: ", "))] + """ + ) + + let upcall = "environment!.interface.\(nativeResult.javaType.jniType.callMethodAName)(environment, \(placeholder), methodID$, arguments$)" + let result = nativeResult.conversion.render(&printer, upcall) + + if nativeResult.javaType.isVoid { + printer.print(result) + } else { + printer.print("return \(result)") + } + + printer.outdent() + printer.print("}") + + return printer.finalize() } } } diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift index d8b6b275..20551465 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift @@ -135,7 +135,7 @@ extension JNISwift2JavaGenerator { &printer, javaMethodName: translatedDecl.nativeFunctionName, parentName: translatedDecl.parentName, - parameters: parameters.map(\.javaParameter), + parameters: parameters.map { JavaParameter(name: $0.name, type: $0.javaType) }, resultType: nativeSignature.result.javaType.jniType ) { printer in self.printFunctionDowncall(&printer, decl) @@ -156,7 +156,7 @@ extension JNISwift2JavaGenerator { // Regular parameters. var arguments = [String]() for parameter in nativeSignature.parameters { - let lowered = parameter.conversion.render(&printer, parameter.javaParameter.name) + let lowered = parameter.conversion.render(&printer, parameter.name) arguments.append(lowered) } @@ -273,6 +273,7 @@ extension JNISwift2JavaGenerator { // Generated by swift-java import JavaKit + import JavaRuntime """ ) diff --git a/Sources/JExtractSwiftLib/JNI/JNIType.swift b/Sources/JExtractSwiftLib/JNI/JNIType.swift index d152942a..feb8a545 100644 --- a/Sources/JExtractSwiftLib/JNI/JNIType.swift +++ b/Sources/JExtractSwiftLib/JNI/JNIType.swift @@ -40,6 +40,22 @@ enum JNIType { case jfloatArray case jdoubleArray case jobjectArray + + var callMethodAName: String { + switch self { + case .jboolean: "CallBooleanMethodA" + case .jbyte: "CallByteMethodA" + case .jchar: "CallCharMethodA" + case .jshort: "CallShortMethodA" + case .jint: "CallIntMethodA" + case .jlong: "CallLongMethodA" + case .jfloat: "CallFloatMethodA" + case .jdouble: "CallDoubleMethodA" + case .void: "CallVoidMethodA" + case .jobject, .jstring, .jclass, .jthrowable: "CallObjectMethodA" + case .jbooleanArray, .jbyteArray, .jcharArray, .jshortArray, .jintArray, .jlongArray, .jfloatArray, .jdoubleArray, .jobjectArray: "CallObjectMethodA" + } + } } extension JavaType { diff --git a/Sources/JavaKit/JavaEnvironment.swift b/Sources/JavaKit/JavaEnvironment.swift index d74146ab..4895b32c 100644 --- a/Sources/JavaKit/JavaEnvironment.swift +++ b/Sources/JavaKit/JavaEnvironment.swift @@ -15,5 +15,5 @@ import JavaRuntime extension UnsafeMutablePointer { - var interface: JNINativeInterface_ { self.pointee!.pointee } + public var interface: JNINativeInterface_ { self.pointee!.pointee } } diff --git a/Sources/JavaKit/JavaValue.swift b/Sources/JavaKit/JavaValue.swift index 1bc156a0..0f208144 100644 --- a/Sources/JavaKit/JavaValue.swift +++ b/Sources/JavaKit/JavaValue.swift @@ -137,7 +137,7 @@ extension JavaValue where Self: ~Copyable { } /// Convert to a jvalue within the given JNI environment. - consuming func getJValue(in environment: JNIEnvironment) -> jvalue { + public consuming func getJValue(in environment: JNIEnvironment) -> jvalue { var result = jvalue() Self.assignJNIType(&result[keyPath: Self.jvalueKeyPath], to: getJNIValue(in: environment)) return result diff --git a/Tests/JExtractSwiftTests/JNI/JNIClosureTests.swift b/Tests/JExtractSwiftTests/JNI/JNIClosureTests.swift new file mode 100644 index 00000000..47d7e35d --- /dev/null +++ b/Tests/JExtractSwiftTests/JNI/JNIClosureTests.swift @@ -0,0 +1,129 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import JExtractSwiftLib +import Testing + +@Suite +struct JNIClosureTests { + let source = + """ + public func emptyClosure(closure: () -> ()) {} + public func closureWithArgumentsAndReturn(closure: (Int64, Bool) -> Int64) {} + """ + + @Test + func emptyClosure_javaBindings() throws { + try assertOutput(input: source, .jni, .java, expectedChunks: [ + """ + public static class emptyClosure { + @FunctionalInterface + public interface closure { + void apply(); + } + } + """, + """ + /** + * Downcall to Swift: + * {@snippet lang=swift : + * public func emptyClosure(closure: () -> ()) + * } + */ + public static void emptyClosure(com.example.swift.SwiftModule.emptyClosure.closure closure) { + SwiftModule.$emptyClosure(closure); + } + """, + """ + private static native void $emptyClosure(com.example.swift.SwiftModule.emptyClosure.closure closure); + """ + ]) + } + + @Test + func emptyClosure_swiftThunks() throws { + try assertOutput( + input: source, + .jni, + .swift, + detectChunkByInitialLines: 1, + expectedChunks: [ + """ + @_cdecl("Java_com_example_swift_SwiftModule__00024emptyClosure__Lcom_example_swift_SwiftModule_00024emptyClosure_00024closure_2") + func Java_com_example_swift_SwiftModule__00024emptyClosure__Lcom_example_swift_SwiftModule_00024emptyClosure_00024closure_2(environment: UnsafeMutablePointer!, thisClass: jclass, closure: jobject) { + SwiftModule.emptyClosure(closure: { + let class$ = environment!.interface.GetObjectClass(environment, closure) + let methodID$ = environment!.interface.GetMethodID(environment, class$, "apply", "()V")! + let arguments$: [jvalue] = [] + environment!.interface.CallVoidMethodA(environment, closure, methodID$, arguments$) + } + ) + } + """ + ] + ) + } + + @Test + func closureWithArgumentsAndReturn_javaBindings() throws { + try assertOutput(input: source, .jni, .java, expectedChunks: [ + """ + public static class closureWithArgumentsAndReturn { + @FunctionalInterface + public interface closure { + long apply(long _0, boolean _1); + } + } + """, + """ + /** + * Downcall to Swift: + * {@snippet lang=swift : + * public func closureWithArgumentsAndReturn(closure: (Int64, Bool) -> Int64) + * } + */ + public static void closureWithArgumentsAndReturn(com.example.swift.SwiftModule.closureWithArgumentsAndReturn.closure closure) { + SwiftModule.$closureWithArgumentsAndReturn(closure); + } + """, + """ + private static native void $closureWithArgumentsAndReturn(com.example.swift.SwiftModule.closureWithArgumentsAndReturn.closure closure); + """ + ]) + } + + @Test + func closureWithArgumentsAndReturn_swiftThunks() throws { + try assertOutput( + input: source, + .jni, + .swift, + detectChunkByInitialLines: 1, + expectedChunks: [ + """ + @_cdecl("Java_com_example_swift_SwiftModule__00024closureWithArgumentsAndReturn__Lcom_example_swift_SwiftModule_00024closureWithArgumentsAndReturn_00024closure_2") + func Java_com_example_swift_SwiftModule__00024closureWithArgumentsAndReturn__Lcom_example_swift_SwiftModule_00024closureWithArgumentsAndReturn_00024closure_2(environment: UnsafeMutablePointer!, thisClass: jclass, closure: jobject) { + SwiftModule.closureWithArgumentsAndReturn(closure: { _0, _1 in + let class$ = environment!.interface.GetObjectClass(environment, closure) + let methodID$ = environment!.interface.GetMethodID(environment, class$, "apply", "(JZ)J")! + let arguments$: [jvalue] = [_0.getJValue(in: environment!), _1.getJValue(in: environment!)] + return Int64(fromJNI: environment!.interface.CallLongMethodA(environment, closure, methodID$, arguments$), in: environment!) + } + ) + } + """ + ] + ) + } +} From 342b5ea87a04666adf8b7e1a4ec10741c3ae64ee Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Wed, 23 Jul 2025 20:26:54 +0900 Subject: [PATCH 322/426] docc documentation, first step (#319) --- .github/actions/prepare_env/action.yml | 6 +- .github/scripts/install_swiftly.sh | 6 +- .github/scripts/validate_docs.sh | 13 + .github/workflows/pull_request.yml | 25 ++ .gitignore | 1 + .spi.yml | 8 + Package.swift | 14 + .../JavaKit/Documentation.docc/JavaKit.md | 254 +---------------- .../Documentation.docc/SupportedFeatures.md | 94 +++++++ .../SwiftJavaCommandLineTool.md | 256 ++++++++++++++++++ .../Documentation.docc/SwiftPMPlugin.md | 126 +++++++++ .../Documentation.docc/index.md | 32 +++ Sources/SwiftJavaDocumentation/empty.swift | 15 + WIP.md | 9 - 14 files changed, 595 insertions(+), 264 deletions(-) create mode 100755 .github/scripts/validate_docs.sh create mode 100644 .spi.yml rename USER_GUIDE.md => Sources/JavaKit/Documentation.docc/JavaKit.md (62%) create mode 100644 Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md create mode 100644 Sources/SwiftJavaDocumentation/Documentation.docc/SwiftJavaCommandLineTool.md create mode 100644 Sources/SwiftJavaDocumentation/Documentation.docc/SwiftPMPlugin.md create mode 100644 Sources/SwiftJavaDocumentation/Documentation.docc/index.md create mode 100644 Sources/SwiftJavaDocumentation/empty.swift diff --git a/.github/actions/prepare_env/action.yml b/.github/actions/prepare_env/action.yml index 8fc986e0..53bb3fd7 100644 --- a/.github/actions/prepare_env/action.yml +++ b/.github/actions/prepare_env/action.yml @@ -26,9 +26,9 @@ runs: elif [[ -n "$JAVA_HOME_24_ARM64" ]]; then echo "JAVA_HOME_24=$JAVA_HOME_24_ARM64" >> $GITHUB_ENV fi - - name: Check Java environment - shell: bash - run: ./gradlew -q javaToolchains + # - name: Check Java environment + # shell: bash + # run: ./gradlew -q javaToolchains - name: Cache local SwiftPM repository if: matrix.os_version == 'jammy' uses: actions/cache@v4 diff --git a/.github/scripts/install_swiftly.sh b/.github/scripts/install_swiftly.sh index 78fa3f6b..e0792894 100755 --- a/.github/scripts/install_swiftly.sh +++ b/.github/scripts/install_swiftly.sh @@ -41,6 +41,7 @@ else curl -O https://download.swift.org/swiftly/darwin/swiftly.pkg && pkgutil --check-signature swiftly.pkg && pkgutil --verbose --expand swiftly.pkg "${SWIFTLY_HOME_DIR}" && tar -C "${SWIFTLY_HOME_DIR}" -xvf "${SWIFTLY_HOME_DIR}"/swiftly-*/Payload && "$SWIFTLY_HOME_DIR/bin/swiftly" init -y --skip-install + chmod +x "$SWIFTLY_HOME_DIR/env.sh" # shellcheck disable=SC1091 . "$SWIFTLY_HOME_DIR/env.sh" fi @@ -84,5 +85,8 @@ echo "Displaying swift version" swiftly run "${runSelector[@]}" swift --version if [[ "$(uname -s)" == "Linux" ]]; then - CC=clang swiftly run "${runSelector[@]}" "$(dirname "$0")/install-libarchive.sh" + if [[ -f "$(dirname "$0")/install-libarchive.sh" ]]; then + CC=clang swiftly run "${runSelector[@]}" "$(dirname "$0")/install-libarchive.sh" + fi fi + diff --git a/.github/scripts/validate_docs.sh b/.github/scripts/validate_docs.sh new file mode 100755 index 00000000..8ee777b0 --- /dev/null +++ b/.github/scripts/validate_docs.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +set -e +set -x + +cat <> Package.swift + +package.dependencies.append( + .package(url: "https://github.com/swiftlang/swift-docc-plugin", from: "1.0.0") +) +EOF + +swift package --disable-sandbox plugin generate-documentation --target "SwiftJavaDocumentation" --warnings-as-errors --analyze diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 9a0b59b8..b2338ed2 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -13,6 +13,31 @@ jobs: # FIXME: Something is off with the format task and it gets "stuck", need to investigate format_check_enabled: false license_header_check_project_name: Swift.org + # Since we need JAVA_HOME to be set up for building the project and depending on a different workflow won't + # give us that, we disable the checking and make a separate job that performs docs validation + docs_check_enabled: false + + # This replicates 'docs-check' from https://github.com/swiftlang/github-workflows/blob/main/.github/workflows/soundness.yml + # because we need to set up environment so we can build the SwiftJava project (including Java runtime/dependencies). + soundness-docs: + name: Documentation check + runs-on: ubuntu-latest + container: + image: 'swift:6.1-noble' + strategy: + fail-fast: true + matrix: + swift_version: ['6.1.2'] + os_version: ['jammy'] + jdk_vendor: ['corretto'] + steps: + - uses: actions/checkout@v4 + - name: Prepare CI Environment + uses: ./.github/actions/prepare_env + - name: Swift Build + run: swift build + - name: Run documentation check + run: ./.github/scripts/validate_docs.sh test-java: name: Test (Java) (${{ matrix.os_version }} swift:${{ matrix.swift_version }} jdk:${{matrix.jdk_vendor}}) diff --git a/.gitignore b/.gitignore index f77390a7..28dfbae2 100644 --- a/.gitignore +++ b/.gitignore @@ -44,3 +44,4 @@ Package.resolved */**/*.o */**/*.swiftdeps */**/*.swiftdeps~ +*/**/.docc-build/ diff --git a/.spi.yml b/.spi.yml new file mode 100644 index 00000000..58345f25 --- /dev/null +++ b/.spi.yml @@ -0,0 +1,8 @@ +version: 1 +builder: + configs: + - documentation_targets: [ + SwiftJavaDocumentation, + JavaKit, + SwiftKitSwift + ] diff --git a/Package.swift b/Package.swift index 81d53b1d..ef529496 100644 --- a/Package.swift +++ b/Package.swift @@ -139,6 +139,12 @@ let package = Package( name: "swift-java", targets: ["SwiftJavaTool"] ), + + + .library( + name: "SwiftJavaDocumentation", + targets: ["SwiftJavaDocumentation"] + ), // ==== Plugin for building Java code .plugin( @@ -198,6 +204,14 @@ let package = Package( .package(url: "https://github.com/ordo-one/package-benchmark", .upToNextMajor(from: "1.4.0")), ], targets: [ + .target( + name: "SwiftJavaDocumentation", + dependencies: [ + "JavaKit", + "SwiftKitSwift", + ] + ), + .macro( name: "JavaKitMacros", dependencies: [ diff --git a/USER_GUIDE.md b/Sources/JavaKit/Documentation.docc/JavaKit.md similarity index 62% rename from USER_GUIDE.md rename to Sources/JavaKit/Documentation.docc/JavaKit.md index 351a3d5c..fe0f50ba 100644 --- a/USER_GUIDE.md +++ b/Sources/JavaKit/Documentation.docc/JavaKit.md @@ -2,11 +2,7 @@ Library and tools to make it easy to use Java libraries from Swift using the Java Native Interface (JNI). -## Getting started - -Before using this package, set the `JAVA_HOME` environment variable to point at your Java installation. Failing to do so will produce errors when processing the package manifest. Alternatively, you can put the path to your Java installation in the file `~/.java_home`. - -### Using Java libraries from Swift +## JavaKit: Using Java libraries from Swift Existing Java libraries can be wrapped for use in Swift with the `swift-java` tool. In a Swift program, the most direct way to access a Java API is to use the SwiftPM plugin to provide Swift wrappers for the Java classes. To do so, add a configuration file `swift-java.config` into the source directory for the Swift target. This is a JSON file that specifies Java classes and the Swift type name that should be generated to wrap them. For example, the following file maps `java.math.BigInteger` to a Swift type named `BigInteger`: @@ -282,7 +278,7 @@ Java native methods that throw any checked exception should be marked as `throws The Swift implementations of Java `native` constructors and static methods require an additional Swift parameter `environment: JNIEnvironment? = nil`, which will receive the JNI environment in which the function is being executed. In case of nil, the `JavaVirtualMachine.shared().environment()` value will be used. -## Using Java libraries from Swift +## JavaKit: Using Java libraries from Swift This section describes how Java libraries and mapped into Swift and their use from Swift. @@ -420,7 +416,7 @@ extension JavaClass { } ``` -### Interfaces +### Java Interfaces Java interfaces are similar to classes, and are projected into Swift in much the same way, but with the macro `JavaInterface`. The `JavaInterface` macro takes the Java interface name as well as any Java interfaces that this interface extends. As an example, here is the Swift projection of the [`java.util.Enumeration`](https://docs.oracle.com/javase/8/docs/api/java/util/Enumeration.html) generic interface: @@ -437,247 +433,3 @@ public struct Enumeration { public func nextElement() -> JavaObject! } ``` - -## Translating Java classes with `swift-java` - -The `swift-java` is a Swift program that uses Java's runtime reflection facilities to translate the requested Java classes into their Swift projections. The output is a number of Swift source files, each of which corresponds to a -single Java class. The `swift-java` can be executed like this: - -``` -swift-java -``` - -to produce help output like the following: - -``` -OVERVIEW: Generate sources and configuration for Swift and Java interoperability. - -USAGE: swift-java - -OPTIONS: - --depends-on - A Java2Swift configuration file for a given Swift module name on which this module depends, e.g., JavaKitJar=Sources/JavaKitJar/Java2Swift.config. There should be one of these options for each Swift module that this - module depends on (transitively) that contains wrapped Java sources. - --jar Specifies that the input is a Jar file whose public classes will be loaded. The output of Java2Swift will be a configuration file (Java2Swift.config) that can be used as input to a subsequent Java2Swift invocation to - generate wrappers for those public classes. - --fetch Fetch dependencies from given target (containing swift-java configuration) or dependency string - --swift-native-implementation - The names of Java classes whose declared native methods will be implemented in Swift. - --output-swift - The directory where generated Swift files should be written. Generally used with jextract mode. - --output-java - The directory where generated Java files should be written. Generally used with jextract mode. - --java-package - The Java package the generated Java code should be emitted into. - -c, --cache-directory - Directory where to write cached values (e.g. swift-java.classpath files) - -o, --output-directory - The directory in which to output the generated Swift files or the SwiftJava configuration file. - --input-swift - Directory containing Swift files which should be extracted into Java bindings. Also known as 'jextract' mode. Must be paired with --output-java and --output-swift. - -l, --log-level - Configure the level of logs that should be printed (values: trace, debug, info, notice, warning, error, critical; default: log level) - --cp, --classpath Class search path of directories and zip/jar files from which Java classes can be loaded. - -f, --filter-java-package - While scanning a classpath, inspect only types included in this package - -h, --help Show help information. - -SUBCOMMANDS: - configure Configure and emit a swift-java.config file based on an input dependency or jar file - resolve Resolve dependencies and write the resulting swift-java.classpath file - - See 'swift-java help ' for detailed help. -``` - -For example, the `JavaKitJar` library is generated with this command line: - -```swift -swift run swift-java --module-name JavaKitJar --depends-on JavaKit=Sources/JavaKit/swift-java.config -o Sources/JavaKitJar/generated Sources/JavaKitJar/swift-java.config -``` - -The `--swift-module JavaKitJar` parameter describes the name of the Swift module in which the code will be generated. - -The `--depends-on` option is followed by the swift-java configuration files for any library on which this Swift library depends. Each `--depends-on` option is of the form `=`, and tells swift-java which other Java classes have already been translated to Swift. For example, if your Java class uses `java.net.URL`, then you should include -`JavaKitNetwork`'s configuration file as a dependency here. - -The `-o` option specifies the output directory. Typically, this will be `Sources//generated` or similar to keep the generated Swift files separate from any hand-written ones. To see the output on the terminal rather than writing files to disk, pass `-` for this option. - -Finally, the command line should contain the `swift-java.config` file containing the list of classes that should be translated into Swift and their corresponding Swift type names. The tool will output a single `.swift` file for each class, along with warnings for any public API that cannot be translated into Swift. The most common warnings are due to missing Swift projections for Java classes. For example, here we have not translated (or provided the translation manifests for) the Java classes -`java.util.zip.ZipOutputStream` and `java.io.OutputStream`: - -``` -warning: Unable to translate 'java.util.jar.JarOutputStream' superclass: Java class 'java.util.zip.ZipOutputStream' has not been translated into Swift -warning: Unable to translate 'java.util.jar.JarOutputStream' constructor: Java class 'java.io.OutputStream' has not been translated into Swift -warning: Unable to translate 'java.util.jar.JarInputStream' method 'transferTo': Java class 'java.io.OutputStream' has not been translated into Swift -``` - -The result of such warnings is that certain information won't be statically available in Swift, e.g., the superclass won't be known (so we will assume it is `JavaObject`), or the specified constructors or methods won't be translated. If you don't need these APIs, the warnings can be safely ignored. The APIs can still be called dynamically via JNI. - -The `--jar` option changes the operation of `swift-java`. Instead of wrapping Java classes in Swift, it scans the given input Jar file to find all public classes and outputs a configuration file `swift-java.config` mapping all of the Java classes in the Jar file to Swift types. The `--jar` mode is expected to be used to help import a Java library into Swift wholesale, after which swift-java should invoked again given the generated configuration file. - -### Under construction: Create a Java class to wrap the Swift library - -**NOTE**: the instructions here work, but we are still smoothing out the interoperability story. - -All JavaKit-based applications start execution within the Java Virtual Machine. First, define your own Java class that loads your native Swift library and provides a `native` entry point to get into the Swift code. Here is a minimal Java class that has all of the program's logic written in Swift, including `main`: - - -```java -package org.swift.javakit; - -public class HelloSwiftMain { - static { - System.loadLibrary("HelloSwift"); - } - - public native static void main(String[] args); -} -``` - -Compile this into a `.class` file with `javac` before we build the Swift half, e.g.,: - -``` -javac Java/src/org/swift/javakit/JavaClassTranslator.java -``` - -### Create a Swift library - -The Java class created above loads a native library `HelloSwift` that needs to contain a definition of the `main` method in the class `org.swift.javakit.HelloSwiftMain`. `HelloSwift` should be defined as a SwiftPM dynamic library product, e.g., - -```swift - products: [ - .library( - name: "HelloSwift", - type: .dynamic, - targets: ["HelloSwift"] - ), - ] -``` - -with an associated target that depends on `JavaKit`: - -```swift - .target( - name: "HelloSwift", - dependencies: [ - .product(name: "ArgumentParser", package: "swift-argument-parser"), - .product(name: "JavaKit", package: "JavaKit") - ]) -``` - -### Implement the `native` Java method in Swift -Now, in the `HelloSwift` Swift library, define a `struct` that provides the `main` method for the Java class we already defined: - -```swift -import JavaKit - -@JavaImplementation("org.swift.javakit.HelloSwiftMain") -struct HelloSwiftMain { - @JavaStaticMethod - static func main(arguments: [String], environment: JNIEnvironment? = nil) { - print("Command line arguments are: \(arguments)") - } -} -``` - -Go ahead and build this library with `swift build`, and find the path to the directory containing the resulting shared library (e.g., `HelloSwift.dylib`, `HelloSwift.so`, or `HelloSwift.dll`, depending on platform). It is often in `.build/debug/` if you ran `swift build` on the command line. - -### Putting it all together! - -Finally, run this program on the command line like this: - -``` -java -cp Java/src -Djava.library.path=$(PATH_CONTAINING_HELLO_SWIFT)/ org.swift.javakit.HelloSwiftMain -v argument -``` - -This will prints the command-line arguments `-v` and `argument` as seen by Swift. - -### Bonus: Swift argument parser - -The easiest way to build a command-line program in Swift is with the [Swift argument parser library](https://github.com/apple/swift-argument-parser). We can extend our `HelloSwiftMain` type to conform to `ParsableCommand` and using the Swift argument parser to process the arguments provided by Java: - -```swift -import ArgumentParser -import JavaKit - -@JavaClass("org.swift.javakit.HelloSwiftMain") -struct HelloSwiftMain: ParsableCommand { - @Option(name: .shortAndLong, help: "Enable verbose output") - var verbose: Bool = false - - @JavaImplementation - static func main(arguments: [String], environment: JNIEnvironment? = nil) { - let command = Self.parseOrExit(arguments) - command.run(environment: environment) - } - - func run(environment: JNIEnvironment? = nil) { - print("Verbose = \(verbose)") - } -} -``` - -# `jextract-swift` - -The project is still very early days, however the general outline of using this approach is as follows: - -- **No code changes** need to be made to Swift libraries that are to be exposed to Java using jextract-swift. -- Swift sources are compiled to `.swiftinterface` files -- These `.swiftinterface` files are imported by jextract-swift which generates `*.java` files -- The generated Java files contain generated code for efficient native invocations. - -You can then use Swift libraries in Java just by calling the appropriate methods and initializers. - -## `jextract-swift`: Generating Java bridging files - -This repository also includes the `jextract-swift` tool which is similar to the JDK's [`jextract`](https://github.com/openjdk/jextract/). - -This approach is using Java's most recent (stable in JDK22) Foreign function and Memory APIs, collectively known as "Project Panama". You can read more about it here: https://openjdk.org/projects/panama/ It promises much higher performance than traditional approaches using JNI, and is primarily aimed for calling native code from a Java application. - -:warning: This feature requires JDK 22. The recommended way to install/manage JDKs is using [sdkman](https://sdkman.io): - -``` -curl -s "https://get.sdkman.io" | bash -sdk install java 22-open - -export JAVA_HOME=$(sdk home java 22-open) -``` - -`jextract-swift` can be pointed at `*.swiftinterface` files and will generate corresponding Java files that use the (new in Java 22) Foreign Function & Memory APIs to expose efficient ways to call "down" into Swift from Java. - -## JExtract: Swift <-> Java Type mapping - -TODO: these are not implemented yet. - -### Closures and Callbacks - -A Swift function may accept a closure which is used as a callback: - -```swift -func callMe(maybe: () -> ()) {} -``` - -Minimal support for c-compatible closures is implemented, more documentation soon. - - -## `jextract-swift` importer behavior - -Only `public` functions, properties and types are imported. - -Global Swift functions become static functions on on a class with the same name as the Swift module in Java, - -```swift -// Swift (Sources/SomeModule/Example.swift) - -public func globalFunction() -``` - -becomes: - -```java -// Java (SomeModule.java) - -public final class SomeModule ... { - public static void globalFunction() { ... } -} -``` diff --git a/Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md b/Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md new file mode 100644 index 00000000..dc2c7b0e --- /dev/null +++ b/Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md @@ -0,0 +1,94 @@ +# Supported Features + +Summary of features supported by the swift-java interoperability libraries and tools. + +## Overview + +JavaKit supports both directions of interoperability, using Swift macros and source generation +(via the `swift-java wrap-java` command). + +### Java -> Swift + +It is possible to use JavaKit macros and the `wrap-java` command to simplify implementing +Java `native` functions. JavaKit simplifies the type conversions + +> tip: This direction of interoperability is covered in the WWDC2025 session 'Explore Swift and Java interoperability' +> around the [7-minute mark](https://youtu.be/QSHO-GUGidA?si=vUXxphTeO-CHVZ3L&t=448). + +| Feature | Macro support | +|--------------------------------------------------|-------------------------| +| Java `static native` method implemented by Swift | ✅ `@JavaImplementation` | +| **This list is very work in progress** | | + +### Swift -> Java + + +> tip: This direction of interoperability is covered in the WWDC2025 session 'Explore Swift and Java interoperability' +> around the [10-minute mark](https://youtu.be/QSHO-GUGidA?si=QyYP5-p2FL_BH7aD&t=616). + +| Java Feature | Macro support | +|----------------------------------------|---------------| +| Java `class` | ✅ | +| Java class inheritance | ✅ | +| Java `abstract class` | TODO | +| Java `enum` | ❌ | +| Java methods: `static`, member | ✅ `@JavaMethod` | +| **This list is very work in progress** | | + + +### JExtract: Java -> Swift + +SwiftJava's `swift-java jextract` tool automates generating Java bindings from Swift sources. + +> tip: This direction of interoperability is covered in the WWDC2025 session 'Explore Swift and Java interoperability' +> around the [14-minute mark](https://youtu.be/QSHO-GUGidA?si=b9YUwAWDWFGzhRXN&t=842). + + +| Swift Feature | FFM | JNI | +|--------------------------------------------------------------------------------------| -------- |-----| +| Initializers: `class`, `struct` | ✅ | ✅ | +| Optional Initializers / Throwing Initializers | ❌ | ❌ | +| Deinitializers: `class`, `struct` | ✅ | ✅ | +| `enum`, `actor` | ❌ | ❌ | +| Global Swift `func` | ✅ | ✅ | +| Class/struct member `func` | ✅ | ✅ | +| Throwing functions: `func x() throws` | ❌ | ✅ | +| Typed throws: `func x() throws(E)` | ❌ | ❌ | +| Stored properties: `var`, `let` (with `willSet`, `didSet`) | ✅ | ✅ | +| Computed properties: `var` (incl. `throws`) | ✅ / TODO | ✅ | +| Async functions `func async` and properties: `var { get async {} }` | ❌ | ❌ | +| Arrays: `[UInt8]`, `[T]` | ❌ | ❌ | +| Dictionaries: `[String: Int]`, `[K:V]` | ❌ | ❌ | +| Generic functions | ❌ | ❌ | +| `Foundation.Data`, `any Foundation.DataProtocol` | ✅ | ❌ | +| Tuples: `(Int, String)`, `(A, B, C)` | ❌ | ❌ | +| Protocols: `protocol`, existential parameters `any Collection` | ❌ | ❌ | +| Optional types: `Int?`, `AnyObject?` | ❌ | ❌ | +| Primitive types: `Bool`, `Int`, `Int8`, `Int16`, `Int32`, `Int64`, `Float`, `Double` | ✅ | ✅ | +| Unsigned primitive types: `UInt`, `UInt8`, `UInt16`, `UInt32`, `UInt64` | ❌ | ❌ | +| String (with copying data) | ✅ | ✅ | +| Variadic parameters: `T...` | ❌ | ❌ | +| Parametrer packs / Variadic generics | ❌ | ❌ | +| Ownership modifiers: `inout`, `borrowing`, `consuming` | ❌ | ❌ | +| Default parameter values: `func p(name: String = "")` | ❌ | ❌ | +| Operators: `+`, `-`, user defined | ❌ | ❌ | +| Subscripts: `subscript()` | ❌ | ❌ | +| Equatable | ❌ | ❌ | +| Pointers: `UnsafeRawPointer`, UnsafeBufferPointer (?) | 🟡 | ❌ | +| Nested types: `struct Hello { struct World {} }` | ❌ | ❌ | +| Inheritance: `class Caplin: Capybara` | ❌ | ❌ | +| Non-escaping `Void` closures: `func callMe(maybe: () -> ())` | ✅ | ✅ | +| Non-escaping closures with primitive arguments/results: `func callMe(maybe: (Int) -> (Double))` | ✅ | ✅ | +| Non-escaping closures with object arguments/results: `func callMe(maybe: (JavaObj) -> (JavaObj))` | ❌ | ❌ | +| `@escaping` closures: `func callMe(_: @escaping () -> ())` | ❌ | ❌ | +| Swift type extensions: `extension String { func uppercased() }` | 🟡 | 🟡 | +| Swift macros (maybe) | ❌ | ❌ | +| Result builders | ❌ | ❌ | +| Automatic Reference Counting of class types / lifetime safety | ✅ | ✅ | +| Value semantic types (e.g. struct copying) | ❌ | ❌ | +| Opaque types: `func get() -> some Builder`, func take(worker: some Worker) | ❌ | ❌ | +| Swift concurrency: `func async`, `actor`, `distribued actor` | ❌ | ❌ | +| | | | +| | | | + +> tip: The list of features may be incomplete, please file an issue if something is unclear or should be clarified in this table. diff --git a/Sources/SwiftJavaDocumentation/Documentation.docc/SwiftJavaCommandLineTool.md b/Sources/SwiftJavaDocumentation/Documentation.docc/SwiftJavaCommandLineTool.md new file mode 100644 index 00000000..f83458d4 --- /dev/null +++ b/Sources/SwiftJavaDocumentation/Documentation.docc/SwiftJavaCommandLineTool.md @@ -0,0 +1,256 @@ +# swift-java command line tool + +The `swift-java` command line tool offers multiple ways to interact your Java interoperability enabled projects. + +## Overview + +The `swift-java` command line tool offers multiple modes which you can use to prepare your Swift and Java code to interact with eachother. + +The following sections will explain the modes in depth. When in doubt, you can always use the command line `--help` to get additional +guidance about the tool and available options: + +```bash +> swift-java --help + +USAGE: swift-java + +OPTIONS: + -h, --help Show help information. + +SUBCOMMANDS: + configure Configure and emit a swift-java.config file based on an input dependency or jar file + resolve Resolve dependencies and write the resulting swift-java.classpath file + wrap-java Wrap Java classes with corresponding Swift bindings. + jextract Wrap Swift functions and types with Java bindings, making them available to be called from Java + + See 'swift-java help ' for detailed help. +``` + +### Expose Java classes to Swift: swift-java wrap-java + +The `swift-java` is a Swift program that uses Java's runtime reflection facilities to translate the requested Java classes into their Swift projections. The output is a number of Swift source files, each of which corresponds to a +single Java class. The `swift-java` can be executed like this: + +``` +swift-java help wrap-java +``` + +to produce help output like the following: + +``` +USAGE: swift-java wrap-java [--output-directory ] [--input-swift ] [--log-level ] [--cp ...] [--filter-java-package ] --swift-module [--depends-on ...] [--swift-native-implementation ...] [--cache-directory ] [--swift-match-package-directory-structure ] + +ARGUMENTS: + Path to .jar file whose Java classes should be wrapped using Swift bindings + +OPTIONS: + -o, --output-directory + The directory in which to output generated SwiftJava configuration files. + --input-swift + Directory containing Swift files which should be extracted into Java bindings. Also known as 'jextract' mode. Must be paired with --output-java and --output-swift. + -l, --log-level + Configure the level of logs that should be printed (values: trace, debug, info, notice, warning, error, critical; default: log level) + --cp, --classpath Class search path of directories and zip/jar files from which Java classes can be loaded. + -f, --filter-java-package + While scanning a classpath, inspect only types included in this package + --swift-module + The name of the Swift module into which the resulting Swift types will be generated. + --depends-on + A swift-java configuration file for a given Swift module name on which this module depends, + e.g., JavaKitJar=Sources/JavaKitJar/Java2Swift.config. There should be one of these options + for each Swift module that this module depends on (transitively) that contains wrapped Java sources. + --swift-native-implementation + The names of Java classes whose declared native methods will be implemented in Swift. + --cache-directory + Cache directory for intermediate results and other outputs between runs + --swift-match-package-directory-structure + Match java package directory structure with generated Swift files (default: false) + -h, --help Show help information. + +``` + +For example, the `JavaKitJar` library is generated with this command line: + +```swift +swift-java wrap-java --swift-module JavaKitJar --depends-on JavaKit=Sources/JavaKit/swift-java.config -o Sources/JavaKitJar/generated Sources/JavaKitJar/swift-java.config +``` + +The `--swift-module JavaKitJar` parameter describes the name of the Swift module in which the code will be generated. + +The `--depends-on` option is followed by the swift-java configuration files for any library on which this Swift library depends. Each `--depends-on` option is of the form `=`, and tells swift-java which other Java classes have already been translated to Swift. For example, if your Java class uses `java.net.URL`, then you should include +`JavaKitNetwork`'s configuration file as a dependency here. + +The `-o` option specifies the output directory. Typically, this will be `Sources//generated` or similar to keep the generated Swift files separate from any hand-written ones. To see the output on the terminal rather than writing files to disk, pass `-` for this option. + +Finally, the command line should contain the `swift-java.config` file containing the list of classes that should be translated into Swift and their corresponding Swift type names. The tool will output a single `.swift` file for each class, along with warnings for any public API that cannot be translated into Swift. The most common warnings are due to missing Swift projections for Java classes. For example, here we have not translated (or provided the translation manifests for) the Java classes +`java.util.zip.ZipOutputStream` and `java.io.OutputStream`: + +``` +warning: Unable to translate 'java.util.jar.JarOutputStream' superclass: Java class 'java.util.zip.ZipOutputStream' has not been translated into Swift +warning: Unable to translate 'java.util.jar.JarOutputStream' constructor: Java class 'java.io.OutputStream' has not been translated into Swift +warning: Unable to translate 'java.util.jar.JarInputStream' method 'transferTo': Java class 'java.io.OutputStream' has not been translated into Swift +``` + +The result of such warnings is that certain information won't be statically available in Swift, e.g., the superclass won't be known (so we will assume it is `JavaObject`), or the specified constructors or methods won't be translated. If you don't need these APIs, the warnings can be safely ignored. The APIs can still be called dynamically via JNI. + +The `--jar` option changes the operation of `swift-java`. Instead of wrapping Java classes in Swift, it scans the given input Jar file to find all public classes and outputs a configuration file `swift-java.config` mapping all of the Java classes in the Jar file to Swift types. The `--jar` mode is expected to be used to help import a Java library into Swift wholesale, after which swift-java should invoked again given the generated configuration file. + +### Under construction: Create a Java class to wrap the Swift library + +**NOTE**: the instructions here work, but we are still smoothing out the interoperability story. + +All JavaKit-based applications start execution within the Java Virtual Machine. First, define your own Java class that loads your native Swift library and provides a `native` entry point to get into the Swift code. Here is a minimal Java class that has all of the program's logic written in Swift, including `main`: + + +```java +package org.swift.javakit; + +public class HelloSwiftMain { + static { + System.loadLibrary("HelloSwift"); + } + + public native static void main(String[] args); +} +``` + +Compile this into a `.class` file with `javac` before we build the Swift half, e.g.,: + +``` +javac Java/src/org/swift/javakit/JavaClassTranslator.java +``` + +### Create a Swift library + +The Java class created above loads a native library `HelloSwift` that needs to contain a definition of the `main` method in the class `org.swift.javakit.HelloSwiftMain`. `HelloSwift` should be defined as a SwiftPM dynamic library product, e.g., + +```swift + products: [ + .library( + name: "HelloSwift", + type: .dynamic, + targets: ["HelloSwift"] + ), + ] +``` + +with an associated target that depends on `JavaKit`: + +```swift + .target( + name: "HelloSwift", + dependencies: [ + .product(name: "ArgumentParser", package: "swift-argument-parser"), + .product(name: "JavaKit", package: "JavaKit") + ]) +``` + +### Implement the `native` Java method in Swift +Now, in the `HelloSwift` Swift library, define a `struct` that provides the `main` method for the Java class we already defined: + +```swift +import JavaKit + +@JavaImplementation("org.swift.javakit.HelloSwiftMain") +struct HelloSwiftMain { + @JavaStaticMethod + static func main(arguments: [String], environment: JNIEnvironment? = nil) { + print("Command line arguments are: \(arguments)") + } +} +``` + +Go ahead and build this library with `swift build`, and find the path to the directory containing the resulting shared library (e.g., `HelloSwift.dylib`, `HelloSwift.so`, or `HelloSwift.dll`, depending on platform). It is often in `.build/debug/` if you ran `swift build` on the command line. + +### Putting it all together! + +Finally, run this program on the command line like this: + +``` +java -cp Java/src -Djava.library.path=$(PATH_CONTAINING_HELLO_SWIFT)/ org.swift.javakit.HelloSwiftMain -v argument +``` + +This will prints the command-line arguments `-v` and `argument` as seen by Swift. + +### Bonus: Swift argument parser + +The easiest way to build a command-line program in Swift is with the [Swift argument parser library](https://github.com/apple/swift-argument-parser). We can extend our `HelloSwiftMain` type to conform to `ParsableCommand` and using the Swift argument parser to process the arguments provided by Java: + +```swift +import ArgumentParser +import JavaKit + +@JavaClass("org.swift.javakit.HelloSwiftMain") +struct HelloSwiftMain: ParsableCommand { + @Option(name: .shortAndLong, help: "Enable verbose output") + var verbose: Bool = false + + @JavaImplementation + static func main(arguments: [String], environment: JNIEnvironment? = nil) { + let command = Self.parseOrExit(arguments) + command.run(environment: environment) + } + + func run(environment: JNIEnvironment? = nil) { + print("Verbose = \(verbose)") + } +} +``` + +### Download Java dependencies in Swift builds: swift-java resolve + +> TIP: See the `Samples/DependencySampleApp` for a fully functional showcase of this mode. + +TODO: documentation on this feature + +### Expose Swift code to Java: swift-java jextract + +The project is still very early days, however the general outline of using this approach is as follows: + +- **No code changes** need to be made to Swift libraries that are to be exposed to Java using jextract-swift. +- Swift sources are compiled to `.swiftinterface` files +- These `.swiftinterface` files are imported by jextract-swift which generates `*.java` files +- The generated Java files contain generated code for efficient native invocations. + +You can then use Swift libraries in Java just by calling the appropriate methods and initializers. + +### Generating Java bindings for Swift libraries + +This repository also includes the `jextract-swift` tool which is similar to the JDK's [`jextract`](https://github.com/openjdk/jextract/). + +This approach offers two modes of operation: + +- the default `--mode ffm` which uses the [JEP-424 Foreign function and Memory APIs](https://openjdk.org/jeps/424) which are available since JDK **22**. It promises much higher performance than traditional approaches using JNI, and is primarily aimed for calling native code from a Java application. + +> Tip: In order to use the ffm mode, you need to install a recent enough JDK (at least JDK 22). The recommended, and simplest way, to install the a JDK distribution of your choice is [sdkman](https://sdkman.io): +> +> ``` +> curl -s "https://get.sdkman.io" | bash +> sdk install java 22-open +> +> export JAVA_HOME=$(sdk home java 22-open) +> ``` + +`jextract-swift` can be pointed at `*.swiftinterface` files and will generate corresponding Java files that use the (new in Java 22) Foreign Function & Memory APIs to expose efficient ways to call "down" into Swift from Java. + +### Default jextract behaviors + +Only `public` functions, properties and types are imported. + +Global Swift functions become static functions on on a class with the same name as the Swift module in Java, + +```swift +// Swift (Sources/SomeModule/Example.swift) + +public func globalFunction() +``` + +becomes: + +```java +// Java (SomeModule.java) + +public final class SomeModule ... { + public static void globalFunction() { ... } +} +``` diff --git a/Sources/SwiftJavaDocumentation/Documentation.docc/SwiftPMPlugin.md b/Sources/SwiftJavaDocumentation/Documentation.docc/SwiftPMPlugin.md new file mode 100644 index 00000000..d10ab387 --- /dev/null +++ b/Sources/SwiftJavaDocumentation/Documentation.docc/SwiftPMPlugin.md @@ -0,0 +1,126 @@ +# SwiftJava SwiftPM Plugin + +The `SwiftJavaPlugin` automates `swift-java` command line tool invocations during the build process. + +## Overview + +### Installing the plugin + +To install the SwiftPM plugin in your target of choice include the `swift-java` package dependency: + +```swift +import Foundation + +let javaHome = findJavaHome() + +let javaIncludePath = "\(javaHome)/include" +#if os(Linux) + let javaPlatformIncludePath = "\(javaIncludePath)/linux" +#elseif os(macOS) + let javaPlatformIncludePath = "\(javaIncludePath)/darwin" +#elseif os(Windows) + let javaPlatformIncludePath = "\(javaIncludePath)/win32" +#endif + +let package = Package( + name: "MyProject", + + products: [ + .library( + name: "JavaKitExample", + type: .dynamic, + targets: ["JavaKitExample"] + ), + ], + + dependencies: [ + .package(url: "https://github.com/apple/swift-java", from: "..."), + ], + + targets: [ + .target( + name: "MyProject", + dependencies: [ + // ... + ], + swiftSettings: [ + .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) + ], + plugins: [ + .plugin(name: "JavaCompilerPlugin", package: "swift-java"), + .plugin(name: "JExtractSwiftPlugin", package: "swift-java"), + .plugin(name: "SwiftJavaPlugin", package: "swift-java"), + ] + ), + ] +) +``` + +```swift + +// Note: the JAVA_HOME environment variable must be set to point to where +// Java is installed, e.g., +// Library/Java/JavaVirtualMachines/openjdk-21.jdk/Contents/Home. +func findJavaHome() -> String { + if let home = ProcessInfo.processInfo.environment["JAVA_HOME"] { + print("JAVA_HOME = \(home)") + return home + } + + // This is a workaround for envs (some IDEs) which have trouble with + // picking up env variables during the build process + let path = "\(FileManager.default.homeDirectoryForCurrentUser.path()).java_home" + if let home = try? String(contentsOfFile: path, encoding: .utf8) { + if let lastChar = home.last, lastChar.isNewline { + return String(home.dropLast()) + } + + return home + } + + if let home = getJavaHomeFromLibexecJavaHome(), + !home.isEmpty { + return home + } + + fatalError("Please set the JAVA_HOME environment variable to point to where Java is installed.") +} + +/// On MacOS we can use the java_home tool as a fallback if we can't find JAVA_HOME environment variable. +func getJavaHomeFromLibexecJavaHome() -> String? { + let task = Process() + task.executableURL = URL(fileURLWithPath: "/usr/libexec/java_home") + + // Check if the executable exists before trying to run it + guard FileManager.default.fileExists(atPath: task.executableURL!.path) else { + print("/usr/libexec/java_home does not exist") + return nil + } + + let pipe = Pipe() + task.standardOutput = pipe + task.standardError = pipe // Redirect standard error to the same pipe for simplicity + + do { + try task.run() + task.waitUntilExit() + + let data = pipe.fileHandleForReading.readDataToEndOfFile() + let output = String(data: data, encoding: .utf8)?.trimmingCharacters(in: .whitespacesAndNewlines) + + if task.terminationStatus == 0 { + return output + } else { + print("java_home terminated with status: \(task.terminationStatus)") + // Optionally, log the error output for debugging + if let errorOutput = String(data: pipe.fileHandleForReading.readDataToEndOfFile(), encoding: .utf8) { + print("Error output: \(errorOutput)") + } + return nil + } + } catch { + print("Error running java_home: \(error)") + return nil + } +} +``` \ No newline at end of file diff --git a/Sources/SwiftJavaDocumentation/Documentation.docc/index.md b/Sources/SwiftJavaDocumentation/Documentation.docc/index.md new file mode 100644 index 00000000..7c695a71 --- /dev/null +++ b/Sources/SwiftJavaDocumentation/Documentation.docc/index.md @@ -0,0 +1,32 @@ +# ``SwiftJavaDocumentation`` + +The SwiftJava project enables interoperability between Swift and Java. + +## Overview + +This project contains a number of support packages, java libraries, tools and plugins that provide a complete +Swift and Java interoperability story. + +Please refer to articles about the specific direction of interoperability you are interested in. + +### Getting started + +TODO: Some general intro + +If you prefer a video introduction, you may want to this +[Explore Swift and Java interoperability](https://www.youtube.com/watch?v=QSHO-GUGidA) +WWDC 2025 session, +which is a quick overview of all the features and approaches offered by SwiftJava. + +## Topics + +### Supported Features + +- + + +### Source generation + +- +- + diff --git a/Sources/SwiftJavaDocumentation/empty.swift b/Sources/SwiftJavaDocumentation/empty.swift new file mode 100644 index 00000000..9c28861c --- /dev/null +++ b/Sources/SwiftJavaDocumentation/empty.swift @@ -0,0 +1,15 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +// Empty file, this target is a docs-only target. diff --git a/WIP.md b/WIP.md index e1f58612..88671233 100644 --- a/WIP.md +++ b/WIP.md @@ -6,9 +6,6 @@ Here is a long yet still very incomplete list of things we would like to do or improve: - Expressivity gaps: - - [x] Translate Java exceptions into Swift and vice versa - - [ ] Expose Swift types to Java - - [x] Figure out when to promote from the local to the global heap - [ ] Automatically turn get/set method pairs into Swift properties? - [ ] Implement a global registry that lets us find the Swift type corresponding to a canonical Java class name (e.g., `java.net.URL` -> `JavaKitNetwork.URL`) - [ ] Introduce overloads of `is` and `as` on the Swift projections so that conversion to any implemented interface or extended superclass returns non-optional. @@ -16,14 +13,8 @@ improve: - [ ] Recognize Java's enum classes and map them into Swift well - [ ] Translate Java constants into Swift constants - [ ] Support nested classes - - [x] Streamline the definition of "main" code in Swift - [ ] Figure out how to subclass a Java class from Swift - Tooling - - [ ] Extract documentation comments from Java and put them in the Swift projections - - [ ] [SwiftPM build plugin](https://github.com/swiftlang/swift-package-manager/blob/main/Documentation/Plugins.md) to generate the Swift projections from Java as part of the build - - [x] Figure out how to launch the Java runtime from Swift code so we don't need to always start via `java` - - [x] Figure out how to unit-test this framework using Swift Testing - - [x] Add a "Jar mode" to `Java2Swift` that translates all classes in the given Jar file. - [ ] Generate Swift projections for more common Java types into JavaKit libraries to make it easier to get started - [ ] Teach `Java2Swift` when to create extensions of already-translated types that pick up any members that couldn't be translated because of missing types. See, for example, how `JavaKitReflection` adds extensions to `JavaClass` based on types like `Method` and `Parameter` - Performance: From c7adc8e063b7d2a7b24c435998b8ef2057ed4ff9 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Thu, 24 Jul 2025 02:07:29 +0900 Subject: [PATCH 323/426] Build: don't crash when building in SPI and JAVA_HOME is missing (#329) --- Package.swift | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Package.swift b/Package.swift index ef529496..84b348c5 100644 --- a/Package.swift +++ b/Package.swift @@ -31,6 +31,11 @@ func findJavaHome() -> String { return home } + + if ProcessInfo.processInfo.environment["SPI_BUILD"] == "1" { + // just ignore that we're missing a JAVA_HOME when building in Swift Package Index + return "" + } fatalError("Please set the JAVA_HOME environment variable to point to where Java is installed.") } From 11dcbedc315845756b7dbf1ff6fa5369dc0d9f08 Mon Sep 17 00:00:00 2001 From: Mads Odgaard Date: Thu, 24 Jul 2025 15:42:04 +0200 Subject: [PATCH 324/426] [JExtract/JNI] Support JavaKit wrapped types as function parameters. (#330) --- .../JExtractSwiftPlugin.swift | 64 +++++++++++++++- .../Sources/MySwiftLibrary/MySwiftClass.swift | 6 ++ .../com/example/swift/MySwiftClassTest.java | 9 +++ .../Convenience/String+Extensions.swift | 39 ++++++++++ ...ISwift2JavaGenerator+JavaTranslation.swift | 42 +++++++++-- ...wift2JavaGenerator+NativeTranslation.swift | 53 +++++++++---- ...ift2JavaGenerator+SwiftThunkPrinting.swift | 26 ------- .../JNI/JNISwift2JavaGenerator.swift | 10 ++- Sources/JExtractSwiftLib/Swift2Java.swift | 15 +++- .../Swift2JavaTranslator.swift | 17 ++++- .../SwiftTypes/SwiftType.swift | 7 ++ .../Configuration.swift | 20 +++++ .../Documentation.docc/SupportedFeatures.md | 2 + .../Commands/JExtractCommand.swift | 20 ++++- .../Commands/WrapJavaCommand.swift | 28 ++----- Sources/SwiftJavaTool/SwiftJava.swift | 4 +- .../Asserts/TextAssertions.swift | 5 +- .../JNI/JNIJavaKitTests.swift | 74 +++++++++++++++++++ 18 files changed, 362 insertions(+), 79 deletions(-) create mode 100644 Tests/JExtractSwiftTests/JNI/JNIJavaKitTests.swift diff --git a/Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift b/Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift index 83c5f0d9..2778cebe 100644 --- a/Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift +++ b/Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift @@ -15,6 +15,8 @@ import Foundation import PackagePlugin +fileprivate let SwiftJavaConfigFileName = "swift-java.config" + @main struct JExtractSwiftBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin { @@ -51,12 +53,14 @@ struct JExtractSwiftBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin { log("Skipping jextract step, no 'javaPackage' configuration in \(getSwiftJavaConfigPath(target: target) ?? "")") return [] } - + // We use the the usual maven-style structure of "src/[generated|main|test]/java/..." // that is common in JVM ecosystem let outputJavaDirectory = context.outputJavaDirectory let outputSwiftDirectory = context.outputSwiftDirectory + let dependentConfigFiles = searchForDependentConfigFiles(in: target) + var arguments: [String] = [ /*subcommand=*/"jextract", "--swift-module", sourceModule.name, @@ -71,6 +75,16 @@ struct JExtractSwiftBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin { // as it depends on the contents of the input files. Therefore we have to implement this as a prebuild plugin. // We'll have to make up some caching inside the tool so we don't re-parse files which have not changed etc. ] + + let dependentConfigFilesArguments = dependentConfigFiles.flatMap { moduleAndConfigFile in + let (moduleName, configFile) = moduleAndConfigFile + return [ + "--depends-on", + "\(configFile.path(percentEncoded: false))" + ] + } + arguments += dependentConfigFilesArguments + if !javaPackage.isEmpty { arguments += ["--java-package", javaPackage] } @@ -117,5 +131,53 @@ struct JExtractSwiftBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin { ) ] } + + /// Find the manifest files from other swift-java executions in any targets + /// this target depends on. + func searchForDependentConfigFiles(in target: any Target) -> [(String, URL)] { + var dependentConfigFiles = [(String, URL)]() + + func _searchForConfigFiles(in target: any Target) { + // log("Search for config files in target: \(target.name)") + let dependencyURL = URL(filePath: target.directory.string) + + // Look for a config file within this target. + let dependencyConfigURL = dependencyURL + .appending(path: SwiftJavaConfigFileName) + let dependencyConfigString = dependencyConfigURL + .path(percentEncoded: false) + + if FileManager.default.fileExists(atPath: dependencyConfigString) { + dependentConfigFiles.append((target.name, dependencyConfigURL)) + } + } + + // Process direct dependencies of this target. + for dependency in target.dependencies { + switch dependency { + case .target(let target): + // log("Dependency target: \(target.name)") + _searchForConfigFiles(in: target) + + case .product(let product): + // log("Dependency product: \(product.name)") + for target in product.targets { + // log("Dependency product: \(product.name), target: \(target.name)") + _searchForConfigFiles(in: target) + } + + @unknown default: + break + } + } + + // Process indirect target dependencies. + for dependency in target.recursiveTargetDependencies { + // log("Recursive dependency target: \(dependency.name)") + _searchForConfigFiles(in: dependency) + } + + return dependentConfigFiles + } } diff --git a/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftClass.swift b/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftClass.swift index b4447f4f..9a78c3c2 100644 --- a/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftClass.swift +++ b/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftClass.swift @@ -12,6 +12,8 @@ // //===----------------------------------------------------------------------===// +import JavaKit + public class MySwiftClass { public let x: Int64 public let y: Int64 @@ -84,4 +86,8 @@ public class MySwiftClass { public func copy() -> MySwiftClass { return MySwiftClass(x: self.x, y: self.y) } + + public func addXWithJavaLong(_ other: JavaLong) -> Int64 { + return self.x + other.longValue() + } } diff --git a/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/MySwiftClassTest.java b/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/MySwiftClassTest.java index 4425d6b2..f034b904 100644 --- a/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/MySwiftClassTest.java +++ b/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/MySwiftClassTest.java @@ -139,4 +139,13 @@ void copy() { assertNotEquals(c1.$memoryAddress(), c2.$memoryAddress()); } } + + @Test + void addXWithJavaLong() { + try (var arena = new ConfinedSwiftMemorySession()) { + MySwiftClass c1 = MySwiftClass.init(20, 10, arena); + Long javaLong = 50L; + assertEquals(70, c1.addXWithJavaLong(javaLong)); + } + } } \ No newline at end of file diff --git a/Sources/JExtractSwiftLib/Convenience/String+Extensions.swift b/Sources/JExtractSwiftLib/Convenience/String+Extensions.swift index 1851e154..0f5cfeac 100644 --- a/Sources/JExtractSwiftLib/Convenience/String+Extensions.swift +++ b/Sources/JExtractSwiftLib/Convenience/String+Extensions.swift @@ -12,6 +12,8 @@ // //===----------------------------------------------------------------------===// +import JavaTypes + extension String { var firstCharacterUppercased: String { @@ -31,4 +33,41 @@ extension String { let thirdCharacterIndex = self.index(self.startIndex, offsetBy: 2) return self[thirdCharacterIndex].isUppercase } + + /// Returns a version of the string correctly escaped for a JNI + var escapedJNIIdentifier: String { + self.map { + if $0 == "_" { + return "_1" + } else if $0 == "/" { + return "_" + } else if $0 == ";" { + return "_2" + } else if $0 == "[" { + return "_3" + } else if $0.isASCII && ($0.isLetter || $0.isNumber) { + return String($0) + } else if let utf16 = $0.utf16.first { + // Escape any non-alphanumeric to their UTF16 hex encoding + let utf16Hex = String(format: "%04x", utf16) + return "_0\(utf16Hex)" + } else { + fatalError("Invalid JNI character: \($0)") + } + } + .joined() + } + + /// Looks up self as a JavaKit wrapped class name and converts it + /// into a `JavaType.class` if it exists in `lookupTable`. + func parseJavaClassFromJavaKitName(in lookupTable: [String: String]) -> JavaType? { + guard let canonicalJavaName = lookupTable[self] else { + return nil + } + let nameParts = canonicalJavaName.components(separatedBy: ".") + let javaPackageName = nameParts.dropLast().joined(separator: ".") + let javaClassName = nameParts.last! + + return .class(package: javaPackageName, name: javaClassName) + } } diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift index e704739c..57ea15b2 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift @@ -24,7 +24,11 @@ extension JNISwift2JavaGenerator { let translated: TranslatedFunctionDecl? do { - let translation = JavaTranslation(swiftModuleName: swiftModuleName, javaPackage: self.javaPackage) + let translation = JavaTranslation( + swiftModuleName: swiftModuleName, + javaPackage: self.javaPackage, + javaClassLookupTable: self.javaClassLookupTable + ) translated = try translation.translate(decl) } catch { self.logger.debug("Failed to translate: '\(decl.swiftDecl.qualifiedNameForDebug)'; \(error)") @@ -38,9 +42,13 @@ extension JNISwift2JavaGenerator { struct JavaTranslation { let swiftModuleName: String let javaPackage: String + let javaClassLookupTable: JavaClassLookupTable func translate(_ decl: ImportedFunc) throws -> TranslatedFunctionDecl { - let nativeTranslation = NativeJavaTranslation(javaPackage: self.javaPackage) + let nativeTranslation = NativeJavaTranslation( + javaPackage: self.javaPackage, + javaClassLookupTable: self.javaClassLookupTable + ) // Types with no parent will be outputted inside a "module" class. let parentName = decl.parentType?.asNominalType?.nominalTypeDecl.qualifiedName ?? swiftModuleName @@ -157,6 +165,8 @@ extension JNISwift2JavaGenerator { ) throws -> TranslatedParameter { switch swiftType { case .nominal(let nominalType): + let nominalTypeName = nominalType.nominalTypeDecl.name + if let knownType = nominalType.nominalTypeDecl.knownTypeKind { guard let javaType = JNISwift2JavaGenerator.translate(knownType: knownType) else { throw JavaTranslationError.unsupportedSwiftType(swiftType) @@ -168,11 +178,25 @@ extension JNISwift2JavaGenerator { ) } - // For now, we assume this is a JExtract class. + if nominalType.isJavaKitWrapper { + guard let javaType = nominalTypeName.parseJavaClassFromJavaKitName(in: self.javaClassLookupTable) else { + throw JavaTranslationError.wrappedJavaClassTranslationNotProvided(swiftType) + } + + return TranslatedParameter( + parameter: JavaParameter( + name: parameterName, + type: javaType + ), + conversion: .placeholder + ) + } + + // We assume this is a JExtract class. return TranslatedParameter( parameter: JavaParameter( name: parameterName, - type: .class(package: nil, name: nominalType.nominalTypeDecl.name) + type: .class(package: nil, name: nominalTypeName) ), conversion: .valueMemoryAddress(.placeholder) ) @@ -213,7 +237,11 @@ extension JNISwift2JavaGenerator { ) } - // For now, we assume this is a JExtract class. + if nominalType.isJavaKitWrapper { + throw JavaTranslationError.unsupportedSwiftType(swiftResult.type) + } + + // We assume this is a JExtract class. let javaType = JavaType.class(package: nil, name: nominalType.nominalTypeDecl.name) return TranslatedResult( javaType: javaType, @@ -350,5 +378,9 @@ extension JNISwift2JavaGenerator { enum JavaTranslationError: Error { case unsupportedSwiftType(SwiftType) + + /// The user has not supplied a mapping from `SwiftType` to + /// a java class. + case wrappedJavaClassTranslationNotProvided(SwiftType) } } diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift index cae6010d..5ccefadb 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift @@ -18,6 +18,7 @@ extension JNISwift2JavaGenerator { struct NativeJavaTranslation { let javaPackage: String + let javaClassLookupTable: JavaClassLookupTable /// Translates a Swift function into the native JNI method signature. func translate( @@ -62,10 +63,12 @@ extension JNISwift2JavaGenerator { swiftParameter: SwiftParameter, parameterName: String, methodName: String, - parentName: String, + parentName: String ) throws -> NativeParameter { switch swiftParameter.type { case .nominal(let nominalType): + let nominalTypeName = nominalType.nominalTypeDecl.name + if let knownType = nominalType.nominalTypeDecl.knownTypeKind { guard let javaType = JNISwift2JavaGenerator.translate(knownType: knownType), javaType.implementsJavaValue else { throw JavaTranslationError.unsupportedSwiftType(swiftParameter.type) @@ -78,6 +81,25 @@ extension JNISwift2JavaGenerator { ) } + if nominalType.isJavaKitWrapper { + guard let javaType = nominalTypeName.parseJavaClassFromJavaKitName(in: self.javaClassLookupTable) else { + throw JavaTranslationError.wrappedJavaClassTranslationNotProvided(swiftParameter.type) + } + + return NativeParameter( + name: parameterName, + javaType: javaType, + conversion: .initializeJavaKitWrapper(wrapperName: nominalTypeName) + ) + } + + // JExtract classes are passed as the pointer. + return NativeParameter( + name: parameterName, + javaType: .long, + conversion: .pointee(.extractSwiftValue(.placeholder, swiftType: swiftParameter.type)) + ) + case .tuple([]): return NativeParameter( name: parameterName, @@ -110,13 +132,6 @@ extension JNISwift2JavaGenerator { case .metatype, .optional, .tuple, .existential, .opaque: throw JavaTranslationError.unsupportedSwiftType(swiftParameter.type) } - - // Classes are passed as the pointer. - return NativeParameter( - name: parameterName, - javaType: .long, - conversion: .pointee(.extractSwiftValue(.placeholder, swiftType: swiftParameter.type)) - ) } func translateClosureResult( @@ -193,6 +208,15 @@ extension JNISwift2JavaGenerator { ) } + if nominalType.isJavaKitWrapper { + throw JavaTranslationError.unsupportedSwiftType(swiftResult.type) + } + + return NativeResult( + javaType: .long, + conversion: .getJNIValue(.allocateSwiftValue(name: "result", swiftType: swiftResult.type)) + ) + case .tuple([]): return NativeResult( javaType: .void, @@ -203,13 +227,7 @@ extension JNISwift2JavaGenerator { throw JavaTranslationError.unsupportedSwiftType(swiftResult.type) } - // TODO: Handle other classes, for example from JavaKit macros. - // for now we assume all passed in classes are JExtract generated - // so we pass the pointer. - return NativeResult( - javaType: .long, - conversion: .getJNIValue(.allocateSwiftValue(name: "result", swiftType: swiftResult.type)) - ) + } } @@ -262,6 +280,8 @@ extension JNISwift2JavaGenerator { indirect case closureLowering(parameters: [NativeParameter], result: NativeResult) + case initializeJavaKitWrapper(wrapperName: String) + /// Returns the conversion string applied to the placeholder. func render(_ printer: inout CodePrinter, _ placeholder: String) -> String { // NOTE: 'printer' is used if the conversion wants to cause side-effects. @@ -348,6 +368,9 @@ extension JNISwift2JavaGenerator { printer.print("}") return printer.finalize() + + case .initializeJavaKitWrapper(let wrapperName): + return "\(wrapperName)(javaThis: \(placeholder), environment: environment!)" } } } diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift index 20551465..35d4dbef 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift @@ -328,29 +328,3 @@ extension JNISwift2JavaGenerator { return newSelfParamName } } - -extension String { - /// Returns a version of the string correctly escaped for a JNI - var escapedJNIIdentifier: String { - self.map { - if $0 == "_" { - return "_1" - } else if $0 == "/" { - return "_" - } else if $0 == ";" { - return "_2" - } else if $0 == "[" { - return "_3" - } else if $0.isASCII && ($0.isLetter || $0.isNumber) { - return String($0) - } else if let utf16 = $0.utf16.first { - // Escape any non-alphanumeric to their UTF16 hex encoding - let utf16Hex = String(format: "%04x", utf16) - return "_0\(utf16Hex)" - } else { - fatalError("Invalid JNI character: \($0)") - } - } - .joined() - } -} diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator.swift index 0cc523b4..79f546ac 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator.swift @@ -14,6 +14,10 @@ import JavaTypes +/// A table that where keys are Swift class names and the values are +/// the fully qualified canoical names. +package typealias JavaClassLookupTable = [String: String] + package class JNISwift2JavaGenerator: Swift2JavaGenerator { let analysis: AnalysisResult let swiftModuleName: String @@ -22,6 +26,8 @@ package class JNISwift2JavaGenerator: Swift2JavaGenerator { let swiftOutputDirectory: String let javaOutputDirectory: String + let javaClassLookupTable: JavaClassLookupTable + var javaPackagePath: String { javaPackage.replacingOccurrences(of: ".", with: "/") } @@ -39,7 +45,8 @@ package class JNISwift2JavaGenerator: Swift2JavaGenerator { translator: Swift2JavaTranslator, javaPackage: String, swiftOutputDirectory: String, - javaOutputDirectory: String + javaOutputDirectory: String, + javaClassLookupTable: JavaClassLookupTable ) { self.logger = Logger(label: "jni-generator", logLevel: translator.log.logLevel) self.analysis = translator.result @@ -47,6 +54,7 @@ package class JNISwift2JavaGenerator: Swift2JavaGenerator { self.javaPackage = javaPackage self.swiftOutputDirectory = swiftOutputDirectory self.javaOutputDirectory = javaOutputDirectory + self.javaClassLookupTable = javaClassLookupTable // If we are forced to write empty files, construct the expected outputs if translator.config.writeEmptyFiles ?? false { diff --git a/Sources/JExtractSwiftLib/Swift2Java.swift b/Sources/JExtractSwiftLib/Swift2Java.swift index dad25299..6473cea3 100644 --- a/Sources/JExtractSwiftLib/Swift2Java.swift +++ b/Sources/JExtractSwiftLib/Swift2Java.swift @@ -20,9 +20,11 @@ import JavaKitConfigurationShared // TODO: this should become SwiftJavaConfigura public struct SwiftToJava { let config: Configuration + let dependentConfigs: [Configuration] - public init(config: Configuration) { + public init(config: Configuration, dependentConfigs: [Configuration]) { self.config = config + self.dependentConfigs = dependentConfigs } public func run() throws { @@ -83,6 +85,14 @@ public struct SwiftToJava { fatalError("Missing --output-java directory!") } + let wrappedJavaClassesLookupTable: JavaClassLookupTable = dependentConfigs.compactMap(\.classes).reduce(into: [:]) { + for (canonicalName, javaClass) in $1 { + $0[javaClass] = canonicalName + } + } + + translator.dependenciesClasses = Array(wrappedJavaClassesLookupTable.keys) + try translator.analyze() switch config.mode { @@ -101,7 +111,8 @@ public struct SwiftToJava { translator: translator, javaPackage: config.javaPackage ?? "", swiftOutputDirectory: outputSwiftDirectory, - javaOutputDirectory: outputJavaDirectory + javaOutputDirectory: outputJavaDirectory, + javaClassLookupTable: wrappedJavaClassesLookupTable ) try generator.generate() diff --git a/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift b/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift index 07023b09..d1141e5f 100644 --- a/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift +++ b/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift @@ -39,6 +39,9 @@ public final class Swift2JavaTranslator { var inputs: [Input] = [] + /// A list of used Swift class names that live in dependencies, e.g. `JavaInteger` + package var dependenciesClasses: [String] = [] + // ==== Output state package var importedGlobalVariables: [ImportedFunc] = [] @@ -111,9 +114,11 @@ extension Swift2JavaTranslator { } package func prepareForTranslation() { + let dependenciesSource = self.buildDependencyClassesSourceFile() + self.symbolTable = SwiftSymbolTable.setup( moduleName: self.swiftModuleName, - inputs.map({ $0.syntax }), + inputs.map({ $0.syntax }) + [dependenciesSource], log: self.log ) } @@ -167,6 +172,16 @@ extension Swift2JavaTranslator { } return false } + + /// Returns a source file that contains all the available dependency classes. + private func buildDependencyClassesSourceFile() -> SourceFileSyntax { + let contents = self.dependenciesClasses.map { + "public class \($0) {}" + } + .joined(separator: "\n") + + return SourceFileSyntax(stringLiteral: contents) + } } // ==== ---------------------------------------------------------------------------------------------------------------- diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftType.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftType.swift index 531ab45c..d0f1f98d 100644 --- a/Sources/JExtractSwiftLib/SwiftTypes/SwiftType.swift +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftType.swift @@ -171,6 +171,13 @@ extension SwiftNominalType: CustomStringConvertible { } } +extension SwiftNominalType { + // TODO: Better way to detect Java wrapped classes. + var isJavaKitWrapper: Bool { + nominalTypeDecl.name.hasPrefix("Java") + } +} + extension SwiftType { init(_ type: TypeSyntax, symbolTable: SwiftSymbolTable) throws { switch type.as(TypeSyntaxEnum.self) { diff --git a/Sources/JavaKitConfigurationShared/Configuration.swift b/Sources/JavaKitConfigurationShared/Configuration.swift index 876b577b..5c57082e 100644 --- a/Sources/JavaKitConfigurationShared/Configuration.swift +++ b/Sources/JavaKitConfigurationShared/Configuration.swift @@ -141,6 +141,26 @@ public func readConfiguration(configPath: URL, file: String = #fileID, line: UIn } } +/// Load all dependent configs configured with `--depends-on` and return a list of +/// `(SwiftModuleName, Configuration)` tuples. +public func loadDependentConfigs(dependsOn: [String]) throws -> [(String?, Configuration)] { + try dependsOn.map { dependentConfig in + let equalLoc = dependentConfig.firstIndex(of: "=") + + var swiftModuleName: String? = nil + if let equalLoc { + swiftModuleName = String(dependentConfig[.. [String] { let basePath: String = FileManager.default.currentDirectoryPath let pluginOutputsDir = URL(fileURLWithPath: basePath) diff --git a/Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md b/Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md index dc2c7b0e..e7acb3eb 100644 --- a/Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md +++ b/Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md @@ -65,6 +65,8 @@ SwiftJava's `swift-java jextract` tool automates generating Java bindings from S | Protocols: `protocol`, existential parameters `any Collection` | ❌ | ❌ | | Optional types: `Int?`, `AnyObject?` | ❌ | ❌ | | Primitive types: `Bool`, `Int`, `Int8`, `Int16`, `Int32`, `Int64`, `Float`, `Double` | ✅ | ✅ | +| Parameters: JavaKit wrapped types `JavaLong`, `JavaInteger` | ❌ | ✅ | +| Return values: JavaKit wrapped types `JavaLong`, `JavaInteger` | ❌ | ❌ | | Unsigned primitive types: `UInt`, `UInt8`, `UInt16`, `UInt32`, `UInt64` | ❌ | ❌ | | String (with copying data) | ✅ | ✅ | | Variadic parameters: `T...` | ❌ | ❌ | diff --git a/Sources/SwiftJavaTool/Commands/JExtractCommand.swift b/Sources/SwiftJavaTool/Commands/JExtractCommand.swift index c7fe51a8..e4901bc2 100644 --- a/Sources/SwiftJavaTool/Commands/JExtractCommand.swift +++ b/Sources/SwiftJavaTool/Commands/JExtractCommand.swift @@ -60,6 +60,15 @@ extension SwiftJava { @Flag(help: "Some build systems require an output to be present when it was 'expected', even if empty. This is used by the JExtractSwiftPlugin build plugin, but otherwise should not be necessary.") var writeEmptyFiles: Bool = false + + @Option( + help: """ + A swift-java configuration file for a given Swift module name on which this module depends, + e.g., Sources/JavaKitJar/Java2Swift.config. There should be one of these options + for each Swift module that this module depends on (transitively) that contains wrapped Java sources. + """ + ) + var dependsOn: [String] = [] } } @@ -82,15 +91,20 @@ extension SwiftJava.JExtractCommand { print("[debug][swift-java] Running 'swift-java jextract' in mode: " + "\(self.mode)".bold) - try jextractSwift(config: config) + // Load all of the dependent configurations and associate them with Swift modules. + let dependentConfigs = try loadDependentConfigs(dependsOn: self.dependsOn) + print("[debug][swift-java] Dependent configs: \(dependentConfigs.count)") + + try jextractSwift(config: config, dependentConfigs: dependentConfigs.map(\.1)) } } extension SwiftJava.JExtractCommand { func jextractSwift( - config: Configuration + config: Configuration, + dependentConfigs: [Configuration] ) throws { - try SwiftToJava(config: config).run() + try SwiftToJava(config: config, dependentConfigs: dependentConfigs).run() } } diff --git a/Sources/SwiftJavaTool/Commands/WrapJavaCommand.swift b/Sources/SwiftJavaTool/Commands/WrapJavaCommand.swift index 05ac7651..4c5bd97b 100644 --- a/Sources/SwiftJavaTool/Commands/WrapJavaCommand.swift +++ b/Sources/SwiftJavaTool/Commands/WrapJavaCommand.swift @@ -77,7 +77,12 @@ extension SwiftJava.WrapJavaCommand { searchDirs: classpathSearchDirs, config: config) // Load all of the dependent configurations and associate them with Swift modules. - let dependentConfigs = try self.loadDependentConfigs() + let dependentConfigs = try loadDependentConfigs(dependsOn: self.dependsOn).map { moduleName, config in + guard let moduleName else { + throw JavaToSwiftError.badConfigOption + } + return (moduleName, config) + } print("[debug][swift-java] Dependent configs: \(dependentConfigs.count)") // Include classpath entries which libs we depend on require... @@ -102,27 +107,6 @@ extension SwiftJava.WrapJavaCommand { } } -extension SwiftJava.WrapJavaCommand { - - /// Load all dependent configs configured with `--depends-on` and return a list of - /// `(SwiftModuleName, Configuration)` tuples. - func loadDependentConfigs() throws -> [(String, Configuration)] { - try dependsOn.map { dependentConfig in - guard let equalLoc = dependentConfig.firstIndex(of: "=") else { - throw JavaToSwiftError.badConfigOption(dependentConfig) - } - - let afterEqual = dependentConfig.index(after: equalLoc) - let swiftModuleName = String(dependentConfig[..=" } } diff --git a/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift b/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift index 47397c63..4b0162f3 100644 --- a/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift +++ b/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift @@ -29,6 +29,7 @@ func assertOutput( _ renderKind: RenderKind, swiftModuleName: String = "SwiftModule", detectChunkByInitialLines _detectChunkByInitialLines: Int = 4, + javaClassLookupTable: [String: String] = [:], expectedChunks: [String], fileID: String = #fileID, filePath: String = #filePath, @@ -38,6 +39,7 @@ func assertOutput( var config = Configuration() config.swiftModule = swiftModuleName let translator = Swift2JavaTranslator(config: config) + translator.dependenciesClasses = Array(javaClassLookupTable.keys) try! translator.analyze(file: "/fake/Fake.swiftinterface", text: input) @@ -64,7 +66,8 @@ func assertOutput( translator: translator, javaPackage: "com.example.swift", swiftOutputDirectory: "/fake", - javaOutputDirectory: "/fake" + javaOutputDirectory: "/fake", + javaClassLookupTable: javaClassLookupTable ) switch renderKind { diff --git a/Tests/JExtractSwiftTests/JNI/JNIJavaKitTests.swift b/Tests/JExtractSwiftTests/JNI/JNIJavaKitTests.swift new file mode 100644 index 00000000..0283780a --- /dev/null +++ b/Tests/JExtractSwiftTests/JNI/JNIJavaKitTests.swift @@ -0,0 +1,74 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import JExtractSwiftLib +import Testing + +@Suite +struct JNIJavaKitTests { + let source = + """ + public func function(javaLong: JavaLong, javaInteger: JavaInteger, int: Int64) {} + """ + + let classLookupTable = [ + "JavaLong": "java.lang.Long", + "JavaInteger": "java.lang.Integer" + ] + + @Test + func function_javaBindings() throws { + try assertOutput( + input: source, + .jni, + .java, + javaClassLookupTable: classLookupTable, + expectedChunks: [ + """ + /** + * Downcall to Swift: + * {@snippet lang=swift : + * public func function(javaLong: JavaLong, javaInteger: JavaInteger, int: Int64) + * } + */ + public static void function(java.lang.Long javaLong, java.lang.Integer javaInteger, long int) { + SwiftModule.$function(javaLong, javaInteger, int); + } + """, + """ + private static native void $function(java.lang.Long javaLong, java.lang.Integer javaInteger, long int); + """ + ] + ) + } + + @Test + func function_swiftThunks() throws { + try assertOutput( + input: source, + .jni, + .swift, + detectChunkByInitialLines: 1, + javaClassLookupTable: classLookupTable, + expectedChunks: [ + """ + @_cdecl("Java_com_example_swift_SwiftModule__00024function__Ljava_lang_Long_2Ljava_lang_Integer_2J") + func Java_com_example_swift_SwiftModule__00024function__Ljava_lang_Long_2Ljava_lang_Integer_2J(environment: UnsafeMutablePointer!, thisClass: jclass, javaLong: jobject, javaInteger: jobject, int: jlong) { + SwiftModule.function(javaLong: JavaLong(javaThis: javaLong, environment: environment!), javaInteger: JavaInteger(javaThis: javaInteger, environment: environment!), int: Int64(fromJNI: int, in: environment!)) + } + """ + ] + ) + } +} From cbbe172dc230c59b05d6e0faa4e18291caa8e8a2 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Mon, 28 Jul 2025 21:08:11 +0900 Subject: [PATCH 325/426] Update to Gradle 8.14.2 so we don't have to keep Java 21 around anymore (#332) --- .github/actions/prepare_env/action.yml | 1 - docker/install_jdk.sh | 13 ++----------- gradle.properties | 2 +- gradle/wrapper/gradle-wrapper.jar | Bin 43583 -> 43764 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 9 ++++----- gradlew.bat | 4 ++-- 7 files changed, 10 insertions(+), 21 deletions(-) diff --git a/.github/actions/prepare_env/action.yml b/.github/actions/prepare_env/action.yml index 53bb3fd7..0e4a1ca3 100644 --- a/.github/actions/prepare_env/action.yml +++ b/.github/actions/prepare_env/action.yml @@ -10,7 +10,6 @@ runs: distribution: ${{ matrix.jdk_vendor }} java-version: | 24 - 21 17 cache: 'gradle' - name: Set JAVA_HOME_{N} diff --git a/docker/install_jdk.sh b/docker/install_jdk.sh index 122c0d06..8746e3ab 100755 --- a/docker/install_jdk.sh +++ b/docker/install_jdk.sh @@ -36,10 +36,6 @@ download_and_install_jdk() { if [ "$JDK_VENDOR" = 'corretto' ]; then if [ "$(uname -m)" = 'aarch64' ]; then case "$jdk_version" in - "21") - jdk_url="https://corretto.aws/downloads/latest/amazon-corretto-21-aarch64-linux-jdk.tar.gz" - expected_md5="87e458029cf9976945dfa3a22af3f850" - ;; "24") jdk_url="https://corretto.aws/downloads/latest/amazon-corretto-24-aarch64-linux-jdk.tar.gz" expected_md5="3b543f4e971350b73d0ab6d8174cc030" @@ -51,10 +47,6 @@ download_and_install_jdk() { esac else case "$jdk_version" in - "21") - jdk_url="https://corretto.aws/downloads/latest/amazon-corretto-21-x64-linux-jdk.tar.gz" - expected_md5="a123e7f50807c27de521bef7378d3377" - ;; "24") jdk_url="https://corretto.aws/downloads/latest/amazon-corretto-24-x64-linux-jdk.tar.gz" expected_md5="130885ded3cbfc712fbe9f7dace45a52" @@ -102,13 +94,12 @@ download_and_install_jdk() { cd "$HOME" } -# Usage: Install both JDK versions -download_and_install_jdk "21" +# Usage: Install JDK 24 download_and_install_jdk "24" ls -la /usr/lib/jvm/ cd /usr/lib/jvm/ -ln -s jdk-21 default-jdk +ln -s jdk-24 default-jdk find . | grep java | grep bin echo "JAVA_HOME = /usr/lib/jvm/default-jdk" /usr/lib/jvm/default-jdk/bin/java -version \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 335b6f40..679a1a1f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1 +1 @@ -org.gradle.java.installations.fromEnv=JAVA_HOME_24,JAVA_HOME_24_X64,JAVA_HOME_24_ARM64,JAVA_HOME_21,JAVA_HOME_21_X64,JAVA_HOME_21_ARM64 \ No newline at end of file +org.gradle.java.installations.fromEnv=JAVA_HOME_24,JAVA_HOME_24_X64,JAVA_HOME_24_ARM64 \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index a4b76b9530d66f5e68d973ea569d8e19de379189..1b33c55baabb587c669f562ae36f953de2481846 100644 GIT binary patch delta 34943 zcmXuKV_+Rz)3%+)Y~1X)v28cDZQE*`9qyPrXx!Mg8{4+s*nWFo&-eXbzt+q-bFO1% zb$T* z+;w-h{ce+s>j$K)apmK~8t5)PdZP3^U%(^I<0#3(!6T+vfBowN0RfQ&0iMAo055!% z04}dC>M#Z2#PO7#|Fj;cQ$sH}E-n7nQM_V}mtmG_)(me#+~0gf?s@gam)iLoR#sr( zrR9fU_ofhp5j-5SLDQP{O+SuE)l8x9_(9@h%eY-t47J-KX-1(`hh#A6_Xs+4(pHhy zuZ1YS9axk`aYwXuq;YN>rYv|U`&U67f=tinhAD$+=o+MWXkx_;qIat_CS1o*=cIxs zIgeoK0TiIa7t`r%%feL8VieY63-Aakfi~qlE`d;ZOn8hFZFX|i^taCw6xbNLb2sOS z?PIeS%PgD)?bPB&LaQDF{PbxHrJQME<^cU5b!Hir(x32zy{YzNzE%sx;w=!C z_(A>eZXkQ1w@ASPXc|CWMNDP1kFQuMO>|1X;SHQS8w<@D;5C@L(3r^8qbbm$nTp%P z&I3Ey+ja9;ZiMbopUNc2txS9$Jf8UGS3*}Y3??(vZYLfm($WlpUGEUgQ52v@AD<~Y z#|B=mpCPt3QR%gX*c^SX>9dEqck79JX+gVPH87~q0-T;ota!lQWdt3C-wY1Ud}!j8 z*2x5$^dsTkXj}%PNKs1YzwK$-gu*lxq<&ko(qrQ_na(82lQ$ z7^0Pgg@Shn!UKTD4R}yGxefP2{8sZ~QZY)cj*SF6AlvE;^5oK=S}FEK(9qHuq|Cm! zx6ILQBsRu(=t1NRTecirX3Iv$-BkLxn^Zk|sV3^MJ1YKJxm>A+nk*r5h=>wW*J|pB zgDS%&VgnF~(sw)beMXXQ8{ncKX;A;_VLcq}Bw1EJj~-AdA=1IGrNHEh+BtIcoV+Te z_sCtBdKv(0wjY{3#hg9nf!*dpV5s7ZvNYEciEp2Rd5P#UudfqXysHiXo`pt27R?Rk zOAWL-dsa+raNw9^2NLZ#Wc^xI=E5Gwz~_<&*jqz0-AVd;EAvnm^&4Ca9bGzM_%(n{>je5hGNjCpZJ%5#Z3&4}f3I1P!6?)d65 z-~d}g{g!&`LkFK9$)f9KB?`oO{a0VXFm1`W{w5bAIC5CsyOV=q-Q7Z8YSmyo;$T?K za96q@djtok=r#TdUkd#%`|QlBywo>ifG69&;k%Ahfic6drRP;K{V8ea_t2qbY48uYWlB3Hf6hnqsCO?kYFhV+{i> zo&AE+)$%ag^)ijm!~gU78tD%tB63b_tbv9gfWzS&$r@i4q|PM+!hS+o+DpKfnnSe{ zewFbI3Jc0?=Vz}3>KmVj$qTWkoUS8@k63XRP2m^e50x-5PU<4X!I#q(zj@EyT9K_E z9P%@Sy6Mq`xD<-E!-<3@MLp2Dq8`x}F?@}V6E#A9v6xm%@x1U3>OoFY{fX5qpxngY z+=2HbnEErBv~!yl%f`Eq2%&K%JTwgN1y@FZ#=ai+TFMFlG?UV{M1#%uCi#Knkb_h| z&ivG$>~NQ4Ou2-gy=8JdRe8`nJDsqYYs?)(LJkJ}NHOj|3gZxVQJWWp>+`H?8$$J5 z*_)+tlyII%x#dId3w(oXo`YEm^-|tFNNj-0rbEuUc2-=pZDk7fxWUlw;|@M9s1 zmK9*C)1Q?F5@NPUJOYOAe`GHnYB%G37_sg3dxAttqLs6Bro)4z ziy8j%C7KKDNL8r#Oj6!IHx|N(?%Zvo31y4;*L1%_KJh$v$6XhFkw*E|fEu9`or?JD_ z13X4g92;TZm0jA0!2R5qPD$W^U z`5XK|Y^27y_Q%D>wWGtF=K00-N0;=svka>o`(;~dOS(eT0gwsP{=Rq+-e2Ajq?D<)zww5V36u6^Ta8YT4cDaw} zfuGnhr_5?)D*1+*q<3tVhg(AsKhR1Di=nsJzt_si+)uac_7zx_pl#t(dh816IM zvToHR%D)$!Zj4Q^$s8A%HLRYa>q9dpbh=*kcF7nkM0RhMIOGq^7Tgn|Fvs)A% zznI7nlbWoA2=rHHbUZ4PJMXf{T$@>W1Tt4lb|Or4L;O!oFj8Op8KEE`^x^*VSJ`9~ z;Pe~{V3x*-2c|jBrvSV8s+*Y3VqFKa@Napr#JAd}4l7;sgn|Q#M!(<|IX1<)z!AC3 zv<5YpN58Fs4NYi|ndYcb=jVO6Ztpwd={@3Yp6orUYe6EG#s{qhX+L^7zMK+@cX1hh?gbp56>jX*_Z|2u9 zb*glt!xK>j!LyLnFtxs&1SLkyiL%xbMqgxywI-U*XV%%qwa5oiufFerY!wn*GgMq` zZ6mFf8MukDPHVaCQk#oyg^dhl*9p@Jc+4Q9+0iv?{}=}+&=>n+q{o z#rEZ<&Ku65y+1eRHwcl3G7bR`e{&~^fGg|0))$uW?B@;_sWSls!ctnjH6ykmM8WJx};hvdXZ>YKLS($5`yBK38HULv}&PKRo9k zdFzj>`CDIUbq8GxeIJ?8=61G-XO?7dYZ;xqtlG?qr`wzbh7YyaD=>eup7bVH`q*N5 z)0&n)!*wW$G<3A&l$vJ^Z-%1^NF$n3iPgqr6Yn_SsAsFQw?9fj z&AvH|_-6zethC3^$mLF7mF$mTKT<_$kbV6jMK0f0UonRN_cY?yM6v&IosO?RN=h z{IqdUJvZd#@5qsr_1xVnaRr`ba-7MyU4<_XjIbr$PmPBYO6rLrxC`|5MN zD8ae4rTxau=7125zw|TQsJpqm`~hLs@w_iUd%eMY6IR9{(?;$f^?`&l?U%JfX%JyV z$IdA`V)5CkvPA0yljj4!Ja&Hjx`zIkg_ceQ;4)vhoyBeW$3D<_LDR~M-DPzQQ?&!L*PUNb^moIz|QXB=S z9^9NnEpF+>_Oh6+Xr55ZLJ7`V=H}@D<70NiNGH{~^QE-U)*Sg@O}M|%{Rcpn z{0nD@D%@8!dE*mndd2g!-q9;)jb=IUED<(Pxh`9B>V3z#f>82~&CVZASC?|;C-VKy zJU35T|3jd(p8F|#n@T~Wh2l1yURI=LC>Uj_!8i7-DE_IaSKIMAx`WMEq8kN%8sAx% zOQs~R1v12(=_ghVxzylsYZum-%8QmjM3-s2V!jY|w#ccP)}OSW?MWhNu@o-t0eTg{ zyy`}x+}GObZC(k>-upb2C6#S*NOfWbKEyReP%gay8MT!pJpsx4jwCu%>7%sY}1L6Vybj_P+;yP`YS92 z^o_G!Gr_NP!ixe7d&82H&achfi83L;le3Fs?u%E*xbeOKkJr7mp=)RXjZF;h*hR<= zP_cs1hjc}0JlHal=enmG&G8wsn%Sm$5Wcgs=Zc}}A%3i6_<4k_`-$k2E5f6QV{a$V zg3VZO36o^w5q`q2ASwJw#?n7pBJyGt3R<`Sd8d|52=h&`|CPq&1Cz&42rRCHNjDZL z$}Y*L+#N;!K2Ov){~fmQM8hVYzj3H@{yS>?q3QhhDHWfNAJ#q@qko|rhlaGG4Qrvh zmHpmg&7YvgRuI|i78-{)|wFx(R^_ z{ag(}Kbbbx=UW42sAu}kg3yB#96dJlOB{+or<(51ylVwpXII7Hrlztq!pefQ?6pQhqSb76y=sQx zOC-swAJaqnL_ok{74u_IHojFk;RSSFfjdLrfqq{syUxA$Ld6D2#TMX(Phf~dvSuuX zmN2xzjwZxWHmbvK2M#OhE#{`urOzs=>%ku}nxymK-dB~smas?Z(YM^>x#K)M@?<&L zeagMnj!XK4=Mid$NvJ+JfSjvc`4rX9mTo^+iFs0q7ntZ{gfU3oSAbK_yzW3WA^`6x zWgPSLXlEVvh!G^fOzZ-O{C_v;V6=;DE+ZqRT4mbCq}xeQ0o z98Cho%25r#!cT_ozTd~FK^@AB3OnrAAEDI4==}#I_v}iw0nhA{y99mFRG*1kxFkZP z+are- z8D|3WoYE>s0<=h)^)0>^up+nPeu}Sv-A($6t3AUedFczOLn;NW5_xM0tMvvrOSZ}) zA2YG1m4GxLAHZ5k>%}pHYtf-caXMGcYmH8ZPLX9VCew0;@Pi-8zkH^#}Cu$%FmKJb=!)Twj!PgBmY0+>VUsyyT}Jy>vMt zo<^5lmPo5Jt-=)z2-F{2{jB{CpW2JDj%~JnP*rq^=(okNQpH=}#{kqMUw{&=e-5;G z!FwJVQTDS7YGL&|=vJ+xhg{dMika2m2A#l@$PazLQ<6$GLC+>4B37`4aW3&MgENJ% z#*tOQsg{>zmcuSgU?peLA}!Rlu&K3LTc@drSBaI?91dK75;_`(V`NHjkMj``jwjJx zcm_!liUxn=^!~0|#{g2#AuX9%;GTBq&k+Jz!~Cc+r?S}y=Q1okG0PRIi3C3wgP8F| zO2jcmnVbGXp*Mu&e#a9Q5a}w7$sITx@)8b}sh(v9#V(H$3GLHF@k!Wh+)kNueq;+r zFtj+^b1TQe?R#Y8{m!7~e6%83hbPKoizd2LIg3yS5=X2HE^l4_|(2q#LB zeNv&njrS$?=zzG?0Min#kY+3A)H1uMfogMYSm|vT%3i<_d9X&~N*ZCL4iB@YaJuo; zq}-;EGx~T43kq-UHmTn!@sc z3bwcs$rp?~73h*uZl_ysD*WK3_PS1G3N^t3U=KoRm_Gz@C?M>+x9HRMk(cA4m&L`! z=Lb~4*9zt*SHJgsAMAcTy*!1W^B>4T_doWvNw7UwmyA=Wq&kE{*GVHp9Yk5goUO;k zVb_3ARrFPG;&>Jv@P&`z%}t!*M|2127pm{S)gs~f_ID^lOH@nIW9DgU$=FjqNW0pv z&GYdoxe@)RAWWx^j|$N}sj*p)_bFpk`Y=NilvsI(>!Z&KBo&I+wb*kM5Vvkkr#;q< z3CobbF+GJ#MxL?rMldP0@XiC~yQCR57=wW_<$j!SY*$5J+^v{Pn!1{&@R-lHCiK8@ z&O=XQ=V?hjM;h&qCitHmHKJ_$=`v%;jixnQrve^x9{ykWs(;!Q9mlr#{VYVE93oaW z&z+vBD}!tBghkriZy7gX7xJp8c}ajR4;JDu^0#RdQo2itM^~uc==~eBgwx5-m7vLj zP)vE#k%~*N$bT#^>(C1sohq+DwAC{U*z(D)qjgghKKSy#$dPih`R09rfbfI-FLE!` zn!tg71Wr(D7ZV*4R@GqG&7)2K*Zc6_CMJoGu#Yc>9D#{eyZ>u-mrWG@4Hk(je3lnH zu9qvXdq+!`5R1mlzWjV^jvaHl>-^Z+g^s5dy49yem$0$>341=EGuOY=W5PCFBTbNN^19iIQ57C3KcV}z~z#Rvngs#j;g2gswC(TLWlViYW}tB5T#g4 z%vDUYTo1@+&zE&`P%fXc^@prE5z;E@;; zKtpEFYftJq-c0sD6lKYoEQ;O1X4uFZZ;3gdgfAKqIc=Dj6>unXAdM}DD*@a5LHk~o zyJjW@aK;XG%qr<)7Rqh7NdUpnTR6jc;6{FKcK_v_#h{IO{mez>^^70DAWB5whqq!J zevvLUotE;I?IWWf!ieJ-Hx`TqY5)ND>K0NCb7IW40Jk*J* z^#m%kIA~Go2=R|y5zM|*ehJxyuX;lOQZkArKVbQV(XmidUH|8U^q`wP(7%F}=uG}U z2~&~CLebE`c%SCdeU(l&hryL~+Y)6I^d@|||6F15IAGo`G+CdVf zc+!EycZnQH)OBE zyTd8k{(_v9d2}osA$*>Q>Q&OB(7ShxA$}p8ChVnYlXl5My$HlVx@ATprrj0}6)ycK zcQy#bwOms1CnS+xd26}k?J;WI{HR_U+1T^I!$B^S=pJkT705QaMF88VJp!s%`?y9z8f$&Xw(A}3u_(n5G{!)yH&zN)S?c1$SZlo>XieJ zyEFa>_p9B*cY){ct8=dq>uQTf# zd4vB4)(ebwQHlSAu}(6GCe28H32pz^}l%Zqs;Yl|B=l2d9HrCcUf%wxLYs4CBqJ#{gz*u6V$>?9IT@uSf~2Rgk6CNw;C21ZbNkm>ZTc@2zeOSXVE^>i5!2>t%!1cI z{FZA`*o4=dTDG3&{v$3xVr%g;3d(!SFJU}w6x_Re(ohlni)I54Wg{t zWLK{A(}qEIH@pamgtr3serA{THlp_IR(gt0CFguk={|Ochh10)7UV4DcnO7fvL<=x z^WCMg_TI?U8(loaUnAe+Nc9I1JIO#_C`=kJG(&wy%Cr9vRFcY9^8{A3A>GuSW~Zk( zMA#t~0Dw?;3^Ue|lhSp4p%YvYmw-&3ey3}+{6Uhz?l1D|6nYNok6?4N_C!OSR=QtS z2X&QtWlkZshPo#-dXBOlSqh3D;#*_`hyohR>vl$W+QC>HPOs0zwHKN`?zIKqCTw&w&NUGNS|abulHe{D+{q z`WvLw?C4K97cd}6V6f2NtfIAO;=c>qi^+y4#oMjK?5Hy9$Tg1#S~Cxoo-Zdpnt2kG^n}`9)Df-Spvx&Oi+6xXT=N*0l|d`p!ZU ziQo9$y}PYIF~Zqh^?6QZ8YS*JtD^gynifSLMlVYRhBi*f-mJFS<>l%5sp5$V$p*X9?V-0r4bKYvo3n@XkCm4vO-_v? zOsLkR?)>ogb>Ys*m^2>*6%Db0!J?Qvpyd+ODlbslPci9r#W>d~%vcU7J_V;#Um1+` zG0>Q$TrOLUF0%a3g=PaCdQVoUUWXgk>($39-P;tusnMlJ=Dz}#S|E== zl6b3bbYaYguw3Bpv|O(YR2aBk?(jo+QqN*^6f0x+to-@2uj!nu6X{qLK>*PxM!i0C zZwrQ}prOw6Ghz?ApvM`!L3Dzc@6mp<2hO0y{_`lqtt!FcUmBG+PBwl?>0Mwu)Ey{L zU;A{ywkT}jCZpPKH4`_o0$#4*^L7=29%)~!L4*czG!bAva#7ZCDR|6@lBE&cyy5eE zlKHwzv7R9gKZTF<8}3*8uVtI)!HE%AZRD-iW!AJI7oY43@9Z$0^MO@Egj1c?o(BwF ziz1|k#WOgAG?^r1 z>+p=DK?cA-RLIvcdmwq$q?R;ina0SPj@;Mus}W_V2xHnYhOq~=sxzA`yTUOsJ`8`VOSTE=IZ!x`cZYqHbgPijF>J>N7( zqbNsHK50vkB1NI52gyb^PflpU0DRw{&v7Y}Hy2>pV@W2f1EOd2j;H?|WiV%2?Dk7u zS(NrEUDl81<}yY9J#OCwM)N?x&PB-%1{oD*`_ZLiBJ=16uR{n+Lk~!t(&9U#>ZfVd8Iqn&idGd>uo?L@sjm>c|Lk z12d3Y>N9U`342@xaHl&Q@oE5V-f$s`04q983f0#m_WF=X_A89W8C#{uCdTNUZ+))$ zakPyNU)?MDayCKxWh0(-v~1rd8FxocW=Dc6B1%N4^SgQj$?ZMoAMQ-35)IMgf&)M?c@}4QG7=DTq{nHc7yp=CZ z1dh~VkK%OTr23U1mJ*a-DxX0Psvh_13t^YcPl9t?_^$pPEhhwGp}s~f=GFR;4@;@f z@B;R1U6Df?yl#Y=BgYTlP&<|8K27||rx_?{s|L);GM3^{Nn8HZp zFqxiG6s3Nb;PW3O=u;(-o(*q!^2i)jHY%N@;O5Hder~_@$zh4xG#-7?#S^-&M~yc} zh5Y=ltLBnTzt;Y%YNqi2d1M1LOz?MJbZ|Nc6>x19&l_S*2Rgk$DhaP7Y-C)4_uPzf zQm)OY)$AFfE1(0SxkbbN4}CHnlU`RqYFGIE7S9ipx_Q0vkE5JRq4Uc%zV7$?y(x$y zV^)5zwjH~+4?xN z9s@x~w`C_cS}khfI14K4Xgn^iuBxkd^u}3cY=VZI@-8iWHolPtt?JD5lZ1V=@g6yR zj0>bd7Z(dw+@)v#r!xpZaAxgT?4Ton(h`0}fkfF!ZDSu{f*r#{ZRp^oOrO3iB|Fa- z;|+PpW5JKZxJ-kjHf`-7ohmnO=a)Xl9lhI8&$)g6R#6PBIN$QSC8kT=4zj?w&=`!qjkCvvz;ypOfR7P)w^ z-7LFhXd6GLrFa_vGLwR5MRvcV*(r!NhQ@}T-ikBGy!fHaiePD$iA{|Q1$kct2`qHz z6nAyERuqvM6i2^?g@w7W2LLr~3s?pBDk6ce8@CxV;b%4%-rXK-GOk+($sSNK;_FBku zm89B}tpzL-x{dPS-IAjwyL*t7N%7~2E)9OsWJJWHc|}BNa5Xwdx(j7i7AmZhs?#zi z5{y$uQdx?O8x3>+5MR05HwUa-YZa*|UVLOb`T)KHk|~Gmwx8MfBUtM|afuM$0wb7m zR+_lU9=W~Y$uNlxt&(@&1;6t!r69A|W%;k3-%SzLlBzc0 z`b?Jmo`8{LI=d|I3JDAa|iK*D6=I_3q?%xFSLg1 zI^!pA=K}l1joBBj8aa8XHp^;Lf`9xNa&Cv+twW&$_HAwZfHrVcNUrRccn_ z1+L!z$k@LK28nc1VB|Fbwm$wO;B~yEdww1EUn|s&{-Tu;@$d94BLL(OQYx|aCa|&2WPT{qJzbNU!ep>j){o5=6le6 z>~Amqs+mCuOR2)aB!#sK5fuui7LsO!Qzl)lz?Lm!QoQFWbNIkfdkrn|)YbSu8WwxZ zO{}a~wE2Cu)`a3X+KI#LHm(Mi+}bOB6@N~H2}Y)e*}w8_z^Sx`c?CWvu*2{K#yqGo zx!Cu*+8&tdw!eiKqZIQlJg5Cb^hZ^Zh~Mb0l(4m4hc1mP&>oTdt7eS-bEz8mU~oObme{^%56|ou~EPOSFBa7VpUZC z0gVc<@IUeo~q)&?o zU@=bz-qfWm)&0Qn@W_fc9{wx={&-#8>0xHJ-+Ijl#P&1qB-%*KUU*DCPkKCLzF*#t z0U_vrk1(&Vwy6Vm8@#Th3J5J%5ZWd)G0mifB3onY8dA&%g6Hir5gqMH|hnEBL0VVvl~aJjdljF$-X@a zMg=J-bI?2LGw-8mHVF7Jbsk1K4LgWi7U>~QovGT2*t^U&XF#iDs_E$~G+t;U;tZn_@73Y6x>vU%x` z6?l`$@U4JYYe#|GcI^f+rsy|MdB|`PQunKSKkja4IGtj9G6buN&ZSnYi|ieaf{k5q z@ABM@!S(A6Y}Sv~YJcB;9JeqsM|-fPIZZfOgc*FSzIpEdT=YYT(R(z{(~X&x%6ZM1 zY0(|PepBl4dK*@9n6@`rUMd)K^^0!^?U-1rrB*b?LEZe<5taFp!NoC^lc>}YUy?5FjT9tFmC+%%DYNa+L zWr)zMB%y_6L{S%;dk6bJPO!wmT=wPPK1b$%+ffWcO8;2T+7C28T?{!96{%d`0G~j3 z)6g<%$dC{vAKJ22nY)fnxlD>P_Xb&@>wrG+ZpfQ%RX=R2kd@bH3N*M8=BO zi|Z$Z5e`0NcU5&aN_DST8O@4v3vroq3t<_5hBX;d)*AJgWPb~p=qx4}^Ms6pgyY`) zu z^|u7XSP^~b1)*61r(}zd!JOny@$KviSp>L|jSR!u*1IgKwId5jmAi2`qe%u+XCTwU z;a62_a~Z}TqDJ?6lje5hblv1f1(6U@kWpc)z|&nRBV*UIieQR{Rru*|$L2SzxtL&| z7abeg@xniYhexYoN6zxY{nI^*xKW0Gz8D~}tE>O4iCkpWn8wt4?S`(Ftv?<8vIvbw z(FFd5`p4~#m<(3uv2+pv7uVC$R(iZuhnxFEY{o}BxPg2nYK zzOjuMR`}t3{8z#zfLXy||4JCt|1nv5VFjS#|JEhRLI>(-;Rh~J7gK{as*K1{IJ%7F zoZnXx&Y54ABfp9q!HDWAJlvFFdSC9}J*llUYXFDN8meEa<0}s z8M~X?%iKLB$*-a}G_$rTh;U{M0vc<}N#PVAE1vQdL#9a-`uH3*cbJZ~u9ag-fny$i z8aCs;3E85mgVK&vWM6}FH9o^WI#G!=%YOB#gT`1^VttnSVf4$YKja@-;zARB-`7v< z*imICw^KX73Gq-go6e?w^os0U0HSxH>60JLWhFbDeGT&Z$d3;9NWy;WvICuoZaKMi z=UvTpLDrtssbhiK&A3EuWf6!)>$sUlRcn5?Pk^OCtvApB=6suN42uKN-Xs7u7EjXh zG|>-1Rp>w1KB%sI*b5dGwFbuHNN=|})sR(dekHBL=>I~l@Nao%H=w0q==`3$zP>!I zmgoBoi7ylm<9Fw6s3&T%wJ%>VQmx(H)!iq?ABhdSzitwHlFNGcBW4sc&9DmTThb^qz`diS`xzQT# zhZff!yj2#rS>yfS5?}{inV5BfcZw zF5uh!Z8b#76;GcBDp7^zWtzQ%J;D}es(iWWWQNA{SvyhO`X8oyNL?j8Afn=x(zHct z7)3c%RKTPAyKS0gwVpGLqR2_%EowBpk>rW}MFfsR9>#2aOL!HKZtg$bAOe+#;;w?3*If zQk=HPWSlX7cF?h1PVE1D>LL{K&Ze4d!#Y2qN+^N-`~RG(O^Gjg~EsZbW^ipD9*+uf$K4Cq=H zxnYj(#+^eUa_1nRDkJJH|9$VB>+n4c)jji1MPz$dV4Ojf;)iYjgw#m+4puPdwgLSj zubNnwfz=z1DqFmy@X!!7D}kTo6yBjVFYT`CisjAgjS^cO%|(B2vzWb5PcrnxTK4xu zm?ZZkCy>+)-K8*)fo5JCWa@}^R!iI}a6OA*S&ibX6V zKk0=}K_M7m$#QEMW=_j=4tDXgH{_l5u?oFF?CXKmk73#~&>ha8CH{7jDKT2WoJ&sW zD1wk_C4Q6m{-YEWeAg*gP5`2Yl>4S@DAbob$M?&Gk2@2%+H*H2wu_)XL3fn{D8ljl zh41$!&_(kR($}4zJj3?zH-A0f2$4;9tH|N9XT48P;?coFH~9`z4S_35{xiUZC4&-3 zo3Yt|ee&RI&qBF zW$mPrwbqtHO$6De21%1=8zUX5=uMV*>#k-H>d5vP zz8OPyI|HLGKn`U2i>k8-dUX}5DJ(|Oy>)cK%QOwU>>~+Wn?bp?yFpx?yE;9q{;DTa$CFGK2S&xDNk$24GuzOgK{np ztsuRfjYmLjvhn$}jK3F_+!AtM`LVw=u&FUIGIU6>0@nqZq~REsb}_1w!VB5-wbS#J zYPBNKKJcnu^LTORcjX|sa8KU?rH5RRhfJ&l7@AtLVi|n8R7-?$+OVx!2BrQCD8{a)Kc#rtcWIC2(YYu=0edjgP9sFpp0=(eKUE2*>jc+n@q? zKTY!?h-S?Ms1kNuRAjowlnTQZF=#1S3XPx<()Wc1>r=QN?#W;6OL z2|Y0fxO0y=?Qi#F4?$+-Qpt&J>-JT?;d6ITN&7R`s4l(v17J7rOD3#Mu@anT`A z88>nZmkgV5o2{_IQ^TOFu9g}ImZrc~3yltx&sdaLvM=bAFpUK=XGx*;5U2#%A{^-G zEpT(GF(}NVJNzn$I*!S`&mA<1j#FEw4`lJ|^Ii?VA+!l%tC)`Q6kS&`LD*!rp)SSZ z!fOJa=BWFG0rWJE<~c2SnT{ykD23&sE?h7iTM20!s3!XMY*WJK_oA3FzU zScKW==wTvjelr=iu2>(0OLprW-Pv$m4wZ7v>;gB4M5m0(gOK>_@aIy}t&Y`H8crZ% zbo1L-*2^hdvzq`~_{<=PT=3jZ#UgMI*bQbOCzf~T53X2F9_QJ+KHwwQCpU%g4AGP z7i4m>KYOFyVXw`L5P#h};Q56X@OHZ-P-1qabm)G~GS>9sP0ToSI#43Q5iDCjG6r<1 zyJZa^U&>SXTW+bvJNB5oHW0xNpCGimZgaFJSb^??Uz1|jbXP-h<65N`CgZYX8jM3^ zSJ2tNSxr8>9)`mMi8nHw1aDz_?+ZRuMO@tou|Q9z11zdD#ka!jZfeXi(bGK&_vVQ^ z?b#6fYLRy70Mb9>3LcE``^rMcoxj~!hvBT%&cQK#L#nhF)C)iw(B$hY1fwak15v#J z-<0Kg=Zh1uk_^yGnO~&Hl|4?14*DFz9!$a(EAbT!5(<}0xUlYlC%`_JfofaWqfWNEfhlbLb2Ds@#m_oKXUJ0 zdSUbdO-BOnM!b2U2o3t3AQ&HGTzjL}LBTpwM2|gf3<(USB~4unKD6^_G>?@N%R2V zE+a}P6(vB@x|W>|ol!d5vws)e>m=0+2Y~#n1%kb=NXlT+^$#v9N z0Lt8wQ#?o)_j$PRavtm~z!aRPQ85^H^}u0bjlfDm(!3xG(oMQY?(DW6m1QdXq-PG; z7jW?rNj(vW&SZZ>B^q=2mU!8NLql4|nTI;pSkw9gbip(A^U<9DVj%Sjd-T0)ldwku z!O)$tFvVGRJnSI!t*v+U;QlSXfMu%J>v5B@Rq<`V$DQ>YTCkc=so?hUx&dda4;A1r z>~5vZ0E0M|B&lv|71*mTuRX`GB3G>9RzF7}+2HIgGrV-?p|bN%&4si|xxb+z1S}F2 zOBQ37uO?>1n_T3UF8nYp?uWnU&+53X|N94hR8WunjZ{}VH({S=x7sRbdLq7vyftJ? z2@;dF{)x|0nI%sYQ|%pe)%r zxP>}6S+ylPH{St~1KGov%?}z^A&&&(B(s+ngv{wKZ_L(*D^+nzoie`$NZ_*#zQ@&T zeLY@LZ5;akVZ}L=Qc=fIphsO^5%YJ0FQWW3*3|ahxk16yr=ZgTqunNMFFko^CZVSh zlk<_(ZLf{~ks&04%zz`tNla=O_`5r6W>d-%mdkEryHLIgIZyrq88$=4=Im4xR_}|) zZ!?V3+6QZ7$+wYJ=>nqKQ2L_gKw%=9`ds2Mdo6`avM-uO$tdP}7Jandkx0}XQhkn# zzq9uFBxvJ^#%sW$s)6J+j5 zXmAN{4mTo60nJnc2C6XtOBsVbJYc5&a0nZ|e?0yj+kThaCezk^Cm!F<|A=cu`uO@u zMai;5H6<@WD$n?-1{?Pzr2mF?F||EI+58#(N9dB2U*+$o$gl7(T>0jTu!?94mCA7^eb%}7cOyZN?nfVx+L$x~x>^tyJj$vmKZOXBKkU?mdopygE`0+rPi zx3F#q)PBC|6M{n@2|m%_24@G{?ql$@S=PPaEh1sG9v zxo35;K!!nAr&^P|c$6z+&vUa@eX|Uw&nednN1SCQSFNx={#kvzFb``4ixf3m zIY=2lKDmS2WGQx#gfP0BOAD4i?UoNdWtRz&Q=#>Y75@;X*z^@rxbLVa`YnIz{oaTE zNGmThd0`N_?*0!a>=f<^TOdF{&|-km!E9iB4IUs0KsvY|y6}%EN>L%XAjjOs+WGAJ z=wAmEmK)JGoI&Uq$`1%&(sh$n^lmT{o9pDd>t(CQ;o9Sr;gFtdZ>-qZg7jbc*P~uh_&U$wOO;{P3h!F3|a}dH-WoGGsXGBvB2c7p<>_CnJAYP}_#gD0t)$ z$Is_In%83bCJkJDij^-Lbnh)JKexs8f3E|dDy=BUEES;}7{*+oxV&iNODhNv#y<$} z=-mY})V@*#j#N6^A*B940E$3$zfmk;3ReX3DO;=d*_(!|f4FL$#0mL1ToWidl)O|S z_mi9mELAQ#S-D7+a2+=an87R;9t|U~1&sgF{`AZ#ZsOL+=sb67R?kPP;SQrDJP#F^ zsr<9}0#5FYl#3;3$mekh_XV=g`LVN$408Oz1ZU^F@kv7gMcyAWTE+yQfcY<&di4?0 z09J)>xHkZoQg!{E*RBSy?JCKOX7n%2$6 z-dzz8T10-8&ZG00yi<2%x`4@L8oj$ZXP|WgZ7E%-(h>@kqIJqt!{ou4J@Anf#HcEw zPSv)TmeUHAmeK2Am3|mkp+~W?)6eVg;c7e2H48x zBw;iPnvFX(a}Y+nn8^W#;6K4qA&N3hg$HYE=n|Dy)1^$6Gxud`0!yZ0d*p;(03ud^ zy^hvb&{_%?^-|c8>2fAn_!5YCX`?Ov6`*x_BAqZdP7`m!E4|c0ttvHBo2}NJT1HQs ze_rYk1e$5HO|)A}>0a7uufbmK{SDV?ndJ&?hXXVWWefy|nb5Neb%C#pK9tl%P-U{v z%DOV=mf@tF5qHo|q4_JBR-PLXOPn6TUrQ#9e83Sw*iIv zU^kn1C|EKWK_mS%Ah;Pks|+@@OxM8{T4o@Zf(mvI z55b=nM5d)6kW5m_Lx%`#@%0J~At8s1=`iJf)}P0CE6_pa-@`H5WIHbP7t4>QJLNX9vAkd8^)UWbAP6$@LZXWxAVbOYkgCYh!Pi4lzTy1%B>Pf9ZYnAH}3- z*{;*nGg_ZWZvV-oB*dF(WQ0^x71UW+hk8Cp_g2sc=tD&+CHpenk8FnaqFX;|TH%e* z9ifj@(1+=xs1s>xxwM`XyvIu)rw0VwCz$GAQ(yL@$J9)4{viA{r49G#c+Z$S3LaiI z8H1fq(Zeb|M4x7oLLr4te=>z$^SG9N2w2ERGL4D=I9HuNqS6>W3ax}f`>ts|P^Zvm z@RHI@6xXbm9v9ry(J7RMY_2a`aPR71XW4B1S$a}He-4?~NS8>v_Z&;WYl>KnqBJ7-hpw*<(4p-DB;Erm4B)LPDS{#kCnL(dCt zzl#E4aVwa$czprcYdPwIDCcme_C!|1U))PSuuI$zk*W(Ap#uWp$Ho58;-{sE*^$YJ zfcvRRKNF?1B4(sbe>9@m?fS5nel8lSJLrFy&YLbuYc7$Di~9RZ6dwe@uT*+bv?gxR zf2UDHLuJLEg$yM9E&WcA_+R7?)37(a^as(%yhwk9vCtzREf&@5r9ab0gl1l{v<@{6 zC3O?M!(VOl{tcWYFh zcWyW`&qG3pOe@HR0(&Pf@bG-DEH=)i05VspTrF}nH!FPJEICoc3S)q%V+;_aFop)l zP;Po#SxD2ff0q4{T+T}wqs1MJ(W0uHR%OPB;l?2?$s`KN)CwvpIWi|N=M^e1V@wxw zhcbE=o-@%8PA~qV;Cea8wH_!IqWp_Sb&NfdNz}9rhH)r2Br^t) zMeQA%TY4kA4{q7j(jMtJ*xS>w>)_TMT^(L-L2JjGxOJj&ZV-)ggVi{5yFFtT>@y74 zJf{=@f2D8cEh09yg6#A&72XCLgRGuD?B$3Jh}mU9;ruBh4ewxD7AzgZW*I&BN(>mh ziz!$}F_R7^NNhzIC6VZOw|xa*NB`8Izi`@_wbT62%UAIpm3#SWG=pW%ix>j~;()!P z=|~#* zs~lrgJ~te{KY{96l8>ex)n>uuGMb%`c#snwpktC*Tn4EfgILng;xZ@8J7YPjGNU7z ziy8fhkvX(Gk4lucz zopwj%<+s`80do~2D`Ae3vs%C2n@KP&f1Tw*W`gvc{0^aDj8k(=qot>B`xmPR?nWM%F_Tp@8f$^zMC-x zxq5eR4y{vI3_c*+I&2E>TUd_fzE&@Pkna^rKrwaahT_Qipb*^GDr(jJ{9!?Jf23IL z(A^If6~w*; z?}1Z(f$4(T18(_hnK5l-&KgXmo>nd-3e?K(mCc5>6~3tQ)BGjdE37LV)Q^&pwQ#S) z&+u1NlKHDJYC|%1Na3%+nyEu^jPYK6&d&RoKPnRF@-yfpj11b3Z`tb@e>%>eq_``W zHjyW%v=QIIjMQf2l5wjwh-GwmTwut$YYW7S)B^oRCLq)v5C#Y+jB#TgxNhmo8p)ig z+m?O7x>V%vtNgs^JCwARHbhpo8tiRe{t^FJ)aIYKNc@@Cy2(NO%_oXe2h_a_mDEVt zmb7j{8H0tCIim0{RsMyjf5xg%)u5J6>nIZ!1*crg#_ZLsWwQbZRQGHCjX?b^(~`4- z%8a=}HZ#K!NGa0IY^23L=>CEKsPgamPfQ#BAATw`rjrHMokCmE$m&;$>$>FdWOl&m z)`l3}takOU{5O^V!Y`N18@mT#Hk8i4BUNORx;`YLf13b*mCvaBe-8<>i!%lf^-2;U z9Xu^Lie6DxK3T%#A{V~ncqJJ#j^vgU*fE*tQzR9Izl^818it9apbd#{E7lZ_VRf}E zc~xnS$S$5Fa)vkpeqLJ|acM0jlw*p5vTxcoxin9j54VyQ6lcuBR|hLNBB)YOqvR9U z!GXe8h=^BOD85uIf0M*0GA*2n7=9$tiDqrej<}AS5rg&?cv&o6pi1XUOT5%!|GH4f zvaj?*$t>7b&`TGoQk8_MWDe?v2r}Dt(=V&+RUEinS|JRG@uWH{KKj7Hj+!Oxo*$h3 zJSiyE3UmxBOJT8wLQ9;~a_QJ0+H$+Y7xq%5dSM}87BbO_f7fWu3%N;ZkQ#*^Fy;8l z+=R>08U>@C^*y3XHwO(!x~UB1eKROeJu9R4i#yRqn*t8KOlnf8LRwpLV^InvOY4y& z6Y0aoAta#nWk$@|ua--OGHHW!xhjPv3`wq-h()h-g$Rf$X%kb&Wa>o&%jl;Juf;h@YL`0DJV={S3<~|Q zxVKlNt>PnLnaimuw=2>%bOF+Krp5q#4}8Z1N3?_qAS?S%)arm{Ww3y0Sj8X=>X^3N zqTq|)7_lk>iEJQee_T8ouuaPZ z`ZGo<5HsR>A7m?9YOlD%ISXt11#1V2EoPx>=owC%+R@3XD;+F;=(T8c8;0RJ zTsm&wf4E6n@v_B&nSvZcHW#06QG>Wc4M@NZjXq_R6tyGE%uPgmQ2BjdC;x_^K7e<&Sro+Qon7}Z6ij>=e%vr_NLQ=+o& zBpJok>#>>@t9yzoIjkHJE78hf09L;KB)w^jj*Zi;(XexzZjXje(A)F$&QZE+l#Y+n z`=Vi2$nPAb_di1SF@@cJ_apQ%rsI6t?-IX1$@BzBhvht-IL`O`<;uJelNOBA7;pvZ zfB49mXR!WQo}M^PexS)v&gcE|!8|>kr>}-xBWE7K{@1Mi2C+ZCIZxkg5`fhJ{k9ES z?Q&jg{rY^Kz9*250O|V{Qa~U%CqezPdlGEt!}O!OX%T>bVgb8HsA8Oc79FMkJ{1BQ zAj1lz_A7b%#c`?Pf$=T5(=0B&}8~QNxNwRw*HCGxKs7 zAbuqb0wZTm!A@E!voDKNVzcs90B98$d1mpu$?pVH>>OjYdz|h7=c8OvnalIse-rG> z^TJ7MQ)h{-eY_~oi=$1-J+wg3^YM~AU$kfB%yWKA6u<1KR)jRN^V))`t?f_yozaju za%E*q=!xg(Q{=;$gM(CgBtI%caf_(Rsq{@aD+#S}=pC z86ka~*GGN4VU#aFW&hkLem=}?e|vn~F~*%Z>oir1(1J)V;P~B;pF%#~KE~a%?9Q`R zT%aOCGZYoCbw1uX$~|Kog$!cB?q~!dDf0Qo*L&^G+IB- z%c7$kALW4)e5h-jQveUupWrMkF~&y@j`9uT{Dx>3B5#~;1W8xjD8D&0f6BK2KH7bP zZxi%s6BzdKTl4((Xp?-8aO}B$ceSl^VLKn+QQT7@lRQFm{BB3JY*{801(`8^XP)m0 zD?Wbj7{5On_W1Gh19`qL&mS4*kHL?eO-i0WS*?JlPt9MR=TBSiCFAu3oJ*WezdvZZ zSy&eKQ%>+G2tl=09#H+Rf3Rl+Zi1CZ#ESIpy09nYSNtA9DI^G;;Ll9Z5|JT@L8pS6 z=LDaMhSef9kKYv$QmRE_E9?E9x+#R7EG1O<>7Jl@f=`e0)6s|@lKP$XQ0bTR{H&FQ zqg^6St}cX+CEqrS#MdXVu^sKs^EdCN)gfU|nuEu;t&|cN=jWpWf4BaikH05EkAG0a z`{60><}kwSr&av3l#hRYOk3;XuMV}FV=&DU*-9CmLvT+ z+WizQMWlnqEBL#Bo<24v@d&Bg{c`sRFGPy!hJDXGw0(p%#G{63F=LblwcdY3eAs2Vm zpQhd8QdM++1Q6AEX;GK+F4-R9ZGBt;ETo9?DCrv0D+1IDFD2JwEAD ztgpk0jFnYAjJJ(@@>0vEgx;*>?T$KtwXGVHwg{EYV4k~Ae-(8Mq(-WYZ0p$a#PooH1&29;1t$_t9$S2(58GNS8RjOP4xdqRX7GP!mS( zwXWr~Th0}t^{$I4?CPWqt{rr_D@Dz&!?e*gOjo$xOPgE|Qj5EaTHR}@&3zZOyYHqB z_w%$_-a=dCx6@YnYt$*fK-=U$L01^rp)ZLX{|8V@2MEVi07E4e007D}b)$q0%WLwQzAecs$;-Nd zASxmv2qLK4kS~#nq5^hlp^Wh%1BQZAKtXf}4pBfw6cmwp&P}qWT{hR>FFo(vkMniU z{hxF9eEi_U02Ygt0^2UTZ1s{$s=JNge?~JFs`gh0d#dZJgLbsfiWrV%$9z#cWYT!t zjF?8kq{&_*;S2Vf!HtPzG*RvEF(L`GzPc~$iyD1Ci)C~-H!lhd7@Lg7h!G1np548{3_1!t0yE`k(y=0q zK|2;q#^YwpX>6fwMt8(ipwh-oMr2;Z4jPg3t-iFjiEVP5Wj8W^l0Y%930Vneg%uYl z%W`q6JIRq+8;=~^6f>R1wX0ice^UuBBdtAFI2o4_6~UJ^kg?F#!|# zYr2j}n9N@@1>7~fuMD#_D5w%BpwLtNrqnEG8-Ir6ou2E2f_VZH!ltvzf8c{mpVs8; z#;m70j=`}S=A%Yn>Zr&LhjZ?R7!(;@XXOpGy-LRkte_4{1m@;F!7*B7==^LD=cSdP zjHE!>@hvj2=j%8b%Xsz_e=^rfuoNB3(?h2TOd@BOcPH#f(lJ*VPOpv?Y41)Ks62d1 zDEI_jNFx|D6O@q)DJR1``t~a28pcUU-Hb zr2w4G3E7TSV_>3VOTsau3RY9(%sAca@`GltA}bxT)ik1H!5XYBe?kY&r90kZSdnDh zJd5IBgehf8^CirA2(Y&E2`TajRIr|su8#*Igb3yNQi%@vQ|Qug0WPFt3=sf32k5POw*CcHVT&e?km<5rfT#*GFEMn@M&;M?CEXnO;5$&MkH%LTOA|6AF?7MP{_m z+0sTkD8^Y27Oe4f``K{+ti76n(*d037~VYDfUe=5dU+nO0CJFdc)it$BU zO%5G8uizR=3aYQ|=4MC7SFo%Y*Wx+?$Cw=WD(3RQ4HU_UDH>}?$Qz?#n3%XpD7%RuqWbW)B70MGJctpNfASD{o7H++vZu$4o1xXFA?ww{ zbWYj1)>vOM11H((N3yjpV{pzA1&`%9C|O8;qTz8oAyBw>%}U=A6;BG(jxNlRaoAGy zw1!8qhjHlOwzNr^`JZaog`d$CAt|9Y>il#($06H=pOe~P#7@x2FSr@lgz zs*2f8e^n2IOcmXU-YNne%Gnnv>GNc2HZc_ZisGIydd#(P!m?R4 zivLigs3CR?D@I^FJ=eFEUL)RNUX(Or!8C~c7a#Nf0~EDxE0#HPRnWs=+UPC{6t^VV zf1XabIi-5(-Jyy?!mSgUnpB~XV_Ytcm>sjoUU_Xrk!*W}#(=%bsJCjxKxz05sY_ z@G}Yk3Dc=EH=Dtv!#Ajku0+&I@M|%_fIyc`EM&DL*fHD9e%b4a#j?E+)M{6be`;Ty zj5$`+JbiP}?32xoXwpP8m%f=<^e{tJxy7oghoq4Pa<`(&N{~HO^qjLoRa7tJT!Sk7 zSsgN9G|@;e$Q&I@$3Q{O#Il^uu=VVmiBk!-Mt8Jk<70+$)=(E;&_XY3YUUYE+mq35 zGroo+M7UH)O&>)Tg_BG8Jq8ffe>0TcVv^EJOj3He0dUd!GEAWt_X^@_X}^c)tlGf( z_1=OVsHoe4Y4tl$>Dz%B-ohQ2HH10$f&WTSjk)Q4h1*FdNq1jYJA(Ovw%S2VOJTtX z>H@W0L#UVR!W51#ZKi)IoH&G~gQ!g5)U9Z$OQB^e8fZ@i{VD?~tQIWX*I2w);@?C{sP+OFC4_IfZtP}LT~3FqJG8Qta_S@ zd{Vkvu5N`^@ADRYnG%9GerFINTpiWH}CfKwRa=su8@xYMtWNUdJgtNAiV;Y+Vvf0(n9&Vd3lf?a|2 zyyMZp2p%U3hp@Z!sUbWwglALO>sM2F-mChR0km_#io86qt3HtRNa-qlkvtm4D=F+N z{ry3=vh!+J>Fd(tHxEt;zf#bwmKV7$3^W(rBK+m*wvRirDL}s&QrJB?i6Atd4)_cB zfJ^^8jKAEEf28nXf9Xdl4z_0iFG!aQePzN$eu?%GQ4sL##QTAOx3DYVE)$-Pf-<3Y z6gGQOqPX1C)iER{rbH=aO-fALiUh}@oulAayfieU^rNVS(J z)mTl^2~@tAe^!b)l2(foB|TZJmNY8*#H->Iagn%6(yPU_l3p*iOM0^ymh>U9SJJ)W zd9fc5FN&8WzhAt?)OC&PM)w4HMnSamqf#jJo|Dn53@=S?$ zm$)mKmy~z{%+m=xH=vS$SKv$n;7+))4h8h&FQj*-2UijZ-vAYN5vYCyO)N(-fvhgV zm>{B<=vszJt~HqKx&S4vAWB_fl({a&6!&VByDvb6JBX?7UQBaugx76LJ#Go~?*9Q$ zO9u!}1dt)a<&)icU4Pq312GVW|5&xPuGV_G@op77bzQ0`Ma3II6cj;0@G{*_x6$l@ zWLq!9K8SDOg$Q2w06vsBTNM!*$jtot=1)l8KVIJeY+_#EvERRF+`CN~+)~_fcio`v z*4!Y8Ql(|4lGuxq7O`$fleEN}9cjIwL&2@>M%LYJOKqvn8>I&WVJ`e@>#4mHnuhzUW>Zd%6?zt$4SI~lcxhl zC4TO|$3j~w-G4Q7M%K!ZiRsf{m&+`_EmNcWDpuKnz~ahZga7dAl|W%-^~!;R$uf$l zI4EIk3?ryIC}TXYW(0;0`IS)TrpP}tglbN4Rm~aBg2TZCuXEfjpuhoC)~>H#Ftz@S z>Dn`9pMU{c7+4fO0Z>Z^2t=Mc0&4*P0OtV!08mQ<1d~V*7L&|-M}HA1L$(|qvP}`9 z6jDcE$(EPEf?NsMWp)>mXxB>G$Z3wYX%eT2l*V%1)^uAZjamt$qeSWzyLHo~Y15=< z+Qx3$rdOKYhok&&0FWRF%4wrdA7*Ff&CHwk{`bE(eC0czzD`8jMNZJgbLWP4J>EL1 zrBCT*rZv%;&bG!{(|=Ze!pLc^VVUu~mC-S7>p5L>bWDzGPCPxXr%ySBywjS7eiGK;*?i?^3SIg!6H8!T(g4QQ%tWV0x-GTxc>x`MRw2YvQwFLXi(-2*! zpH1fqj&WM*)ss%^jQh*xx>$V^%w2Z&j!JV31wR!8-t%AmCUa;)Y-AU<8!|LS2%021Y5tmW3yZsi6 zH<#N!hAI1YOn3Won&Sv+4!2kBB?os0>2|tcxyat=z9bOEGV>NELSSm<+>3@EO`so2dTfRpG`DsAVrtljgQiju@ zLi;Ew$mLtxrwweRuSZebVg~sWWptaT7 z4VV)J7hC9B-cNaEhxy8v@MbAw(nN(FFn>3184{8gUtj=V_*gGP(WQby4xL6c6(%y8 z3!VL#8W`a1&e9}n@)*R^Im^+5^aGq99C`xc8L2Ne1WWY>>Fx9mmi@ts)>Sv|Ef~2B zXN7kvbe@6II43cH)FLy+yI?xkdQd-GTC)hTvjO{VdXGXsOz-7Xj=I4e57Lj&0e_C+ zAH@(u#l-zKg!>k+E-Qjf-cLWyx_m%Td}$9YvGPN_@+qVd*Q)5cI$TrLpP-Mh>_<6k zysd!BC`cEXVf*Q0Y(UgdE^PYo5;;FDXeF@IGwN8mf~#|e4$?Ec!zTJEQCEM2VQr*k z8Kzplz+)oH5+-jyAK;GP8!A zSKV>V#gDFTsa`xXt|1Uc3i&PSgl%D=JEwjW^F5vD0l6G!z|~>y03#T)?a;@!*(vAwmBFr?|-8vt&)jK z!?QG5DNz%WTH4H>vbUDpIEl_O19mVOmP_8bVz-kCsYEtX_1Ovb zj+KS444hDHKJfNHwq&hQ29#QGU>;3P1P+D_kVfmXiA~y=y{YGCGep{s6iwTA*ge*SZSH9K;{Gc1^NWT z@{>XOdHMwf#oVVr5e4%x1I%+r&CEE*Qu8V$tmu5mm?%|OR}{L++~wCzm$RIp(7a-4 zuUW|Jw)8G^n5G$)e{tS^RU&@6hKR!RWWQzWdvkgoyCMKT%caX_=zlus#?;Tc<%xwM zJewbXg?^RAe+_wMk=A>m=A@r~0~#Z6hmh`q^b!Z`=jde+%aR2&hxQ>`<7bXmDk+!% ze+$*7qh)2_^In4P`ktr>O8z!|UZGd$clcz~c=h>Hr~z=--z_oAmq3RVC-fGwS&sJu z1-B|M{Jx;us@*hy_J0o)`U?9cH0RlBfikrIP@yl=AE9!T32=5+P-i$<+jN!7%+FG| z&!5nrvTOegUa57UpZ*+hJA>p2ga0MxsK21E^Uo8!3b{#gdjViLw zDj?{%qL2b=fc}>G8S&udSPszN3la#if5csvd~EsYTU;zzV}C*VHpkOH)4w1W41*h( zbOQ8mmEBsPEo@ObLg z93$OR0O5mpOQ~kA@~zx=sm%~6;&yQdTLO>ECg3w&$V;K3Rxm$Mx#E3$#)AP`Y5ET>GF+K7Ons=3AJy$clM99)e@XPVK;DaXeI#{!nwqZB>eS#gwM4Gc z+UQjZ#jeu&%Mv~fw1GC37KsP2q#o_EXrxGY9xc+Ai=@m@d~k~Hixz2HYVc*MpSt<2 z$TixLN>0<8uJ7@5d0V_2pQVkF7Vq{{!dIm33#3Ft_}G2)yjM)!d^I{4d6C{M=mM$U zf6tOXHRy?rH1$Si=)u8jv@ewuk!jjLMIV6_5a7L3EjF@9Y$D=$k&f1(*4c#dO{r8e z(v+H}hoI~Q3P)vOmA?n#aMPBi8^%0|sj#w@`5rIzh zQ!tSbr|=trz3XA)gH(s7qlZqzSnr3Gf1k$a6s-R${PJy>^CsjPC{3BNQR^|!p8G=V zW%6Eb%Fa-3=o*=+gf}`(Z);pdp9v&gz7C z*}oPKd5d(eNI!)2=dpg8p7eD2T72>A&r(Oc#kZr8Zl0T=_oWh8{A0N9vXFPxf7T*> z@F=#&(1(wn_rW1wit#=dQbR@h$qP^^nkv#IIQ!Y8pN*0_p744iBi`tUFE&yiA8GoT zkhf%^=TflG&)tw(+<*mIXdUgu%{CxCbK8#JowN2@0SO=M^#R!H6?`{v`CUe5FJ?Sw zyCTwGaWuckZrbd*cS97n*}$HSe?&KIhht~x@pz>vsk20GwyCM?#|=m*99Q+xzrHv4AaMp^qVvE1qqxlUZ9nHsoy&~b@Pi; zbSxIXMqg&hucX*B)AZGlZ<_wNNMB2M8@&ts^)Xsm@z<+UH@_KAm7Vk&fBsM1e8*q} zC%twfR;0hW%s)2}p$g))S6XPbY}b-1+g56mZJ4@bdpGTo?Oxg^+aw*3?Jyme?QuE* z>k?^{mF+lLvMtd2WXr!S_d)uoY)gJo;16IEvvuH(Z&YlEF~4MtgVERw{mtdnP$YGQ zLX5QNiKcH()87Fhz);gaf8Zxp{{AQY07^yr*Rp8*MAN@Z(f^s9xq-6?{;3ChGh2NJ z5h72l13;O%#FbbiB|~{IS`?nriNJPIz>*(s7WJjAq^m9+Eguv+(JTTuX-2FlipGi# z>xbCfU@qZdcZ!5pBz#h2ErNo*n((t*0g$h4ur7sb6@-iGc#L$?z0#Uu)Xh){P%^cBVZ7wOS8%9=n+@X6!d z0j(RK8a`Hw2l5S1eVl@8los!kPhF(7@ijcCcL%PBB!<=~MKK)m$2=`T0Eu_#R=NXI zH=h{{`4iqLa>{Mue;U1>Y8Hp4#o-&#kU!*$UlB)|#anUx3hcmxfhe0Q0&^ZadKv7! zbC8#@-C);d@h~h3LJ*D3;sie9@`|I)B2%(-WLk{fsNVS{3NYNyg}nR)ue=tyK_MEW zlVVgDvV8=;&C^-g=a&0t>2a|ceQr0P|8{y#_POQ$^YjVXUgwtkpQOvO&n@>kdb!Un z_g|vV%RaZ<|2lm`_POQ$>nH%Z&n^1GBO19cTkgk1x9oGv{j_*W>RF15CZPW_^!Tj4^T{T!k9N#2;RO7iBy{i;&QUo$Tz+ znfE#GOwP=ozrTJ1Sc55We021t`blp}YoGj;%5y1uf!uNG{2U zc(N@c!)lX%wI3y3q;Kp>H=-52V;i3A7>>%(TwkwPYfo4kR?qm|#C16kwWU$vA^EoB z6NQd%bM%nHh`l&oU46V-HClA2e;$PpNH>BcwCIK7lE8cr+NK@KmP_V`PLn)Sf8 zDbz3|Fu5lWrRhrFHeWUO$ci zK|;QNMYU4B-{xxq=2gh0MJ_>CzIO%I2C`dQ0}U%zLwzhCD9eXj_~Pck%ya+e`Xnf; z1j}62O+JMJ**YJ(mx~=JE+{p9z;saHl6M^@O>uaJ(zL_pbbfg95AEkMI{P zQrP_-wu~WeK)#DjC~RTz1jWl>>J%&u_A8uVH0UJwtHj+O|MgSsVS$&sSO#aG3~yMr6^X${<>0 zQle|Lj@}|34Nrzqkl>m>`@k4<9*UKfc&#)tI4W!!rdA{x!$&L15^Z=Vs_fD^%wvtV z4GjkS3$YfV7A6gE;|0p94J`((b7fR@!QilW^Ak`-SZ_W1@A@+aUavpvf)AYzv|)!q z4VaP^lJwjZ|A#8&wqkPDwLy5?V^3lqxn2iXkLKsKp3v z)lw?h02Q#9dcl*)Nir~*8P80hEVZkB@JF-{`qDZ}%ic=6I zm%FuV~79YG9K?LnO!Z^jy-SC}sEQ=yjZJve> zhLEVZ{w5(ZoQbyviJ%i_b(}#LLsvu9$Wy~P3VYSGP5*j5?A-{?qgO|N4=ynDG-o(t zyH$VDmx5O`yrrVG6j*nCTSp%*G6XD#7Z}brjGFxGwwDl7VfqSEf=l#B~g+q=IW=b5Z!M<&ucX9YRuprWo1}sWhaiRi-Z__Z`V_?vU@yo}2(i zFdD}DxXjRbRIlL*gGOwBofG%{2tGu67-Ps#wKfT;#rvpD6d}xUOenjnl!5P12Z*7q zw!2cYy^fD{X!wL7>>Y4wID{LA*tcu0;U>}9^SSiBWz#PcPvS>06_ak^GaXZyW_ZJ^ z=DocXy5lp)=I}XgE9)%v+M=maz{HH12<9-a6nE%cQa3OVKU(g8u^m{zqPmtPawHNk zWR7wCpHO$PtcdUx!|AF`o4_oZJa38m07T<0{69Jm_wcovhi@1zG{6_Cwr^I%)O|y^ zYO*wZw@?12&fKV)RzYoo?-}~1q;zC-qb%&GVmhg#?!i<=i!>0|LdgHijnpTlpo4>E zJ*c*hO|z2vk8U1+%7RKMp{yWG^+$Y3922QYvQ(DNhU(N_cuU6$Dzv>0=5xNOeup?c zNo$t6oTaTgSFPlQTvG0VOE^gcRX<`ALi8~FK&RITk_PxKQN!sc(4M3F**1D|x$G9+ z+(ut+b|{%kY$001J2kwwjltaQEs*i>3w*#Zn|y(f7#?GPoIb8Gtu3 z6l++mVQpv&_A5%Vi@5j`T=XJZe@D@ehm?9h2I}XB_@(}4kR&~YHrm3(cAUT?`X&;S z^aR@e0Z>Z|2MApz`fv6F008!r5R-0yTcB1zlqZ!0#k7KfkdSS=y&hcen!76`8u=i8 z2484mW8w=xfFH^@+q=`!9=6HN?9Tr;yF0V{>-UeJ0FZ%A0-r7~^SKXVk(SPwS{9eZ zQbn8-OIociE7X)VHCfZj4Ci&GFlsOiR;iIJRaxoGXw(dGxk43#&53m>S)=uTq|9>^ zv)ObhvxHhb=kS$=qTqy4rO7l7nJURDW4f$LID5`?1J}a&-2B3PE?H*h;zu740{(*5 z&`a#OtS|ymO_x%VPRj~QUFfu4XL{-O9v0OB=uyFEst^tz2VT!z4g<2#lRmMJ`j5ZM7xZ*AM>%2rvSpe(=Ig+{%mm`qu9D$$nuwfAVtg)wU1D1@Oa-0qBDX0)tL}srdd3AKVr| zu!4652w2`d0fsD36d(v8?%fw448z=eKw!vV=GK+cg<@B0$2aAJ0j^IF7?!T;tpbe1 z;%>zpHr&Lcv2JbrpgXly(as#!?0ARvZ(9Tyw9dPLBI6nnUO(iIoc8&R_JI|#ma!w& zAcT?E9qq-QVS__Pcf=Ea+u?_rKX*`?w+8~YR^5P4}7sOkF z9^v<)Wd+*~+BRU@A=_f}TNYc7Hi#bHH2iMhXaTblw9&-j;qmcz7z^KOLL_{r36tEL z;@)&98f?OhrwP%oz<(i#LEKIdh93L_^e1MUFzdwUAZf=#X!!zWeTi=n`C^CXA?1cg z9Q>gxKI!0TcYM;pGp_iegD<(`iw>T3#itznkvl%+;5k=(+QA>Y9v3?#|5p?&G^NcjljeZ~g^f18y^%J9)Cd^>|=NijQzL5oim< zlYvkmuB9`wBAK$LhSPsqg44Xt6)qW^7KbGx93STK5hI&60&Pi2F?cADNrlr=CM*jZ zLoF@q;~O@SuHKr*C$ow|6UMLxJIZx~e9?Ss^Ty`ZaDtBpPPoAs zJW(yH$N4T<;S2#yPeoF?lu&qNOqVhlu1EGea_2aYXH89ap^|@L(Gh7>iYStriu4X0 z;c?T2YBH74HPSR?ZZItAvUReitVH^z=C?2`C}=rO7dV=-77=68sE%uDQcf{6cFi77 zhpm&o07Yne+0~cxtd5_*)sP&)@HC}ize=e%9 z#0xj(imzo}crbrYe63*c7RTYjDhiU1%Z6##t_Qui5BGbp8h+wH(WFEnJTC%R=pic) zGR)Vxl-NNqUE8ZG40R2ST?P81rl{~1FV5^e_8Pg(x$FW_6(mpMLKFJ(*W5>({#DW*Q zoCKbj>CJyx?{us_MShE|Mu(*hn_8mTv>ROv%chy0TJ@sGvER$E`JN~loQ0D;f|Gu7 zWz6bozzKCPos?s8CQ8kPJJs7yy@Vnhlrv7zVopqhG;I`3KjYvJ7U3Q84o~47P9z6E zG=+Dj6AqqAR72W5+#J*NkpVf)wXA6$(M~T?7#4pzGDBrUrkr3p#=R| z)ud>4j>mb%X;#lOggUgWlJKjV=@*U0pX+Y^LM!$sbuI0$Ut`oayK%Cl!#hQF;YI3S zNlkxGOJ@1oTeu+m*V=%8d-n8%+f;C_H)8o;-_FbP`qm5+m$!#sUS3~az?6UCnEncp zrIoW1GYikZ3^9(J+*73a_E2=I+@yTZzO&nHEt<<$te&=8HKwBfgjml-JG}$lI=92@ z4z$bd>F@tEaq6laA2^*uV=f+<_SYxIZ2lu1)15Avq4jrv%t_4M85a1jrdBbg?&OBO z?w|X;yr%s=o>F|n{!ss|&@a-Ga?>Xp`Tt1WnzOgFxn}QvF`pdqH+A0O6M<{R?*8aI zm|Fe9w=3;hq}hV*9V%VFm_Nouyj`+eMRi@5yyP88PxBQT&vbZ!!)Ky@-W>G*(aL2R zRrh*#Vd#O=-{*82{_t)2Q0>X_c9z?Dty^;DE4*(gK1oaCZ038&qGr3{1N+o{&GW)S zR_RrFeoeXT93w9WTJ=k2WmwRsyZJjz~raN31L?*7OZAKosxIC_$obw$Vto-F(G};KG84}n`sf{TwU%2wY3la+hh1Mo zOk8XAThu>BWiTy&7qj>ZQ^xVsJ)L}CZf)Xc&#mN8-WF1DX4>(>Q`45ejQ0=-ZM4zk z5L6XanSS@s%!u+}4U5KdXED2N1@ELz7MFYE%Vl0?GTZp&z)8j5fxVV0(M{Jk-YLI# zD7^e3@2_*4y-s~w)iFmb?A6PWbS|JU~kQ>A{z z<#_KpR{ZVn&J%Zz?8+_T3iQ3CX&uXK`8Ms6*u@`B+O_xJ&pYz;K_cUp%GV7lwA_XQ7h?=EiYO%jA1g4LkyE%H;C7 zPBKh~SnewUyI}=DY{&pStppCf@lAGIC^PvppTgt~O9f-}d3G+pn zHcEm8XU#X20bkb$bjx(06{tEH6~T)57MRE&F1=%5uthQcpfXUA=H!#g@?du$?pR}B zus~7Bs}5H9dx4fr4CvY|pq0)*@1y!kP7|oePX>Iq6EG0Z0Tmgcm@-Wp?51-IwPcVl z;ju?iv_==K$b6Bx4B|cu^pKur092#|ys(EK0ARQEYY^^{l%|QCuAjeEkp14?q>9h4@!6nkbbJ&fg5yu+?X8=+3#!VJj5-STn zB^PM!VxULuP~>AB87AvHdVm8Jad0aGgFcF?DbAA>SBOrobXEl`gda@_j7wDOI$XgD zA?Lm7ffXYk=VyXqs+K2Iu@*=nEBNf4$p*_rnW}xj5^+A_U=u*+w%i1|eiP93x+o@C zhJh7Ihbe;@`y&KjUXYgX_u)8xbzqD+z9U^n!xP?doXqyT+|nlWGZ zf)zbpp(6wDM6oe2=%E;$(+^UFIrO3?4Q`17gDC*02i4ujCr@1I$qFe_?ym&yj++j) RhRK)Bhkwq`;Yh)md4RrtR%sNbw?F7+wVN@9oT5^KvyxHCChVwDz29-_(~6`YI}kOI zb^sOR2x~T#ZdIJ>Rf@`fWMMck8Z~Fk7!ymA-q=^Hp5eZ$X)}%69EWv#a)HMQBo+#f z36F86&q=PH!h1hfL>Ol{cXt`zy7GFq%Eq79O{IA-u!cH*(wj1wN}D2M4WT6o(qxrW zEB}r}@-+r4&wIr;xO0(AI@=cYWb?m21~K;0A^-T{gEQnxfCN&@N(#Zq#RXZY87O0m z;t0Wp7M~;I&<5qU1T+?pjfUye_TixR_f>$?rT1}+*6u;9Gn0cXM{`4grB6(W zyBDpHwv$&%UIzt(jZMh^e3jZ{I@kE301olpI{yj0+;ZWogmFjno1+v zMW;sMFf7sR(_fhVjl~QhEC!kN?S1GnQ8&fuPw9z{5eDbyAAsT&CyjpUf=RK)X*YhW zwf>HLeXJxlm0mFjo>lB@ni;CUkg)*JRligsG*5>@wN*UJvbS&X^}x zn@^UJmJ90QY)d4OLkji-vg;l*>VWz+eRS?0G0Bg!HhZc?2Wz}S3kMg^_@+65nA?uo zkBwh=aDQVGH8XVK>zh0u{gJbev&iTnS1h3p(pF$?`aC^rhJj2lK`5&HHV#_?kJb zGMSi_SJ(*5xg|k>>Dvgt0#5hN#b8)>x5&pj4Wy_c7=p-XQ=>p*vRykohWoq+vj1uk znu?X~2=n2?uaB_*+Lr;+&434q#3lhbD9@_k1Te#nwy}MM^TTHt=B7p23Hvw*C##@< z$6AnfJ+Ri~X^`J(;3$v;d?J5C5U~zQwBA9#k|t1Y#>7ZrY#I@2J`|kfQ=Sxhc*rH| z{varkusu6HJ$Ca6x^v$ZA6sX;#AVi73(ebp61*3)LCF6yToc0LMMm{D%k+S_eJ<3CTZgjVEpgE=i5mX z0o|kFlPT7$0gM?NfN_Wk=T=zCXFhtz_fJrXuKFQ#uaUzUCWj%}$pz$g05t#ar{-1o z#ZYh6o&A&s>>NA5>#m&gf?X>M)bj>Q7YY}AR8nPC<0CJ`QolY!M*@PhNF4%4$5nFf z4{VxA-;8{~$A&>%Yo@~y4|O}IqYemSgP7Sy?d}}+e`ng%{?_hDUhCm`I`hP=rda|n zVWx~(i&}Q|fj^k+l$Y30zv6ME&AX7HTjy~frLaX)QgCMmQq3_qKEcRyY7nk_fa}Z$ ztrwMjNeJ|A@3=y7o^6LMBj@LkTyHm7pK(Vxq%M=uXr;M7{wWsrG~I1ki5OQ6#92Ih%Quj|8Z|qUzyy6 zUf%s*-I*73e%AX}cTI5r+ZsgVR1jr6I*hnu%*rSWqzs(T0KD7A4U}76 z)lH{eBF=pRy0q*o<*iM4@ojv65`y{#TKm=!5+7PwC>z)to^he4BI9`z60IYcFC8XC zZ<65C;OV<=0*{u4*i@nn?J4m6_p_jauY-;RSof^%yxer|uPQvyzOCP1x_-}6H;)~6 zkQH$^6A(lu&B^q)5vwSypjGu5P`Y#UdzM%Uhuh>vlisoS7c?a}|1hah-vo_i`e5;! z93hb``au;ow+t;(wB3-=ww(pgb`ZrEODvFvfEiQvXaSX6+A0ooWdEx3u-oBf9V((3iwRO z7r|AqsNjl$(oTUVvOf^E%G%WX=xJnm>@^c!%RBGy7j<>%w26$G5`?s89=$6leu-z; zm&YocPl2@2EDw6AVuSU&r>cR{&34@7`cLYzqnX)TU_5wibwZ+NC5dMyxz3f!>0(Y zJDdZUg*VS5udu>$bd~P>Zq^r)bO{ndzlaMiO5{7vEWb3Jf#FOpb7ZDmmnP?5x?`TX z@_zlHn)+{T;BtNeJ1Kdp2+u!?dDx4`{9omcB_-%HYs2n5W-t74WV76()dbBN+P)HN zEpCJy82#5rQM+vTjIbX*7<~F)AB_%L*_LL*fW-7b@ATWT1AoUpajnr9aJ19 zmY}jSdf+bZ;V~9%$rJ-wJ3!DTQ3``rU@M~E-kH$kdWfBiS8QL&(56OM&g*O73qNi( zRjq8{%`~n?-iv!fKL>JDO7S4!aujA}t+u6;A0sxCv_hy~Y2Pbe53I*A1qHMYgSCj0z6O zJ!z}o>nI#-@4ZvRP|M!GqkTNYb7Y)$DPWBF3NCjNU-395FoDOuM6T+OSEwNQn3C`D z-I}Tw$^1)2!XX+o@sZp^B4*!UJ=|lZi63u~M4Q%rQE`2}*SW$b)?||O1ay`#&Xjc! z0RB3AaS%X&szV$SLIsGT@24^$5Z8p%ECKsnE92`h{xp^i(i3o%;W{mjAQmWf(6O8A zf7uXY$J^4o{w}0hV)1am8s1awoz0g%hOx4-7 zx8o@8k%dNJ(lA#*fC+}@0ENA#RLfdZB|fY9dXBb;(hk%{m~8J)QQ7CO5zQ4|)Jo4g z67cMld~VvYe6F!2OjfYz?+gy}S~<7gU@;?FfiET@6~z&q*ec+5vd;KI!tU4``&reW zL3}KkDT;2%n{ph5*uxMj0bNmy2YRohzP+3!P=Z6JA*Crjvb+#p4RTQ=sJAbk@>dP^ zV+h!#Ct4IB`es)P;U!P5lzZCHBH#Q(kD*pgWrlx&qj1p`4KY(+c*Kf7$j5nW^lOB#@PafVap`&1;j9^+4;EDO%G9G4gK zBzrL7D#M1;*$YefD2I-+LH{qgzvY8#|K=-X`LN578mTYqDhU}$>9W&VOs z*wW$@o?Vfqr4R0v4Yo_zlb?HKOFS zU@WY7^A8Y{P)qU9gAz52zB8JHL`Ef!)aK7P)8dct2GxC*y2eQV4gSRoLzW*ovb>hR zb0w+7w?v6Q5x1@S@t%$TP0Wiu2czDS*s8^HFl3HOkm{zwCL7#4wWP6AyUGp_WB8t8 zon>`pPm(j}2I7<SUzI=fltEbSR`iSoE1*F3pH4`ax^yEo<-pi;Os;iXcNrWfCGP^Jmp935cN;!T8bve@Qljm z>3ySDAULgN1!F~X7`sAjokd_;kBL99gBC2yjO+ zEqO##8mjsq`|9xpkae&q&F=J#A}#1%b%i3jK-lptc_O$uVki1KJ?Y=ulf*D$sa)HC z=vNki?1aP~%#31<#s+6US0>wX5}nI zhec(KhqxFhhq%8hS?5p|OZ02EJsNPTf!r5KKQB>C#3||j4cr3JZ%iiKUXDCHr!!{g z=xPxc@U28V8&DpX-UCYz*k~2e)q?lRg<{o%1r;+U)q^{v&abJ9&nc6a32ft(Yk}`j ztiQP@yEKf@Nu3F;yo9O})Roh9P08j7@%ftn7U1y;`mard4+5 zB62wpg$Py_YvQ!PE2HpuC}3el-F3g{*&a z3q{eLy6Xz|F+aMrn8R8IW2NZu{tgsyc(>*TdV79@?V$jG(O+Iz2rnDBc|1cK8gR$Y zthvVTI;(eYhOdjapHe=9KI`|2i;{VIfvnR6`qof=4a=(BTZkev78+6GJW**Z!|yvS zes)T%U573C~Hm`&XJzE=2t7tFIZM`!^r^&z;W?dOj-N+a10^>wV(l~2naa?s; zTxU{z;Go|Ve!vUjUrZ$B#mWH)NSdxi;dWa-@w)-$wBOpo`DEG<;C#W||W}&@z>C`*j9V|`ai)z*2PG`TZt6T{a zj!#m3`Vz5R9wJkNMsJ1`fSCS2mHnizWDT!G0Ukp$%*_^X1=k=%mmO$^_0_d|kc8ek4_DZwomL(>GGtfEB)Wy&cfZ@9-T|hAq&fx;XR$$_yl6iogcR{u zm9g)axS6=_IL4=wQXf|EkzO68$Ms4*JXAt8gFxLCibt^C#C|I|v|U{%A;+NaBX-Yn z`HAmP*x5Ux@@Wkpxest$F~K8v0wlb9$3gHoPU(RMt+!BfjH?`8>KMK|!{28+fAk%6 zWdfyaD;Dr~`aJHn0}HIf^Y9*keGvm6!t?o%;je)wm`Dm$fN?YtdPI7S=Y23+15L{J zr;n3MYg`<50nW^`BM$&M(+PQ7@p7Lvn(kE`cmoNS7UkQmfvXQBs_unhdfM){k`Ho! zHL0#a6}Uzs=(bu;jnBAu>}%LzU3+{sDa6~)q_|pW1~*Is5J(~!lWvX(NpK_$=3Rbn zej|)%uR0imC;D5qF7p}kdg(-e{8#o!D_}?Fa<&{!5#8^b(dQl40ES%O_S(k8Z$?Hs z;~ee=^2*5S#A*gzEJgBkXyn*|;BBH97OOmvaZ>&U&RfU0P(?jgLPyFzybR2)7wG`d zkkwi) zJ^sn7D-;I;%VS+>JLjS6a2bmmL^z^IZTokqBEWpG=9{ zZ@<^lIYqt3hPZgAFLVv6uGt}XhW&^JN!ZUQ|IO5fq;G|b|H@nr{(q!`hDI8ss7%C$ zL2}q02v(8fb2+LAD>BvnEL8L(UXN0um^QCuG@s}4!hCn@Pqn>MNXS;$oza~}dDz>J zx3WkVLJ22a;m4TGOz)iZO;Era%n#Tl)2s7~3%B<{6mR!X`g^oa>z#8i)szD%MBe?uxDud2It3SKV>?7XSimsnk#5p|TaeZ7of*wH>E{djABdP7#qXq- z7iLK+F>>2{EYrg>)K^JAP;>L@gIShuGpaElqp)%cGY2UGfX1E;7jaP6|2dI@cYG%4 zr`K1dRDGg3CuY~h+s&b2*C>xNR_n>ftWSwQDO(V&fXn=Iz`58^tosmz)h73w%~rVOFitWa9sSsrnbp|iY8z20EdnnHIxEX6||k-KWaxqmyo?2Yd?Cu$q4)Qn8~hf0=Lw#TAuOs(*CwL085Qn9qZxg=)ntN*hVHrYCF3cuI2CJk7zS2a%yTNifAL{2M>vhQxo?2 zfu8%hd1$q{Sf0+SPq8pOTIzC&9%Ju9Rc1U9&yjGazlHEDaxY|nnS7rATYCW_NA&U? zN!7-zF#DXu0}k4pjN05yu#>x8o#Jx7|Fk=%OR((ti%UVKWQNH>+JhH#ziW1hD=rk* zD#1j?WuGxd-8VqG@n_Lqj^i=VBOg@GLePo0oHX9P*e7qBzIs1lzyp;}L3tP1 zl5;OiHG&-flQ;rYznH%~hz>fuJ!n*H#O)3NM3`3Z9H|VFfS-_xHRCuLjoIS9wT!F0 zJ-kV3w>7EguDzoBPxW>Rra0#+Y?;Woi7qJ1kpxTad?O?^=1cG@GeNtRZRi8_l-1CS z`(#oF<;VYR(l(gHIYH$y2=rj5m3QL{HQgbW9O!TU*jGj!bFazIL?MYnJEvELf}=I5 zTA6EhkHVTa0U#laMQ6!wT;4Tm4_gN$lp?l~w37UJeMInp}P>2%3b^Pv_E1wcwh zI$`G-I~h!*k^k!)POFjjRQMq+MiE@Woq$h3Dt8A%*8xj1q#x?x%D+o3`s*)JOj2oD7-R4Z*QKknE3S9x z8yA8NsVl&>T`a;qPP9b7l{gF&2x9t5iVUdV-yOC12zJnqe5#5wx0so2I)@8xb$uPG zNmv=X)TjpHG(H!$6Xp>)*S}r538R99Y{Pofv}pAFlUK;xi{E43^->z1srWR=J$8N! z4jRu;EAiLG9R$5#{gR){5?o^W^!t140^f=vCVSs@vK7#`-fv`P*WV|>nX610pK08< z>r#{r)fR?2pNG}8o)?uvX#UJI)YM5CG@0E8s1lEV`rom|kBmf={%h!o|26a=lNJbX z6gkBS7e{-p$-Vubn$(l_IbwS02j;+6h2Q5F7P?Du2N!r;Ql$M>S7Frf*r3M`!bvWU zbTgl2p}E<*fv?`N8=B71Dk03J=K@EEQ^|GY*NoHaB~(}_ zx`Su{onY@5(Owc#f`!=H`+_#I<0#PTT9kxp4Ig;Y4*Zi>!ehJ3AiGpwSGd<{Q7Ddh z8jZ(NQ*Nsz5Mu_F_~rtIK$YnxRsOcP-XzNZ)r|)zZYfkLFE8jK)LV-oH{?#)EM%gW zV^O7T z0Kmc1`!7m_~ zJl!{Cb80G#fuJa1K3>!bT@5&ww_VSVYIh_R#~;If$43z`T4-@R=a1Px7r@*tdBOTw zj-VzI{klG5NP!tNEo#~KLk(n`6CMgiinc1-i79z$SlM+eaorY!WDll+m6%i+5_6Mc zf#5j#MYBbY)Z#rd21gtgo3y@c(zQVYaIYKI%y2oVzbPWm;IE#Cw$8O$fV}v}S%QDA zkwxW{fa#Goh1O|+=CF3h3DWNw+L^ly?BNQ7DY~Eca}5nt^>p#3cc9s3iDub0nh`Wy z?oH|dW8-HG@d5E@U>NWPjnhTjr7C${Iwj#;F2G@++N=Y2tjV;z57RNgE|kXQC)1h- zx8ODU>kk};J8KiSUx5jSsA_XPou1OH8=R~q9{`r>VnHkU6A=!zNOH8IGJoO!+bQys zDS2-H(7+Jfe+&zf#;OSV=83I|^M;0`Kv*#4%%O7x>@BgGMU*@ajUvY>cYw^`*jm@+ z{LZ2lr{OTMoQXn2XUsK-l72oysi9vgV4Sux^1GsW6zTV;?p#J06EvSVyUq5$f4kq< z{Chq5Z?I%ZW}6&uL+f&0uCW#^LyL!Ac2*QRII5TDGfZ43YpXyS^9%6HBqqog$Sal3 zJjI$J+@}ja9Xp)Bnbk+pi=*ZAHN}8q@g$$g<6_4?ej&Rw)I%w(%jgGlS5dTHN`9(^<}Hg zD$PbZX+X>;$v4NjGJxMDvVBiIam$cP-;h0YqQ{YgxYn-g&!}lHgaG3^B=>Z!D*7tp zu19e;r`u*+@4h41Da&NZv$qy-i6#DdI)EVvmKO*PvIKz-9E5R*k#|`$zJza8QJ)Q{ zf~Vl+I=8oaq)K!lL7Et5ycH;m&LKIvC|z4FH5bo|>#Kg5z+Jy*8Ifai}5A#%@)TgPRaC4f>Qk&} z4WciN&V(T~u^xBgH=iP(#nd;_@L&`7FUF>Qm-;hOljv(!74f&if;fz2Mg=b%^8$^C zna!2I&iCz&9I5ckX-5mVoAwz~)_&b#&k$e+pp=U2q-OjkS@yZ8ly1$2Vh?}yF0={P zPd3O@g{0L=eT-Dm9?imeUP(!As&DJ_D=5lwQ=3)XWXg)12CoB=-g-HX9RSXgL;yo0 z?$7z8Sy9w?DvA^u`Fnl7r_J&_jJ7claq*2l9E~#iJIWAPXuAHfmF3-4YjFYhOXkNJ zVz8BS_4KCUe68n{cPOTTuD<#H&?*|ayPR2-eJ2U0j$#P!>fhd(LXM>b_0^Gm27$;s ze#JTrkdpb*ws{iJ1jprw#ta&Lz6OjSJhJgmwIaVo!K}znCdX>y!=@@V_=VLZlF&@t z!{_emFt$Xar#gSZi_S5Sn#7tBp`eSwPf73&Dsh52J3bXLqWA`QLoVjU35Q3S4%|Zl zR2x4wGu^K--%q2y=+yDfT*Ktnh#24Sm86n`1p@vJRT|!$B3zs6OWxGN9<}T-XX>1; zxAt4#T(-D3XwskNhJZ6Gvd?3raBu$`W+c(+$2E{_E_;yghgs~U1&XO6$%47BLJF4O zXKZLVTr6kc$Ee0WUBU0cw+uAe!djN=dvD*scic%t)0Jp*1& zhjKqEK+U~w93c<~m_Oh;HX{|zgz=>@(45=Ynh{k#3xlfg!k z>hsq90wPe(!NljYbnuL6s`Z!wQSL8|(A*@M8K>`nPJ<9Hb^ zB6o?#^9zP>3hp0>JAite*3N?Rm>nJ1Lpq4)eqSe8KM_f(0DB?k8DNN6(3 zU#>-{0}3~vYJ7iIwC?Zbh@aJ8kfIvY%RveZltThMN73#Ew}jOwVw+|vU5u-wMoo9C zO(tv#&5`DOhlzunPV?M~qlM|K74x4cBC_AC?2GNw_-Uv&QtPOj(7L4NtVh$`J%xci zioGVvj5s|GY886)(}g`4WS3_%%PrF(O|s-n&-SdfbssL`!Gi7Hrz_r$IO@*$1fYbQ zgdp6?(IUaNPaH7}0%U|9X8HFonsJRrVwfmf*o1;k0+PwV^i%f7U{LAayu`!x*FmhN za(#a^@Idw9)jN)K!=sFC(G)ZNaYY169*IJ_ouY9>W8tC>S&MEp$+7 zy)NFumpuE>=7T@`j}8pa)MGpJaZoG(Ex3AzzH>gUU^eyWp*N2Fx+9*4k~BU;lQ1PG zj4)_JlelzJ==t*7=n2(}B4^^bqqcKFcJ7yVzbH_CWK?{eXdpKm);4|o{aM=M&`E$=_~PVi2>>L zKTN_x&qA)@ak=v=0Hl5H6~?LOfO@1+fu5(sB|VWID)w?%{m+n#7bLaszEJ#;$HMdt z9qP0gk)hIYvE1!jseA^FGTyK=i4eTPjTL$R;6FywMBZBPlh2ar9!8wlj1sinLF-1g zR5}hLq>pb1|AC-WcF!38e*kFv|9n<$etuB=xE%B=PUs}iVFl>m;BiWUqRIxYh7}L&2w@{SS-t(zUp`wLWAyO=PEE=Ekvn@YS*K@($=i zBkTMaH<&cAk${idNy0KZ8xh}u;eAl*tstdM8DYnM5N;bDa`AB+(8>DqX+mj17R2xBp45UES|H*#GHb_%Nc{xWs7l{0pqmiBIPe@r=X%Y-h<-Ceo;4I>isrw1Hd zZd*VjT`H9gxbf{b3krEKNAaV$k>SzK(gzv}>;byq##WEhzTN^@B4+VJvW>y|U}}AQ z4^Bdz9%QKBWCy+h$I?L@ffl{fLLL41Tx|M+NjjRf(`KjHG4^y=x3l z!!-{*v7_^6MiJOC@C$WV=hz9J^Y^lK9#tzs6}-

Gn4F+B~IivciU9^t0j-Mgao3 zSDF_?f~c=V=QJRSDTG0SibzjML$_?2eqZ;J*7Sv$*0SQ|ck$fX&LMyXFj}UH(!X;; zB_rKmM-taavzEk&gLSiCiBQajx$z%gBZY2MWvC{Hu6xguR`}SPCYt=dRq%rvBj{Fm zC((mn$ribN^qcyB1%X3(k|%E_DUER~AaFfd`ka)HnDr+6$D@YQOxx6KM*(1%3K(cN)g#u>Nj zSe+9sTUSkMGjfMgDtJR@vD1d)`pbSW-0<1e-=u}RsMD+k{l0hwcY_*KZ6iTiEY zvhB)Rb+_>O`_G{!9hoB`cHmH^`y16;w=svR7eT_-3lxcF;^GA1TX?&*pZ^>PO=rAR zf>Bg{MSwttyH_=OVpF`QmjK>AoqcfNU(>W7vLGI)=JN~Wip|HV<;xk6!nw-e%NfZ| zzTG*4uw&~&^A}>E>0cIw_Jv-|Eb%GzDo(dt3%-#DqGwPwTVxB|6EnQ;jGl@ua``AFlDZP;dPLtPI}=%iz-tv8 z0Wsw+|0e=GQ7YrS|6^cT|7SaRiKzV3V^_ao_ zLY3Jnp<0O6yE&KIx6-5V@Xf^n02@G2n5}2Z;SiD4L{RAFnq$Q#yt1)MDoHmEC6mX1 zS^rhw8mZJk9tiETa5*ryrCn&Ev?`7mQWz*vQE!SAF{D@b7IGpKrj^_PC2Cpj!8E{W zvFzy&O4Z-Exr$Z*YH4e|imE`&n<$L-_Bju=Axiik+hBtA4XNDik(G_;6^mQ3bT)Y% z6x=a+LKFZbjyb;`MRk~Dbxyc&L; z8*}!9&j0wewMM#O`c#7HJ|+Gh5%3~W10b6sdmCg3G_v+@H>n*c5H`f+7%{TeSrzt89GYJqm>j-!*dReeu&KHubhzjSy_c~BJcbaFtZWAB}~KP3%*u{zHi zVSUi2H8EsuSb3l7_T1hP!$xTtb{3|ZZNAJ{&Ko;#>^^43b7`eE;`87q81Jp;dZfC< z$BD`h-*j=%uTpG8Me6dF zrH%)Bw-a0}S41ILo*k2zn6P@?USXtC>pX*tzce7A^JD7^^p7K5kh-HO&2haDTL%2^ zSWQb2B6}e*;x?eKq?CdG7F=wHVY)Lb(kQu1R#1Fx|3?>_%cjNM-xJlAg9kr`!>&;E zTYmHhqHh&qbfO`~w3V;BM(q(_Q-5^!esaBI&QbZ^%N-ZDYft#FTS;%{ zKzlSwZIS%zDi#%DMK>`_vmE^krJL5@PmpT2m26Q`O)VRAL>){MN45|7GTk=q^zLpF zjS(Os=`#On$XI#$A5ewac9Ma}mDxSu^5{#jHC+24a2GbfBJ&Zn8W= zm=l7VE0g^z$3ikyU#ysh8b-PH(&-yZL$JV-of-ZM@~N^#DbQ3Ltlq*5@>WzSNxrRK zYl2VS8r;TT`wLfD_O0dhX9vR#S8rMOuUCRkWZE#OjRi$l*#C7}mgGzZBD%Z=p3z|CaVM$$pyW5-pJJDCToY zO3R5)P(Gnd>6wh9Z$Sr@cMXmClU(h-@5kmiBTNTU-|5vq&Fs!ah|o47kW?SO8uWv> zW$=Ud@@|*9p@Rb=!wl;%>k)kH7fPtcD=gd}^IxN^=Cg>zq^jij!f=1PlT|9jh3K9g zF~Z)B;kb^a0hLmJvON8Ho)foq-oC)&E)b|a^|b}6n!8&AIaousO^VnYzYfuijuEo5 z7IcUMbYD=vec4eZX7;p31NB+T9BOMJp9ZI9$dH1kJsJpEtf@}tL4)_*PxgdOge9_EaR!?wWtBx%*f$IGoR>f3Qf2aT0%+fq=1xVEqRl;UaA2Ncs4B1M1#foI2bj4 znX}t7;-FCLK&;>ZGP}{GxK67$Kz&pO%%J>DBMP_zZsLOmdpDUDp&f8=L>(Kcj+S^jA5dco4-7XN z)h;m#54CEy9)Ch-E7gHP@a@TXl=_%&|iUlIrQzn=LqONBu9FCn`3f8aqvRu=RrJ_RH1^Uf=t z%Ir*({+wEeC??C+u!hCi<5m`RsRO6ti7YaEtY0|U)-QfNsdN{=83K_}m$0Z=ElWyt znvo5=%f<;|hNnL-r#v5ab&S2*yK>~a7m(My$cfd*tff?=?7-j3^|&9H7G*W`)m8M7 zzd0+b)c@`bQN1-^dC$_04tK0{mU5tx_zo;&TWou8F(H_J?O+Y)VLXzmU^> zvL!5+1H?opj`?lAktaOu%N#k4;X;UX5LuO`4UCVO$t+kZBYu`1&6IV@J>0}x1ecuH zlD9U=_lk1TIRMm6DeY2;BJJEE%b0z;UdvH_a3%o)Z^wM&<$zhQpv90@0c+t?W`9kolKUklpX5M&Qw06u=>GPCr5Imvh*% zfI`tI-eneDRQo?m*zD1i;!B>*z4Xioa_-S=cbv-k_#Wg=)b$0@{SK>Mr!_T?H`S-?j;3$4)ITn$`g;J$^TppD)^pRz#^l?XgZ2CW z3g5G^iF*GZYQ}{B|H-fqh=_>)E~=3y3Zg=i75G5E)*a>R9bn~cNW{h5&P(vQ6!WHv zw1-89smtY~JnCQS(=9zM)6>UAi%G-r^LA9_HF0Vp3%JF2P%+E&^afy61yxnAyU;Z{ z$~H5X6?sMoUuOT_tU7i5i%5HI{^@#Hx@zhtP55>r_<3LwusK*SC#%i+gn&iRg z_8UN=rLVp*gT(K~{0X0f_=?~bBbfB`=XrTFn3U!)9n*@Uj$-mr^9PNi<22UJKAK&D z|1@Ck3(Ub;>68;)gIn_Zu{uoVRMhAkIqgBS(v2b2{gf?0xd(1sJfY`56mVy>~^w!wmX_kjW8#?_Nk{}zB9ULo>4fO(vnWfC+pG4>%*KZ?JuCdXu%aZ}q7pC%E50@U9+KQZL5 z!*I`SOtNf$Y$CsRsNaf~yyw^>#X_mCiF&*gr=cBb zoPu7PwX(+Wvl~i(XH|)jj@Cu+rzpJMn4kVvCJ~ReCf08viF$q9;CYnv-96k{G?pf_ zQglN`JiS#vok)~^Z2>41#7LPFgd_xrqNO%DQI|!Qs|nWt`co#BwY$&Wm^6#~)`_1k zpwiR~&z#mtSDuYm(=NoLv$%Y}bTjog$RJ8$j1(s})=}su0b?o8i28-|xu58ipFBml z2`4qZ$BbY5>(i2%wmh!+C}$97?X3LgTQ_{(SaFZvq9YCn@BNz z&h#;4h?5#`&_0()uJ;_rR(Q^eY*=&vu)#EeMeaN1puPv5+iQFg1EC(`_99_5v<1r4D ztc(+-eVWf_np;q$M*H49#{R)eIWCI%R&6F34;h9eNG(XNO5ao2MI8;j}y% zZeA>zX{#$;muhtY{_|;bkk~!U~Ih z2QUO}hk~o?sn;#|Mt$0}4=+BRa703n6>fBm(cesk8Cmugg_wi|BWj}V-VuU9jNH+o zgNYGSKPm>qR&nI(2Gu*})AOBfXf0J~CC50C!3KXu6-qZAG!VMZbmnqL6HWG>o$^sjoSLbQxra@WyKV$+_Qe}t7d)c`bpJG++ zw|9D3>XUH^Wplo~MN%WK18n3HeXoe*jKwVRK!=RMtIr1v z;Py~7;eZl&=^UyumN&CecrGBEat}4?mtZ>@`wPjVK@Z)FZ;05^9kztq;qmbxQIJ4kXTk)) zaVfD^K2x7SB6E!Zz@0p|Fkge*0(0?ogmTX8d=?n{2x)}K2$`bjDmcLg3#wU)i)by? zW^G8rRQKBwjke5zHScinRlE|wo0XyhBc9R52IsKWf4-@=l!yO&+l=K`-7Ib9U~hPy z!cH>H)e6$;m&w^0d`axGqDwBgu`B+L4a`xr#5g%b=0?c41`|lx0O9fiIVaFAsO$Ol zayhm4C9X%hzUf&ctylV$%ntuA$(yo*X`gaVX0$|x{#!YK^cvLmNWPZaTd3&xP7ny% zkn}2AdJkpAgmsh}Q$tY3(2RtO;%R*~8r#ZbSbMR4LaL9Sb6O&Ce(GlO${jtl&`n|D z9;zUQPXCHqTm&t^lk9RlZiiquSY_og^?kgVruz%myd95Fr!V z-$OIXSt?(pxN-M{NjA)j1KKIp(&c2RVjd_}7+CbQfw zTRjg}A0~}Ht_?-@wD0bI-;LQwT?mKywmDZ7*j4>4pR6@UVU3mb?-cbQt~aIG&RBjl zs-4UNtOH3+dAF%U=={qB@qijh4J6K?Et zPLlfPlv<+i>ty5rh;Q>iGFoaq4LyBIZl3L{KGUmqPL~ZCosOl;7w2SxcE}pvK;5|6 zly3JjUsvk|d7L3bFs&;q@_|p?vdU_UzhrS$Fw-_NoEdoIT#-0hKC37!>-i6FaO(es zY97)m4YO<|eqGMrYejC&-IFmc{=P7>qFWX;)}q!&e9-F59o>V+`X>J}%Te0$|A>0W z;7*>m4>udzwr$(C?TzhZqi<~6wv&x*+qP}v?C<}aI_Jeq*K|$4>AGurZe5=U>-0IX z>&2?v81(_Tn1tITYDSF@^Enhl9>e1$iAnX!+&YJVi>1uYEWsZ?o*Vyg+K~%XCxQP(WrdtEpc3sgbpTM_ zI7i6|pDr z{=xGh4O=PrB}pkX@o@A(%GfdU!c<$p#T*mLo^*7@bd4rIJ5eS&&A9VB$EhabJ1^TG z+dke8lOG5I(xMYZ`Xw8+olY0y6M)M0rcr%9tZHa=G0zICN@DQ>0rVASCK4=3OeMSv zD!v+POT0`UZEnP~1ro1?HPLqJ)xx0#Pg^yBJz@S6gmFN~cGvl(#fz4oTs7_Pi^+i_ zZP7<#ukx>i%V;uJJ~WwUW7pgq=>yuT+A5w(J5$1no67e(;mIO5>@`(U0{}+kg)B_8 zs=bfBbmZ{U`xjMpkAcEcEeF7^#ka}2zDU-sBt6yQqw&2p<+6Hb(Hi56S!+bU9AJJv*{ep2vD zG;PVwX@NC)+=6@I6J=nW6_99&4R00FKpUPepXoBVN*|V*C{e7X+Q({6O_^@SlI(9Y z8kRO3WDG5u=vmTjZ4DW89H&vNa;i%H@`{%(|J%tVs;1gDadzF0Jy%}C68|k?Zr!B9 z*lBN4{#6p#SQS-q#Ck&x#xhAOu4mK=Jxf+5E$h8l3-F4mQY^qaS5;Z* z-ddglOueLtXJhJ!%yJGk^-iZ_+qLJ zpTZn+6kq81D@^m(v$VFFI1Q!dtczYBt1xSn9~Q=@h%tsf*hCm%fwfx2u(u=-4|qf=I8WR*%`lsQ ziP!-b?(d_`TdA=^<$@(2c77&FowB0vhswM)fS>lYvjK7B_$<0SiQNzL6T?D721Y*( z9nG=@aWvmJMd%j$Jxp3-L4x99-X-9aGkW}yiPAo*9{^6b1>tDg4zIPFiTqVK$xq1rv1*kaE|~T5-jH#8{g31#^7M_uSsmQvNjyk; zbo|yP0w|uD1)wGrSavi=<;=H>IejRQlac$HMkU2rbq1{8UntI;oJ}*o(bXy{JC*l&^W{Y^}<%Nj1Tk z$(9f2a`BoyZZqxWF=hhmc3ldg+8&Ep%fVCSjopduonggw7@?XulP^JPo+_le`o@z)ofi9U%I z=~YZ3?Jok#3NeQ)U&qUqvoyuEMA?b&Ki=s%;_MTDX+8^>z@TOxb3qw~biG4!)XuQp z=>cVLGcp<{Piu-TqWLFz^P0>R1go1M41xFSn~y%8LZ{~t{iz!z$|ne5qkw!VwuI<6 z*6Bsnap!L>JA;B$u$J09!L&_iGdX<&v1jeDcEWM4&2q97^g9gK1%+zl7nY)PUU9<~ z!B??-0oFH5TEpfNW#V1m;(6-=mlUxm699O$g=ZrFZpn(6h%3n#!U7eFnC1BJzLFB) z-)SER^cpQ~AF(`0^?pNYWsz6(suJg4)Ke+|iTo4!8P8ND$ML1a%4|QMYe@SDDH#d& z)P6SOk~%xdQ?i^t{N0)(baSgQ(Fp*daGXR>=Vt-*#@)>A1Sfz0!iqKtjlY4}1i0v0 zyz)Z|vB+_QIX99Q+NFppI1+3`=qUen8NVELr!SOS8Vq1;{<}WKOhe7HMurM4mg~j5 z%|wM0)r4^=uC{9_OTf*An{G}>6hw}C=H|&8MY~l@u zmW-R8h;dJxjKNqEdGf85(5BrR>lY2A= z-_%9;IglQfHBuO%U)bt|g%1h-OMbL9H{TdFgM^rdBTt~gJ%{*c<;b$D13(ac>}*nJ zo@&y3%13-hUh^Oa$9U1ImdNfGO4bPX$I!c!6e;sRC>z{knTf~G5{#4J7y(vbrq-qWk%J5#0Iv((P!QKa6f#3?;#q$+(teR!nw%kOp&_W`3L^Xw}Dw&e2#l zc{fk56;UyHDpT@XdB?u!*)EdIMT8X1&e>VO;M_QH&MXI5|3xTbET#NTfyi14#+0+t zDS(NC?jbc{yIDjm-=9g^4*f1c;0!ytb~iQ;DSTKoa4ow@d-x3HI`EYcAe(li zjajb0cM*@u*kiU{)jd9yTNeRZLL+Y1&q`L>gx^Jj_B%sh2+%Z1d6xNVmTw5Fw!kd@ z+uT`4r(0=PXUZCNn9$VPo=aj+p${a|eqjB{Mf+k&$GEGV(lWHl#1xy1%5E)1KD$bK z0Z1Tsk4LpTn+b-iy}25uN>wvTfN+B~4r!aC19d7}&hDFchbqZ0;e7I0BK}RNujj9n zY8As>D%ez?Fkng~c1L3e^}<%h%!NhB5ZFmv4qmi`am*+A28lE6Pu4ekBJ8DW?YR4c zPeG`sZYLihHq~K3`oYvnQL$26Ojwnj1AOypgX_ca^06&6f`T8bedVhWj1y>F>d-sg zr9@SeL^T`CHIwyKW*F#~AZd==$aA_zOLRP>>S_&HK0s{HcEDpNQm9u|IZ{W%#*w4} zmN;)dX5OA?I{M$KLje0TCiQd&|g9E!YKD5 z)_8>@<$&L)EoO;WhhvUYgEDDJ8PPVpR_u`RN${}`PnjHc-4^~CwIh;mLF+#KK>Wc> zE|Wkj(OZ@zIa8-8rUq=a=x-F%J+$ozWaVUV@yS!{UWJ)}=^jM1_f&XffEjCb6H?Es zrqQ!sdrLtEHq=DIu@B|%&N$@{wC|>I`>>2EXn@+22x7PaM4p3V5XhXp8gSH8{)yq+VsXB@4DmPLA`4Qc`r2Z>3E&lVsUbpRejKO8Xc|ayAI6YT)d!q zrfQj!sa@T&5KPMxDUd4bZwub#5<;yenI>0~Zx=@R*M{S6d|Z3TAEsEW-w#undSQP7 z0ryg{By3CNOC^`$t=P&xCf<~vRz1}|>Oh+v>rBMi?&+;xKSGs;7Ie~^T>J4C9Ke&G zL&{aTYZk-|Pa*unK});DaF?Y=y73~NA0(lMPUz1G>G;8n^cmm2S>twrpU6ynN~J1! zHD!AXWk^D?nq)%#A^&d%DwIkh3Ku$<4{$Bnqe{R^e!E zD6qaK4g^V5kCJH~Ot$Im{2T}8sS28Gk(>QFg9I7A-=nDns|{X8NjAD%l(zhXxPR+i zsaKZiVQjKRN#@N{`Cm?#slb!NghtaUv~`T@mvslIbq5TcS-15muB2Hb$Zs``b(Pmm z>-keg*068f|SD zm-1~aS@!4?{PuWQ(%MlB?$oG~Y0UBQX_Nz{MC3%JvnoK+x5+GR`cIfTOE7r3_Xi|f z(1x{Bqg$A^m57WLbkEAc&hWkBABmV|cqNS(`o`}NaSI8Lm6{l$b%3paaK-^r1yrc* zQM|lY+je@P=AS7fX6VXPV>UYV77X|5G z5Zow(9=j+q0*H%#H}fpu-HF%`(GEbvHmWK({pqfv^b!p^KiWxjYXL)gZO^yLvY!1#{eH$?|l`7XcETF-V>)m#$Y-KUauf z^b+<*r?&Mks6o?n2JrEvgk?j+9|~S~2U~dq^}6M%or)_T?%jaFi!#+q3>YaIG?m3X z;{>&cQSHf29MCWgsDR$xyTZCe^~uYQ{iM+(@1tKCpyDxFoeVGQeW)9uT349)IDK!3 zsmbQfykCr7P5@r7$@N8b6KjN-vAfM%rz7|bveQ2v`Y|)B{2rfRwNw!r&1%%b*lWIy z+l$A~f%;yYgfY6h_(-1nXB!C4(VAsEqS^YKh9a{{_uW8t$M^?gPsm-J}^#E z_uO7hC+?sb1Iw^TeS$QC`8qwrX85eSYLIFX93I>dS^)6QIMdwX$;6F>2_T&M6o;jL zp&W3|Bd8rLlV}iSVY9G7Lo?V2_E`JVM(`rw^}DX9)wk0Q5GJ%esB@}u@C>dZ-byh| zBFz*MoXGGiF}DG?h!UZ#FN`;~1bd*pAWflMa5AtD-+Ut8Ymf#=b`potx5YLf&A%ZwGv$|Si7 z(0)Re$(F;{=Dhtq1%wCl0ijfk+T4jd3}^2Z$Q?L=1_lkM&nIax-Yo%VqZk6#Et%n& z0S9_V?yja0r@wi$m!-JJM2G=aQ@nYectR_Ln*dN6gmAR8L^dIf-bxR>0A)c$?#Ug@ zVlrY8#6Wp4wiP3OZ1@T=EBaaz(jrxuLG%?*J+=c#K7CorpL5*eKWVYiw<>#a7zv(N zO^RpkPM=xn!2?&s^7NCTu~a+aiGwc^_4Rnyqj!-l3-f+;6mkOx5@ynO(YF&u{yH5a z0{{W^{1E}V-LFeZcLzkH=SpZ_y1l&>1S=X`+@!Ai#KmNT?5ox%_;tp9`=F^;&%fxn zpX4I|M!d6`y%-8hequbo4%INVKruc+o|NwhsZB0<&TBCe}v2@CyI^$jlCsTrwmBFnzIMofx8PeKa1Av-Nj zlLtw2SI?rq_1(xc%<3sF%)ZrYIf>Xe7@jPt9BWoU%bg~g+6=1f;eW00nOrbo#*(mjYHCr_?8!#my~|i(0+2j{Uo+J%%rvg+%X5* z4!HCVyg~`t!LBG+X&89L&@QkGXe};GQ^moDsqI%U>#?IVQc53nUukdN%ij?m+%#Fv z*$`n_GFdWHC(!1z-ZhRjEV&n1wt#7VUXkgkW9Q5V;)k`XOO{*>9)xi@4}6zxlm4Ck zPC4Eq^0qB+yLg@{^VCgieuns3B!x#NzSr6q_VlhP>I4gzH4BI}DTx^r5(>Dyhc;-w znWU^i-9$N49%O1eIWyBV{K>wROpYjgCc5b?os*f=l~V;o)CB3G-E7LA7Rg3;!)~m@8(whM7Es zwF%4mEd^gMI<<|N60&DB)!+6-+8@EFbvGs4UP0$q5NEO<7?$NeaVcvz#eXkrXV;$H zPjNrI8gWTpphtwY&md>1N7T|$T^i@CM$EWZ;`6{q__Yr(^B!<>OPXT5%ICC%;4jl=T77^3T z0A$3`@j>`8*wH>vT`en;tj&YA60zbZw2F#^jE;rfTJ}-rcajHddN|Q>g}o$TX~osy`RPP=q0j_f1g@QgXPlY@q1Jh?-r4bB@~25Cj@AmJph{QR^Ya<4r(z*{F~ z=-nsVQY2K`sKEl*CR=AMEDIZD88T(wtjZ_((xf$>SIA*D#|jjfGw84wta;Nk03w~g zI(#i!OQDMse#AO065D@_gm?pQx@{rBjMat|bA$6MfVPq;S5zT5IKK&|LFZXuA zqj(kJK8jP}^ZYm?74hlPtf)m?w!rUP42d;f3Xx1K3raV-*P;*>hmzjAkyfcbEfZVM zJuLMoUQ0*&6p_BS@>f9!k`6HtNO_~}(0Jkg|_f8#- z!m%Jn^dX^G#qp$LnY0H)6WbFMeDL2eCjALoKs@6Ai81!~l3d5bNgZQ?f zTgufN#)|A&im|)K13cIGc?~(RCQ+E^pAR%xa6I`LxD$=mcOf z@v4=zb!i^TVJ(CsX?zlhk2fs((qe>+8Y#o60peO430M?7HT|g( zcVfD7@Ob>SyV%mu6}7g*=p&J}hJTo9hFn2o9Jy}QCXfAbC}WgpkeMXs7QNle)Z`PI zaU4~Uz`idIpQPmpq$?{N(5Wj_y%UX!5{=9|{BFV$P&Z}ciIVj<`zLyWb*T2wf|8o* zOk|-Qs_aJayia$?0k_jr6b#)1ONJ!Z;{~4NDyZJ6id*&SjT|kFCPH^!Q8MlaAE-*_ zNR!vqG}YZ6i}M3h>ENPmCHxC(#1( z7}2c0*RmVw1@+)M+n8t~gQT#+Yg3>|OA<9`Ynl5)ftY4g0EGA!t?E*;j*jRcB>mr~ z4f=etCrR1X;V_euWY<6p_AK%IoHB+bS8vl&LZ-5Q*QvzmfHq zZ>>MgWVvSa-wRV7cJ8O%vi&R+@2I&X=r`1P1;x8lhOpY4Z58^@Wm+--yBQ{&>GOL- zIJm(euOw?WYjBR|f~ue4(%k0i{lp`gI1~mF;g{;-0_gdf@ z*Q?M9wQ1ZdZwvrK|IY39={n^R^(zI|p=Px@ff|e_NEBug4N0vK!L9-J_DIiI7e5Pr z^Sce&Prjs*$mOY7Rf3V+?poBWP^ki{PIa+)OK%4)E`rV zxx7V^Qy14sZ;Dc2jD|ccyt5(5Zp~;Rg7N_IwB&EZ1jv&GoxT!1H7k>pY>Aa{$&oHg z`ykhr&GpvCL?|Xb;O}(ErzQAl=DZgICR);;Y=xkO<~chKzvaND<3}Wy~d>W0L>Q| z2-}wM73&w!hC@XZojB#$EnGzb4HAp3FWovUq|4f%x4KLKUg6YfVpokO|+JO^JSzIZEji>8`uBI~^1wYq9L`S;8*pu)y zTN!cO5)p_vO7vsEgglr#ee5WTiRh}7f0zLYNA)eB;_ z63%8_pGF-Dnkx@eu`dPn7Z1~vMk@*nIMW6HtpQX86HiyI1H>8W+4Y50C=@;!{F)Za-A9+#^G9aiAu<-#DuLR>+Vm6|21n$W?isfhl9KnurA)AcxJ* zIl$Iy_sl)Ewu1nV)Wiqc6M8RZ-OvG~x&%#S9h{L)QE&q|7$gk|*5h2|^bAvwHm@~P zRY4`*Kw4vB$#(Yqt2+Rd{vNGl*GA$FksiM6%fjfp!BEgA!3EEIq!j+(-cS%{(44@I z+KuDSMAy-fyJ3j}-3vV|_^?zVAkrrzw!3@QF<9e~z*m55Kjm<#D3z(4wCoyq=E3Z+5+o%*c82=9Dn;-mR<5ukCVG}$pfS0a zGXdRdAa-u4>?Cv7*|^+XrkWQGzzvT;h$l5u$vMI>9ouxPD^S{5-qvWAprQ>*&?#SpxdJ-SE&Kk2hn zy8lWI>IKrj;hSj%<-bXl8V%B!q_?jcj{k-hy&J%P3vb%^Qfyv08YOw$Qv~F2IOcFi z%I^ScI`VdU!El-&Werf%8X2asF7Tsk7{xt!qlOL$mCejuXC38O9pJ8y|M>$P50HUy zhcG}uKWP7NB@OTY;fq3kG@GPwLy>1x#YEu`vmQ=(0K)g*ckkeaAkM(C2nZ)rJS}8_IMTxIBXH|>190=4 zD%!`?a-E!T;jSVXMP%ETk{4ij&~`Q)&DZieRx)rLfXGfwvm9#PvZgMyX7+TpsoXa= z4Qq583C|0#1W{@tX6kUwtN40v^oyycsiqPP<(V!5f5bA~B0ZGZ{CU#4q>RznC|I_) z7I8BytRK$$wnfi79s*Phn%|0s_u9`zwWi2#=GE5F_sk({H`bq&(QCDy^X97O7~dVV zjm7hN0FhFY>Zr6d?l;%A(Z~&Ew$4)I4_&92>1%LB&Iz>(85AY z;VB`o-(qZZj2^wUL9TY=pDZ9{|L{Rg0eiHZxKR(>6I;B}xV?kpOG_~18o5kM9>bF; zvl22sk@FP)d1Mu!iPBd8n%hqPUH?B{lf+vBfKDaUjH};FB`hI|=TD}i4-Df(W|+FB zCt09JV@dNOy}=s3AS(U4&Ca^LI#IkDbY6-0Iby5ba=y`Wp2hYzhwTE5+|7W}HwTbp z9OzNwQYpe;mIt%rDX*W89h~mxYK3jmf-7Q*)B9kUP?Evo3sn(X81NyML>*eVx+RUlBPA+sDViBwk z7*Dl;#i5JP1+7=3^WriySJy*Ub#&|n!0jaOtW}%-grYW2t+eT{wz)iu1P?+?*78D4 z?m5`fN!6Uv7J4JU)^8tW`D-N9QO%RdtYTA8+bXhEgPf34?k{g{4Tq?|%C$Kz+U{9j z8RcUt*R}dKX*G74+BGaNebZUV{DCm;@U(5XnJYWyX(1gNvxR#br(Qa6)^hmsfX#aR zk+}yFE?Rp5@=+8!0rVoYMrk4eHt6+-pV!|CZFOXL81z;&nOQ!ct!B%hYyCe z$8CC^HadwLAC?`$JgYtvu%$b7`9Y=%pqA!R6Z96z- zLhL(4qE89OG&)oMjo05P>;5?Mp60` zPWdJ5-2@SE9T{-ytDRE{6sX)|Y1X;+C@K>yY^}14Y!088xh~SPfbJG?M1tBi?E>u?zdU>G{5+S>|$%tGJB zQ*X_vOy)g;@fbPm0a(Zh7zTzw2Ct$FB6Gz7!tmK*tZ2h588F#jY1p`jSJMli*7u-; z3tSU(fscAw1h}5i`&i`+?4UAF;AeV|b}3)i5zA^E*L0X|u;#%xYNx~?#g6jEh~;8t zQ8$5Sx)(-Y-j-9ugVW%b2(t*(k6(`>S>s9^t-podjkrgd0G}k7#${=(J0T7``%9)` zbz@# z89pMA4}>(ymEcPbh@I>#D9Az~sbv{(OXEh+fnx{b z6H8ULM@UCCdJbtvxLPl+w?prh49<(wWQ*(&g-1S%fFdrWy;&bp2wdG!zXt0n@O|(h^&64U7Am>%tK&1tn{(CN?9?pRJVbV0abQse6W* zjaunJ1r9_dkDSXE8y~{blX@E9+XdZr?+Cj9fSv4Dr%sM0X8+%}yVNrc%}Pks zfLfd-a~NL@9Ae&`->H9ihbrSTQK7`l0(9ei<9)-C-ZjdIKdOKOVrZbL^1x5+({hmz z^ka^IzOo7Z5kDX{UB^aJa=ZJ664{}im=U8r5}V}6e33gr#%&kPksN&;R!|y`-hx0+!ub!fTfgoWJ@3*jQ48CTp{?Y z$+bKR>!aBjD7x?Y0>>e`M#1*rfv0;edmByS@dJq0U>!j z12B#0J8%)E#AT3Tv<7hwsa2De$TgZ!6ya*gBbt8{dMpCoYg`{48qN!f$4KFI>9kSj zXqP7qQXV6DfRu{Jr(Mj>;=zUW>U{0sd8$z^(2$UE1b=z(K3T=YUsL(r3UwB%vS_@i zUw15;g`ql@wnozVkC>v|rqdrPO1t2>x^$SM@_>ucDEgntIq=60A2|p%szF-JmH5_! z>2S4sVX}c!H;5b!MnOy^fZYTP60VDhA{ikCTh{$>P4GK|N)1u_VGJ22k_IyXwj7Sj zcn5~M5{rQqE`|I<$3Bj`K#{b$K^z(UVwE$D46wB&kBgN&?rjSskPyQ3X&G^Acx^iv zW6lXF-}{o%ux^olbi{%ZmZM_C=6u(%CKQ={xs{jYqD zM26k$`Qj{UlW5Jt`l&1QP|d=7B{Dx;qd$8JdU$AE5&l(!MUkXC0mFRCM3JnDw?zVe z7`mm7)u~!VZs$|ahb9Y>#(9sjOV zcH~0w!lwVVM3oxLQd(|~MDZCpxbXh7qmbj2l;)N4J+?HVc6Jx7LG<@F&tGUvek#38UUOBInuVP22k}b4Ep?bEu^--cB#Ag|hqHNP79!T*v5&|g?2bQG86x5lB{ff(Rjr7|;rT&I0Ef(#dGARy zq-)N|z^0X-fAevH$bL+ip~x^dH#=T?vKN@HF~)7*3?~kd(`GwzGp*%S?H7db>`8F> zgx!tP`bl5-7lQ@AQ4i^?mNUb^ki+(Qvxg{R!^Ut%ya1_K$Ci-wGtO^W+(5We9^Z|i*}v@%bg{vBl7i??boO`xvQUh$k~C|d$i?y7U=W| z!<=;Y;tf9FpB=nOaU(_U#7Npj4id5?8H4? zsL^r@1_p9?VMR4cVe#mEOOH=f?>dB_m{#vzpM&E&KVbxd<&r?NMbz+F*duzV(?Y8LUgUpO4?&3)QPk z5&HoWONJr}EUHfHzJW4vCdqg&<>PN7f)paE#1!i^P<-8JfbLD7%T`A%By{h7P)CAW zJ1E&XBE96%#4a;dwNYQjcdiR0Nxh?uH~|2q&7C9LQ+QSv8X^PP0>Usz*HSS9C0>to ze1pO&s7BCS{x!VW_Pg@E-%TErJGYbnQ2hXL%RBzBNmFecgMmO#_uULhV~c2I)KHP{ zv{Eui!aMjaX?Mf>WoHp0KtGR^e4E^69*4@*{%8^>HwxUFNcSt7W0h7X$VzQ5JTGQg zLpd?yN%(bgiP_o-cst z@QA_VD0&n&*dj?j63J-vndy~X;lwmo=Q_8PV#w^VZOiYw;}mS|B;|u)e#GS8JRqxP zoWEuBMb#F=PknRG3P* z4GJA~MMpEbM%i4(YahXGEOSo2nB;oM z*5&1O`U}@hdRDps0PqD~2c@$6cz7sxmZ+b)O!Nllqto*I#I^<9nQ}0`3gtZjgFSc` zr<;IuXQCn=vP25FV3h8Z+}TdG6Sel7VCP+9#!U`9SHR~u*QtV&Ir;S6Z^sSGm|s;y z-f{CTn7y-&!B@eo#~6{h(77Nh6dHLyQG)b$p_3Gj)aRs!q6N>lUC*~^HSvWstrW}u z*CU=O3^xF*0&%aIQS)f~p!Vfgr70q9_)Pqs1=T}zL2n7bM8o8g#*F|Q%n>{#zGI3aoM5ptgqb|5#Q0-fuPveFm}*t#6J>nQI?04W zddadPl-27!^`1tRpwAVEqlr1diwI*)RCifevrPbt5Gp@fxs&zT5 zsb*ne&_BG~c(7H^P%7ADWn2!iMjp*h2XH3HT6VU72#$t`4=n-ZMCj(Lx2fTA@Q*v3DH1nr6oj-PQmZ9zCOcnn|~y1H8R1_aO#cRLv8n zA^SQ>qnD0V>X0{ZGw#)({*;uB(U$-bb3>y#gPQ0j{V0TAh2!q01pnET-gA>Z&%Zu& z{QmIumszVzi2m>gDlumvArvK|eWjErehNwr_*YQB+{U0n2iH{TJ z;qL1>Q|tNR;tK>w-Y~Xr!pxa~?@n`+EF(yvE$iV|s+c}C9kp5-ApELWNNyD z|D+=Q7PY%KH^%y&U#ewXB(vfZd=y2g6mLmY^!M=zO*K@jEGVFm+gRBYv6`7`j!j#_ z9w|2DzzCJJ^>~J#5j;E8*py74CK@&dIy0mkEqwTPE}}scXFHs_!v+39v(Q!~u%}FWO}FpFHX>#>99{bVQXu z&Mv05icalrL5O4IcpQ-%8V0q0)*4^oV6E1=wCFNkQG8D|Vcl#K3ekLmEmuno2}tcn+QcBWaoDND z?$>_WkP~3jJBVSpFIV5PxKA;nAt-PpDTxDvS|U0B~sCx$DrPuUWy1s-9;QX4FU@5U37&vhcuXyFpWC$dZ2bo2M?j zANK_Zrju>J;S;e;$Q-lXs>AJ;X+V(MnIVQV<}7RvF2tip0dAnk>SJRl?)-~WoU!77 zQ=Tzv)wwG*H6)RHIJxxBSAnc$34YukwX=MWwb+&MO&{6*3?R8{8xnSKM?Fx^SIqyB zbIrq9*-wfEPB-!(hD)U;417Yhr*_v$3yfCOLjgK9ct=m3wC4po@*K`;f?423NQ%Ha z=HQfTdxjl&#yC@aA?gUOwDc`m_JtKN%GtmX{+jhTzM{j)Zz!HLVWS zT3ud61ZuseM>#VB zB1v^H3>~f3ZuQ1y1W{>t-Z=ZAh`cL8Ph>}_y|h?Wg&}{_PP-`L`oK-Ig}U9hdlkA` zD(w7nYK?aP_vu?cAgjvw$DWY~|Nr`6dn+Ike-c>$`F=-2aTLj*LyZCcadEaCUHG~; z86DPAtoK5nu-&tR!-E*UKmtjQ&F-bed^U;yv{`=a-Q3MyR&EFcei`C7LwUEikDKv_ z{n2hUv{KSVf+2Ghr?p6~s8Uo}UNjM-Va{4f?=S0P)GQHiP&5mMDO6_~Oh#6NWhYTD zHVIY-Br?zR-A}*_d1E(u4)4jZiSX;qv}@p<)$5PHa8uof$- zN#h;PX!Sh`GyKY@#3`XavDTF!tlLp7pOnP|n7ydSTSeRN`9lT0{FsiXdyibTb1c%L zVA^GmC!c-pE7zzK?fNiiRLgGuZTzKsr@X+hJ&sngBnxa3+bfw(?G&G3Q%W|MUt{C{~s zF!W;nx?2MjfY!+%*n5u;$!Pee07wYZ@g^V02=j281Q-OI#l0q(9<@WCr<;o4(a|TM zH_t`S9?g&v-JRw*Z;u>5#?|UTBD=ggqWPrGOk$%Eut6-?OV>%E(R=5l*y|X#64&>rZ z#W3LPCfr7TgzQ0(qgidWUQd+uWMCx7o zEB>|%Jj&TVz$-D|qVAVU4!CF!@J}!yxFe4cX8SF|Y-XBWZzD>se-R!+{t?Wh6=}E7 zVI*Eoa1su_6K2`e8XfsS4OJM|U+&-7VS zIRJ0}JFs%}kcBm|$KkOHXW8Yj-C+KS#mq``V56%9am)P^?MzJPWU+*SyoQeWkRCz< zQ&Lq-Q>VTUJh=@7B#nHSC6HUHAey1!j}y>tP-yPh!o;992`-QHd7AI5t9 zPzm;}i0kMO6~Kl4TT`Y-BTU9Ku;r}*Q1TDl8m%S{+PFzk4&HGip;0#LkTx>X5q%>5 zvea2A%tl(PyC6CoWZ>)xHQQMu6n`UxQHJwS^%+zbld7C*CafaNLfh=(7&7eb)>jvC znLDJo2#ICn^BvWW7|$|a>!k)dOwPL;_Ao<@lzuJMoVs>;vkRhel4yyS2) zNMgz=@z?&pdF|R2kYSCb~_c?Vn#f0va))?V7TyrsA4t^o14=CVLW+YJt zornR!@R}SEh5X@8Mecwsv4(I7&TsC{FBAkUqM~hI4`ElK`EdgmwXTtz>9XPZVjTba zBi?BtsK{w&VnIK?b}XqbS5ujgFthngi(n$Qf0!GV*Ck3#A5=c-XwE4I2shGOBSw|T zij+DsI~26%8A9#jM#!kkG4k(|p=DlNOtp$^w;d!`3Z6v)Np-zYDWC&3J{ zwaUiwtA2L~pTeKQ%+q-puz^>p5WizwIVWT}a7;I6vmOl}V!9x!Q0+N)w0dK<>Zy?Q zIMqMK-zUY;#%$)=v;*}7l%0g)L@qrQ%(KKJ+7(26naCnPXDl!4!)l8vCvdPEi@Jw* z|6Y0vPmvHvkk-$$00p5yRzY+{Zx>_nKI_Xh)l_9kFz3dgjETw(U=}g;=}5EaiyMu4 z_K5!H6(p54QnUJxGgc8!K#+;aOOofhNq5c;z10R2IrtP1H4@T9A)rjBp`BPHrYhlL z+@cieQ3~0svr%Pi6*}fPW-L9x=CjjPl73d0y^9szowR56%tm}k>B)RtEMvOL*=5n6 z-O4NJdBneKC@(Ak6105naj(;SX_5pO7!J@7^!qDe`+jzeJ|J9eMX~dq_a4ty_&9?( zEDkVKBj$N0>Ka>58Y|PQq{Q2j-1e%45yo0bM~*k}vj%t;)h4!(={qG%V1_LSFm}aK zY-tE~MG&?}B;H1))pTEj@~LYqj3<1_=`$4^b24-b8Y}Do-qUr>x|NiG?ruc-9+TCz z;?EP^qy0SZdX`9sh!jt2^KgHyRrl?I`X8rO z8NK~qffuwrcv^i<^-sN;(~rF>En&Wk(?xUpXJ1i$BT!_#xy7-)Kt@ezB>Cmr;5qh^mji@urT}VzT*Om+_r%F`x$OqeakZ|EVfr%`L5IZXlLN1Lx$X$ z+~*?=bbBH!DkWE20Z&N_tCU_B5$>9N<-1b_)B4t9h0o5Fdg(TV#T=ZS;k;e9y5Pt( zcf%BKR`r}pq4b=}Y5!VT0!2?uu5S_u400^GsdDb9m9+E0!adTPK5T5=_*&)oy9xJV zF2%9jIC6B{IhfKk_L`{##PdAGvbj`=i^IWZR_QpWl7Pcg=0JJdXRWYv_wxuM9&rzRW2JGR-w|x_nY#<=SNhGv@xPUGak-)N>My zOneaxybJRv4`{BQkx7I>1a{^b!-nmXAIx>-%-v{b>i|3i&3>}pJSUmS2~`n_z^+yS z5F0W84=jO$-F%Y+=gUmi<5!s6KVLxR@N}V>dBECiGq5qIhN93#0IX18zN$3hPIm?d zV-!XFlLO}a%OLKmW?-;Ek-sboG(;JA1H1~@Hsm`!ZBY~!NrDxAkW>XLMBK-SZsJh| zutEn#h>3_B?HCwPO>9vHDV(GNHjo8$f7;~2gO;L~=q~SL-0fWZ~#j)X&6Bqf(AYY$jk0PJ03wGnXMds4rYbk)o%O?X5s6!3k zfXNPvon#Tm&!fx7m@-U0Xlej*iY)lxbYN7j0b(5#t3F$TR4GoDU7{+BI87QonpRme zOct=Q1)0SHI@Eabh9zRm!uB9RsmW9A4Z;2eABzjLU@_3Yb|{tzO}1YeB?~&EwGSvS z2b9-Gk@s+Bn7q;166{pOsgw*1jwq^ZTtTWtCL1hsmqk9p&jdx)T@RQl&dDjBieNJl zr|tj``9o2y>jP8GF7ag{X4W>)a%KhoKvyva1`M9A)97C%`B`O-U1bAu471WI(n_BRXdc33Qc~vQcM(m z%*7)yFC}Mk;$lTsaNBmW!75Q^;mHs)A-y`Vxw6QmkOqpmsncMpwYY?M85qRpg322J DDw4oP diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 9355b415..ff23a68d 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.2-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index f5feea6d..23d15a93 100755 --- a/gradlew +++ b/gradlew @@ -86,8 +86,7 @@ done # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s -' "$PWD" ) || exit +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -115,7 +114,7 @@ case "$( uname )" in #( NONSTOP* ) nonstop=true ;; esac -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar +CLASSPATH="\\\"\\\"" # Determine the Java command to use to start the JVM. @@ -206,7 +205,7 @@ fi DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Collect all arguments for the java command: -# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, # and any embedded shellness will be escaped. # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be # treated as '${Hostname}' itself on the command line. @@ -214,7 +213,7 @@ DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ "$@" # Stop when "xargs" is not available. diff --git a/gradlew.bat b/gradlew.bat index 9b42019c..5eed7ee8 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -70,11 +70,11 @@ goto fail :execute @rem Setup the command line -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar +set CLASSPATH= @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* :end @rem End local scope for the variables with windows NT shell From 4495da6b8704035486b377420d8b962d022bc1d3 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Tue, 29 Jul 2025 12:09:45 +0900 Subject: [PATCH 326/426] more readme updates, installation instruction for all (#331) --- README.md | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 73 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index f9f4ca3f..940b478c 100644 --- a/README.md +++ b/README.md @@ -62,22 +62,65 @@ Required language/runtime versions: This project contains multiple builds, living side by side together. -Depending on which part you are developing, you may want to run just the swift tests: +You will need to have: +- Swift (6.1.x+) +- Java (24+ for FFM, even though we support lower JDK targets) +- Gradle (installed by "Gradle wrapper" automatically when you run gradle through `./gradlew`) + +### Preparing your environment + +Install **Swift**, the easiest way to do this is to use **Swiftly**: [swift.org/install/](https://www.swift.org/install/). +This should automatically install a recent Swift, but you can always make sure by running: + +```bash +swiftly install 6.1.2 --use +``` + +Install a recent enough Java distribution. We validate this project using Corretto so you can choose to use that as well, +however any recent enough Java distribution should work correctly. You can use sdkman to install Java: + +```bash +# Install sdkman from: https://sdkman.io +curl -s "https://get.sdkman.io" | bash +sdk install java 17.0.15-amzn +sdk install java 24.0.1-amzn + +sdk use java 24.0.1-amzn +``` + +The use of JDK 24 is required to build the project, even though the libraries being published may target lower Java versions. + +❗️ Please make sure to `export JAVA_HOME` such that swift-java can find the necessary java libraries! +When using sdkman the easiest way to export JAVA_HOME is to export the "current" used JDK's home, like this: + +```bash +export JAVA_HOME="$(sdk home java current) +``` + +### Testing your changes + +Many tests, including source generation tests, are written in Swift and you can execute them all by running the +swift package manager test command: ```bash > swift test ``` -or the Java tests through the Gradle build. The Gradle build may also trigger some Swift compilation because of -interlinked dependencies of the two parts of Swift-Java. To run the Java build and tests use the Gradle wrapper script: +When adding tests in `Tests/...` targets, you can run these tests (or filter a specific test using `swift test --filter type-or-method-name`). + +Some tests are implemented in Java and therefore need to be executed using Gradle. +Please always use the gradle wrapper (`./gradlew`) to make sure to use the appropriate Gradle version ```bash > ./gradlew test ``` -Currently it is suggested to use Swift 6.0 and a Java 24+. +> Tip: A lot of the **runtime tests** for code relying on `jextract` are **located in sample apps**, +> so if you need to runtime test any code relying on source generation steps of jextract, consider adding the tests +> to an appropriate Sample. These tests are also executed in CI (which you can check in the `ci-validate.sh` script +> contained in every sample repository). -### Sample Apps +### Sample apps & tests Sample apps are located in the `Samples/` directory, and they showcase full "roundtrip" usage of the library and/or tools. @@ -101,12 +144,18 @@ To run a simple example app showcasing the jextract (Java calling Swift) approac This will also generate the necessary sources (by invoking jextract, extracting the `Sources/ExampleSwiftLibrary`) and generating Java sources in `src/generated/java`. +#### Other sample apps + +Please refer to the [Samples](Samples) directory for more sample apps which showcase the various usage modes of swift-java. + ## Benchmarks You can run Swift [ordo-one/package-benchmark](https://github.com/ordo-one/package-benchmark) and OpenJDK [JMH](https://github.com/openjdk/jmh) benchmarks in this project. Swift benchmarks are located under `Benchmarks/` and JMH benchmarks are currently part of the SwiftKit sample project: `Samples/SwiftKitSampleApp/src/jmh` because they depend on generated sources from the sample. +### Swift benchmarks + To run **Swift benchmarks** you can: ```bash @@ -114,6 +163,8 @@ cd Benchmarks swift package benchmark ``` +### Java benchmarks + In order to run JMH benchmarks you can: ```bash @@ -125,4 +176,20 @@ Please read documentation of both performance testing tools and understand that ## User Guide -More details about the project and how it can be used are available in [USER_GUIDE.md](USER_GUIDE.md) +More details about the project can be found in [docc](https://www.swift.org/documentation/docc/) documentation. + +To view the rendered docc documentation you can use the docc preview command: + +```bash +xcrun docc preview Sources/SwiftJavaDocumentation/Documentation.docc + +# OR JavaKit to view JavaKit documentation: +# xcrun docc preview Sources/JavaKit/Documentation.docc + +# ======================================== +# Starting Local Preview Server +# Address: http://localhost:8080/documentation/documentation +# ======================================== +# Monitoring /Users/ktoso/code/swift-java/Sources/SwiftJavaDocumentation/Documentation.docc for changes... + +``` From 7f24d6276f59c34544a4c8f6771a8bc560aa5db9 Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Wed, 30 Jul 2025 19:51:11 -0700 Subject: [PATCH 327/426] [JExtract] Translate generic parameters (#336) * Integrate `SwiftLexicalLookup` for unqualified type lookups * Introduce `SwiftTypeLookupContext` as a facade for `SwiftLexicalLookup` and a cached conversion from Syntax to `SwiftTypeDeclaration` instance. This wraps and replaces `SwiftSymbolTable`. * Introduce `SwiftGenericParameterDeclration` as a subclass of `SwiftTypeDeclaration` to represent generic parameters. * Store generic parameters and requirements in `SwiftFunctionSignature`. * `SwiftType.representativeConcreteTypeIn()` for getting `Data` from `T: DataProtocol` type. --- Package.swift | 1 + .../FFM/CDeclLowering/CRepresentation.swift | 4 +- ...Swift2JavaGenerator+FunctionLowering.swift | 75 ++++----- ...MSwift2JavaGenerator+JavaTranslation.swift | 81 ++++++---- ...ift2JavaGenerator+SwiftThunkPrinting.swift | 2 +- .../FFM/FFMSwift2JavaGenerator.swift | 4 +- ...ISwift2JavaGenerator+JavaTranslation.swift | 4 +- ...wift2JavaGenerator+NativeTranslation.swift | 8 +- .../Swift2JavaTranslator.swift | 16 +- .../JExtractSwiftLib/Swift2JavaVisitor.swift | 6 +- .../SwiftTypes/SwiftFunctionSignature.swift | 133 +++++++++++---- .../SwiftTypes/SwiftFunctionType.swift | 6 +- .../SwiftNominalTypeDeclaration.swift | 46 ++++-- .../SwiftTypes/SwiftParameter.swift | 4 +- .../SwiftParsedModuleSymbolTableBuilder.swift | 3 +- ...wiftType+RepresentativeConcreteeType.swift | 65 ++++++++ .../SwiftTypes/SwiftType.swift | 85 ++++++---- .../SwiftTypes/SwiftTypeLookupContext.swift | 151 ++++++++++++++++++ .../Asserts/TextAssertions.swift | 1 + .../JExtractSwiftTests/DataImportTests.swift | 29 ++-- .../FunctionLoweringTests.swift | 21 +++ 21 files changed, 567 insertions(+), 178 deletions(-) create mode 100644 Sources/JExtractSwiftLib/SwiftTypes/SwiftType+RepresentativeConcreteeType.swift create mode 100644 Sources/JExtractSwiftLib/SwiftTypes/SwiftTypeLookupContext.swift diff --git a/Package.swift b/Package.swift index 84b348c5..51608c31 100644 --- a/Package.swift +++ b/Package.swift @@ -422,6 +422,7 @@ let package = Package( name: "JExtractSwiftLib", dependencies: [ .product(name: "SwiftBasicFormat", package: "swift-syntax"), + .product(name: "SwiftLexicalLookup", package: "swift-syntax"), .product(name: "SwiftSyntax", package: "swift-syntax"), .product(name: "SwiftSyntaxBuilder", package: "swift-syntax"), .product(name: "ArgumentParser", package: "swift-argument-parser"), diff --git a/Sources/JExtractSwiftLib/FFM/CDeclLowering/CRepresentation.swift b/Sources/JExtractSwiftLib/FFM/CDeclLowering/CRepresentation.swift index c2bb53ab..d2a71def 100644 --- a/Sources/JExtractSwiftLib/FFM/CDeclLowering/CRepresentation.swift +++ b/Sources/JExtractSwiftLib/FFM/CDeclLowering/CRepresentation.swift @@ -68,7 +68,7 @@ extension CType { case .optional(let wrapped) where wrapped.isPointer: try self.init(cdeclType: wrapped) - case .metatype, .optional, .tuple, .opaque, .existential: + case .genericParameter, .metatype, .optional, .tuple, .opaque, .existential: throw CDeclToCLoweringError.invalidCDeclType(cdeclType) } } @@ -98,7 +98,7 @@ extension CFunction { enum CDeclToCLoweringError: Error { case invalidCDeclType(SwiftType) - case invalidNominalType(SwiftNominalTypeDeclaration) + case invalidNominalType(SwiftTypeDeclaration) case invalidFunctionConvention(SwiftFunctionType) } diff --git a/Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift b/Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift index bb994164..085a6331 100644 --- a/Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift +++ b/Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift @@ -26,10 +26,10 @@ extension FFMSwift2JavaGenerator { ) throws -> LoweredFunctionSignature { let signature = try SwiftFunctionSignature( decl, - enclosingType: try enclosingType.map { try SwiftType($0, symbolTable: symbolTable) }, - symbolTable: symbolTable + enclosingType: try enclosingType.map { try SwiftType($0, lookupContext: lookupContext) }, + lookupContext: lookupContext ) - return try CdeclLowering(symbolTable: symbolTable).lowerFunctionSignature(signature) + return try CdeclLowering(symbolTable: lookupContext.symbolTable).lowerFunctionSignature(signature) } /// Lower the given initializer to a C-compatible entrypoint, @@ -42,11 +42,11 @@ extension FFMSwift2JavaGenerator { ) throws -> LoweredFunctionSignature { let signature = try SwiftFunctionSignature( decl, - enclosingType: try enclosingType.map { try SwiftType($0, symbolTable: symbolTable) }, - symbolTable: symbolTable + enclosingType: try enclosingType.map { try SwiftType($0, lookupContext: lookupContext) }, + lookupContext: lookupContext ) - return try CdeclLowering(symbolTable: symbolTable).lowerFunctionSignature(signature) + return try CdeclLowering(symbolTable: lookupContext.symbolTable).lowerFunctionSignature(signature) } /// Lower the given variable decl to a C-compatible entrypoint, @@ -66,10 +66,10 @@ extension FFMSwift2JavaGenerator { let signature = try SwiftFunctionSignature( decl, isSet: isSet, - enclosingType: try enclosingType.map { try SwiftType($0, symbolTable: symbolTable) }, - symbolTable: symbolTable + enclosingType: try enclosingType.map { try SwiftType($0, lookupContext: lookupContext) }, + lookupContext: lookupContext ) - return try CdeclLowering(symbolTable: symbolTable).lowerFunctionSignature(signature) + return try CdeclLowering(symbolTable: lookupContext.symbolTable).lowerFunctionSignature(signature) } } @@ -98,7 +98,9 @@ struct CdeclLowering { try lowerParameter( selfParameter.type, convention: selfParameter.convention, - parameterName: selfParameter.parameterName ?? "self" + parameterName: selfParameter.parameterName ?? "self", + genericParameters: signature.genericParameters, + genericRequirements: signature.genericRequirements ) case nil, .initializer(_), .staticMethod(_): nil @@ -106,10 +108,12 @@ struct CdeclLowering { // Lower all of the parameters. let loweredParameters = try signature.parameters.enumerated().map { (index, param) in - try lowerParameter( + return try lowerParameter( param.type, convention: param.convention, - parameterName: param.parameterName ?? "_\(index)" + parameterName: param.parameterName ?? "_\(index)", + genericParameters: signature.genericParameters, + genericRequirements: signature.genericRequirements ) } @@ -142,7 +146,9 @@ struct CdeclLowering { func lowerParameter( _ type: SwiftType, convention: SwiftParameterConvention, - parameterName: String + parameterName: String, + genericParameters: [SwiftGenericParameterDeclaration], + genericRequirements: [SwiftGenericRequirement] ) throws -> LoweredParameter { // If there is a 1:1 mapping between this Swift type and a C type, we just // return it. @@ -257,7 +263,7 @@ struct CdeclLowering { guard let genericArgs = nominal.genericArguments, genericArgs.count == 1 else { throw LoweringError.unhandledType(type) } - return try lowerOptionalParameter(genericArgs[0], convention: convention, parameterName: parameterName) + return try lowerOptionalParameter(genericArgs[0], convention: convention, parameterName: parameterName, genericParameters: genericParameters, genericRequirements: genericRequirements) case .string: // 'String' is passed in by C string. i.e. 'UnsafePointer' ('const uint8_t *') @@ -300,7 +306,7 @@ struct CdeclLowering { case .tuple(let tuple): if tuple.count == 1 { - return try lowerParameter(tuple[0], convention: convention, parameterName: parameterName) + return try lowerParameter(tuple[0], convention: convention, parameterName: parameterName, genericParameters: genericParameters, genericRequirements: genericRequirements) } if convention == .inout { throw LoweringError.inoutNotSupported(type) @@ -310,7 +316,7 @@ struct CdeclLowering { for (idx, element) in tuple.enumerated() { // FIXME: Use tuple element label. let cdeclName = "\(parameterName)_\(idx)" - let lowered = try lowerParameter(element, convention: convention, parameterName: cdeclName) + let lowered = try lowerParameter(element, convention: convention, parameterName: cdeclName, genericParameters: genericParameters, genericRequirements: genericRequirements) parameters.append(contentsOf: lowered.cdeclParameters) conversions.append(lowered.conversion) @@ -330,20 +336,14 @@ struct CdeclLowering { conversion: conversion ) - case .opaque(let proto), .existential(let proto): - // If the protocol has a known representative implementation, e.g. `String` for `StringProtocol` - // Translate it as the concrete type. - // NOTE: This is a temporary workaround until we add support for generics. - if - let knownProtocol = proto.asNominalTypeDeclaration?.knownTypeKind, - let concreteTy = knownTypes.representativeType(of: knownProtocol) - { - return try lowerParameter(concreteTy, convention: convention, parameterName: parameterName) + case .opaque, .existential, .genericParameter: + if let concreteTy = type.representativeConcreteTypeIn(knownTypes: knownTypes, genericParameters: genericParameters, genericRequirements: genericRequirements) { + return try lowerParameter(concreteTy, convention: convention, parameterName: parameterName, genericParameters: genericParameters, genericRequirements: genericRequirements) } throw LoweringError.unhandledType(type) case .optional(let wrapped): - return try lowerOptionalParameter(wrapped, convention: convention, parameterName: parameterName) + return try lowerOptionalParameter(wrapped, convention: convention, parameterName: parameterName, genericParameters: genericParameters, genericRequirements: genericRequirements) } } @@ -354,7 +354,9 @@ struct CdeclLowering { func lowerOptionalParameter( _ wrappedType: SwiftType, convention: SwiftParameterConvention, - parameterName: String + parameterName: String, + genericParameters: [SwiftGenericParameterDeclaration], + genericRequirements: [SwiftGenericRequirement] ) throws -> LoweredParameter { // If there is a 1:1 mapping between this Swift type and a C type, lower it to 'UnsafePointer?' if let _ = try? CType(cdeclType: wrappedType) { @@ -398,18 +400,15 @@ struct CdeclLowering { conversion: .pointee(.typedPointer(.optionalChain(.placeholder), swiftType: wrappedType)) ) - case .existential(let proto), .opaque(let proto): - if - let knownProtocol = proto.asNominalTypeDeclaration?.knownTypeKind, - let concreteTy = knownTypes.representativeType(of: knownProtocol) - { - return try lowerOptionalParameter(concreteTy, convention: convention, parameterName: parameterName) + case .existential, .opaque, .genericParameter: + if let concreteTy = wrappedType.representativeConcreteTypeIn(knownTypes: knownTypes, genericParameters: genericParameters, genericRequirements: genericRequirements) { + return try lowerOptionalParameter(concreteTy, convention: convention, parameterName: parameterName, genericParameters: genericParameters, genericRequirements: genericRequirements) } throw LoweringError.unhandledType(.optional(wrappedType)) case .tuple(let tuple): if tuple.count == 1 { - return try lowerOptionalParameter(tuple[0], convention: convention, parameterName: parameterName) + return try lowerOptionalParameter(tuple[0], convention: convention, parameterName: parameterName, genericParameters: genericParameters, genericRequirements: genericRequirements) } throw LoweringError.unhandledType(.optional(wrappedType)) @@ -514,7 +513,7 @@ struct CdeclLowering { // Custom types are not supported yet. throw LoweringError.unhandledType(type) - case .function, .metatype, .optional, .tuple, .existential, .opaque: + case .genericParameter, .function, .metatype, .optional, .tuple, .existential, .opaque: // TODO: Implement throw LoweringError.unhandledType(type) } @@ -668,7 +667,7 @@ struct CdeclLowering { conversion: .tupleExplode(conversions, name: outParameterName) ) - case .function, .optional, .existential, .opaque: + case .genericParameter, .function, .optional, .existential, .opaque: throw LoweringError.unhandledType(type) } } @@ -754,7 +753,9 @@ public struct LoweredFunctionSignature: Equatable { selfParameter: nil, parameters: allLoweredParameters, result: SwiftResult(convention: .direct, type: result.cdeclResultType), - effectSpecifiers: [] + effectSpecifiers: [], + genericParameters: [], + genericRequirements: [] ) } } diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift index 9f658188..b29ca5d9 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift @@ -24,7 +24,7 @@ extension FFMSwift2JavaGenerator { let translated: TranslatedFunctionDecl? do { - let translation = JavaTranslation(symbolTable: self.symbolTable) + let translation = JavaTranslation(knownTypes: SwiftKnownTypes(symbolTable: lookupContext.symbolTable)) translated = try translation.translate(decl) } catch { self.log.info("Failed to translate: '\(decl.swiftDecl.qualifiedNameForDebug)'; \(error)") @@ -115,8 +115,8 @@ extension FFMSwift2JavaGenerator { struct JavaTranslation { var knownTypes: SwiftKnownTypes - init(symbolTable: SwiftSymbolTable) { - self.knownTypes = SwiftKnownTypes(symbolTable: symbolTable) + init(knownTypes: SwiftKnownTypes) { + self.knownTypes = knownTypes } func translate( @@ -256,7 +256,9 @@ extension FFMSwift2JavaGenerator { convention: swiftSelf.convention, parameterName: swiftSelf.parameterName ?? "self", loweredParam: loweredFunctionSignature.selfParameter!, - methodName: methodName + methodName: methodName, + genericParameters: swiftSignature.genericParameters, + genericRequirements: swiftSignature.genericRequirements ) } else { selfParameter = nil @@ -272,7 +274,9 @@ extension FFMSwift2JavaGenerator { convention: swiftParam.convention, parameterName: parameterName, loweredParam: loweredParam, - methodName: methodName + methodName: methodName, + genericParameters: swiftSignature.genericParameters, + genericRequirements: swiftSignature.genericRequirements ) } @@ -295,7 +299,9 @@ extension FFMSwift2JavaGenerator { convention: SwiftParameterConvention, parameterName: String, loweredParam: LoweredParameter, - methodName: String + methodName: String, + genericParameters: [SwiftGenericParameterDeclaration], + genericRequirements: [SwiftGenericRequirement] ) throws -> TranslatedParameter { // If there is a 1:1 mapping between this Swift type and a C type, that can @@ -352,7 +358,15 @@ extension FFMSwift2JavaGenerator { guard let genericArgs = swiftNominalType.genericArguments, genericArgs.count == 1 else { throw JavaTranslationError.unhandledType(swiftType) } - return try translateOptionalParameter(wrappedType: genericArgs[0], convention: convention, parameterName: parameterName, loweredParam: loweredParam, methodName: methodName) + return try translateOptionalParameter( + wrappedType: genericArgs[0], + convention: convention, + parameterName: parameterName, + loweredParam: loweredParam, + methodName: methodName, + genericParameters: genericParameters, + genericRequirements: genericRequirements + ) case .string: return TranslatedParameter( @@ -399,20 +413,16 @@ extension FFMSwift2JavaGenerator { conversion: .call(.placeholder, function: "\(methodName).$toUpcallStub", withArena: true) ) - case .existential(let proto), .opaque(let proto): - // If the protocol has a known representative implementation, e.g. `String` for `StringProtocol` - // Translate it as the concrete type. - // NOTE: This is a temporary workaround until we add support for generics. - if - let knownProtocol = proto.asNominalTypeDeclaration?.knownTypeKind, - let concreteTy = knownTypes.representativeType(of: knownProtocol) - { + case .existential, .opaque, .genericParameter: + if let concreteTy = swiftType.representativeConcreteTypeIn(knownTypes: knownTypes, genericParameters: genericParameters, genericRequirements: genericRequirements) { return try translateParameter( type: concreteTy, convention: convention, parameterName: parameterName, loweredParam: loweredParam, - methodName: methodName + methodName: methodName, + genericParameters: genericParameters, + genericRequirements: genericRequirements ) } @@ -420,7 +430,15 @@ extension FFMSwift2JavaGenerator { throw JavaTranslationError.unhandledType(swiftType) case .optional(let wrapped): - return try translateOptionalParameter(wrappedType: wrapped, convention: convention, parameterName: parameterName, loweredParam: loweredParam, methodName: methodName) + return try translateOptionalParameter( + wrappedType: wrapped, + convention: convention, + parameterName: parameterName, + loweredParam: loweredParam, + methodName: methodName, + genericParameters: genericParameters, + genericRequirements: genericRequirements + ) } } @@ -430,12 +448,14 @@ extension FFMSwift2JavaGenerator { convention: SwiftParameterConvention, parameterName: String, loweredParam: LoweredParameter, - methodName: String + methodName: String, + genericParameters: [SwiftGenericParameterDeclaration], + genericRequirements: [SwiftGenericRequirement] ) throws -> TranslatedParameter { // If there is a 1:1 mapping between this Swift type and a C type, that can // be expressed as a Java primitive type. if let cType = try? CType(cdeclType: swiftType) { - var (translatedClass, lowerFunc) = switch cType.javaType { + let (translatedClass, lowerFunc) = switch cType.javaType { case .int: ("OptionalInt", "toOptionalSegmentInt") case .long: ("OptionalLong", "toOptionalSegmentLong") case .double: ("OptionalDouble", "toOptionalSegmentDouble") @@ -473,23 +493,30 @@ extension FFMSwift2JavaGenerator { ], conversion: .call(.placeholder, function: "SwiftRuntime.toOptionalSegmentInstance", withArena: false) ) - case .existential(let proto), .opaque(let proto): - if - let knownProtocol = proto.asNominalTypeDeclaration?.knownTypeKind, - let concreteTy = knownTypes.representativeType(of: knownProtocol) - { + case .existential, .opaque, .genericParameter: + if let concreteTy = swiftType.representativeConcreteTypeIn(knownTypes: knownTypes, genericParameters: genericParameters, genericRequirements: genericRequirements) { return try translateOptionalParameter( wrappedType: concreteTy, convention: convention, parameterName: parameterName, loweredParam: loweredParam, - methodName: methodName + methodName: methodName, + genericParameters: genericParameters, + genericRequirements: genericRequirements ) } throw JavaTranslationError.unhandledType(.optional(swiftType)) case .tuple(let tuple): if tuple.count == 1 { - return try translateOptionalParameter(wrappedType: tuple[0], convention: convention, parameterName: parameterName, loweredParam: loweredParam, methodName: methodName) + return try translateOptionalParameter( + wrappedType: tuple[0], + convention: convention, + parameterName: parameterName, + loweredParam: loweredParam, + methodName: methodName, + genericParameters: genericParameters, + genericRequirements: genericRequirements + ) } throw JavaTranslationError.unhandledType(.optional(swiftType)) default: @@ -580,7 +607,7 @@ extension FFMSwift2JavaGenerator { // TODO: Implement. throw JavaTranslationError.unhandledType(swiftType) - case .optional, .function, .existential, .opaque: + case .genericParameter, .optional, .function, .existential, .opaque: throw JavaTranslationError.unhandledType(swiftType) } diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+SwiftThunkPrinting.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+SwiftThunkPrinting.swift index 10dab4b9..1e32d1e5 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+SwiftThunkPrinting.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+SwiftThunkPrinting.swift @@ -125,7 +125,7 @@ extension FFMSwift2JavaGenerator { } func printSwiftThunkImports(_ printer: inout CodePrinter) { - for module in self.symbolTable.importedModules.keys.sorted() { + for module in self.lookupContext.symbolTable.importedModules.keys.sorted() { guard module != "Swift" else { continue } diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift index a24dabb1..d30d3e74 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift @@ -24,7 +24,7 @@ package class FFMSwift2JavaGenerator: Swift2JavaGenerator { let javaPackage: String let swiftOutputDirectory: String let javaOutputDirectory: String - let symbolTable: SwiftSymbolTable + let lookupContext: SwiftTypeLookupContext var javaPackagePath: String { javaPackage.replacingOccurrences(of: ".", with: "/") @@ -51,7 +51,7 @@ package class FFMSwift2JavaGenerator: Swift2JavaGenerator { self.javaPackage = javaPackage self.swiftOutputDirectory = swiftOutputDirectory self.javaOutputDirectory = javaOutputDirectory - self.symbolTable = translator.symbolTable + self.lookupContext = translator.lookupContext // If we are forced to write empty files, construct the expected outputs if translator.config.writeEmptyFiles ?? false { diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift index 57ea15b2..8d18e6ae 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift @@ -216,7 +216,7 @@ extension JNISwift2JavaGenerator { conversion: .placeholder ) - case .metatype, .optional, .tuple, .existential, .opaque: + case .metatype, .optional, .tuple, .existential, .opaque, .genericParameter: throw JavaTranslationError.unsupportedSwiftType(swiftType) } } @@ -251,7 +251,7 @@ extension JNISwift2JavaGenerator { case .tuple([]): return TranslatedResult(javaType: .void, conversion: .placeholder) - case .metatype, .optional, .tuple, .function, .existential, .opaque: + case .metatype, .optional, .tuple, .function, .existential, .opaque, .genericParameter: throw JavaTranslationError.unsupportedSwiftType(swiftResult.type) } } diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift index 5ccefadb..48a6e8d4 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift @@ -129,7 +129,7 @@ extension JNISwift2JavaGenerator { ) ) - case .metatype, .optional, .tuple, .existential, .opaque: + case .metatype, .optional, .tuple, .existential, .opaque, .genericParameter: throw JavaTranslationError.unsupportedSwiftType(swiftParameter.type) } } @@ -160,7 +160,7 @@ extension JNISwift2JavaGenerator { conversion: .placeholder ) - case .function, .metatype, .optional, .tuple, .existential, .opaque: + case .function, .metatype, .optional, .tuple, .existential, .opaque, .genericParameter: throw JavaTranslationError.unsupportedSwiftType(type) } } @@ -187,7 +187,7 @@ extension JNISwift2JavaGenerator { // Custom types are not supported yet. throw JavaTranslationError.unsupportedSwiftType(type) - case .function, .metatype, .optional, .tuple, .existential, .opaque: + case .function, .metatype, .optional, .tuple, .existential, .opaque, .genericParameter: throw JavaTranslationError.unsupportedSwiftType(type) } } @@ -223,7 +223,7 @@ extension JNISwift2JavaGenerator { conversion: .placeholder ) - case .metatype, .optional, .tuple, .function, .existential, .opaque: + case .metatype, .optional, .tuple, .function, .existential, .opaque, .genericParameter: throw JavaTranslationError.unsupportedSwiftType(swiftResult.type) } diff --git a/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift b/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift index d1141e5f..3e2359f2 100644 --- a/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift +++ b/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift @@ -23,7 +23,7 @@ import SwiftSyntax public final class Swift2JavaTranslator { static let SWIFT_INTERFACE_SUFFIX = ".swiftinterface" - package var log = Logger(label: "translator", logLevel: .info) + package var log: Logger let config: Configuration @@ -52,7 +52,11 @@ public final class Swift2JavaTranslator { /// type representation. package var importedTypes: [String: ImportedNominalType] = [:] - package var symbolTable: SwiftSymbolTable! = nil + var lookupContext: SwiftTypeLookupContext! = nil + + var symbolTable: SwiftSymbolTable! { + return lookupContext?.symbolTable + } public init( config: Configuration @@ -60,6 +64,7 @@ public final class Swift2JavaTranslator { guard let swiftModule = config.swiftModule else { fatalError("Missing 'swiftModule' name.") // FIXME: can we make it required in config? but we shared config for many cases } + self.log = Logger(label: "translator", logLevel: config.logLevel ?? .info) self.config = config self.swiftModuleName = swiftModule } @@ -116,11 +121,12 @@ extension Swift2JavaTranslator { package func prepareForTranslation() { let dependenciesSource = self.buildDependencyClassesSourceFile() - self.symbolTable = SwiftSymbolTable.setup( + let symbolTable = SwiftSymbolTable.setup( moduleName: self.swiftModuleName, inputs.map({ $0.syntax }) + [dependenciesSource], log: self.log ) + self.lookupContext = SwiftTypeLookupContext(symbolTable: symbolTable) } /// Check if any of the imported decls uses a nominal declaration that satisfies @@ -140,6 +146,8 @@ extension Swift2JavaTranslator { return check(ty) case .existential(let ty), .opaque(let ty): return check(ty) + case .genericParameter: + return false } } @@ -206,7 +214,7 @@ extension Swift2JavaTranslator { func importedNominalType( _ typeNode: TypeSyntax ) -> ImportedNominalType? { - guard let swiftType = try? SwiftType(typeNode, symbolTable: self.symbolTable) else { + guard let swiftType = try? SwiftType(typeNode, lookupContext: lookupContext) else { return nil } guard let swiftNominalDecl = swiftType.asNominalTypeDeclaration else { diff --git a/Sources/JExtractSwiftLib/Swift2JavaVisitor.swift b/Sources/JExtractSwiftLib/Swift2JavaVisitor.swift index 7ce982a2..90181757 100644 --- a/Sources/JExtractSwiftLib/Swift2JavaVisitor.swift +++ b/Sources/JExtractSwiftLib/Swift2JavaVisitor.swift @@ -104,7 +104,7 @@ final class Swift2JavaVisitor { signature = try SwiftFunctionSignature( node, enclosingType: typeContext?.swiftType, - symbolTable: self.translator.symbolTable + lookupContext: translator.lookupContext ) } catch { self.log.debug("Failed to import: '\(node.qualifiedNameForDebug)'; \(error)") @@ -145,7 +145,7 @@ final class Swift2JavaVisitor { node, isSet: kind == .setter, enclosingType: typeContext?.swiftType, - symbolTable: self.translator.symbolTable + lookupContext: translator.lookupContext ) let imported = ImportedFunc( @@ -193,7 +193,7 @@ final class Swift2JavaVisitor { signature = try SwiftFunctionSignature( node, enclosingType: typeContext.swiftType, - symbolTable: self.translator.symbolTable + lookupContext: translator.lookupContext ) } catch { self.log.debug("Failed to import: \(node.qualifiedNameForDebug); \(error)") diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftFunctionSignature.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftFunctionSignature.swift index 5cca79bf..85b96110 100644 --- a/Sources/JExtractSwiftLib/SwiftTypes/SwiftFunctionSignature.swift +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftFunctionSignature.swift @@ -15,6 +15,11 @@ import SwiftSyntax import SwiftSyntaxBuilder +enum SwiftGenericRequirement: Equatable { + case inherits(SwiftType, SwiftType) + case equals(SwiftType, SwiftType) +} + /// Provides a complete signature for a Swift function, which includes its /// parameters and return type. public struct SwiftFunctionSignature: Equatable { @@ -22,17 +27,23 @@ public struct SwiftFunctionSignature: Equatable { var parameters: [SwiftParameter] var result: SwiftResult var effectSpecifiers: [SwiftEffectSpecifier] + var genericParameters: [SwiftGenericParameterDeclaration] + var genericRequirements: [SwiftGenericRequirement] init( selfParameter: SwiftSelfParameter? = nil, parameters: [SwiftParameter], result: SwiftResult, - effectSpecifiers: [SwiftEffectSpecifier] + effectSpecifiers: [SwiftEffectSpecifier], + genericParameters: [SwiftGenericParameterDeclaration], + genericRequirements: [SwiftGenericRequirement] ) { self.selfParameter = selfParameter self.parameters = parameters self.result = result self.effectSpecifiers = effectSpecifiers + self.genericParameters = genericParameters + self.genericRequirements = genericRequirements } } @@ -54,13 +65,8 @@ extension SwiftFunctionSignature { init( _ node: InitializerDeclSyntax, enclosingType: SwiftType?, - symbolTable: SwiftSymbolTable + lookupContext: SwiftTypeLookupContext ) throws { - // Prohibit generics for now. - if let generics = node.genericParameterClause { - throw SwiftFunctionTranslationError.generic(generics) - } - guard let enclosingType else { throw SwiftFunctionTranslationError.missingEnclosingType(node) } @@ -70,33 +76,36 @@ extension SwiftFunctionSignature { throw SwiftFunctionTranslationError.failableInitializer(node) } - // Prohibit generics for now. - if let generics = node.genericParameterClause { - throw SwiftFunctionTranslationError.generic(generics) - } - + let (genericParams, genericRequirements) = try Self.translateGenericParameters( + parameterClause: node.genericParameterClause, + whereClause: node.genericWhereClause, + lookupContext: lookupContext + ) let (parameters, effectSpecifiers) = try Self.translateFunctionSignature( node.signature, - symbolTable: symbolTable + lookupContext: lookupContext ) self.init( selfParameter: .initializer(enclosingType), parameters: parameters, result: SwiftResult(convention: .direct, type: enclosingType), - effectSpecifiers: effectSpecifiers + effectSpecifiers: effectSpecifiers, + genericParameters: genericParams, + genericRequirements: genericRequirements ) } init( _ node: FunctionDeclSyntax, enclosingType: SwiftType?, - symbolTable: SwiftSymbolTable + lookupContext: SwiftTypeLookupContext ) throws { - // Prohibit generics for now. - if let generics = node.genericParameterClause { - throw SwiftFunctionTranslationError.generic(generics) - } + let (genericParams, genericRequirements) = try Self.translateGenericParameters( + parameterClause: node.genericParameterClause, + whereClause: node.genericWhereClause, + lookupContext: lookupContext + ) // If this is a member of a type, so we will have a self parameter. Figure out the // type and convention for the self parameter. @@ -132,7 +141,7 @@ extension SwiftFunctionSignature { // Translate the parameters. let (parameters, effectSpecifiers) = try Self.translateFunctionSignature( node.signature, - symbolTable: symbolTable + lookupContext: lookupContext ) // Translate the result type. @@ -140,20 +149,81 @@ extension SwiftFunctionSignature { if let resultType = node.signature.returnClause?.type { result = try SwiftResult( convention: .direct, - type: SwiftType(resultType, symbolTable: symbolTable) + type: SwiftType(resultType, lookupContext: lookupContext) ) } else { result = .void } - self.init(selfParameter: selfParameter, parameters: parameters, result: result, effectSpecifiers: effectSpecifiers) + self.init( + selfParameter: selfParameter, + parameters: parameters, + result: result, + effectSpecifiers: effectSpecifiers, + genericParameters: genericParams, + genericRequirements: genericRequirements + ) + } + + static func translateGenericParameters( + parameterClause: GenericParameterClauseSyntax?, + whereClause: GenericWhereClauseSyntax?, + lookupContext: SwiftTypeLookupContext + ) throws -> (parameters: [SwiftGenericParameterDeclaration], requirements: [SwiftGenericRequirement]) { + var params: [SwiftGenericParameterDeclaration] = [] + var requirements: [SwiftGenericRequirement] = [] + + // Parameter clause + if let parameterClause { + for parameterNode in parameterClause.parameters { + guard parameterNode.specifier == nil else { + throw SwiftFunctionTranslationError.genericParameterSpecifier(parameterNode) + } + let param = try lookupContext.typeDeclaration(for: parameterNode) as! SwiftGenericParameterDeclaration + params.append(param) + if let inheritedNode = parameterNode.inheritedType { + let inherited = try SwiftType(inheritedNode, lookupContext: lookupContext) + requirements.append(.inherits(.genericParameter(param), inherited)) + } + } + } + + // Where clause + if let whereClause { + for requirementNode in whereClause.requirements { + let requirement: SwiftGenericRequirement + switch requirementNode.requirement { + case .conformanceRequirement(let conformance): + requirement = .inherits( + try SwiftType(conformance.leftType, lookupContext: lookupContext), + try SwiftType(conformance.rightType, lookupContext: lookupContext) + ) + case .sameTypeRequirement(let sameType): + guard let leftType = sameType.leftType.as(TypeSyntax.self) else { + throw SwiftFunctionTranslationError.expressionInGenericRequirement(requirementNode) + } + guard let rightType = sameType.rightType.as(TypeSyntax.self) else { + throw SwiftFunctionTranslationError.expressionInGenericRequirement(requirementNode) + } + requirement = .equals( + try SwiftType(leftType, lookupContext: lookupContext), + try SwiftType(rightType, lookupContext: lookupContext) + ) + case .layoutRequirement: + throw SwiftFunctionTranslationError.layoutRequirement(requirementNode) + } + requirements.append(requirement) + } + } + + return (params, requirements) } /// Translate the function signature, returning the list of translated /// parameters and effect specifiers. static func translateFunctionSignature( _ signature: FunctionSignatureSyntax, - symbolTable: SwiftSymbolTable + lookupContext: SwiftTypeLookupContext ) throws -> ([SwiftParameter], [SwiftEffectSpecifier]) { var effectSpecifiers = [SwiftEffectSpecifier]() if signature.effectSpecifiers?.throwsClause != nil { @@ -164,13 +234,18 @@ extension SwiftFunctionSignature { } let parameters = try signature.parameterClause.parameters.map { param in - try SwiftParameter(param, symbolTable: symbolTable) + try SwiftParameter(param, lookupContext: lookupContext) } return (parameters, effectSpecifiers) } - init(_ varNode: VariableDeclSyntax, isSet: Bool, enclosingType: SwiftType?, symbolTable: SwiftSymbolTable) throws { + init( + _ varNode: VariableDeclSyntax, + isSet: Bool, + enclosingType: SwiftType?, + lookupContext: SwiftTypeLookupContext + ) throws { // If this is a member of a type, so we will have a self parameter. Figure out the // type and convention for the self parameter. @@ -205,7 +280,7 @@ extension SwiftFunctionSignature { guard let varTypeNode = binding.typeAnnotation?.type else { throw SwiftFunctionTranslationError.missingTypeAnnotation(varNode) } - let valueType = try SwiftType(varTypeNode, symbolTable: symbolTable) + let valueType = try SwiftType(varTypeNode, lookupContext: lookupContext) var effectSpecifiers: [SwiftEffectSpecifier]? = nil switch binding.accessorBlock?.accessors { @@ -230,6 +305,8 @@ extension SwiftFunctionSignature { self.parameters = [] self.result = .init(convention: .direct, type: valueType) } + self.genericParameters = [] + self.genericRequirements = [] } private static func effectSpecifiers(from decl: AccessorDeclSyntax) throws -> [SwiftEffectSpecifier] { @@ -287,11 +364,13 @@ extension VariableDeclSyntax { enum SwiftFunctionTranslationError: Error { case `throws`(ThrowsClauseSyntax) case async(TokenSyntax) - case generic(GenericParameterClauseSyntax) case classMethod(TokenSyntax) case missingEnclosingType(InitializerDeclSyntax) case failableInitializer(InitializerDeclSyntax) case multipleBindings(VariableDeclSyntax) case missingTypeAnnotation(VariableDeclSyntax) case unsupportedAccessor(AccessorDeclSyntax) + case genericParameterSpecifier(GenericParameterSyntax) + case expressionInGenericRequirement(GenericRequirementSyntax) + case layoutRequirement(GenericRequirementSyntax) } diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftFunctionType.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftFunctionType.swift index 565a24c3..da6fd2a2 100644 --- a/Sources/JExtractSwiftLib/SwiftTypes/SwiftFunctionType.swift +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftFunctionType.swift @@ -40,18 +40,18 @@ extension SwiftFunctionType { init( _ node: FunctionTypeSyntax, convention: Convention, - symbolTable: SwiftSymbolTable + lookupContext: SwiftTypeLookupContext ) throws { self.convention = convention self.parameters = try node.parameters.map { param in let isInout = param.inoutKeyword != nil return SwiftParameter( convention: isInout ? .inout : .byValue, - type: try SwiftType(param.type, symbolTable: symbolTable) + type: try SwiftType(param.type, lookupContext: lookupContext) ) } - self.resultType = try SwiftType(node.returnClause.type, symbolTable: symbolTable) + self.resultType = try SwiftType(node.returnClause.type, lookupContext: lookupContext) // check for effect specifiers if let throwsClause = node.effectSpecifiers?.throwsClause { diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftNominalTypeDeclaration.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftNominalTypeDeclaration.swift index 8be645c8..b377fd85 100644 --- a/Sources/JExtractSwiftLib/SwiftTypes/SwiftNominalTypeDeclaration.swift +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftNominalTypeDeclaration.swift @@ -18,9 +18,24 @@ import SwiftSyntax @_spi(Testing) public typealias NominalTypeDeclSyntaxNode = any DeclGroupSyntax & NamedDeclSyntax & WithAttributesSyntax & WithModifiersSyntax +package class SwiftTypeDeclaration { + /// The module in which this nominal type is defined. If this is a nested type, the + /// module might be different from that of the parent type, if this nominal type + /// is defined in an extension within another module. + let moduleName: String + + /// The name of this nominal type, e.g., 'MyCollection'. + let name: String + + init(moduleName: String, name: String) { + self.moduleName = moduleName + self.name = name + } +} + /// Describes a nominal type declaration, which can be of any kind (class, struct, etc.) /// and has a name, parent type (if nested), and owning module. -package class SwiftNominalTypeDeclaration { +package class SwiftNominalTypeDeclaration: SwiftTypeDeclaration { enum Kind { case actor case `class` @@ -40,14 +55,6 @@ package class SwiftNominalTypeDeclaration { /// MyCollection.Iterator. let parent: SwiftNominalTypeDeclaration? - /// The module in which this nominal type is defined. If this is a nested type, the - /// module might be different from that of the parent type, if this nominal type - /// is defined in an extension within another module. - let moduleName: String - - /// The name of this nominal type, e.g., 'MyCollection'. - let name: String - // TODO: Generic parameters. /// Identify this nominal declaration as one of the known standard library @@ -63,9 +70,7 @@ package class SwiftNominalTypeDeclaration { parent: SwiftNominalTypeDeclaration?, node: NominalTypeDeclSyntaxNode ) { - self.moduleName = moduleName self.parent = parent - self.name = node.name.text self.syntax = node // Determine the kind from the syntax node. @@ -77,6 +82,7 @@ package class SwiftNominalTypeDeclaration { case .structDecl: self.kind = .struct default: fatalError("Not a nominal type declaration") } + super.init(moduleName: moduleName, name: node.name.text) } /// Determine the known standard library type for this nominal type @@ -107,13 +113,25 @@ package class SwiftNominalTypeDeclaration { } } -extension SwiftNominalTypeDeclaration: Equatable { - package static func ==(lhs: SwiftNominalTypeDeclaration, rhs: SwiftNominalTypeDeclaration) -> Bool { +package class SwiftGenericParameterDeclaration: SwiftTypeDeclaration { + let syntax: GenericParameterSyntax + + init( + moduleName: String, + node: GenericParameterSyntax + ) { + self.syntax = node + super.init(moduleName: moduleName, name: node.name.text) + } +} + +extension SwiftTypeDeclaration: Equatable { + package static func ==(lhs: SwiftTypeDeclaration, rhs: SwiftTypeDeclaration) -> Bool { lhs === rhs } } -extension SwiftNominalTypeDeclaration: Hashable { +extension SwiftTypeDeclaration: Hashable { package func hash(into hasher: inout Hasher) { hasher.combine(ObjectIdentifier(self)) } diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftParameter.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftParameter.swift index 24b3d8b4..75d165e9 100644 --- a/Sources/JExtractSwiftLib/SwiftTypes/SwiftParameter.swift +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftParameter.swift @@ -58,7 +58,7 @@ enum SwiftParameterConvention: Equatable { } extension SwiftParameter { - init(_ node: FunctionParameterSyntax, symbolTable: SwiftSymbolTable) throws { + init(_ node: FunctionParameterSyntax, lookupContext: SwiftTypeLookupContext) throws { // Determine the convention. The default is by-value, but there are // specifiers on the type for other conventions (like `inout`). var type = node.type @@ -90,7 +90,7 @@ extension SwiftParameter { self.convention = convention // Determine the type. - self.type = try SwiftType(type, symbolTable: symbolTable) + self.type = try SwiftType(type, lookupContext: lookupContext) // FIXME: swift-syntax itself should have these utilities based on identifiers. if let secondName = node.secondName { diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftParsedModuleSymbolTableBuilder.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftParsedModuleSymbolTableBuilder.swift index 4026e624..9b8ef236 100644 --- a/Sources/JExtractSwiftLib/SwiftTypes/SwiftParsedModuleSymbolTableBuilder.swift +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftParsedModuleSymbolTableBuilder.swift @@ -122,7 +122,8 @@ extension SwiftParsedModuleSymbolTableBuilder { parsedModule: symbolTable, importedModules: importedModules ) - guard let extendedType = try? SwiftType(node.extendedType, symbolTable: table) else { + let lookupContext = SwiftTypeLookupContext(symbolTable: table) + guard let extendedType = try? SwiftType(node.extendedType, lookupContext: lookupContext) else { return false } guard let extendedNominal = extendedType.asNominalTypeDeclaration else { diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftType+RepresentativeConcreteeType.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftType+RepresentativeConcreteeType.swift new file mode 100644 index 00000000..ce668485 --- /dev/null +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftType+RepresentativeConcreteeType.swift @@ -0,0 +1,65 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +extension SwiftType { + /// Returns a concrete type if this is a generic parameter in the list and it + /// conforms to a protocol with representative concrete type. + func representativeConcreteTypeIn( + knownTypes: SwiftKnownTypes, + genericParameters: [SwiftGenericParameterDeclaration], + genericRequirements: [SwiftGenericRequirement] + ) -> SwiftType? { + return representativeConcreteType( + self, + knownTypes: knownTypes, + genericParameters: genericParameters, + genericRequirements: genericRequirements + ) + } +} + +private func representativeConcreteType( + _ type: SwiftType, + knownTypes: SwiftKnownTypes, + genericParameters: [SwiftGenericParameterDeclaration], + genericRequirements: [SwiftGenericRequirement] +) -> SwiftType? { + var maybeProto: SwiftType? = nil + switch type { + case .existential(let proto), .opaque(let proto): + maybeProto = proto + case .genericParameter(let genericParam): + // If the type is a generic parameter declared in this function and + // conforms to a protocol with representative concrete type, use it. + if genericParameters.contains(genericParam) { + for requirement in genericRequirements { + if case .inherits(let left, let right) = requirement, left == type { + guard maybeProto == nil else { + // multiple requirements on the generic parameter. + return nil + } + maybeProto = right + break + } + } + } + default: + return nil + } + + if let knownProtocol = maybeProto?.asNominalTypeDeclaration?.knownTypeKind { + return knownTypes.representativeType(of: knownProtocol) + } + return nil +} diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftType.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftType.swift index d0f1f98d..da738d39 100644 --- a/Sources/JExtractSwiftLib/SwiftTypes/SwiftType.swift +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftType.swift @@ -18,6 +18,8 @@ import SwiftSyntax enum SwiftType: Equatable { case nominal(SwiftNominalType) + case genericParameter(SwiftGenericParameterDeclaration) + indirect case function(SwiftFunctionType) /// `.Type` @@ -43,7 +45,7 @@ enum SwiftType: Equatable { switch self { case .nominal(let nominal): nominal case .tuple(let elements): elements.count == 1 ? elements[0].asNominalType : nil - case .function, .metatype, .optional, .existential, .opaque: nil + case .genericParameter, .function, .metatype, .optional, .existential, .opaque: nil } } @@ -86,7 +88,7 @@ enum SwiftType: Equatable { return nominal.nominalTypeDecl.isReferenceType case .metatype, .function: return true - case .optional, .tuple, .existential, .opaque: + case .genericParameter, .optional, .tuple, .existential, .opaque: return false } } @@ -98,13 +100,14 @@ extension SwiftType: CustomStringConvertible { private var postfixRequiresParentheses: Bool { switch self { case .function, .existential, .opaque: true - case .metatype, .nominal, .optional, .tuple: false + case .genericParameter, .metatype, .nominal, .optional, .tuple: false } } var description: String { switch self { case .nominal(let nominal): return nominal.description + case .genericParameter(let genericParam): return genericParam.name case .function(let functionType): return functionType.description case .metatype(let instanceType): var instanceTypeStr = instanceType.description @@ -179,7 +182,7 @@ extension SwiftNominalType { } extension SwiftType { - init(_ type: TypeSyntax, symbolTable: SwiftSymbolTable) throws { + init(_ type: TypeSyntax, lookupContext: SwiftTypeLookupContext) throws { switch type.as(TypeSyntaxEnum.self) { case .arrayType, .classRestrictionType, .compositionType, .dictionaryType, .missingType, .namedOpaqueReturnType, @@ -192,7 +195,7 @@ extension SwiftType { // FIXME: This string matching is a horrible hack. switch attributedType.attributes.trimmedDescription { case "@convention(c)", "@convention(swift)": - let innerType = try SwiftType(attributedType.baseType, symbolTable: symbolTable) + let innerType = try SwiftType(attributedType.baseType, lookupContext: lookupContext) switch innerType { case .function(var functionType): let isConventionC = attributedType.attributes.trimmedDescription == "@convention(c)" @@ -208,7 +211,7 @@ extension SwiftType { case .functionType(let functionType): self = .function( - try SwiftFunctionType(functionType, convention: .swift, symbolTable: symbolTable) + try SwiftFunctionType(functionType, convention: .swift, lookupContext: lookupContext) ) case .identifierType(let identifierType): @@ -217,7 +220,7 @@ extension SwiftType { try genericArgumentClause.arguments.map { argument in switch argument.argument { case .type(let argumentTy): - try SwiftType(argumentTy, symbolTable: symbolTable) + try SwiftType(argumentTy, lookupContext: lookupContext) default: throw TypeTranslationError.unimplementedType(type) } @@ -228,13 +231,13 @@ extension SwiftType { self = try SwiftType( originalType: type, parent: nil, - name: identifierType.name.text, + name: identifierType.name, genericArguments: genericArgs, - symbolTable: symbolTable + lookupContext: lookupContext ) case .implicitlyUnwrappedOptionalType(let optionalType): - self = .optional(try SwiftType(optionalType.wrappedType, symbolTable: symbolTable)) + self = .optional(try SwiftType(optionalType.wrappedType, lookupContext: lookupContext)) case .memberType(let memberType): // If the parent type isn't a known module, translate it. @@ -244,7 +247,7 @@ extension SwiftType { if memberType.baseType.trimmedDescription == "Swift" { parentType = nil } else { - parentType = try SwiftType(memberType.baseType, symbolTable: symbolTable) + parentType = try SwiftType(memberType.baseType, lookupContext: lookupContext) } // Translate the generic arguments. @@ -252,7 +255,7 @@ extension SwiftType { try genericArgumentClause.arguments.map { argument in switch argument.argument { case .type(let argumentTy): - try SwiftType(argumentTy, symbolTable: symbolTable) + try SwiftType(argumentTy, lookupContext: lookupContext) default: throw TypeTranslationError.unimplementedType(type) } @@ -262,27 +265,27 @@ extension SwiftType { self = try SwiftType( originalType: type, parent: parentType, - name: memberType.name.text, + name: memberType.name, genericArguments: genericArgs, - symbolTable: symbolTable + lookupContext: lookupContext ) case .metatypeType(let metatypeType): - self = .metatype(try SwiftType(metatypeType.baseType, symbolTable: symbolTable)) + self = .metatype(try SwiftType(metatypeType.baseType, lookupContext: lookupContext)) case .optionalType(let optionalType): - self = .optional(try SwiftType(optionalType.wrappedType, symbolTable: symbolTable)) + self = .optional(try SwiftType(optionalType.wrappedType, lookupContext: lookupContext)) case .tupleType(let tupleType): self = try .tuple(tupleType.elements.map { element in - try SwiftType(element.type, symbolTable: symbolTable) + try SwiftType(element.type, lookupContext: lookupContext) }) case .someOrAnyType(let someOrAntType): if someOrAntType.someOrAnySpecifier.tokenKind == .keyword(.some) { - self = .opaque(try SwiftType(someOrAntType.constraint, symbolTable: symbolTable)) + self = .opaque(try SwiftType(someOrAntType.constraint, lookupContext: lookupContext)) } else { - self = .opaque(try SwiftType(someOrAntType.constraint, symbolTable: symbolTable)) + self = .opaque(try SwiftType(someOrAntType.constraint, lookupContext: lookupContext)) } } } @@ -290,25 +293,37 @@ extension SwiftType { init( originalType: TypeSyntax, parent: SwiftType?, - name: String, + name: TokenSyntax, genericArguments: [SwiftType]?, - symbolTable: SwiftSymbolTable + lookupContext: SwiftTypeLookupContext ) throws { // Look up the imported types by name to resolve it to a nominal type. - guard let nominalTypeDecl = symbolTable.lookupType( - name, - parent: parent?.asNominalTypeDeclaration - ) else { - throw TypeTranslationError.unknown(originalType) + let typeDecl: SwiftTypeDeclaration? + if let parent { + guard let parentDecl = parent.asNominalTypeDeclaration else { + throw TypeTranslationError.unknown(originalType) + } + typeDecl = lookupContext.symbolTable.lookupNestedType(name.text, parent: parentDecl) + } else { + typeDecl = try lookupContext.unqualifiedLookup(name: Identifier(name)!, from: name) + } + guard let typeDecl else { + throw TypeTranslationError.unknown(originalType) } - self = .nominal( - SwiftNominalType( - parent: parent?.asNominalType, - nominalTypeDecl: nominalTypeDecl, - genericArguments: genericArguments + if let nominalDecl = typeDecl as? SwiftNominalTypeDeclaration { + self = .nominal( + SwiftNominalType( + parent: parent?.asNominalType, + nominalTypeDecl: nominalDecl, + genericArguments: genericArguments + ) ) - ) + } else if let genericParamDecl = typeDecl as? SwiftGenericParameterDeclaration { + self = .genericParameter(genericParamDecl) + } else { + fatalError("unknown SwiftTypeDeclaration: \(type(of: typeDecl))") + } } init?( @@ -345,11 +360,11 @@ extension SwiftType { enum TypeTranslationError: Error { /// We haven't yet implemented support for this type. - case unimplementedType(TypeSyntax) + case unimplementedType(TypeSyntax, file: StaticString = #file, line: Int = #line) /// Missing generic arguments. - case missingGenericArguments(TypeSyntax) + case missingGenericArguments(TypeSyntax, file: StaticString = #file, line: Int = #line) /// Unknown nominal type. - case unknown(TypeSyntax) + case unknown(TypeSyntax, file: StaticString = #file, line: Int = #line) } diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftTypeLookupContext.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftTypeLookupContext.swift new file mode 100644 index 00000000..9ede2b1b --- /dev/null +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftTypeLookupContext.swift @@ -0,0 +1,151 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import SwiftSyntax +@_spi(Experimental) import SwiftLexicalLookup + +/// Unqualified type lookup manager. +/// All unqualified lookup should be done via this instance. This caches the +/// association of `Syntax.ID` to `SwiftTypeDeclaration`, and guarantees that +/// there's only one `SwiftTypeDeclaration` per declaration `Syntax`. +class SwiftTypeLookupContext { + var symbolTable: SwiftSymbolTable + + private var typeDecls: [Syntax.ID: SwiftTypeDeclaration] = [:] + + init(symbolTable: SwiftSymbolTable) { + self.symbolTable = symbolTable + } + + /// Perform unqualified type lookup. + /// + /// - Parameters: + /// - name: name to lookup + /// - node: `Syntax` node the lookup happened + func unqualifiedLookup(name: Identifier, from node: some SyntaxProtocol) throws -> SwiftTypeDeclaration? { + + for result in node.lookup(name) { + switch result { + case .fromScope(_, let names): + if !names.isEmpty { + return typeDeclaration(for: names) + } + + case .fromFileScope(_, let names): + if !names.isEmpty { + return typeDeclaration(for: names) + } + + case .lookInMembers(let scopeNode): + if let nominalDecl = try typeDeclaration(for: scopeNode) { + if let found = symbolTable.lookupNestedType(name.name, parent: nominalDecl as! SwiftNominalTypeDeclaration) { + return found + } + } + + case .lookInGenericParametersOfExtendedType(let extensionNode): + // TODO: Implement + _ = extensionNode + break + + case .mightIntroduceDollarIdentifiers: + // Dollar identifier can't be a type, ignore. + break + } + } + + // Fallback to global symbol table lookup. + return symbolTable.lookupTopLevelNominalType(name.name) + } + + /// Find the first type declaration in the `LookupName` results. + private func typeDeclaration(for names: [LookupName]) -> SwiftTypeDeclaration? { + for name in names { + switch name { + case .identifier(let identifiableSyntax, _): + return try? typeDeclaration(for: identifiableSyntax) + case .declaration(let namedDeclSyntax): + return try? typeDeclaration(for: namedDeclSyntax) + case .implicit(let implicitDecl): + // TODO: Implement + _ = implicitDecl + break + case .dollarIdentifier: + break + } + } + return nil + } + + /// Returns the type declaration object associated with the `Syntax` node. + /// If there's no declaration created, create an instance on demand, and cache it. + func typeDeclaration(for node: some SyntaxProtocol) throws -> SwiftTypeDeclaration? { + if let found = typeDecls[node.id] { + return found + } + + let typeDecl: SwiftTypeDeclaration + switch Syntax(node).as(SyntaxEnum.self) { + case .genericParameter(let node): + typeDecl = SwiftGenericParameterDeclaration(moduleName: symbolTable.moduleName, node: node) + case .classDecl(let node): + typeDecl = try nominalTypeDeclaration(for: node) + case .actorDecl(let node): + typeDecl = try nominalTypeDeclaration(for: node) + case .structDecl(let node): + typeDecl = try nominalTypeDeclaration(for: node) + case .enumDecl(let node): + typeDecl = try nominalTypeDeclaration(for: node) + case .protocolDecl(let node): + typeDecl = try nominalTypeDeclaration(for: node) + case .typeAliasDecl: + fatalError("typealias not implemented") + case .associatedTypeDecl: + fatalError("associatedtype not implemented") + default: + throw TypeLookupError.notType(Syntax(node)) + } + + typeDecls[node.id] = typeDecl + return typeDecl + } + + /// Create a nominal type declaration instance for the specified syntax node. + private func nominalTypeDeclaration(for node: NominalTypeDeclSyntaxNode) throws -> SwiftNominalTypeDeclaration { + SwiftNominalTypeDeclaration( + moduleName: self.symbolTable.moduleName, + parent: try parentTypeDecl(for: node), + node: node + ) + } + + /// Find a parent nominal type declaration of the specified syntax node. + private func parentTypeDecl(for node: some DeclSyntaxProtocol) throws -> SwiftNominalTypeDeclaration? { + var node: DeclSyntax = DeclSyntax(node) + while let parentDecl = node.ancestorDecl { + switch parentDecl.as(DeclSyntaxEnum.self) { + case .structDecl, .classDecl, .actorDecl, .enumDecl, .protocolDecl: + return (try typeDeclaration(for: parentDecl) as! SwiftNominalTypeDeclaration) + default: + node = parentDecl + continue + } + } + return nil + } +} + +enum TypeLookupError: Error { + case notType(Syntax) +} diff --git a/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift b/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift index 4b0162f3..ffefe907 100644 --- a/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift +++ b/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift @@ -37,6 +37,7 @@ func assertOutput( column: Int = #column ) throws { var config = Configuration() + config.logLevel = .trace config.swiftModule = swiftModuleName let translator = Swift2JavaTranslator(config: config) translator.dependenciesClasses = Array(javaClassLookupTable.keys) diff --git a/Tests/JExtractSwiftTests/DataImportTests.swift b/Tests/JExtractSwiftTests/DataImportTests.swift index af71c157..7416779d 100644 --- a/Tests/JExtractSwiftTests/DataImportTests.swift +++ b/Tests/JExtractSwiftTests/DataImportTests.swift @@ -28,7 +28,7 @@ final class DataImportTests { """ import Foundation - public func receiveDataProtocol(dat: some DataProtocol) + public func receiveDataProtocol(dat: some DataProtocol, dat2: T?) """ @@ -342,9 +342,9 @@ final class DataImportTests { import Foundation """, """ - @_cdecl("swiftjava_SwiftModule_receiveDataProtocol_dat") - public func swiftjava_SwiftModule_receiveDataProtocol_dat(_ dat: UnsafeRawPointer) { - receiveDataProtocol(dat: dat.assumingMemoryBound(to: Data.self).pointee) + @_cdecl("swiftjava_SwiftModule_receiveDataProtocol_dat_dat2") + public func swiftjava_SwiftModule_receiveDataProtocol_dat_dat2(_ dat: UnsafeRawPointer, _ dat2: UnsafeRawPointer?) { + receiveDataProtocol(dat: dat.assumingMemoryBound(to: Data.self).pointee, dat2: dat2?.assumingMemoryBound(to: Data.self).pointee) } """, @@ -365,22 +365,23 @@ final class DataImportTests { """ /** * {@snippet lang=c : - * void swiftjava_SwiftModule_receiveDataProtocol_dat(const void *dat) + * void swiftjava_SwiftModule_receiveDataProtocol_dat_dat2(const void *dat, const void *dat2) * } */ - private static class swiftjava_SwiftModule_receiveDataProtocol_dat { + private static class swiftjava_SwiftModule_receiveDataProtocol_dat_dat2 { private static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( - /* dat: */SwiftValueLayout.SWIFT_POINTER + /* dat: */SwiftValueLayout.SWIFT_POINTER, + /* dat2: */SwiftValueLayout.SWIFT_POINTER ); private static final MemorySegment ADDR = - SwiftModule.findOrThrow("swiftjava_SwiftModule_receiveDataProtocol_dat"); + SwiftModule.findOrThrow("swiftjava_SwiftModule_receiveDataProtocol_dat_dat2"); private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); - public static void call(java.lang.foreign.MemorySegment dat) { + public static void call(java.lang.foreign.MemorySegment dat, java.lang.foreign.MemorySegment dat2) { try { if (CallTraces.TRACE_DOWNCALLS) { - CallTraces.traceDowncall(dat); + CallTraces.traceDowncall(dat, dat2); } - HANDLE.invokeExact(dat); + HANDLE.invokeExact(dat, dat2); } catch (Throwable ex$) { throw new AssertionError("should not reach here", ex$); } @@ -392,11 +393,11 @@ final class DataImportTests { /** * Downcall to Swift: * {@snippet lang=swift : - * public func receiveDataProtocol(dat: some DataProtocol) + * public func receiveDataProtocol(dat: some DataProtocol, dat2: T?) * } */ - public static void receiveDataProtocol(Data dat) { - swiftjava_SwiftModule_receiveDataProtocol_dat.call(dat.$memorySegment()); + public static void receiveDataProtocol(Data dat, Optional dat2) { + swiftjava_SwiftModule_receiveDataProtocol_dat_dat2.call(dat.$memorySegment(), SwiftRuntime.toOptionalSegmentInstance(dat2)); } """, diff --git a/Tests/JExtractSwiftTests/FunctionLoweringTests.swift b/Tests/JExtractSwiftTests/FunctionLoweringTests.swift index 8419ec61..ba1aad06 100644 --- a/Tests/JExtractSwiftTests/FunctionLoweringTests.swift +++ b/Tests/JExtractSwiftTests/FunctionLoweringTests.swift @@ -404,6 +404,27 @@ final class FunctionLoweringTests { """) } + @Test("Lowering generic parameters") + func genericParam() throws { + try assertLoweredFunction( + """ + func fn(x: T, y: U?) where T: DataProtocol + """, + sourceFile: """ + import Foundation + """, + expectedCDecl: """ + @_cdecl("c_fn") + public func c_fn(_ x: UnsafeRawPointer, _ y: UnsafeRawPointer?) { + fn(x: x.assumingMemoryBound(to: Data.self).pointee, y: y?.assumingMemoryBound(to: Data.self).pointee) + } + """, + expectedCFunction: """ + void c_fn(const void *x, const void *y) + """ + ) + } + @Test("Lowering read accessor") func lowerGlobalReadAccessor() throws { try assertLoweredVariableAccessor( From ac30ee40131c3062ff1131d74bcc9a1d493bcf8c Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Thu, 31 Jul 2025 17:25:52 +0900 Subject: [PATCH 328/426] Initial support for unsigned numbers in jextract (#333) --- .unacceptablelanguageignore | 3 +- .../MySwiftLibrary/MySwiftLibrary.swift | 5 + .../com/example/swift/MySwiftLibraryTest.java | 7 + .../Sources/MySwiftLibrary/MySwiftClass.swift | 12 + .../example/swift/UnsignedNumbersTest.java | 36 +++ .../Common/TypeAnnotations.swift | 26 ++ .../Configuration+Extensions.swift | 25 ++ ...t2JavaGenerator+JavaBindingsPrinting.swift | 40 ++- ...MSwift2JavaGenerator+JavaTranslation.swift | 112 +++++++- ...ift2JavaGenerator+SwiftThunkPrinting.swift | 4 +- .../FFM/FFMSwift2JavaGenerator.swift | 14 +- .../FFM/ForeignValueLayouts.swift | 8 + Sources/JExtractSwiftLib/ImportedDecls.swift | 9 + .../JNI/JNIJavaTypeTranslator.swift | 57 ++++ ...t2JavaGenerator+JavaBindingsPrinting.swift | 20 +- ...ISwift2JavaGenerator+JavaTranslation.swift | 136 ++++++--- ...wift2JavaGenerator+NativeTranslation.swift | 16 +- ...ift2JavaGenerator+SwiftThunkPrinting.swift | 2 +- .../JNI/JNISwift2JavaGenerator.swift | 7 +- Sources/JExtractSwiftLib/JNI/JNIType.swift | 2 +- Sources/JExtractSwiftLib/JavaParameter.swift | 17 +- .../JavaType+JDK.swift} | 0 .../JavaTypes/JavaType+SwiftKit.swift | 88 ++++++ Sources/JExtractSwiftLib/Swift2Java.swift | 2 + .../SwiftTypes/SwiftType.swift | 11 + .../BridgedValues/JavaValue+Integers.swift | 178 ++++++++++++ .../Configuration.swift | 5 + .../GenerationMode.swift | 44 +++ Sources/JavaTypes/JavaAnnotation.swift | 47 +++ Sources/JavaTypes/JavaType+JavaSource.swift | 15 +- Sources/JavaTypes/JavaType+SwiftNames.swift | 44 +-- Sources/JavaTypes/JavaType.swift | 34 ++- .../Documentation.docc/SupportedFeatures.md | 70 ++++- .../SwiftJavaLib/JavaClassTranslator.swift | 6 +- .../Commands/JExtractCommand.swift | 32 +++ .../Commands/ResolveCommand.swift | 2 +- Sources/_Subprocess/Configuration.swift | 2 +- SwiftKitCore/build.gradle | 16 +- .../swiftkit/core/NotImplementedError.java | 24 ++ .../swift/swiftkit/core/Preconditions.java | 153 ++++++++++ .../swiftkit/core/annotations/NonNull.java | 28 ++ .../swiftkit/core/annotations/Nullable.java | 28 ++ .../swiftkit/core/annotations/Unsigned.java | 42 +++ .../swift/swiftkit/ffm/SwiftValueLayout.java | 10 +- .../Asserts/LoweringAssertions.swift | 2 + .../Asserts/TextAssertions.swift | 6 +- .../FuncCallbackImportTests.swift | 4 +- .../FunctionDescriptorImportTests.swift | 2 + .../JNI/JNIClassTests.swift | 172 +++++------ .../JNI/JNIModuleTests.swift | 5 + .../JNI/JNIStructTests.swift | 128 +++++---- .../JNI/JNIUnsignedNumberTests.swift | 154 ++++++++++ .../JNI/JNIVariablesTests.swift | 1 + .../MethodImportTests.swift | 9 + .../UnsignedNumberTests.swift | 268 ++++++++++++++++++ 55 files changed, 1922 insertions(+), 268 deletions(-) create mode 100644 Samples/SwiftKitSampleApp/src/test/java/com/example/swift/UnsignedNumbersTest.java create mode 100644 Sources/JExtractSwiftLib/Common/TypeAnnotations.swift create mode 100644 Sources/JExtractSwiftLib/Configuration+Extensions.swift create mode 100644 Sources/JExtractSwiftLib/JNI/JNIJavaTypeTranslator.swift rename Sources/JExtractSwiftLib/{JavaConstants/JavaTypes.swift => JavaTypes/JavaType+JDK.swift} (100%) create mode 100644 Sources/JExtractSwiftLib/JavaTypes/JavaType+SwiftKit.swift create mode 100644 Sources/JavaTypes/JavaAnnotation.swift create mode 100644 SwiftKitCore/src/main/java/org/swift/swiftkit/core/NotImplementedError.java create mode 100644 SwiftKitCore/src/main/java/org/swift/swiftkit/core/Preconditions.java create mode 100644 SwiftKitCore/src/main/java/org/swift/swiftkit/core/annotations/NonNull.java create mode 100644 SwiftKitCore/src/main/java/org/swift/swiftkit/core/annotations/Nullable.java create mode 100644 SwiftKitCore/src/main/java/org/swift/swiftkit/core/annotations/Unsigned.java create mode 100644 Tests/JExtractSwiftTests/JNI/JNIUnsignedNumberTests.swift create mode 100644 Tests/JExtractSwiftTests/UnsignedNumberTests.swift diff --git a/.unacceptablelanguageignore b/.unacceptablelanguageignore index 92a1d726..c3f97d3d 100644 --- a/.unacceptablelanguageignore +++ b/.unacceptablelanguageignore @@ -3,4 +3,5 @@ Sources/_Subprocess/Platforms/Subprocess+Darwin.swift Sources/_Subprocess/Platforms/Subprocess+Linux.swift Sources/_Subprocess/Platforms/Subprocess+Unix.swift Sources/_Subprocess/Teardown.swift -Sources/_Subprocess/Subprocess.swift \ No newline at end of file +Sources/_Subprocess/Subprocess.swift +NOTICE.txt \ No newline at end of file diff --git a/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift b/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift index 1dd84547..09903638 100644 --- a/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift +++ b/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift @@ -45,6 +45,11 @@ public func globalTakeIntInt(i: Int64, j: Int64) { p("i:\(i), j:\(j)") } +public func echoUnsignedInt(i: UInt32, j: UInt64) -> UInt64 { + p("i:\(i), j:\(j)") + return UInt64(i) + j +} + // ==== Internal helpers func p(_ msg: String, file: String = #fileID, line: UInt = #line, function: String = #function) { diff --git a/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/MySwiftLibraryTest.java b/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/MySwiftLibraryTest.java index 5c9c2358..6da2fd4b 100644 --- a/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/MySwiftLibraryTest.java +++ b/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/MySwiftLibraryTest.java @@ -61,4 +61,11 @@ void globalVariable() { MySwiftLibrary.setGlobalVariable(100); assertEquals(100, MySwiftLibrary.getGlobalVariable()); } + + @Test + void globalUnsignedIntEcho() { + int i = 12; + long l = 1200; + assertEquals(1212, MySwiftLibrary.echoUnsignedInt(12, 1200)); + } } \ No newline at end of file diff --git a/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftClass.swift b/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftClass.swift index 30661045..e1139c2b 100644 --- a/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftClass.swift +++ b/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftClass.swift @@ -60,4 +60,16 @@ public class MySwiftClass { public func makeRandomIntMethod() -> Int { return Int.random(in: 1..<256) } + + public func takeUnsignedChar(arg: UInt16) { + p("\(UInt32.self) = \(arg)") + } + + public func takeUnsignedInt(arg: UInt32) { + p("\(UInt32.self) = \(arg)") + } + + public func takeUnsignedLong(arg: UInt64) { + p("\(UInt64.self) = \(arg)") + } } diff --git a/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/UnsignedNumbersTest.java b/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/UnsignedNumbersTest.java new file mode 100644 index 00000000..beb0f817 --- /dev/null +++ b/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/UnsignedNumbersTest.java @@ -0,0 +1,36 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package com.example.swift; + +import org.junit.jupiter.api.Test; +import org.swift.swiftkit.ffm.AllocatingSwiftArena; + +public class UnsignedNumbersTest { + @Test + void take_uint32() { + try (var arena = AllocatingSwiftArena.ofConfined()) { + var c = MySwiftClass.init(1, 2, arena); + c.takeUnsignedInt(128); + } + } + + @Test + void take_uint64() { + try (var arena = AllocatingSwiftArena.ofConfined()) { + var c = MySwiftClass.init(1, 2, arena); + c.takeUnsignedLong(Long.MAX_VALUE); + } + } +} diff --git a/Sources/JExtractSwiftLib/Common/TypeAnnotations.swift b/Sources/JExtractSwiftLib/Common/TypeAnnotations.swift new file mode 100644 index 00000000..70a86e82 --- /dev/null +++ b/Sources/JExtractSwiftLib/Common/TypeAnnotations.swift @@ -0,0 +1,26 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import JavaTypes +import JavaKitConfigurationShared + +/// Determine if the given type needs any extra annotations that should be included +/// in Java sources when the corresponding Java type is rendered. +func getTypeAnnotations(swiftType: SwiftType, config: Configuration) -> [JavaAnnotation] { + if swiftType.isUnsignedInteger, config.effectiveUnsignedNumbersMode == .annotate { + return [JavaAnnotation.unsigned] + } + + return [] +} diff --git a/Sources/JExtractSwiftLib/Configuration+Extensions.swift b/Sources/JExtractSwiftLib/Configuration+Extensions.swift new file mode 100644 index 00000000..d85cf447 --- /dev/null +++ b/Sources/JExtractSwiftLib/Configuration+Extensions.swift @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import JavaKitConfigurationShared // TODO: this should become SwiftJavaConfigurationShared +import JavaTypes // TODO: this should become SwiftJavaConfigurationShared + +extension Configuration { + public var effectiveUnsignedNumericsMode: UnsignedNumericsMode { + switch effectiveUnsignedNumbersMode { + case .annotate: .ignoreSign + case .wrapGuava: .wrapUnsignedGuava + } + } +} \ No newline at end of file diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift index 28b3aba1..b8749299 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift @@ -105,9 +105,16 @@ extension FFMSwift2JavaGenerator { var params: [String] = [] var args: [String] = [] for param in cFunc.parameters { - // ! unwrapping because cdecl lowering guarantees the parameter named. - params.append("\(param.type.javaType) \(param.name!)") - args.append(param.name!) + let name = param.name! // !-safe, because cdecl lowering guarantees the parameter named. + + let annotationsStr = + if param.type.javaType.parameterAnnotations.isEmpty { + "" + } else { + param.type.javaType.parameterAnnotations.map({$0.render()}).joined(separator: " ") + " " + } + params.append("\(annotationsStr)\(param.type.javaType) \(name)") + args.append(name) } let paramsStr = params.joined(separator: ", ") let argsStr = args.joined(separator: ", ") @@ -316,23 +323,21 @@ extension FFMSwift2JavaGenerator { let translatedSignature = translated.translatedSignature let returnTy = translatedSignature.result.javaResultType + var annotationsStr = translatedSignature.annotations.map({ $0.render() }).joined(separator: "\n") + if !annotationsStr.isEmpty { annotationsStr += "\n" } + var paramDecls = translatedSignature.parameters .flatMap(\.javaParameters) - .map { "\($0.type) \($0.name)" } + .map { $0.renderParameter() } if translatedSignature.requiresSwiftArena { paramDecls.append("AllocatingSwiftArena swiftArena$") } // TODO: we could copy the Swift method's documentation over here, that'd be great UX + printDeclDocumentation(&printer, decl) printer.printBraceBlock( """ - /** - * Downcall to Swift: - * {@snippet lang=swift : - * \(decl.signatureString) - * } - */ - \(modifiers) \(returnTy) \(methodName)(\(paramDecls.joined(separator: ", "))) + \(annotationsStr)\(modifiers) \(returnTy) \(methodName)(\(paramDecls.joined(separator: ", "))) """ ) { printer in if case .instance(_) = decl.functionSignature.selfParameter { @@ -344,6 +349,19 @@ extension FFMSwift2JavaGenerator { } } + private func printDeclDocumentation(_ printer: inout CodePrinter, _ decl: ImportedFunc) { + printer.print( + """ + /** + * Downcall to Swift: + * {@snippet lang=swift : + * \(decl.signatureString) + * } + */ + """ + ) + } + /// Print the actual downcall to the Swift API. /// /// This assumes that all the parameters are passed-in with appropriate names. diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift index b29ca5d9..f8b2e7e8 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// import JavaTypes +import JavaKitConfigurationShared extension FFMSwift2JavaGenerator { func translatedDecl( @@ -24,7 +25,9 @@ extension FFMSwift2JavaGenerator { let translated: TranslatedFunctionDecl? do { - let translation = JavaTranslation(knownTypes: SwiftKnownTypes(symbolTable: lookupContext.symbolTable)) + let translation = JavaTranslation( + config: self.config, + knownTypes: SwiftKnownTypes(symbolTable: lookupContext.symbolTable)) translated = try translation.translate(decl) } catch { self.log.info("Failed to translate: '\(decl.swiftDecl.qualifiedNameForDebug)'; \(error)") @@ -52,6 +55,9 @@ extension FFMSwift2JavaGenerator { /// Java type that represents the Swift result type. var javaResultType: JavaType + /// Java annotations that should be propagated from the result type onto the method + var annotations: [JavaAnnotation] = [] + /// Required indirect return receivers for receiving the result. /// /// 'JavaParameter.name' is the suffix for the receiver variable names. For example @@ -85,8 +91,13 @@ extension FFMSwift2JavaGenerator { /// Function signature. let translatedSignature: TranslatedFunctionSignature - /// Cdecl lowerd signature. + /// Cdecl lowered signature. let loweredSignature: LoweredFunctionSignature + + /// Annotations to include on the Java function declaration + var annotations: [JavaAnnotation] { + self.translatedSignature.annotations + } } /// Function signature for a Java API. @@ -94,6 +105,12 @@ extension FFMSwift2JavaGenerator { var selfParameter: TranslatedParameter? var parameters: [TranslatedParameter] var result: TranslatedResult + + // if the result type implied any annotations, + // propagate them onto the function the result is returned from + var annotations: [JavaAnnotation] { + self.result.annotations + } } /// Represent a Swift closure type in the user facing Java API. @@ -113,15 +130,15 @@ extension FFMSwift2JavaGenerator { } struct JavaTranslation { + let config: Configuration var knownTypes: SwiftKnownTypes - init(knownTypes: SwiftKnownTypes) { + init(config: Configuration, knownTypes: SwiftKnownTypes) { + self.config = config self.knownTypes = knownTypes } - func translate( - _ decl: ImportedFunc - ) throws -> TranslatedFunctionDecl { + func translate(_ decl: ImportedFunc) throws -> TranslatedFunctionDecl { let lowering = CdeclLowering(knownTypes: knownTypes) let loweredSignature = try lowering.lowerFunctionSignature(decl.functionSignature) @@ -303,6 +320,18 @@ extension FFMSwift2JavaGenerator { genericParameters: [SwiftGenericParameterDeclaration], genericRequirements: [SwiftGenericRequirement] ) throws -> TranslatedParameter { + // If the result type should cause any annotations on the method, include them here. + let parameterAnnotations: [JavaAnnotation] = getTypeAnnotations(swiftType: swiftType, config: config) + + // If we need to handle unsigned integers do so here + if config.effectiveUnsignedNumbersMode.needsConversion { + if let unsignedWrapperType = JavaType.unsignedWrapper(for: swiftType) { + return TranslatedParameter( + javaParameters: [ + JavaParameter(name: parameterName, type: unsignedWrapperType, annotations: parameterAnnotations) + ], conversion: .call(.placeholder, function: "UnsignedNumbers.toPrimitive", withArena: false)) + } + } // If there is a 1:1 mapping between this Swift type and a C type, that can // be expressed as a Java primitive type. @@ -311,8 +340,9 @@ extension FFMSwift2JavaGenerator { return TranslatedParameter( javaParameters: [ JavaParameter( - name: parameterName, type: javaType - ) + name: parameterName, + type: javaType, + annotations: parameterAnnotations) ], conversion: .placeholder ) @@ -324,7 +354,10 @@ extension FFMSwift2JavaGenerator { return TranslatedParameter( javaParameters: [ JavaParameter( - name: parameterName, type: JavaType.class(package: "org.swift.swiftkit.ffm", name: "SwiftAnyType")) + name: parameterName, + type: JavaType.class(package: "org.swift.swiftkit.ffm", name: "SwiftAnyType"), + annotations: parameterAnnotations + ) ], conversion: .swiftValueSelfSegment(.placeholder) ) @@ -524,6 +557,37 @@ extension FFMSwift2JavaGenerator { } } + func unsignedResultConversion(_ from: SwiftType, to javaType: JavaType, + mode: JExtractUnsignedIntegerMode) -> JavaConversionStep { + switch mode { + case .annotate: + return .placeholder // no conversions + + case .wrapGuava: + guard let typeName = javaType.fullyQualifiedClassName else { + fatalError("Missing target class name for result conversion step from \(from) to \(javaType)") + } + + switch from { + case .nominal(let nominal): + switch nominal.nominalTypeDecl.knownTypeKind { + case .uint8: + return .call(.placeholder, function: "\(typeName).fromIntBits", withArena: false) + case .uint16: + return .placeholder // no conversion, UInt16 can be returned as-is and will be seen as char by Java + case .uint32: + return .call(.placeholder, function: "\(typeName).fromIntBits", withArena: false) + case .uint64: + return .call(.placeholder, function: "\(typeName).fromLongBits", withArena: false) + default: + fatalError("unsignedResultConversion: Unsupported conversion from \(from) to \(javaType)") + } + default: + fatalError("unsignedResultConversion: Unsupported conversion from \(from) to \(javaType)") + } + } + } + /// Translate a Swift API result to the user-facing Java API result. func translate( swiftResult: SwiftResult, @@ -531,12 +595,29 @@ extension FFMSwift2JavaGenerator { ) throws -> TranslatedResult { let swiftType = swiftResult.type + // If we need to handle unsigned integers do so here + if config.effectiveUnsignedNumbersMode.needsConversion { + if let unsignedWrapperType = JavaType.unsignedWrapper(for: swiftType) /* and we're in safe wrapper mode */ { + return TranslatedResult( + javaResultType: unsignedWrapperType, + outParameters: [], + conversion: unsignedResultConversion( + swiftType, to: unsignedWrapperType, + mode: self.config.effectiveUnsignedNumbersMode) + ) + } + } + + // If the result type should cause any annotations on the method, include them here. + let resultAnnotations: [JavaAnnotation] = getTypeAnnotations(swiftType: swiftType, config: config) + // If there is a 1:1 mapping between this Swift type and a C type, that can // be expressed as a Java primitive type. if let cType = try? CType(cdeclType: swiftType) { let javaType = cType.javaType return TranslatedResult( javaResultType: javaType, + annotations: resultAnnotations, outParameters: [], conversion: .placeholder ) @@ -548,6 +629,7 @@ extension FFMSwift2JavaGenerator { let javaType = JavaType.class(package: "org.swift.swiftkit.ffm", name: "SwiftAnyType") return TranslatedResult( javaResultType: javaType, + annotations: resultAnnotations, outParameters: [], conversion: .construct(.placeholder, javaType) ) @@ -558,6 +640,7 @@ extension FFMSwift2JavaGenerator { case .unsafeRawBufferPointer, .unsafeMutableRawBufferPointer: return TranslatedResult( javaResultType: .javaForeignMemorySegment, + annotations: resultAnnotations, outParameters: [ JavaParameter(name: "pointer", type: .javaForeignMemorySegment), JavaParameter(name: "count", type: .long), @@ -597,6 +680,7 @@ extension FFMSwift2JavaGenerator { let javaType: JavaType = .class(package: nil, name: swiftNominalType.nominalTypeDecl.name) return TranslatedResult( javaResultType: javaType, + annotations: resultAnnotations, outParameters: [ JavaParameter(name: "", type: javaType) ], @@ -702,7 +786,7 @@ extension CType { case .integral(.signed(bits: 32)): return .int case .integral(.signed(bits: 64)): return .long case .integral(.unsigned(bits: 8)): return .byte - case .integral(.unsigned(bits: 16)): return .short + case .integral(.unsigned(bits: 16)): return .char // char is Java's only unsigned primitive, we can use it! case .integral(.unsigned(bits: 32)): return .int case .integral(.unsigned(bits: 64)): return .long @@ -739,10 +823,10 @@ extension CType { case .integral(.signed(bits: 32)): return .SwiftInt32 case .integral(.signed(bits: 64)): return .SwiftInt64 - case .integral(.unsigned(bits: 8)): return .SwiftInt8 - case .integral(.unsigned(bits: 16)): return .SwiftInt16 - case .integral(.unsigned(bits: 32)): return .SwiftInt32 - case .integral(.unsigned(bits: 64)): return .SwiftInt64 + case .integral(.unsigned(bits: 8)): return .SwiftUInt8 + case .integral(.unsigned(bits: 16)): return .SwiftUInt16 + case .integral(.unsigned(bits: 32)): return .SwiftUInt32 + case .integral(.unsigned(bits: 64)): return .SwiftUInt64 case .floating(.double): return .SwiftDouble case .floating(.float): return .SwiftFloat diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+SwiftThunkPrinting.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+SwiftThunkPrinting.swift index 1e32d1e5..f35973eb 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+SwiftThunkPrinting.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+SwiftThunkPrinting.swift @@ -38,7 +38,7 @@ extension FFMSwift2JavaGenerator { let moduleFilenameBase = "\(self.swiftModuleName)Module+SwiftJava" let moduleFilename = "\(moduleFilenameBase).swift" do { - log.info("Printing contents: \(moduleFilename)") + log.debug("Printing contents: \(moduleFilename)") try printGlobalSwiftThunkSources(&printer) @@ -58,7 +58,7 @@ extension FFMSwift2JavaGenerator { for (_, ty) in self.analysis.importedTypes.sorted(by: { (lhs, rhs) in lhs.key < rhs.key }) { let fileNameBase = "\(ty.swiftNominal.qualifiedName)+SwiftJava" let filename = "\(fileNameBase).swift" - log.info("Printing contents: \(filename)") + log.debug("Printing contents: \(filename)") do { try printSwiftThunkSources(&printer, ty: ty) diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift index d30d3e74..29962621 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift @@ -15,10 +15,12 @@ import JavaTypes import SwiftSyntax import SwiftSyntaxBuilder +import JavaKitConfigurationShared import struct Foundation.URL package class FFMSwift2JavaGenerator: Swift2JavaGenerator { let log: Logger + let config: Configuration let analysis: AnalysisResult let swiftModuleName: String let javaPackage: String @@ -40,12 +42,14 @@ package class FFMSwift2JavaGenerator: Swift2JavaGenerator { var expectedOutputSwiftFiles: Set package init( + config: Configuration, translator: Swift2JavaTranslator, javaPackage: String, swiftOutputDirectory: String, javaOutputDirectory: String ) { self.log = Logger(label: "ffm-generator", logLevel: translator.log.logLevel) + self.config = config self.analysis = translator.result self.swiftModuleName = translator.swiftModuleName self.javaPackage = javaPackage @@ -96,7 +100,9 @@ extension FFMSwift2JavaGenerator { "org.swift.swiftkit.core.*", "org.swift.swiftkit.core.util.*", "org.swift.swiftkit.ffm.*", - "org.swift.swiftkit.ffm.SwiftRuntime", + + // NonNull, Unsigned and friends + "org.swift.swiftkit.core.annotations.*", // Necessary for native calls and type mapping "java.lang.foreign.*", @@ -120,7 +126,7 @@ extension FFMSwift2JavaGenerator { package func writeExportedJavaSources(printer: inout CodePrinter) throws { for (_, ty) in analysis.importedTypes.sorted(by: { (lhs, rhs) in lhs.key < rhs.key }) { let filename = "\(ty.swiftNominal.name).java" - log.info("Printing contents: \(filename)") + log.debug("Printing contents: \(filename)") printImportedNominal(&printer, ty) if let outputFile = try printer.writeContents( @@ -134,7 +140,7 @@ extension FFMSwift2JavaGenerator { do { let filename = "\(self.swiftModuleName).java" - log.info("Printing contents: \(filename)") + log.debug("Printing contents: \(filename)") printModule(&printer) if let outputFile = try printer.writeContents( @@ -178,7 +184,7 @@ extension FFMSwift2JavaGenerator { func printImportedNominal(_ printer: inout CodePrinter, _ decl: ImportedNominalType) { printHeader(&printer) printPackage(&printer) - printImports(&printer) + printImports(&printer) // TODO: we could have some imports be driven from types used in the generated decl printNominal(&printer, decl) { printer in // We use a static field to abuse the initialization order such that by the time we get type metadata, diff --git a/Sources/JExtractSwiftLib/FFM/ForeignValueLayouts.swift b/Sources/JExtractSwiftLib/FFM/ForeignValueLayouts.swift index 3784a75a..329efaad 100644 --- a/Sources/JExtractSwiftLib/FFM/ForeignValueLayouts.swift +++ b/Sources/JExtractSwiftLib/FFM/ForeignValueLayouts.swift @@ -67,11 +67,19 @@ extension ForeignValueLayout { public static let SwiftBool = Self(javaConstant: "SWIFT_BOOL") public static let SwiftInt = Self(javaConstant: "SWIFT_INT") + public static let SwiftUInt = Self(javaConstant: "SWIFT_UINT") + public static let SwiftInt64 = Self(javaConstant: "SWIFT_INT64") + public static let SwiftUInt64 = Self(javaConstant: "SWIFT_UINT64") + public static let SwiftInt32 = Self(javaConstant: "SWIFT_INT32") + public static let SwiftUInt32 = Self(javaConstant: "SWIFT_UINT32") + public static let SwiftInt16 = Self(javaConstant: "SWIFT_INT16") public static let SwiftUInt16 = Self(javaConstant: "SWIFT_UINT16") + public static let SwiftInt8 = Self(javaConstant: "SWIFT_INT8") + public static let SwiftUInt8 = Self(javaConstant: "SWIFT_UINT8") public static let SwiftFloat = Self(javaConstant: "SWIFT_FLOAT") public static let SwiftDouble = Self(javaConstant: "SWIFT_DOUBLE") diff --git a/Sources/JExtractSwiftLib/ImportedDecls.swift b/Sources/JExtractSwiftLib/ImportedDecls.swift index dd7e9c10..4c4d9c0f 100644 --- a/Sources/JExtractSwiftLib/ImportedDecls.swift +++ b/Sources/JExtractSwiftLib/ImportedDecls.swift @@ -78,6 +78,15 @@ public final class ImportedFunc: ImportedDecl, CustomStringConvertible { } } + /// If this function type uses types that require any additional `import` statements, + /// these would be exported here. + var additionalJavaImports: Set { + var imports: Set = [] +// imports += self.functionSignature.parameters.flatMap { $0.additionalJavaImports } +// imports += self.functionSignature.result.additionalJavaImports + return imports + } + var isStatic: Bool { if case .staticMethod = functionSignature.selfParameter { return true diff --git a/Sources/JExtractSwiftLib/JNI/JNIJavaTypeTranslator.swift b/Sources/JExtractSwiftLib/JNI/JNIJavaTypeTranslator.swift new file mode 100644 index 00000000..fe10ef72 --- /dev/null +++ b/Sources/JExtractSwiftLib/JNI/JNIJavaTypeTranslator.swift @@ -0,0 +1,57 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024-2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import JavaTypes +import JavaKitConfigurationShared + +enum JNIJavaTypeTranslator { + + static func translate(knownType: SwiftKnownTypeDeclKind, config: Configuration) -> JavaType? { + let unsigned = config.effectiveUnsignedNumbersMode + guard unsigned == .annotate else { + // We do not support wrap mode in JNI mode currently; + // In the future this is where it would be interesting to implement Kotlin UInt support. + return nil + } + + switch knownType { + case .bool: return .boolean + + case .int8: return .byte + case .uint8: return .byte + + case .int16: return .short + case .uint16: return .char + + case .int32: return .int + case .uint32: return .int + + case .int64: return .long + case .uint64: return .long + + case .float: return .float + case .double: return .double + case .void: return .void + + case .string: return .javaLangString + case .int, .uint, // FIXME: why not supported int/uint? + .unsafeRawPointer, .unsafeMutableRawPointer, + .unsafePointer, .unsafeMutablePointer, + .unsafeRawBufferPointer, .unsafeMutableRawBufferPointer, + .unsafeBufferPointer, .unsafeMutableBufferPointer, + .optional, .data, .dataProtocol: + return nil + } + } +} \ No newline at end of file diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift index e0e5cb70..63b9dcd1 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift @@ -20,6 +20,9 @@ extension JNISwift2JavaGenerator { static let defaultJavaImports: Array = [ "org.swift.swiftkit.core.*", "org.swift.swiftkit.core.util.*", + + // NonNull, Unsigned and friends + "org.swift.swiftkit.core.annotations.*", ] } @@ -32,9 +35,11 @@ extension JNISwift2JavaGenerator { } package func writeExportedJavaSources(_ printer: inout CodePrinter) throws { - for (_, ty) in analysis.importedTypes.sorted(by: { (lhs, rhs) in lhs.key < rhs.key }) { + let importedTypes = analysis.importedTypes.sorted(by: { (lhs, rhs) in lhs.key < rhs.key }) + + for (_, ty) in importedTypes { let filename = "\(ty.swiftNominal.name).java" - logger.info("Printing contents: \(filename)") + logger.debug("Printing contents: \(filename)") printImportedNominal(&printer, ty) if let outputFile = try printer.writeContents( @@ -62,6 +67,7 @@ extension JNISwift2JavaGenerator { private func printModule(_ printer: inout CodePrinter) { printHeader(&printer) printPackage(&printer) + printImports(&printer) printModuleClass(&printer) { printer in printer.print( @@ -81,6 +87,7 @@ extension JNISwift2JavaGenerator { } for decl in analysis.importedGlobalVariables { + self.logger.trace("Print global variable: \(decl)") printFunctionDowncallMethods(&printer, decl) printer.println() } @@ -219,7 +226,7 @@ extension JNISwift2JavaGenerator { _ printer: inout CodePrinter, _ functionType: TranslatedFunctionType ) { - let apiParams = functionType.parameters.map(\.parameter.asParameter) + let apiParams = functionType.parameters.map({ $0.parameter.renderParameter() }) printer.print( """ @@ -243,18 +250,21 @@ extension JNISwift2JavaGenerator { let translatedSignature = translatedDecl.translatedFunctionSignature let resultType = translatedSignature.resultType.javaType - var parameters = translatedDecl.translatedFunctionSignature.parameters.map(\.parameter.asParameter) + var parameters = translatedDecl.translatedFunctionSignature.parameters.map({ $0.parameter.renderParameter() }) if translatedSignature.requiresSwiftArena { parameters.append("SwiftArena swiftArena$") } let throwsClause = decl.isThrowing ? " throws Exception" : "" + var annotationsStr = translatedSignature.annotations.map({ $0.render() }).joined(separator: "\n") + if !annotationsStr.isEmpty { annotationsStr += "\n" } + let modifiersStr = modifiers.joined(separator: " ") let parametersStr = parameters.joined(separator: ", ") printDeclDocumentation(&printer, decl) printer.printBraceBlock( - "\(modifiersStr) \(resultType) \(translatedDecl.name)(\(parametersStr))\(throwsClause)" + "\(annotationsStr)\(modifiersStr) \(resultType) \(translatedDecl.name)(\(parametersStr))\(throwsClause)" ) { printer in printDowncall(&printer, decl) } diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift index 8d18e6ae..5908cfb1 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// import JavaTypes +import JavaKitConfigurationShared extension JNISwift2JavaGenerator { func translatedDecl( @@ -25,6 +26,7 @@ extension JNISwift2JavaGenerator { let translated: TranslatedFunctionDecl? do { let translation = JavaTranslation( + config: config, swiftModuleName: swiftModuleName, javaPackage: self.javaPackage, javaClassLookupTable: self.javaClassLookupTable @@ -40,12 +42,14 @@ extension JNISwift2JavaGenerator { } struct JavaTranslation { + let config: Configuration let swiftModuleName: String let javaPackage: String let javaClassLookupTable: JavaClassLookupTable func translate(_ decl: ImportedFunc) throws -> TranslatedFunctionDecl { let nativeTranslation = NativeJavaTranslation( + config: self.config, javaPackage: self.javaPackage, javaClassLookupTable: self.javaClassLookupTable ) @@ -117,12 +121,12 @@ extension JNISwift2JavaGenerator { ) } - let transltedResult = try translate(swiftResult: SwiftResult(convention: .direct, type: swiftType.resultType)) + let translatedResult = try translate(swiftResult: SwiftResult(convention: .direct, type: swiftType.resultType)) return TranslatedFunctionType( name: name, parameters: translatedParams, - result: transltedResult, + result: translatedResult, swiftType: swiftType ) } @@ -150,10 +154,12 @@ extension JNISwift2JavaGenerator { selfParameter = nil } - return try TranslatedFunctionSignature( + let resultType = try translate(swiftResult: functionSignature.result) + + return TranslatedFunctionSignature( selfParameter: selfParameter, parameters: parameters, - resultType: translate(swiftResult: functionSignature.result) + resultType: resultType ) } @@ -163,17 +169,33 @@ extension JNISwift2JavaGenerator { methodName: String, parentName: String ) throws -> TranslatedParameter { + + // If the result type should cause any annotations on the method, include them here. + let parameterAnnotations: [JavaAnnotation] = getTypeAnnotations(swiftType: swiftType, config: config) + + // If we need to handle unsigned integers do so here + if config.effectiveUnsignedNumbersMode.needsConversion { + if let unsignedWrapperType = JavaType.unsignedWrapper(for: swiftType) { + return TranslatedParameter( + parameter: JavaParameter(name: parameterName, type: unsignedWrapperType, annotations: parameterAnnotations), + conversion: unsignedResultConversion( + swiftType, to: unsignedWrapperType, + mode: self.config.effectiveUnsignedNumbersMode) + ) + } + } + switch swiftType { case .nominal(let nominalType): let nominalTypeName = nominalType.nominalTypeDecl.name if let knownType = nominalType.nominalTypeDecl.knownTypeKind { - guard let javaType = JNISwift2JavaGenerator.translate(knownType: knownType) else { + guard let javaType = JNIJavaTypeTranslator.translate(knownType: knownType, config: self.config) else { throw JavaTranslationError.unsupportedSwiftType(swiftType) } return TranslatedParameter( - parameter: JavaParameter(name: parameterName, type: javaType), + parameter: JavaParameter(name: parameterName, type: javaType, annotations: parameterAnnotations), conversion: .placeholder ) } @@ -184,10 +206,7 @@ extension JNISwift2JavaGenerator { } return TranslatedParameter( - parameter: JavaParameter( - name: parameterName, - type: javaType - ), + parameter: JavaParameter(name: parameterName, type: javaType, annotations: parameterAnnotations), conversion: .placeholder ) } @@ -196,14 +215,15 @@ extension JNISwift2JavaGenerator { return TranslatedParameter( parameter: JavaParameter( name: parameterName, - type: .class(package: nil, name: nominalTypeName) + type: .class(package: nil, name: nominalTypeName), + annotations: parameterAnnotations ), conversion: .valueMemoryAddress(.placeholder) ) case .tuple([]): return TranslatedParameter( - parameter: JavaParameter(name: parameterName, type: .void), + parameter: JavaParameter(name: parameterName, type: .void, annotations: parameterAnnotations), conversion: .placeholder ) @@ -211,7 +231,8 @@ extension JNISwift2JavaGenerator { return TranslatedParameter( parameter: JavaParameter( name: parameterName, - type: .class(package: javaPackage, name: "\(parentName).\(methodName).\(parameterName)") + type: .class(package: javaPackage, name: "\(parentName).\(methodName).\(parameterName)"), + annotations: parameterAnnotations ), conversion: .placeholder ) @@ -221,30 +242,46 @@ extension JNISwift2JavaGenerator { } } - func translate( - swiftResult: SwiftResult - ) throws -> TranslatedResult { - switch swiftResult.type { + func unsignedResultConversion(_ from: SwiftType, to javaType: JavaType, + mode: JExtractUnsignedIntegerMode) -> JavaNativeConversionStep { + switch mode { + case .annotate: + return .placeholder // no conversions + + case .wrapGuava: + fatalError("JExtract in JNI mode does not support the \(JExtractUnsignedIntegerMode.wrapGuava) unsigned numerics mode") + } + } + + func translate(swiftResult: SwiftResult) throws -> TranslatedResult { + let swiftType = swiftResult.type + + // If the result type should cause any annotations on the method, include them here. + let resultAnnotations: [JavaAnnotation] = getTypeAnnotations(swiftType: swiftType, config: config) + + switch swiftType { case .nominal(let nominalType): if let knownType = nominalType.nominalTypeDecl.knownTypeKind { - guard let javaType = JNISwift2JavaGenerator.translate(knownType: knownType) else { - throw JavaTranslationError.unsupportedSwiftType(swiftResult.type) + guard let javaType = JNIJavaTypeTranslator.translate(knownType: knownType, config: self.config) else { + throw JavaTranslationError.unsupportedSwiftType(swiftType) } return TranslatedResult( javaType: javaType, + annotations: resultAnnotations, conversion: .placeholder ) } if nominalType.isJavaKitWrapper { - throw JavaTranslationError.unsupportedSwiftType(swiftResult.type) + throw JavaTranslationError.unsupportedSwiftType(swiftType) } // We assume this is a JExtract class. let javaType = JavaType.class(package: nil, name: nominalType.nominalTypeDecl.name) return TranslatedResult( javaType: javaType, + annotations: resultAnnotations, conversion: .constructSwiftValue(.placeholder, javaType) ) @@ -252,7 +289,7 @@ extension JNISwift2JavaGenerator { return TranslatedResult(javaType: .void, conversion: .placeholder) case .metatype, .optional, .tuple, .function, .existential, .opaque, .genericParameter: - throw JavaTranslationError.unsupportedSwiftType(swiftResult.type) + throw JavaTranslationError.unsupportedSwiftType(swiftType) } } } @@ -275,33 +312,23 @@ extension JNISwift2JavaGenerator { /// Function signature of the native function that will be implemented by Swift let nativeFunctionSignature: NativeFunctionSignature - } - static func translate(knownType: SwiftKnownTypeDeclKind) -> JavaType? { - switch knownType { - case .bool: .boolean - case .int8: .byte - case .uint16: .char - case .int16: .short - case .int32: .int - case .int64: .long - case .float: .float - case .double: .double - case .void: .void - case .string: .javaLangString - case .int, .uint, .uint8, .uint32, .uint64, - .unsafeRawPointer, .unsafeMutableRawPointer, - .unsafePointer, .unsafeMutablePointer, - .unsafeRawBufferPointer, .unsafeMutableRawBufferPointer, - .unsafeBufferPointer, .unsafeMutableBufferPointer, .optional, .data, .dataProtocol: - nil + /// Annotations to include on the Java function declaration + var annotations: [JavaAnnotation] { + self.translatedFunctionSignature.annotations } } struct TranslatedFunctionSignature { - let selfParameter: TranslatedParameter? - let parameters: [TranslatedParameter] - let resultType: TranslatedResult + var selfParameter: TranslatedParameter? + var parameters: [TranslatedParameter] + var resultType: TranslatedResult + + // if the result type implied any annotations, + // propagate them onto the function the result is returned from + var annotations: [JavaAnnotation] { + self.resultType.annotations + } var requiresSwiftArena: Bool { return self.resultType.conversion.requiresSwiftArena @@ -318,6 +345,9 @@ extension JNISwift2JavaGenerator { struct TranslatedResult { let javaType: JavaType + /// Java annotations that should be propagated from the result type onto the method + var annotations: [JavaAnnotation] = [] + /// Represents how to convert the Java native result into a user-facing result. let conversion: JavaNativeConversionStep } @@ -343,6 +373,8 @@ extension JNISwift2JavaGenerator { /// Call `new \(Type)(\(placeholder), swiftArena$)` indirect case constructSwiftValue(JavaNativeConversionStep, JavaType) + indirect case call(JavaNativeConversionStep, function: String) + /// Returns the conversion string applied to the placeholder. func render(_ printer: inout CodePrinter, _ placeholder: String) -> String { // NOTE: 'printer' is used if the conversion wants to cause side-effects. @@ -350,14 +382,18 @@ extension JNISwift2JavaGenerator { switch self { case .placeholder: return placeholder - + case .valueMemoryAddress: return "\(placeholder).$memoryAddress()" - + case .constructSwiftValue(let inner, let javaType): let inner = inner.render(&printer, placeholder) return "new \(javaType.className!)(\(inner), swiftArena$)" - + + case .call(let inner, let function): + let inner = inner.render(&printer, placeholder) + return "\(function)(\(inner))" + } } @@ -372,12 +408,18 @@ extension JNISwift2JavaGenerator { case .valueMemoryAddress(let inner): return inner.requiresSwiftArena + + case .call(let inner, _): + return inner.requiresSwiftArena } } } enum JavaTranslationError: Error { - case unsupportedSwiftType(SwiftType) + case unsupportedSwiftType(SwiftType, fileID: String, line: Int) + static func unsupportedSwiftType(_ type: SwiftType, _fileID: String = #fileID, _line: Int = #line) -> JavaTranslationError { + .unsupportedSwiftType(type, fileID: _fileID, line: _line) + } /// The user has not supplied a mapping from `SwiftType` to /// a java class. diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift index 48a6e8d4..9f1113fc 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift @@ -13,10 +13,12 @@ //===----------------------------------------------------------------------===// import JavaTypes +import JavaKitConfigurationShared extension JNISwift2JavaGenerator { struct NativeJavaTranslation { + let config: Configuration let javaPackage: String let javaClassLookupTable: JavaClassLookupTable @@ -70,7 +72,8 @@ extension JNISwift2JavaGenerator { let nominalTypeName = nominalType.nominalTypeDecl.name if let knownType = nominalType.nominalTypeDecl.knownTypeKind { - guard let javaType = JNISwift2JavaGenerator.translate(knownType: knownType), javaType.implementsJavaValue else { + guard let javaType = JNIJavaTypeTranslator.translate(knownType: knownType, config: self.config), + javaType.implementsJavaValue else { throw JavaTranslationError.unsupportedSwiftType(swiftParameter.type) } @@ -140,7 +143,8 @@ extension JNISwift2JavaGenerator { switch type { case .nominal(let nominal): if let knownType = nominal.nominalTypeDecl.knownTypeKind { - guard let javaType = JNISwift2JavaGenerator.translate(knownType: knownType), javaType.implementsJavaValue else { + guard let javaType = JNIJavaTypeTranslator.translate(knownType: knownType, config: self.config), + javaType.implementsJavaValue else { throw JavaTranslationError.unsupportedSwiftType(type) } @@ -172,7 +176,8 @@ extension JNISwift2JavaGenerator { switch type { case .nominal(let nominal): if let knownType = nominal.nominalTypeDecl.knownTypeKind { - guard let javaType = JNISwift2JavaGenerator.translate(knownType: knownType), javaType.implementsJavaValue else { + guard let javaType = JNIJavaTypeTranslator.translate(knownType: knownType, config: self.config), + javaType.implementsJavaValue else { throw JavaTranslationError.unsupportedSwiftType(type) } @@ -198,7 +203,10 @@ extension JNISwift2JavaGenerator { switch swiftResult.type { case .nominal(let nominalType): if let knownType = nominalType.nominalTypeDecl.knownTypeKind { - guard let javaType = JNISwift2JavaGenerator.translate(knownType: knownType), javaType.implementsJavaValue else { + guard let javaType = JNIJavaTypeTranslator.translate(knownType: knownType, config: self.config) else { + throw JavaTranslationError.unsupportedSwiftType(swiftResult.type) + } + guard javaType.implementsJavaValue else { throw JavaTranslationError.unsupportedSwiftType(swiftResult.type) } diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift index 35d4dbef..8b910ffb 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift @@ -59,7 +59,7 @@ extension JNISwift2JavaGenerator { for (_, ty) in self.analysis.importedTypes.sorted(by: { (lhs, rhs) in lhs.key < rhs.key }) { let fileNameBase = "\(ty.swiftNominal.qualifiedName)+SwiftJava" let filename = "\(fileNameBase).swift" - logger.info("Printing contents: \(filename)") + logger.debug("Printing contents: \(filename)") do { try printNominalTypeThunks(&printer, ty) diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator.swift index 79f546ac..c5f3a5b6 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator.swift @@ -13,16 +13,19 @@ //===----------------------------------------------------------------------===// import JavaTypes +import JavaKitConfigurationShared /// A table that where keys are Swift class names and the values are /// the fully qualified canoical names. package typealias JavaClassLookupTable = [String: String] package class JNISwift2JavaGenerator: Swift2JavaGenerator { + + let logger: Logger + let config: Configuration let analysis: AnalysisResult let swiftModuleName: String let javaPackage: String - let logger: Logger let swiftOutputDirectory: String let javaOutputDirectory: String @@ -42,12 +45,14 @@ package class JNISwift2JavaGenerator: Swift2JavaGenerator { var expectedOutputSwiftFiles: Set package init( + config: Configuration, translator: Swift2JavaTranslator, javaPackage: String, swiftOutputDirectory: String, javaOutputDirectory: String, javaClassLookupTable: JavaClassLookupTable ) { + self.config = config self.logger = Logger(label: "jni-generator", logLevel: translator.log.logLevel) self.analysis = translator.result self.swiftModuleName = translator.swiftModuleName diff --git a/Sources/JExtractSwiftLib/JNI/JNIType.swift b/Sources/JExtractSwiftLib/JNI/JNIType.swift index feb8a545..cdedb0a1 100644 --- a/Sources/JExtractSwiftLib/JNI/JNIType.swift +++ b/Sources/JExtractSwiftLib/JNI/JNIType.swift @@ -88,7 +88,7 @@ extension JavaType { /// Returns whether this type returns `JavaValue` from JavaKit var implementsJavaValue: Bool { - switch self { + return switch self { case .boolean, .byte, .char, .short, .int, .long, .float, .double, .void, .javaLangString: true default: diff --git a/Sources/JExtractSwiftLib/JavaParameter.swift b/Sources/JExtractSwiftLib/JavaParameter.swift index 72896419..a12b13b2 100644 --- a/Sources/JExtractSwiftLib/JavaParameter.swift +++ b/Sources/JExtractSwiftLib/JavaParameter.swift @@ -18,8 +18,21 @@ import JavaTypes struct JavaParameter { let name: String let type: JavaType + /// Parameter annotations are used in parameter declarations like this: `@Annotation int example` + let annotations: [JavaAnnotation] - var asParameter: String { - "\(type) \(name)" + init(name: String, type: JavaType, annotations: [JavaAnnotation] = []) { + self.name = name + self.type = type + self.annotations = annotations + } + + func renderParameter() -> String { + if annotations.isEmpty { + return "\(type) \(name)" + } + + let annotationsStr = annotations.map({$0.render()}).joined(separator: "") + return "\(annotationsStr) \(type) \(name)" } } diff --git a/Sources/JExtractSwiftLib/JavaConstants/JavaTypes.swift b/Sources/JExtractSwiftLib/JavaTypes/JavaType+JDK.swift similarity index 100% rename from Sources/JExtractSwiftLib/JavaConstants/JavaTypes.swift rename to Sources/JExtractSwiftLib/JavaTypes/JavaType+JDK.swift diff --git a/Sources/JExtractSwiftLib/JavaTypes/JavaType+SwiftKit.swift b/Sources/JExtractSwiftLib/JavaTypes/JavaType+SwiftKit.swift new file mode 100644 index 00000000..2ab9c0a2 --- /dev/null +++ b/Sources/JExtractSwiftLib/JavaTypes/JavaType+SwiftKit.swift @@ -0,0 +1,88 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import JavaTypes + +extension JavaType { + + /// Try to map a Swift type name (e.g., from the module Swift) over to a + /// primitive Java type, or fail otherwise. + public init?(swiftTypeName: String, WHT_unsigned unsigned: UnsignedNumericsMode) { + switch swiftTypeName { + case "Bool": self = .boolean + + case "Int8": self = .byte + case "UInt8": + self = switch unsigned { + case .ignoreSign: .byte + case .wrapUnsignedGuava: JavaType.guava.primitives.UnsignedInteger + } + + case "Int16": self = .short + case "UInt16": self = .char + + case "Int32": self = .int + case "UInt32": + self = switch unsigned { + case .ignoreSign: .int + case .wrapUnsignedGuava: JavaType.guava.primitives.UnsignedInteger + } + + case "Int64": self = .long + case "UInt64": + self = switch unsigned { + case .ignoreSign: .long + case .wrapUnsignedGuava: JavaType.guava.primitives.UnsignedLong + } + + case "Float": self = .float + case "Double": self = .double + case "Void": self = .void + default: return nil + } + } +} + +extension JavaType { + + static func unsignedWrapper(for swiftType: SwiftType) -> JavaType? { + switch swiftType { + case .nominal(let nominal): + switch nominal.nominalTypeDecl.knownTypeKind { + case .uint8: return guava.primitives.UnsignedInteger + case .uint16: return .char // no wrapper necessary, we can express it as 'char' natively in Java + case .uint32: return guava.primitives.UnsignedInteger + case .uint64: return guava.primitives.UnsignedLong + default: return nil + } + default: return nil + } + } + + /// Known types from the Google Guava library + enum guava { + enum primitives { + static let package = "com.google.common.primitives" + + static var UnsignedInteger: JavaType { + .class(package: primitives.package, name: "UnsignedInteger") + } + + static var UnsignedLong: JavaType { + .class(package: primitives.package, name: "UnsignedLong") + } + } + } + +} diff --git a/Sources/JExtractSwiftLib/Swift2Java.swift b/Sources/JExtractSwiftLib/Swift2Java.swift index 6473cea3..5a73e328 100644 --- a/Sources/JExtractSwiftLib/Swift2Java.swift +++ b/Sources/JExtractSwiftLib/Swift2Java.swift @@ -98,6 +98,7 @@ public struct SwiftToJava { switch config.mode { case .some(.ffm), .none: let generator = FFMSwift2JavaGenerator( + config: self.config, translator: translator, javaPackage: config.javaPackage ?? "", swiftOutputDirectory: outputSwiftDirectory, @@ -108,6 +109,7 @@ public struct SwiftToJava { case .jni: let generator = JNISwift2JavaGenerator( + config: self.config, translator: translator, javaPackage: config.javaPackage ?? "", swiftOutputDirectory: outputSwiftDirectory, diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftType.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftType.swift index da738d39..3cc14406 100644 --- a/Sources/JExtractSwiftLib/SwiftTypes/SwiftType.swift +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftType.swift @@ -92,6 +92,17 @@ enum SwiftType: Equatable { return false } } + + var isUnsignedInteger: Bool { + switch self { + case .nominal(let nominal): + switch nominal.nominalTypeDecl.knownTypeKind { + case .uint8, .uint16, .uint32, .uint64: true + default: false + } + default: false + } + } } extension SwiftType: CustomStringConvertible { diff --git a/Sources/JavaKit/BridgedValues/JavaValue+Integers.swift b/Sources/JavaKit/BridgedValues/JavaValue+Integers.swift index 1af1b549..005753eb 100644 --- a/Sources/JavaKit/BridgedValues/JavaValue+Integers.swift +++ b/Sources/JavaKit/BridgedValues/JavaValue+Integers.swift @@ -14,6 +14,66 @@ import JavaTypes +extension UInt8: JavaValue { + public typealias JNIType = jbyte + + public static var jvalueKeyPath: WritableKeyPath { \.b } + + public static var javaType: JavaType { .byte } + + /// Retrieve the JNI value. + public func getJNIValue(in environment: JNIEnvironment) -> JNIType { JNIType(self) } + + /// Initialize from a JNI value. + public init(fromJNI value: JNIType, in environment: JNIEnvironment) { + self = Self(value) + } + + public static func jniMethodCall( + in environment: JNIEnvironment + ) -> ((JNIEnvironment, jobject, jmethodID, UnsafePointer?) -> JNIType) { + environment.interface.CallByteMethodA + } + + public static func jniFieldGet(in environment: JNIEnvironment) -> JNIFieldGet { + environment.interface.GetByteField + } + + public static func jniFieldSet(in environment: JNIEnvironment) -> JNIFieldSet { + environment.interface.SetByteField + } + + public static func jniStaticMethodCall( + in environment: JNIEnvironment + ) -> ((JNIEnvironment, jobject, jmethodID, UnsafePointer?) -> JNIType) { + environment.interface.CallStaticByteMethodA + } + + public static func jniStaticFieldGet(in environment: JNIEnvironment) -> JNIStaticFieldGet { + environment.interface.GetStaticByteField + } + + public static func jniStaticFieldSet(in environment: JNIEnvironment) -> JNIStaticFieldSet { + environment.interface.SetStaticByteField + } + + public static func jniNewArray(in environment: JNIEnvironment) -> JNINewArray { + environment.interface.NewByteArray + } + + public static func jniGetArrayRegion(in environment: JNIEnvironment) -> JNIGetArrayRegion { + environment.interface.GetByteArrayRegion + } + + public static func jniSetArrayRegion(in environment: JNIEnvironment) -> JNISetArrayRegion { + environment.interface.SetByteArrayRegion + } + + public static var jniPlaceholderValue: jbyte { + 0 + } +} + extension Int8: JavaValue { public typealias JNIType = jbyte @@ -170,6 +230,66 @@ extension Int16: JavaValue { } } +extension UInt32: JavaValue { + public typealias JNIType = jint + + public static var jvalueKeyPath: WritableKeyPath { \.i } + + public static var javaType: JavaType { .int } + + /// Retrieve the JNI value. + public func getJNIValue(in environment: JNIEnvironment) -> JNIType { JNIType(self) } + + /// Initialize from a JNI value. + public init(fromJNI value: JNIType, in environment: JNIEnvironment) { + self = Self(value) + } + + public static func jniMethodCall( + in environment: JNIEnvironment + ) -> ((JNIEnvironment, jobject, jmethodID, UnsafePointer?) -> JNIType) { + environment.interface.CallIntMethodA + } + + public static func jniFieldGet(in environment: JNIEnvironment) -> JNIFieldGet { + environment.interface.GetIntField + } + + public static func jniFieldSet(in environment: JNIEnvironment) -> JNIFieldSet { + environment.interface.SetIntField + } + + public static func jniStaticMethodCall( + in environment: JNIEnvironment + ) -> ((JNIEnvironment, jobject, jmethodID, UnsafePointer?) -> JNIType) { + environment.interface.CallStaticIntMethodA + } + + public static func jniStaticFieldGet(in environment: JNIEnvironment) -> JNIStaticFieldGet { + environment.interface.GetStaticIntField + } + + public static func jniStaticFieldSet(in environment: JNIEnvironment) -> JNIStaticFieldSet { + environment.interface.SetStaticIntField + } + + public static func jniNewArray(in environment: JNIEnvironment) -> JNINewArray { + environment.interface.NewIntArray + } + + public static func jniGetArrayRegion(in environment: JNIEnvironment) -> JNIGetArrayRegion { + environment.interface.GetIntArrayRegion + } + + public static func jniSetArrayRegion(in environment: JNIEnvironment) -> JNISetArrayRegion { + environment.interface.SetIntArrayRegion + } + + public static var jniPlaceholderValue: jint { + 0 + } +} + extension Int32: JavaValue { public typealias JNIType = jint @@ -228,6 +348,64 @@ extension Int32: JavaValue { } } +extension UInt64: JavaValue { + public typealias JNIType = jlong + + public static var jvalueKeyPath: WritableKeyPath { \.j } + + public func getJNIValue(in environment: JNIEnvironment) -> JNIType { JNIType(self) } + + public init(fromJNI value: JNIType, in environment: JNIEnvironment) { + self = UInt64(value) + } + + public static var javaType: JavaType { .long } + + public static func jniMethodCall( + in environment: JNIEnvironment + ) -> ((JNIEnvironment, jobject, jmethodID, UnsafePointer?) -> JNIType) { + environment.interface.CallLongMethodA + } + + public static func jniFieldGet(in environment: JNIEnvironment) -> JNIFieldGet { + environment.interface.GetLongField + } + + public static func jniFieldSet(in environment: JNIEnvironment) -> JNIFieldSet { + environment.interface.SetLongField + } + + public static func jniStaticMethodCall( + in environment: JNIEnvironment + ) -> ((JNIEnvironment, jobject, jmethodID, UnsafePointer?) -> JNIType) { + environment.interface.CallStaticLongMethodA + } + + public static func jniStaticFieldGet(in environment: JNIEnvironment) -> JNIStaticFieldGet { + environment.interface.GetStaticLongField + } + + public static func jniStaticFieldSet(in environment: JNIEnvironment) -> JNIStaticFieldSet { + environment.interface.SetStaticLongField + } + + public static func jniNewArray(in environment: JNIEnvironment) -> JNINewArray { + environment.interface.NewLongArray + } + + public static func jniGetArrayRegion(in environment: JNIEnvironment) -> JNIGetArrayRegion { + environment.interface.GetLongArrayRegion + } + + public static func jniSetArrayRegion(in environment: JNIEnvironment) -> JNISetArrayRegion { + environment.interface.SetLongArrayRegion + } + + public static var jniPlaceholderValue: jlong { + 0 + } +} + extension Int64: JavaValue { public typealias JNIType = jlong diff --git a/Sources/JavaKitConfigurationShared/Configuration.swift b/Sources/JavaKitConfigurationShared/Configuration.swift index 5c57082e..c1ae7dd2 100644 --- a/Sources/JavaKitConfigurationShared/Configuration.swift +++ b/Sources/JavaKitConfigurationShared/Configuration.swift @@ -42,6 +42,11 @@ public struct Configuration: Codable { public var writeEmptyFiles: Bool? // FIXME: default it to false, but that plays not nice with Codable + public var unsignedNumbersMode: JExtractUnsignedIntegerMode? + public var effectiveUnsignedNumbersMode: JExtractUnsignedIntegerMode { + unsignedNumbersMode ?? .default + } + // ==== java 2 swift --------------------------------------------------------- /// The Java class path that should be passed along to the swift-java tool. diff --git a/Sources/JavaKitConfigurationShared/GenerationMode.swift b/Sources/JavaKitConfigurationShared/GenerationMode.swift index b4a96476..190323a0 100644 --- a/Sources/JavaKitConfigurationShared/GenerationMode.swift +++ b/Sources/JavaKitConfigurationShared/GenerationMode.swift @@ -12,6 +12,7 @@ // //===----------------------------------------------------------------------===// +/// Determines which source generation mode JExtract should be using: JNI or Foreign Function and Memory. public enum JExtractGenerationMode: String, Codable { /// Foreign Value and Memory API case ffm @@ -19,3 +20,46 @@ public enum JExtractGenerationMode: String, Codable { /// Java Native Interface case jni } + +/// Configures how Swift unsigned integers should be extracted by jextract. +public enum JExtractUnsignedIntegerMode: String, Codable { + /// Treat unsigned Swift integers as their signed equivalents in Java signatures, + /// however annotate them using the `@Unsigned` annotation which serves as a hint + /// to users of APIs with unsigned integers that a given parameter or return type + /// is actually unsigned, and must be treated carefully. + /// + /// Specifically negative values of a `@Unchecked long` must be interpreted carefully as + /// a value larger than the Long.MAX_VALUE can represent in Java. + case annotate + + /// Wrap any unsigned Swift integer values in an explicit `Unsigned...` wrapper types. + /// + /// This mode trades off performance, due to needing to allocate the type-safe wrapper objects around + /// primitive values, however allows to retain static type information about the unsignedness of + /// unsigned number types in the Java side of generated bindings. + case wrapGuava + +// /// If possible, use a wider Java signed integer type to represent an Unsigned Swift integer type. +// /// For example, represent a Swift `UInt32` (width equivalent to Java `int`) as a Java signed `long`, +// /// because UInt32's max value is possible to be stored in a signed Java long (64bit). +// /// +// /// Since it is not possible to widen a value beyond 64bits (Java `long`), the Long type would be wrapped +// case widenOrWrap +// +// /// Similar to `widenOrWrap`, however instead of wrapping `UInt64` as an `UnsignedLong` in Java, +// /// only annotate it as `@Unsigned long`. +// case widenOrAnnotate +} + +extension JExtractUnsignedIntegerMode { + public var needsConversion: Bool { + switch self { + case .annotate: false + case .wrapGuava: true + } + } + + public static var `default`: JExtractUnsignedIntegerMode { + .annotate + } +} diff --git a/Sources/JavaTypes/JavaAnnotation.swift b/Sources/JavaTypes/JavaAnnotation.swift new file mode 100644 index 00000000..a643c298 --- /dev/null +++ b/Sources/JavaTypes/JavaAnnotation.swift @@ -0,0 +1,47 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +/// Describes a Java annotation (e.g. `@Deprecated` or `@Unsigned`) +public struct JavaAnnotation: Equatable, Hashable { + public let type: JavaType + public let arguments: [String] + + public init(className name: some StringProtocol, arguments: [String] = []) { + type = JavaType(className: name) + self.arguments = arguments + } + + public func render() -> String { + guard let className = type.className else { + fatalError("Java annotation must have a className") + } + + var res = "@\(className)" + guard !arguments.isEmpty else { + return res + } + + res += "(" + res += arguments.joined(separator: ",") + res += ")" + return res + } + +} + +extension JavaAnnotation { + public static var unsigned: JavaAnnotation { + JavaAnnotation(className: "Unsigned") + } +} \ No newline at end of file diff --git a/Sources/JavaTypes/JavaType+JavaSource.swift b/Sources/JavaTypes/JavaType+JavaSource.swift index ccb4e96b..f9e2e0cd 100644 --- a/Sources/JavaTypes/JavaType+JavaSource.swift +++ b/Sources/JavaTypes/JavaType+JavaSource.swift @@ -60,7 +60,7 @@ extension JavaType: CustomStringConvertible { } } - /// Returns the a class name if this java type was a class, + /// Returns the class name if this java type was a class, /// and nil otherwise. public var className: String? { switch self { @@ -70,4 +70,17 @@ extension JavaType: CustomStringConvertible { return nil } } + + /// Returns the fully qualified class name if this java type was a class, + /// and nil otherwise. + public var fullyQualifiedClassName: String? { + switch self { + case .class(.some(let package), let name): + return "\(package).\(name)" + case .class(nil, let name): + return name + default: + return nil + } + } } diff --git a/Sources/JavaTypes/JavaType+SwiftNames.swift b/Sources/JavaTypes/JavaType+SwiftNames.swift index 492ff459..20de73fc 100644 --- a/Sources/JavaTypes/JavaType+SwiftNames.swift +++ b/Sources/JavaTypes/JavaType+SwiftNames.swift @@ -85,20 +85,32 @@ extension JavaType { } } - /// Try to map a Swift type name (e.g., from the module Swift) over to a - /// primitive Java type, or fail otherwise. - public init?(swiftTypeName: String) { - switch swiftTypeName { - case "Bool": self = .boolean - case "Int8": self = .byte - case "UInt16": self = .char - case "Int16": self = .short - case "Int32": self = .int - case "Int64": self = .long - case "Float": self = .float - case "Double": self = .double - case "Void": self = .void - default: return nil - } - } +} + +/// Determines how type conversion should deal with Swift's unsigned numeric types. +/// +/// When `ignoreSign` is used, unsigned Swift types are imported directly as their corresponding bit-width types, +/// which may yield surprising values when an unsigned Swift value is interpreted as a signed Java type: +/// - `UInt8` is imported as `byte` +/// - `UInt16` is imported as `char` (this is always correct, since `char` is unsigned in Java) +/// - `UInt32` is imported as `int` +/// - `UInt64` is imported as `long` +/// +/// When `wrapUnsignedGuava` is used, unsigned Swift types are imported as safe "wrapper" types from the popular Guava +/// library on the Java side. SwiftJava does not include these types, so you would have to make sure your project depends +/// on Guava for such generated code to be able to compile. +/// +/// These make the Unsigned nature of the types explicit in Java, however they come at a cost of allocating the wrapper +/// object, and indirection when accessing the underlying numeric value. These are often useful as a signal to watch out +/// when dealing with a specific API, however in high performance use-cases, one may want to choose using the primitive +/// values directly, and interact with them using {@code UnsignedIntegers} SwiftKit helper classes on the Java side. +/// +/// The type mappings in this mode are as follows: +/// - `UInt8` is imported as `com.google.common.primitives.UnsignedInteger` +/// - `UInt16` is imported as `char` (this is always correct, since `char` is unsigned in Java) +/// - `UInt32` is imported as `com.google.common.primitives.UnsignedInteger` +/// - `UInt64` is imported as `com.google.common.primitives.UnsignedLong` +public enum UnsignedNumericsMode { + case ignoreSign + case wrapUnsignedGuava } diff --git a/Sources/JavaTypes/JavaType.swift b/Sources/JavaTypes/JavaType.swift index 6c5f5357..2a2d901f 100644 --- a/Sources/JavaTypes/JavaType.swift +++ b/Sources/JavaTypes/JavaType.swift @@ -13,13 +13,15 @@ //===----------------------------------------------------------------------===// /// Describes the Java type system. +/// +/// Some types may need to be annotated when in parameter position, public enum JavaType: Equatable, Hashable { case boolean - case byte - case char - case short - case int - case long + case byte(parameterAnnotations: [JavaAnnotation]) + case char(parameterAnnotations: [JavaAnnotation]) + case short(parameterAnnotations: [JavaAnnotation]) + case int(parameterAnnotations: [JavaAnnotation]) + case long(parameterAnnotations: [JavaAnnotation]) case float case double case void @@ -31,6 +33,12 @@ public enum JavaType: Equatable, Hashable { /// A Java array. indirect case array(JavaType) + public static var byte: JavaType { .byte(parameterAnnotations: []) } + public static var char: JavaType { .char(parameterAnnotations: []) } + public static var short: JavaType { .short(parameterAnnotations: []) } + public static var int: JavaType { .int(parameterAnnotations: []) } + public static var long: JavaType { .long(parameterAnnotations: []) } + /// Given a class name such as "java.lang.Object", split it into /// its package and class name to form a class instance. public init(className name: some StringProtocol) { @@ -45,6 +53,21 @@ public enum JavaType: Equatable, Hashable { } } +extension JavaType { + /// List of Java annotations this type should have include in parameter position, + /// e.g. `void example(@Unsigned long num)` + public var parameterAnnotations: [JavaAnnotation] { + switch self { + case .byte(let parameterAnnotations): return parameterAnnotations + case .char(let parameterAnnotations): return parameterAnnotations + case .short(let parameterAnnotations): return parameterAnnotations + case .int(let parameterAnnotations): return parameterAnnotations + case .long(let parameterAnnotations): return parameterAnnotations + default: return [] + } + } +} + extension JavaType { /// Whether this is a primitive Java type. public var isPrimitive: Bool { @@ -57,3 +80,4 @@ extension JavaType { } } } + diff --git a/Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md b/Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md index e7acb3eb..b3d02276 100644 --- a/Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md +++ b/Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md @@ -45,7 +45,7 @@ SwiftJava's `swift-java jextract` tool automates generating Java bindings from S | Swift Feature | FFM | JNI | -|--------------------------------------------------------------------------------------| -------- |-----| +|--------------------------------------------------------------------------------------|----------|-----| | Initializers: `class`, `struct` | ✅ | ✅ | | Optional Initializers / Throwing Initializers | ❌ | ❌ | | Deinitializers: `class`, `struct` | ✅ | ✅ | @@ -67,7 +67,7 @@ SwiftJava's `swift-java jextract` tool automates generating Java bindings from S | Primitive types: `Bool`, `Int`, `Int8`, `Int16`, `Int32`, `Int64`, `Float`, `Double` | ✅ | ✅ | | Parameters: JavaKit wrapped types `JavaLong`, `JavaInteger` | ❌ | ✅ | | Return values: JavaKit wrapped types `JavaLong`, `JavaInteger` | ❌ | ❌ | -| Unsigned primitive types: `UInt`, `UInt8`, `UInt16`, `UInt32`, `UInt64` | ❌ | ❌ | +| Unsigned primitive types: `UInt`, `UInt8`, `UInt16`, `UInt32`, `UInt64` | ✅ * | ✅ * | | String (with copying data) | ✅ | ✅ | | Variadic parameters: `T...` | ❌ | ❌ | | Parametrer packs / Variadic generics | ❌ | ❌ | @@ -76,14 +76,14 @@ SwiftJava's `swift-java jextract` tool automates generating Java bindings from S | Operators: `+`, `-`, user defined | ❌ | ❌ | | Subscripts: `subscript()` | ❌ | ❌ | | Equatable | ❌ | ❌ | -| Pointers: `UnsafeRawPointer`, UnsafeBufferPointer (?) | 🟡 | ❌ | +| Pointers: `UnsafeRawPointer`, UnsafeBufferPointer (?) | 🟡 | ❌ | | Nested types: `struct Hello { struct World {} }` | ❌ | ❌ | | Inheritance: `class Caplin: Capybara` | ❌ | ❌ | | Non-escaping `Void` closures: `func callMe(maybe: () -> ())` | ✅ | ✅ | | Non-escaping closures with primitive arguments/results: `func callMe(maybe: (Int) -> (Double))` | ✅ | ✅ | | Non-escaping closures with object arguments/results: `func callMe(maybe: (JavaObj) -> (JavaObj))` | ❌ | ❌ | | `@escaping` closures: `func callMe(_: @escaping () -> ())` | ❌ | ❌ | -| Swift type extensions: `extension String { func uppercased() }` | 🟡 | 🟡 | +| Swift type extensions: `extension String { func uppercased() }` | 🟡 | 🟡 | | Swift macros (maybe) | ❌ | ❌ | | Result builders | ❌ | ❌ | | Automatic Reference Counting of class types / lifetime safety | ✅ | ✅ | @@ -94,3 +94,65 @@ SwiftJava's `swift-java jextract` tool automates generating Java bindings from S | | | | > tip: The list of features may be incomplete, please file an issue if something is unclear or should be clarified in this table. + +## Detailed feature support discussion + +### Unsigned integers + +### Java <-> Swift Type mapping + +Java does not support unsigned numbers (other than the 16-bit wide `char`), and therefore mapping Swift's (and C) +unsigned integer types is somewhat problematic. + +SwiftJava's jextract mode, similar to OpenJDK jextract, does extract unsigned types from native code to Java +as their bit-width equivalents. This is potentially dangerous because values larger than the `MAX_VALUE` of a given +*signed* type in Java, e.g. `200` stored in an `UInt8` in Swift, would be interpreted as a `byte` of value `-56`, +because Java's `byte` type is _signed_. + +#### Unsigned numbers mode: annotate (default) + +Because in many situations the data represented by such numbers is merely passed along, and not interpreted by Java, +this may be safe to pass along. However, interpreting unsigned values incorrectly like this can lead to subtle mistakes +on the Java side. + +| Swift type | Java type | +|------------|-----------| +| `Int8` | `byte` | +| `UInt8` | `byte` ⚠️ | +| `Int16` | `short` | +| `UInt16` | `char` | +| `Int32` | `int` | +| `UInt32` | `int` ⚠️ | +| `Int64` | `long` | +| `UInt64` | `long` ⚠️ | +| `Float` | `float` | +| `Double` | `double` | + +#### Unsigned numbers mode: wrap-guava + +You can configure `jextract` (in FFM mode) to instead import unsigned values as their unsigned type-safe representations +as offered by the Guava library: `UnsignedLong` or `UnsignedInt`. To enable this mode pass the `--unsigned-numbers wrap-guava` +command line option, or set the corresponding configuration value in `swift-java.config` (TODO). + +This approach is type-safe, however it incurs a performance penalty for allocating a wrapper class for every +unsigned integer parameter passed to and from native Swift functions. + +SwiftJava _does not_ vendor or provide the Guava library as a dependency, and when using this mode +you are expected to add a Guava dependency to your Java project. + +> You can read more about the unsigned integers support + +| Swift type | Java type | +|------------|--------------------------------------------------------| +| `Int8` | `byte` | +| `UInt8` | `com.google.common.primitives.UnsignedInteger` (class) | +| `Int16` | `short` | +| `UInt16` | `char` | +| `Int32` | `int` | +| `UInt32` | `com.google.common.primitives.UnsignedInteger` (class)️ | +| `Int64` | `long` | +| `UInt64` | `com.google.common.primitives.UnsignedLong` (class) | +| `Float` | `float` | +| `Double` | `double` | + +> Note: The `wrap-guava` mode is currently only available in FFM mode of jextract. diff --git a/Sources/SwiftJavaLib/JavaClassTranslator.swift b/Sources/SwiftJavaLib/JavaClassTranslator.swift index bfd1657f..ea6ca481 100644 --- a/Sources/SwiftJavaLib/JavaClassTranslator.swift +++ b/Sources/SwiftJavaLib/JavaClassTranslator.swift @@ -517,7 +517,7 @@ extension JavaClassTranslator { package func renderConstructor( _ javaConstructor: Constructor ) throws -> DeclSyntax { - let parameters = try translateParameters(javaConstructor.getParameters()) + ["environment: JNIEnvironment? = nil"] + let parameters = try translateJavaParameters(javaConstructor.getParameters()) + ["environment: JNIEnvironment? = nil"] let parametersStr = parameters.map { $0.description }.joined(separator: ", ") let throwsStr = javaConstructor.throwsCheckedException ? "throws" : "" let accessModifier = javaConstructor.isPublic ? "public " : "" @@ -537,7 +537,7 @@ extension JavaClassTranslator { whereClause: String = "" ) throws -> DeclSyntax { // Map the parameters. - let parameters = try translateParameters(javaMethod.getParameters()) + let parameters = try translateJavaParameters(javaMethod.getParameters()) let parametersStr = parameters.map { $0.description }.joined(separator: ", ") @@ -700,7 +700,7 @@ extension JavaClassTranslator { } // Translate a Java parameter list into Swift parameters. - private func translateParameters(_ parameters: [Parameter?]) throws -> [FunctionParameterSyntax] { + private func translateJavaParameters(_ parameters: [Parameter?]) throws -> [FunctionParameterSyntax] { return try parameters.compactMap { javaParameter in guard let javaParameter else { return nil } diff --git a/Sources/SwiftJavaTool/Commands/JExtractCommand.swift b/Sources/SwiftJavaTool/Commands/JExtractCommand.swift index e4901bc2..03ca0cd7 100644 --- a/Sources/SwiftJavaTool/Commands/JExtractCommand.swift +++ b/Sources/SwiftJavaTool/Commands/JExtractCommand.swift @@ -61,6 +61,9 @@ extension SwiftJava { @Flag(help: "Some build systems require an output to be present when it was 'expected', even if empty. This is used by the JExtractSwiftPlugin build plugin, but otherwise should not be necessary.") var writeEmptyFiles: Bool = false + @Option(help: "The mode of generation to use for the output files. Used with jextract mode. By default, unsigned Swift types are imported as their bit-width compatible signed Java counterparts, and annotated using the '@Unsigned' annotation. You may choose the 'wrap-guava' mode in order to import types as class wrapper types (`UnsignedInteger` et al) defined by the Google Guava library's `com.google.common.primitives' package. that ensure complete type-safety with regards to unsigned values, however they incur an allocation and performance overhead.") + var unsignedNumbers: JExtractUnsignedIntegerMode = .default + @Option( help: """ A swift-java configuration file for a given Swift module name on which this module depends, @@ -81,6 +84,12 @@ extension SwiftJava.JExtractCommand { config.outputJavaDirectory = outputJava config.outputSwiftDirectory = outputSwift config.writeEmptyFiles = writeEmptyFiles + config.unsignedNumbersMode = unsignedNumbers + + guard checkModeCompatibility() else { + // check would have logged the reason for early exit. + return + } if let inputSwift = commonOptions.inputSwift { config.inputSwiftDirectory = inputSwift @@ -97,6 +106,28 @@ extension SwiftJava.JExtractCommand { try jextractSwift(config: config, dependentConfigs: dependentConfigs.map(\.1)) } + + /// Check if the configured modes are compatible, and fail if not + func checkModeCompatibility() -> Bool { + if self.mode == .jni { + switch self.unsignedNumbers { + case .annotate: + print("Error: JNI mode does not support '\(JExtractUnsignedIntegerMode.wrapGuava)' Unsigned integer mode! \(Self.helpMessage)") + return false + case .wrapGuava: + () // OK + } + } + + return true + } +} + +struct IncompatibleModeError: Error { + let message: String + init(_ message: String) { + self.message = message + } } extension SwiftJava.JExtractCommand { @@ -110,3 +141,4 @@ extension SwiftJava.JExtractCommand { } extension JExtractGenerationMode: ExpressibleByArgument {} +extension JExtractUnsignedIntegerMode: ExpressibleByArgument {} diff --git a/Sources/SwiftJavaTool/Commands/ResolveCommand.swift b/Sources/SwiftJavaTool/Commands/ResolveCommand.swift index 4f022d71..3eb01fe7 100644 --- a/Sources/SwiftJavaTool/Commands/ResolveCommand.swift +++ b/Sources/SwiftJavaTool/Commands/ResolveCommand.swift @@ -148,7 +148,7 @@ extension SwiftJava.ResolveCommand { } else { let suggestDisablingSandbox = "It may be that the Sandbox has prevented dependency fetching, please re-run with '--disable-sandbox'." fatalError("Gradle output had no SWIFT_JAVA_CLASSPATH! \(suggestDisablingSandbox). \n" + - "Output was:<<<\(outString ?? "")>>>; Err was:<<<\(errString ?? "")>>>") + "Output was:<<<\(outString)>>>; Err was:<<<\(errString ?? "")>>>") } return String(classpathOutput.dropFirst(SwiftJavaClasspathPrefix.count)) diff --git a/Sources/_Subprocess/Configuration.swift b/Sources/_Subprocess/Configuration.swift index 4dad1a47..ba6f15ba 100644 --- a/Sources/_Subprocess/Configuration.swift +++ b/Sources/_Subprocess/Configuration.swift @@ -40,7 +40,7 @@ public struct Configuration: Sendable { public var environment: Environment /// The working directory to use when running the executable. public var workingDirectory: FilePath - /// The platform specifc options to use when + /// The platform specific options to use when /// running the subprocess. public var platformOptions: PlatformOptions diff --git a/SwiftKitCore/build.gradle b/SwiftKitCore/build.gradle index 7bab76e0..82874e20 100644 --- a/SwiftKitCore/build.gradle +++ b/SwiftKitCore/build.gradle @@ -14,6 +14,7 @@ plugins { id("build-logic.java-application-conventions") + id("me.champeau.jmh") version "0.7.2" id("maven-publish") } @@ -45,12 +46,21 @@ java { languageVersion.set(JavaLanguageVersion.of(17)) } // Support Android 6+ (Java 7) - sourceCompatibility = JavaVersion.VERSION_1_7 - targetCompatibility = JavaVersion.VERSION_1_7 + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 } dependencies { - testImplementation 'junit:junit:4.13.2' + testImplementation(platform("org.junit:junit-bom:5.10.0")) + testImplementation("org.junit.jupiter:junit-jupiter") +} + +testing { + suites { + test { + useJUnitJupiter('5.10.3') + } + } } tasks.test { diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/NotImplementedError.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/NotImplementedError.java new file mode 100644 index 00000000..6956eaca --- /dev/null +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/NotImplementedError.java @@ -0,0 +1,24 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package org.swift.swiftkit.core; + +public class NotImplementedError extends AssertionError { + + private static final long serialVersionUID = 1L; + + public NotImplementedError(String message) { + super(message); + } +} \ No newline at end of file diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/Preconditions.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/Preconditions.java new file mode 100644 index 00000000..bd1e52b0 --- /dev/null +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/Preconditions.java @@ -0,0 +1,153 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +/* + * Copyright (C) 2007 The Guava Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +package org.swift.swiftkit.core; + +import org.swift.swiftkit.core.annotations.Nullable; + +/** + * Collection of convenience functions to check argument preconditions. + *

+ * Partially based on {@code com.google.common.base.Preconditions}. + */ +public final class Preconditions { + private Preconditions() { + } + + public static void checkArgument(boolean expression) { + if (!expression) { + throw new IllegalArgumentException(); + } + } + + public static void checkArgument(boolean expression, @Nullable String format) { + if (!expression) { + throw new IllegalArgumentException(format); + } + } + + public static void checkArgument(boolean expression, @Nullable String format, + @Nullable Object arg1) { + if (!expression) { + throw new IllegalArgumentException(String.format(format, arg1)); + } + } + + public static void checkArgument(boolean expression, @Nullable String format, + @Nullable Object arg1, + @Nullable Object arg2) { + if (!expression) { + throw new IllegalArgumentException(String.format(format, arg1, arg2)); + } + } + + public static T checkNotNull(@Nullable T reference) { + if (reference == null) { + throw new NullPointerException(); + } + + return reference; + } + + public static T checkNotNull(@Nullable T reference, @Nullable String message) { + if (reference == null) { + throw new NullPointerException(message); + } + + return reference; + } + + /* + * All recent hotspots (as of 2009) *really* like to have the natural code + * + * if (guardExpression) { + * throw new BadException(messageExpression); + * } + * + * refactored so that messageExpression is moved to a separate String-returning method. + * + * if (guardExpression) { + * throw new BadException(badMsg(...)); + * } + * + * The alternative natural refactorings into void or Exception-returning methods are much slower. + * This is a big deal - we're talking factors of 2-8 in microbenchmarks, not just 10-20%. (This is + * a hotspot optimizer bug, which should be fixed, but that's a separate, big project). + * + * The coding pattern above is heavily used in java.util, e.g. in ArrayList. There is a + * RangeCheckMicroBenchmark in the JDK that was used to test this. + * + * But the methods in this class want to throw different exceptions, depending on the args, so it + * appears that this pattern is not directly applicable. But we can use the ridiculous, devious + * trick of throwing an exception in the middle of the construction of another exception. Hotspot + * is fine with that. + */ + + /** + * Ensures that {@code index} specifies a valid element in an array, list or string of size + * {@code size}. An element index may range from zero, inclusive, to {@code size}, exclusive. + * + * @param index a user-supplied index identifying an element of an array, list or string + * @param size the size of that array, list or string + * @return the value of {@code index} + * @throws IndexOutOfBoundsException if {@code index} is negative or is not less than {@code size} + * @throws IllegalArgumentException if {@code size} is negative + */ + public static int checkElementIndex(int index, int size) { + return checkElementIndex(index, size, "index"); + } + + /** + * Ensures that {@code index} specifies a valid element in an array, list or string of size + * {@code size}. An element index may range from zero, inclusive, to {@code size}, exclusive. + * + * @param index a user-supplied index identifying an element of an array, list or string + * @param size the size of that array, list or string + * @param desc the text to use to describe this index in an error message + * @return the value of {@code index} + * @throws IndexOutOfBoundsException if {@code index} is negative or is not less than {@code size} + * @throws IllegalArgumentException if {@code size} is negative + */ + public static int checkElementIndex(int index, int size, String desc) { + // Carefully optimized for execution by hotspot (explanatory comment above) + if (index < 0 || index >= size) { + throw new IndexOutOfBoundsException( + String.format("%s, index:%d, size:%d", desc, index, size)); + } + return index; + } + + public static void checkPositionIndexes(int start, int end, int size) { + // Carefully optimized for execution by hotspot (explanatory comment above) + if (start < 0 || end < start || end > size) { + throw new IndexOutOfBoundsException( + String.format("Start index:%d, end index:%d, size: %d", start, end, size)); + } + } + +} diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/annotations/NonNull.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/annotations/NonNull.java new file mode 100644 index 00000000..cad6cd8b --- /dev/null +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/annotations/NonNull.java @@ -0,0 +1,28 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package org.swift.swiftkit.core.annotations; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.TYPE_USE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +// TODO: Consider depending on jspecify instead +@Documented +@Target(TYPE_USE) +@Retention(RUNTIME) +public @interface NonNull {} \ No newline at end of file diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/annotations/Nullable.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/annotations/Nullable.java new file mode 100644 index 00000000..c20ad884 --- /dev/null +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/annotations/Nullable.java @@ -0,0 +1,28 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package org.swift.swiftkit.core.annotations; + +import static java.lang.annotation.ElementType.TYPE_USE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +// TODO: Consider depending on jspecify instead +@Documented +@Target(TYPE_USE) +@Retention(RUNTIME) +public @interface Nullable {} \ No newline at end of file diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/annotations/Unsigned.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/annotations/Unsigned.java new file mode 100644 index 00000000..4bf8e354 --- /dev/null +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/annotations/Unsigned.java @@ -0,0 +1,42 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package org.swift.swiftkit.core.annotations; + +import jdk.jfr.Description; +import jdk.jfr.Label; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.*; + +/** + * Value is of an unsigned numeric type. + *

+ * This annotation is used to annotate java integer primitives when their + * corresponding Swift type was actually unsigned, e.g. an {@code @Unsigned long} + * in a method signature corresponds to a Swift {@code UInt64} type, and therefore + * negative values reported by the signed {@code long} should instead be interpreted positive values, + * larger than {@code Long.MAX_VALUE} that are just not representable using a signed {@code long}. + */ +@Documented +@Label("Unsigned integer type") +@Description("Value should be interpreted as unsigned data type") +@Target({TYPE_USE, PARAMETER, FIELD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface Unsigned { +} diff --git a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/SwiftValueLayout.java b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/SwiftValueLayout.java index c0a75144..be883e05 100644 --- a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/SwiftValueLayout.java +++ b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/SwiftValueLayout.java @@ -34,11 +34,19 @@ public static long addressByteSize() { } public static final ValueLayout.OfBoolean SWIFT_BOOL = ValueLayout.JAVA_BOOLEAN; + public static final ValueLayout.OfByte SWIFT_INT8 = ValueLayout.JAVA_BYTE; - public static final ValueLayout.OfChar SWIFT_UINT16 = ValueLayout.JAVA_CHAR; + public static final ValueLayout.OfByte SWIFT_UINT8 = SWIFT_INT8; + public static final ValueLayout.OfShort SWIFT_INT16 = ValueLayout.JAVA_SHORT; + public static final ValueLayout.OfChar SWIFT_UINT16 = ValueLayout.JAVA_CHAR; + public static final ValueLayout.OfInt SWIFT_INT32 = ValueLayout.JAVA_INT; + public static final ValueLayout.OfInt SWIFT_UINT32 = SWIFT_INT32; + public static final ValueLayout.OfLong SWIFT_INT64 = ValueLayout.JAVA_LONG; + public static final ValueLayout.OfLong SWIFT_UINT64 = SWIFT_INT64; + public static final ValueLayout.OfFloat SWIFT_FLOAT = ValueLayout.JAVA_FLOAT; public static final ValueLayout.OfDouble SWIFT_DOUBLE = ValueLayout.JAVA_DOUBLE; diff --git a/Tests/JExtractSwiftTests/Asserts/LoweringAssertions.swift b/Tests/JExtractSwiftTests/Asserts/LoweringAssertions.swift index eebfdf4a..0b8ca1d3 100644 --- a/Tests/JExtractSwiftTests/Asserts/LoweringAssertions.swift +++ b/Tests/JExtractSwiftTests/Asserts/LoweringAssertions.swift @@ -43,6 +43,7 @@ func assertLoweredFunction( translator.prepareForTranslation() let generator = FFMSwift2JavaGenerator( + config: config, translator: translator, javaPackage: "com.example.swift", swiftOutputDirectory: "/fake", @@ -128,6 +129,7 @@ func assertLoweredVariableAccessor( translator.prepareForTranslation() let generator = FFMSwift2JavaGenerator( + config: config, translator: translator, javaPackage: javaPackage, swiftOutputDirectory: "/fake", diff --git a/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift b/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift index ffefe907..e975d223 100644 --- a/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift +++ b/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift @@ -25,6 +25,7 @@ enum RenderKind { func assertOutput( dump: Bool = false, input: String, + config: Configuration? = nil, _ mode: JExtractGenerationMode, _ renderKind: RenderKind, swiftModuleName: String = "SwiftModule", @@ -36,8 +37,7 @@ func assertOutput( line: Int = #line, column: Int = #column ) throws { - var config = Configuration() - config.logLevel = .trace + var config = config ?? Configuration() config.swiftModule = swiftModuleName let translator = Swift2JavaTranslator(config: config) translator.dependenciesClasses = Array(javaClassLookupTable.keys) @@ -49,6 +49,7 @@ func assertOutput( switch mode { case .ffm: let generator = FFMSwift2JavaGenerator( + config: config, translator: translator, javaPackage: "com.example.swift", swiftOutputDirectory: "/fake", @@ -64,6 +65,7 @@ func assertOutput( case .jni: let generator = JNISwift2JavaGenerator( + config: config, translator: translator, javaPackage: "com.example.swift", swiftOutputDirectory: "/fake", diff --git a/Tests/JExtractSwiftTests/FuncCallbackImportTests.swift b/Tests/JExtractSwiftTests/FuncCallbackImportTests.swift index 1678f91f..a87294b0 100644 --- a/Tests/JExtractSwiftTests/FuncCallbackImportTests.swift +++ b/Tests/JExtractSwiftTests/FuncCallbackImportTests.swift @@ -47,6 +47,7 @@ final class FuncCallbackImportTests { let funcDecl = st.importedGlobalFuncs.first { $0.name == "callMe" }! let generator = FFMSwift2JavaGenerator( + config: config, translator: st, javaPackage: "com.example.swift", swiftOutputDirectory: "/fake", @@ -129,13 +130,13 @@ final class FuncCallbackImportTests { var config = Configuration() config.swiftModule = "__FakeModule" let st = Swift2JavaTranslator(config: config) - st.log.logLevel = .error try st.analyze(file: "Fake.swift", text: Self.class_interfaceFile) let funcDecl = st.importedGlobalFuncs.first { $0.name == "callMeMore" }! let generator = FFMSwift2JavaGenerator( + config: config, translator: st, javaPackage: "com.example.swift", swiftOutputDirectory: "/fake", @@ -251,6 +252,7 @@ final class FuncCallbackImportTests { let funcDecl = st.importedGlobalFuncs.first { $0.name == "withBuffer" }! let generator = FFMSwift2JavaGenerator( + config: config, translator: st, javaPackage: "com.example.swift", swiftOutputDirectory: "/fake", diff --git a/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift b/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift index 6854b260..a8d83a2a 100644 --- a/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift +++ b/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift @@ -246,6 +246,7 @@ extension FunctionDescriptorTests { }! let generator = FFMSwift2JavaGenerator( + config: config, translator: st, javaPackage: javaPackage, swiftOutputDirectory: "/fake", @@ -275,6 +276,7 @@ extension FunctionDescriptorTests { try st.analyze(file: "/fake/Sample.swiftinterface", text: interfaceFile) let generator = FFMSwift2JavaGenerator( + config: config, translator: st, javaPackage: javaPackage, swiftOutputDirectory: "/fake", diff --git a/Tests/JExtractSwiftTests/JNI/JNIClassTests.swift b/Tests/JExtractSwiftTests/JNI/JNIClassTests.swift index cfe78fbd..483d53f5 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIClassTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIClassTests.swift @@ -18,78 +18,92 @@ import Testing @Suite struct JNIClassTests { let source = """ - public class MyClass { - let x: Int64 - let y: Int64 - - public static func method() {} - - public init(x: Int64, y: Int64) { - self.x = y - self.y = y - } - - public init() { - self.x = 0 - self.y = 0 + public class MyClass { + let x: Int64 + let y: Int64 + + public static func method() {} + + public init(x: Int64, y: Int64) { + self.x = y + self.y = y + } + + public init() { + self.x = 0 + self.y = 0 + } + + public func doSomething(x: Int64) {} + + public func copy() -> MyClass {} + public func isEqual(to other: MyClass) -> Bool {} } - - public func doSomething(x: Int64) {} - - public func copy() -> MyClass {} - public func isEqual(to other: MyClass) -> Bool {} - } - """ + """ @Test func generatesJavaClass() throws { - try assertOutput(input: source, .jni, .java, expectedChunks: [ - """ - // Generated by jextract-swift - // Swift module: SwiftModule + try assertOutput( + input: source, + .jni, .java, + expectedChunks: [ + """ + // Generated by jextract-swift + // Swift module: SwiftModule - package com.example.swift; - - import org.swift.swiftkit.core.*; - import org.swift.swiftkit.core.util.*; + package com.example.swift; - public final class MyClass extends JNISwiftInstance { - static final String LIB_NAME = "SwiftModule"; - - @SuppressWarnings("unused") - private static final boolean INITIALIZED_LIBS = initializeLibs(); - static boolean initializeLibs() { - System.loadLibrary(LIB_NAME); - return true; - } - - public MyClass(long selfPointer, SwiftArena swiftArena) { - super(selfPointer, swiftArena); - } - """, - """ - private static native void $destroy(long selfPointer); - """, - """ - @Override - protected Runnable $createDestroyFunction() { - long self$ = this.$memoryAddress(); - if (CallTraces.TRACE_DOWNCALLS) { - CallTraces.traceDowncall("MyClass.$createDestroyFunction", - "this", this, - "self", self$); - } - return new Runnable() { - @Override - public void run() { - if (CallTraces.TRACE_DOWNCALLS) { - CallTraces.traceDowncall("MyClass.$destroy", "self", self$); - } - MyClass.$destroy(self$); + import org.swift.swiftkit.core.*; + import org.swift.swiftkit.core.util.*; + """, + """ + public final class MyClass extends JNISwiftInstance { + static final String LIB_NAME = "SwiftModule"; + + @SuppressWarnings("unused") + private static final boolean INITIALIZED_LIBS = initializeLibs(); + static boolean initializeLibs() { + System.loadLibrary(LIB_NAME); + return true; + } + + public MyClass(long selfPointer, SwiftArena swiftArena) { + super(selfPointer, swiftArena); + } + """, + ]) + try assertOutput( + input: source, + .jni, .java, + expectedChunks: [ + """ + private static native void $destroy(long selfPointer); + """ + ]) + try assertOutput( + input: source, + .jni, .java, + expectedChunks: [ + """ + @Override + protected Runnable $createDestroyFunction() { + long self$ = this.$memoryAddress(); + if (CallTraces.TRACE_DOWNCALLS) { + CallTraces.traceDowncall("MyClass.$createDestroyFunction", + "this", this, + "self", self$); } - }; - """ - ]) + return new Runnable() { + @Override + public void run() { + if (CallTraces.TRACE_DOWNCALLS) { + CallTraces.traceDowncall("MyClass.$destroy", "self", self$); + } + MyClass.$destroy(self$); + } + }; + """ + ]) } @Test @@ -101,18 +115,18 @@ struct JNIClassTests { expectedChunks: [ """ /** - * Downcall to Swift: - * {@snippet lang=swift : - * public static func method() - * } - */ + * Downcall to Swift: + * {@snippet lang=swift : + * public static func method() + * } + */ public static void method() { MyClass.$method(); } """, """ private static native void $method(); - """ + """, ] ) } @@ -169,7 +183,7 @@ struct JNIClassTests { """, """ private static native long $init(); - """ + """, ] ) } @@ -199,7 +213,7 @@ struct JNIClassTests { let resultBits$ = Int64(Int(bitPattern: result$)) return resultBits$.getJNIValue(in: environment!) } - """ + """, ] ) } @@ -251,7 +265,7 @@ struct JNIClassTests { """, """ private static native void $doSomething(long x, long self); - """ + """, ] ) } @@ -274,7 +288,7 @@ struct JNIClassTests { } self$.pointee.doSomething(x: Int64(fromJNI: x, in: environment!)) } - """, + """ ] ) } @@ -299,7 +313,7 @@ struct JNIClassTests { """, """ private static native long $copy(long self); - """ + """, ] ) } @@ -325,7 +339,7 @@ struct JNIClassTests { let resultBits$ = Int64(Int(bitPattern: result$)) return resultBits$.getJNIValue(in: environment!) } - """, + """ ] ) } @@ -350,7 +364,7 @@ struct JNIClassTests { """, """ private static native boolean $isEqual(long other, long self); - """ + """, ] ) } @@ -378,7 +392,7 @@ struct JNIClassTests { } return self$.pointee.isEqual(to: other$.pointee).getJNIValue(in: environment!) } - """, + """ ] ) } diff --git a/Tests/JExtractSwiftTests/JNI/JNIModuleTests.swift b/Tests/JExtractSwiftTests/JNI/JNIModuleTests.swift index 4696253c..be9cf0ce 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIModuleTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIModuleTests.swift @@ -43,6 +43,10 @@ struct JNIModuleTests { package com.example.swift; + import org.swift.swiftkit.core.*; + import org.swift.swiftkit.core.util.*; + import org.swift.swiftkit.core.annotations.*; + public final class SwiftModule { static final String LIB_NAME = "SwiftModule"; @@ -81,6 +85,7 @@ struct JNIModuleTests { * public func takeIntegers(i1: Int8, i2: Int16, i3: Int32, i4: Int64) -> UInt16 * } */ + @Unsigned public static char takeIntegers(byte i1, short i2, int i3, long i4) { return SwiftModule.$takeIntegers(i1, i2, i3, i4); } diff --git a/Tests/JExtractSwiftTests/JNI/JNIStructTests.swift b/Tests/JExtractSwiftTests/JNI/JNIStructTests.swift index a4084654..09a8626d 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIStructTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIStructTests.swift @@ -18,69 +18,81 @@ import Testing @Suite struct JNIStructTests { let source = """ - public struct MyStruct { - let x: Int64 - let y: Int64 - - public init(x: Int64, y: Int64) { - self.x = y - self.y = y + public struct MyStruct { + let x: Int64 + let y: Int64 + + public init(x: Int64, y: Int64) { + self.x = y + self.y = y + } + + public func doSomething(x: Int64) {} } - - public func doSomething(x: Int64) {} - } - """ + """ @Test func generatesJavaClass() throws { - try assertOutput(input: source, .jni, .java, expectedChunks: [ - """ - // Generated by jextract-swift - // Swift module: SwiftModule + try assertOutput( + input: source, .jni, .java, + expectedChunks: [ + """ + // Generated by jextract-swift + // Swift module: SwiftModule - package com.example.swift; - - import org.swift.swiftkit.core.*; - import org.swift.swiftkit.core.util.*; + package com.example.swift; - public final class MyStruct extends JNISwiftInstance { - static final String LIB_NAME = "SwiftModule"; - - @SuppressWarnings("unused") - private static final boolean INITIALIZED_LIBS = initializeLibs(); - static boolean initializeLibs() { - System.loadLibrary(LIB_NAME); - return true; - } - - public MyStruct(long selfPointer, SwiftArena swiftArena) { - super(selfPointer, swiftArena); - } - """, - """ - private static native void $destroy(long selfPointer); - """, - """ - @Override - protected Runnable $createDestroyFunction() { - long self$ = this.$memoryAddress(); - if (CallTraces.TRACE_DOWNCALLS) { - CallTraces.traceDowncall("MyStruct.$createDestroyFunction", - "this", this, - "self", self$); - } - return new Runnable() { - @Override - public void run() { - if (CallTraces.TRACE_DOWNCALLS) { - CallTraces.traceDowncall("MyStruct.$destroy", "self", self$); - } - MyStruct.$destroy(self$); + import org.swift.swiftkit.core.*; + import org.swift.swiftkit.core.util.*; + """,]) + try assertOutput(input: source, .jni, .java, expectedChunks: [ + """ + public final class MyStruct extends JNISwiftInstance { + static final String LIB_NAME = "SwiftModule"; + + @SuppressWarnings("unused") + private static final boolean INITIALIZED_LIBS = initializeLibs(); + static boolean initializeLibs() { + System.loadLibrary(LIB_NAME); + return true; } - }; - } - """ - ]) + + public MyStruct(long selfPointer, SwiftArena swiftArena) { + super(selfPointer, swiftArena); + } + """ + ]) + try assertOutput( + input: source, .jni, .java, + expectedChunks: [ + """ + private static native void $destroy(long selfPointer); + """ + ]) + try assertOutput( + input: source, .jni, .java, + expectedChunks: [ + """ + @Override + protected Runnable $createDestroyFunction() { + long self$ = this.$memoryAddress(); + if (CallTraces.TRACE_DOWNCALLS) { + CallTraces.traceDowncall("MyStruct.$createDestroyFunction", + "this", this, + "self", self$); + } + return new Runnable() { + @Override + public void run() { + if (CallTraces.TRACE_DOWNCALLS) { + CallTraces.traceDowncall("MyStruct.$destroy", "self", self$); + } + MyStruct.$destroy(self$); + } + }; + } + """ + ]) } @Test @@ -175,7 +187,7 @@ struct JNIStructTests { """, """ private static native void $doSomething(long x, long self); - """ + """, ] ) } @@ -198,7 +210,7 @@ struct JNIStructTests { } self$.pointee.doSomething(x: Int64(fromJNI: x, in: environment!)) } - """, + """ ] ) } diff --git a/Tests/JExtractSwiftTests/JNI/JNIUnsignedNumberTests.swift b/Tests/JExtractSwiftTests/JNI/JNIUnsignedNumberTests.swift new file mode 100644 index 00000000..f4dbffed --- /dev/null +++ b/Tests/JExtractSwiftTests/JNI/JNIUnsignedNumberTests.swift @@ -0,0 +1,154 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import JExtractSwiftLib +import JavaKitConfigurationShared +import Testing + +final class JNIUnsignedNumberTests { + + @Test("Import: UInt16 (char)") + func jni_unsignedChar() throws { + try assertOutput( + input: "public func unsignedChar(_ arg: UInt16)", + .jni, .java, + detectChunkByInitialLines: 2, + expectedChunks: [ + """ + /** + * Downcall to Swift: + * {@snippet lang=swift : + * public func unsignedChar(_ arg: UInt16) + * } + */ + public static void unsignedChar(@Unsigned char arg) { + SwiftModule.$unsignedChar(arg); + } + """, + """ + private static native void $unsignedChar(char arg); + """, + ] + ) + } + + @Test("Import: UInt32 (annotate)") + func jni_unsignedInt_annotate() throws { + var config = Configuration() + config.unsignedNumbersMode = .annotate + config.logLevel = .trace + + try assertOutput( + input: "public func unsignedInt(_ arg: UInt32)", + config: config, + .jni, .java, + detectChunkByInitialLines: 2, + expectedChunks: [ + """ + /** + * Downcall to Swift: + * {@snippet lang=swift : + * public func unsignedInt(_ arg: UInt32) + * } + */ + public static void unsignedInt(@Unsigned int arg) { + SwiftModule.$unsignedInt(arg); + } + private static native void $unsignedInt(int arg); + """, + ] + ) + } + + @Test("Import: return UInt32 (default)") + func jni_returnUnsignedIntDefault() throws { + let config = Configuration() + + try assertOutput( + input: "public func returnUnsignedInt() -> UInt32", + config: config, + .jni, .java, + detectChunkByInitialLines: 2, + expectedChunks: [ + """ + /** + * Downcall to Swift: + * {@snippet lang=swift : + * public func returnUnsignedInt() -> UInt32 + * } + */ + @Unsigned + public static int returnUnsignedInt() { + return SwiftModule.$returnUnsignedInt(); + } + private static native int $returnUnsignedInt(); + """, + ] + ) + } + + @Test("Import: return UInt64 (wrap, unsupported)") + func jni_return_unsignedLongWrap() throws { + var config = Configuration() + config.unsignedNumbersMode = .wrapGuava + + try assertOutput( + input: "public func returnUnsignedLong() -> UInt64", + config: config, + .jni, .java, + detectChunkByInitialLines: 2, + expectedChunks: [ + // we do not import in wrap mode + """ + public final class SwiftModule { + static final String LIB_NAME = "SwiftModule"; + + static { + System.loadLibrary(LIB_NAME); + } + + } + """, + ] + ) + } + + @Test("Import: take UInt64 return UInt32 (annotate)") + func jni_echo_unsignedLong_annotate() throws { + var config = Configuration() + config.unsignedNumbersMode = .annotate + + try assertOutput( + input: "public func unsignedLong(first: UInt64, second: UInt32) -> UInt32", + config: config, + .jni, .java, + detectChunkByInitialLines: 2, + expectedChunks: [ + """ + /** + * Downcall to Swift: + * {@snippet lang=swift : + * public func unsignedLong(first: UInt64, second: UInt32) -> UInt32 + * } + */ + @Unsigned + public static int unsignedLong(@Unsigned long first, @Unsigned int second) { + return SwiftModule.$unsignedLong(first, second); + } + private static native int $unsignedLong(long first, int second); + """, + ] + ) + } +} diff --git a/Tests/JExtractSwiftTests/JNI/JNIVariablesTests.swift b/Tests/JExtractSwiftTests/JNI/JNIVariablesTests.swift index 5757e8da..9d2fcb22 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIVariablesTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIVariablesTests.swift @@ -20,6 +20,7 @@ struct JNIVariablesTests { let membersSource = """ public class MyClass { + public let someByte: UInt8 public let constant: Int64 public var mutable: Int64 public var computed: Int64 { diff --git a/Tests/JExtractSwiftTests/MethodImportTests.swift b/Tests/JExtractSwiftTests/MethodImportTests.swift index 73357d6b..fd885f1b 100644 --- a/Tests/JExtractSwiftTests/MethodImportTests.swift +++ b/Tests/JExtractSwiftTests/MethodImportTests.swift @@ -73,6 +73,7 @@ final class MethodImportTests { try st.analyze(file: "Fake.swift", text: class_interfaceFile) let generator = FFMSwift2JavaGenerator( + config: config, translator: st, javaPackage: "com.example.swift", swiftOutputDirectory: "/fake", @@ -116,6 +117,7 @@ final class MethodImportTests { }! let generator = FFMSwift2JavaGenerator( + config: config, translator: st, javaPackage: "com.example.swift", swiftOutputDirectory: "/fake", @@ -157,6 +159,7 @@ final class MethodImportTests { }! let generator = FFMSwift2JavaGenerator( + config: config, translator: st, javaPackage: "com.example.swift", swiftOutputDirectory: "/fake", @@ -200,6 +203,7 @@ final class MethodImportTests { }! let generator = FFMSwift2JavaGenerator( + config: config, translator: st, javaPackage: "com.example.swift", swiftOutputDirectory: "/fake", @@ -243,6 +247,7 @@ final class MethodImportTests { }! let generator = FFMSwift2JavaGenerator( + config: config, translator: st, javaPackage: "com.example.swift", swiftOutputDirectory: "/fake", @@ -289,6 +294,7 @@ final class MethodImportTests { }! let generator = FFMSwift2JavaGenerator( + config: config, translator: st, javaPackage: "com.example.swift", swiftOutputDirectory: "/fake", @@ -331,6 +337,7 @@ final class MethodImportTests { }! let generator = FFMSwift2JavaGenerator( + config: config, translator: st, javaPackage: "com.example.swift", swiftOutputDirectory: "/fake", @@ -373,6 +380,7 @@ final class MethodImportTests { }! let generator = FFMSwift2JavaGenerator( + config: config, translator: st, javaPackage: "com.example.swift", swiftOutputDirectory: "/fake", @@ -417,6 +425,7 @@ final class MethodImportTests { }! let generator = FFMSwift2JavaGenerator( + config: config, translator: st, javaPackage: "com.example.swift", swiftOutputDirectory: "/fake", diff --git a/Tests/JExtractSwiftTests/UnsignedNumberTests.swift b/Tests/JExtractSwiftTests/UnsignedNumberTests.swift new file mode 100644 index 00000000..11b91e53 --- /dev/null +++ b/Tests/JExtractSwiftTests/UnsignedNumberTests.swift @@ -0,0 +1,268 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import JExtractSwiftLib +import JavaKitConfigurationShared +import Testing + +final class UnsignedNumberTests { + + @Test("Import: UInt16 (char)") + func unsignedChar() throws { + try assertOutput( + input: "public func unsignedChar(_ arg: UInt16)", + .ffm, .java, + detectChunkByInitialLines: 2, + expectedChunks: [ + """ + /** + * {@snippet lang=c : + * void swiftjava_SwiftModule_unsignedChar__(uint16_t arg) + * } + */ + private static class swiftjava_SwiftModule_unsignedChar__ { + private static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( + /* arg: */SwiftValueLayout.SWIFT_UINT16 + ); + """, + """ + public static void unsignedChar(@Unsigned char arg) { + swiftjava_SwiftModule_unsignedChar__.call(arg); + } + """, + ] + ) + } + + @Test("Import: UInt32 (wrap)") + func unsignedInt() throws { + var config = Configuration() + config.unsignedNumbersMode = .wrapGuava + + try assertOutput( + input: "public func unsignedInt(_ arg: UInt32)", + config: config, + .ffm, .java, + detectChunkByInitialLines: 2, + expectedChunks: [ + """ + /** + * {@snippet lang=c : + * void swiftjava_SwiftModule_unsignedInt__(uint32_t arg) + * } + */ + private static class swiftjava_SwiftModule_unsignedInt__ { + private static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( + /* arg: */SwiftValueLayout.SWIFT_UINT32 + ); + """, + """ + public static void unsignedInt(com.google.common.primitives.UnsignedInteger arg) { + swiftjava_SwiftModule_unsignedInt__.call(UnsignedNumbers.toPrimitive(arg)); + } + """, + ] + ) + } + + @Test("Import: UInt32 (annotate)") + func unsignedIntAnnotate() throws { + var config = Configuration() + config.unsignedNumbersMode = .annotate + + try assertOutput( + input: "public func unsignedInt(_ arg: UInt32)", + config: config, + .ffm, .java, + detectChunkByInitialLines: 2, + expectedChunks: [ + """ + /** + * {@snippet lang=c : + * void swiftjava_SwiftModule_unsignedInt__(uint32_t arg) + * } + */ + private static class swiftjava_SwiftModule_unsignedInt__ { + private static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( + /* arg: */SwiftValueLayout.SWIFT_UINT32 + ); + """, + """ + public static void unsignedInt(@Unsigned int arg) { + swiftjava_SwiftModule_unsignedInt__.call(arg); + } + """, + ] + ) + } + + @Test("Import: return UInt32 (default)") + func returnUnsignedIntDefault() throws { + let config = Configuration() + + try assertOutput( + input: "public func returnUnsignedInt() -> UInt32", + config: config, + .ffm, .java, + detectChunkByInitialLines: 2, + expectedChunks: [ + """ + /** + * {@snippet lang=c : + * uint32_t swiftjava_SwiftModule_returnUnsignedInt(void) + * } + */ + private static class swiftjava_SwiftModule_returnUnsignedInt { + private static final FunctionDescriptor DESC = FunctionDescriptor.of( + /* -> */SwiftValueLayout.SWIFT_UINT32 + ); + """, + """ + @Unsigned + public static int returnUnsignedInt() { + return swiftjava_SwiftModule_returnUnsignedInt.call(); + } + """, + ] + ) + } + + @Test("Import: return UInt64 (wrap)") + func return_unsignedLongWrap() throws { + var config = Configuration() + config.unsignedNumbersMode = .wrapGuava + + try assertOutput( + input: "public func returnUnsignedLong() -> UInt64", + config: config, + .ffm, .java, + detectChunkByInitialLines: 2, + expectedChunks: [ + """ + /** + * {@snippet lang=c : + * uint64_t swiftjava_SwiftModule_returnUnsignedLong(void) + * } + */ + private static class swiftjava_SwiftModule_returnUnsignedLong { + private static final FunctionDescriptor DESC = FunctionDescriptor.of( + /* -> */SwiftValueLayout.SWIFT_UINT64 + ); + """, + """ + public static com.google.common.primitives.UnsignedLong returnUnsignedLong() { + return com.google.common.primitives.UnsignedLong.fromLongBits(swiftjava_SwiftModule_returnUnsignedLong.call()); + } + """, + ] + ) + } + + @Test("Import: return UInt64 (annotate)") + func return_unsignedLong_annotate() throws { + var config = Configuration() + config.unsignedNumbersMode = .annotate + + try assertOutput( + input: "public func returnUnsignedLong() -> UInt64", + config: config, + .ffm, .java, + detectChunkByInitialLines: 2, + expectedChunks: [ + """ + /** + * {@snippet lang=c : + * uint64_t swiftjava_SwiftModule_returnUnsignedLong(void) + * } + */ + private static class swiftjava_SwiftModule_returnUnsignedLong { + private static final FunctionDescriptor DESC = FunctionDescriptor.of( + /* -> */SwiftValueLayout.SWIFT_UINT64 + ); + """, + """ + @Unsigned + public static long returnUnsignedLong() { + return swiftjava_SwiftModule_returnUnsignedLong.call(); + } + """, + ] + ) + } + + @Test("Import: take UInt64 (annotate)") + func take_unsignedLong_annotate() throws { + var config = Configuration() + config.unsignedNumbersMode = .annotate + + try assertOutput( + input: "public func takeUnsignedLong(arg: UInt64)", + config: config, + .ffm, .java, + detectChunkByInitialLines: 2, + expectedChunks: [ + """ + /** + * {@snippet lang=c : + * void swiftjava_SwiftModule_takeUnsignedLong_arg(uint64_t arg) + * } + */ + private static class swiftjava_SwiftModule_takeUnsignedLong_arg { + private static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( + /* arg: */SwiftValueLayout.SWIFT_UINT64 + ); + """, + """ + public static void takeUnsignedLong(@Unsigned long arg) { + swiftjava_SwiftModule_takeUnsignedLong_arg.call(arg); + } + """, + ] + ) + } + + @Test("Import: take UInt64 return UInt32 (annotate)") + func echo_unsignedLong_annotate() throws { + var config = Configuration() + config.unsignedNumbersMode = .annotate + + try assertOutput( + input: "public func unsignedLong(first: UInt64, second: UInt32) -> UInt32", + config: config, + .ffm, .java, + detectChunkByInitialLines: 2, + expectedChunks: [ + """ + /** + * {@snippet lang=c : + * uint32_t swiftjava_SwiftModule_unsignedLong_first_second(uint64_t first, uint32_t second) + * } + */ + private static class swiftjava_SwiftModule_unsignedLong_first_second { + private static final FunctionDescriptor DESC = FunctionDescriptor.of( + /* -> */SwiftValueLayout.SWIFT_UINT32 + /* first: */SwiftValueLayout.SWIFT_UINT64 + /* second: */SwiftValueLayout.SWIFT_UINT32 + ); + """, + """ + @Unsigned + public static int unsignedLong(@Unsigned long first, @Unsigned int second) { + return swiftjava_SwiftModule_unsignedLong_first_second.call(first, second); + } + """, + ] + ) + } +} From 2d89c613445a3baf41594529542dc167d4ebc115 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Fri, 1 Aug 2025 13:24:49 +0900 Subject: [PATCH 329/426] Fix: JNI + unsigned modes checking (#342) --- .../Commands/JExtractCommand.swift | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/Sources/SwiftJavaTool/Commands/JExtractCommand.swift b/Sources/SwiftJavaTool/Commands/JExtractCommand.swift index 03ca0cd7..105ace45 100644 --- a/Sources/SwiftJavaTool/Commands/JExtractCommand.swift +++ b/Sources/SwiftJavaTool/Commands/JExtractCommand.swift @@ -86,10 +86,7 @@ extension SwiftJava.JExtractCommand { config.writeEmptyFiles = writeEmptyFiles config.unsignedNumbersMode = unsignedNumbers - guard checkModeCompatibility() else { - // check would have logged the reason for early exit. - return - } + try checkModeCompatibility() if let inputSwift = commonOptions.inputSwift { config.inputSwiftDirectory = inputSwift @@ -108,18 +105,15 @@ extension SwiftJava.JExtractCommand { } /// Check if the configured modes are compatible, and fail if not - func checkModeCompatibility() -> Bool { + func checkModeCompatibility() throws { if self.mode == .jni { switch self.unsignedNumbers { case .annotate: - print("Error: JNI mode does not support '\(JExtractUnsignedIntegerMode.wrapGuava)' Unsigned integer mode! \(Self.helpMessage)") - return false + throw IllegalModeCombinationError("JNI mode does not support '\(JExtractUnsignedIntegerMode.wrapGuava)' Unsigned integer mode! \(Self.helpMessage)") case .wrapGuava: () // OK } } - - return true } } @@ -140,5 +134,12 @@ extension SwiftJava.JExtractCommand { } +struct IllegalModeCombinationError: Error { + let message: String + init(_ message: String) { + self.message = message + } +} + extension JExtractGenerationMode: ExpressibleByArgument {} extension JExtractUnsignedIntegerMode: ExpressibleByArgument {} From f7a5082b3e2794637b327bc2792a7363042e23a3 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Fri, 1 Aug 2025 14:05:13 +0900 Subject: [PATCH 330/426] Mark Sendable types as @ThreadSafe (#341) --- .../FFM/FFMSwift2JavaGenerator.swift | 3 + ...t2JavaGenerator+JavaBindingsPrinting.swift | 3 + .../SwiftNominalTypeDeclaration.swift | 16 ++++++ .../swiftkit/core/annotations/ThreadSafe.java | 42 ++++++++++++++ Tests/JExtractSwiftTests/SendableTests.swift | 56 +++++++++++++++++++ 5 files changed, 120 insertions(+) create mode 100644 SwiftKitCore/src/main/java/org/swift/swiftkit/core/annotations/ThreadSafe.java create mode 100644 Tests/JExtractSwiftTests/SendableTests.swift diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift index 29962621..3e60db14 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift @@ -278,6 +278,9 @@ extension FFMSwift2JavaGenerator { parentProtocol = "SwiftValue" } + if decl.swiftNominal.isSendable { + printer.print("@ThreadSafe // Sendable") + } printer.printBraceBlock("public final class \(decl.swiftNominal.name) extends FFMSwiftInstance implements \(parentProtocol)") { printer in // Constants diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift index 63b9dcd1..b91588df 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift @@ -171,6 +171,9 @@ extension JNISwift2JavaGenerator { private func printNominal( _ printer: inout CodePrinter, _ decl: ImportedNominalType, body: (inout CodePrinter) -> Void ) { + if decl.swiftNominal.isSendable { + printer.print("@ThreadSafe // Sendable") + } printer.printBraceBlock("public final class \(decl.swiftNominal.name) extends JNISwiftInstance") { printer in body(&printer) } diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftNominalTypeDeclaration.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftNominalTypeDeclaration.swift index b377fd85..cef4e731 100644 --- a/Sources/JExtractSwiftLib/SwiftTypes/SwiftNominalTypeDeclaration.swift +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftNominalTypeDeclaration.swift @@ -85,6 +85,22 @@ package class SwiftNominalTypeDeclaration: SwiftTypeDeclaration { super.init(moduleName: moduleName, name: node.name.text) } + /// Returns true if this type conforms to `Sendable` and therefore is "threadsafe". + lazy var isSendable: Bool = { + // Check if Sendable is in the inheritance list + guard let inheritanceClause = self.syntax?.inheritanceClause else { + return false + } + + for inheritedType in inheritanceClause.inheritedTypes { + if inheritedType.type.trimmedDescription == "Sendable" { + return true + } + } + + return false + }() + /// Determine the known standard library type for this nominal type /// declaration. private func computeKnownStandardLibraryType() -> SwiftKnownTypeDeclKind? { diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/annotations/ThreadSafe.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/annotations/ThreadSafe.java new file mode 100644 index 00000000..2e62a8b6 --- /dev/null +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/annotations/ThreadSafe.java @@ -0,0 +1,42 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package org.swift.swiftkit.core.annotations; + +import jdk.jfr.Description; +import jdk.jfr.Label; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.*; + +/** + * Used to mark a type as thread-safe, i.e. no additional synchronization is necessary when accessing it + * from multiple threads. + * + *

In SwiftJava specifically, this attribute is applied when an extracted Swift type conforms to the Swift + * {@code Sendable} protocol, which is a compiler enforced mechanism to enforce thread-safety in Swift. + * + * @see Swift Sendable API documentation. + */ +@Documented +@Label("Thread-safe") +@Description("Value should be interpreted as safe to be shared across threads.") +@Target({TYPE_USE}) +@Retention(RetentionPolicy.RUNTIME) +public @interface ThreadSafe { +} diff --git a/Tests/JExtractSwiftTests/SendableTests.swift b/Tests/JExtractSwiftTests/SendableTests.swift new file mode 100644 index 00000000..d6d0d2d6 --- /dev/null +++ b/Tests/JExtractSwiftTests/SendableTests.swift @@ -0,0 +1,56 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import JExtractSwiftLib +import Testing + +final class SendableTests { + let source = + """ + public struct SendableStruct: Sendable {} + """ + + + @Test("Import: Sendable struct (ffm)") + func sendableStruct_ffm() throws { + + try assertOutput( + input: source, .ffm, .java, + expectedChunks: [ + """ + @ThreadSafe // Sendable + public final class SendableStruct extends FFMSwiftInstance implements SwiftValue { + static final String LIB_NAME = "SwiftModule"; + static final Arena LIBRARY_ARENA = Arena.ofAuto(); + """, + ] + ) + } + + @Test("Import: Sendable struct (jni)") + func sendableStruct_jni() throws { + + try assertOutput( + input: source, .jni, .java, + expectedChunks: [ + """ + @ThreadSafe // Sendable + public final class SendableStruct extends JNISwiftInstance { + static final String LIB_NAME = "SwiftModule"; + """, + ] + ) + } + +} \ No newline at end of file From 02de9675d1f227b2814d581b7b56a2c6f0d4f6d9 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Fri, 1 Aug 2025 15:12:15 +0900 Subject: [PATCH 331/426] Allow jextract to optionally import package/internal decls as well (#343) --- .../Convenience/SwiftSyntax+Extensions.swift | 69 ++++++++++++++++--- Sources/JExtractSwiftLib/Logger.swift | 17 +++++ .../Swift2JavaTranslator.swift | 4 +- .../JExtractSwiftLib/Swift2JavaVisitor.swift | 27 +++++--- .../Configuration.swift | 4 ++ .../GenerationMode.swift | 15 +++- .../Commands/JExtractCommand.swift | 5 ++ .../InternalExtractTests.swift | 49 +++++++++++++ 8 files changed, 171 insertions(+), 19 deletions(-) create mode 100644 Tests/JExtractSwiftTests/InternalExtractTests.swift diff --git a/Sources/JExtractSwiftLib/Convenience/SwiftSyntax+Extensions.swift b/Sources/JExtractSwiftLib/Convenience/SwiftSyntax+Extensions.swift index da836d45..e71300af 100644 --- a/Sources/JExtractSwiftLib/Convenience/SwiftSyntax+Extensions.swift +++ b/Sources/JExtractSwiftLib/Convenience/SwiftSyntax+Extensions.swift @@ -51,23 +51,76 @@ extension DeclModifierSyntax { extension DeclModifierSyntax { var isPublic: Bool { switch self.name.tokenKind { - case .keyword(.private): return false - case .keyword(.fileprivate): return false - case .keyword(.internal): return false - case .keyword(.package): return false - case .keyword(.public): return true - case .keyword(.open): return true - default: return false + case .keyword(.private): false + case .keyword(.fileprivate): false + case .keyword(.internal): false + case .keyword(.package): false + case .keyword(.public): true + case .keyword(.open): true + default: false } } + + var isPackage: Bool { + switch self.name.tokenKind { + case .keyword(.private): false + case .keyword(.fileprivate): false + case .keyword(.internal): false + case .keyword(.package): true + case .keyword(.public): false + case .keyword(.open): false + default: false + } + } + + var isAtLeastPackage: Bool { + isPackage || isPublic + } + + var isInternal: Bool { + return switch self.name.tokenKind { + case .keyword(.private): false + case .keyword(.fileprivate): false + case .keyword(.internal): true + case .keyword(.package): false + case .keyword(.public): false + case .keyword(.open): false + default: false + } + } + + var isAtLeastInternal: Bool { + isInternal || isPackage || isPublic + } } extension WithModifiersSyntax { var isPublic: Bool { - self.modifiers.contains { modifier in + return self.modifiers.contains { modifier in modifier.isPublic } } + + var isAtLeastPackage: Bool { + if self.modifiers.isEmpty { + return false + } + + return self.modifiers.contains { modifier in + modifier.isAtLeastInternal + } + } + + var isAtLeastInternal: Bool { + if self.modifiers.isEmpty { + // we assume that default access level is internal + return true + } + + return self.modifiers.contains { modifier in + modifier.isAtLeastInternal + } + } } extension AttributeListSyntax.Element { diff --git a/Sources/JExtractSwiftLib/Logger.swift b/Sources/JExtractSwiftLib/Logger.swift index 541dbae4..5bffdc8c 100644 --- a/Sources/JExtractSwiftLib/Logger.swift +++ b/Sources/JExtractSwiftLib/Logger.swift @@ -27,6 +27,23 @@ public struct Logger { self.logLevel = logLevel } + public func error( + _ message: @autoclosure () -> String, + metadata: [String: Any] = [:], + file: String = #fileID, + line: UInt = #line, + function: String = #function + ) { + guard logLevel <= .error else { + return + } + + let metadataString: String = + if metadata.isEmpty { "" } else { "\(metadata)" } + + print("[error][\(file):\(line)](\(function)) \(message()) \(metadataString)") + } + public func warning( _ message: @autoclosure () -> String, metadata: [String: Any] = [:], diff --git a/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift b/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift index 3e2359f2..300b979f 100644 --- a/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift +++ b/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift @@ -200,7 +200,7 @@ extension Swift2JavaTranslator { _ nominalNode: some DeclGroupSyntax & NamedDeclSyntax & WithModifiersSyntax & WithAttributesSyntax, parent: ImportedNominalType? ) -> ImportedNominalType? { - if !nominalNode.shouldImport(log: log) { + if !nominalNode.shouldExtract(config: config, log: log) { return nil } @@ -225,7 +225,7 @@ extension Swift2JavaTranslator { guard swiftNominalDecl.moduleName == self.swiftModuleName else { return nil } - guard swiftNominalDecl.syntax!.shouldImport(log: log) else { + guard swiftNominalDecl.syntax!.shouldExtract(config: config, log: log) else { return nil } diff --git a/Sources/JExtractSwiftLib/Swift2JavaVisitor.swift b/Sources/JExtractSwiftLib/Swift2JavaVisitor.swift index 90181757..3efddbfc 100644 --- a/Sources/JExtractSwiftLib/Swift2JavaVisitor.swift +++ b/Sources/JExtractSwiftLib/Swift2JavaVisitor.swift @@ -15,9 +15,13 @@ import Foundation import SwiftParser import SwiftSyntax +import JavaKitConfigurationShared final class Swift2JavaVisitor { let translator: Swift2JavaTranslator + var config: Configuration { + self.translator.config + } init(translator: Swift2JavaTranslator) { self.translator = translator @@ -48,7 +52,7 @@ final class Swift2JavaVisitor { case .extensionDecl(let node): self.visit(extensionDecl: node, in: parent) case .typeAliasDecl: - break // TODO: Implement + break // TODO: Implement; https://github.com/swiftlang/swift-java/issues/338 case .associatedTypeDecl: break // TODO: Implement @@ -93,7 +97,7 @@ final class Swift2JavaVisitor { } func visit(functionDecl node: FunctionDeclSyntax, in typeContext: ImportedNominalType?) { - guard node.shouldImport(log: log) else { + guard node.shouldExtract(config: config, log: log) else { return } @@ -128,7 +132,7 @@ final class Swift2JavaVisitor { } func visit(variableDecl node: VariableDeclSyntax, in typeContext: ImportedNominalType?) { - guard node.shouldImport(log: log) else { + guard node.shouldExtract(config: config, log: log) else { return } @@ -182,7 +186,7 @@ final class Swift2JavaVisitor { self.log.info("Initializer must be within a current type; \(node)") return } - guard node.shouldImport(log: log) else { + guard node.shouldExtract(config: config, log: log) else { return } @@ -212,13 +216,20 @@ final class Swift2JavaVisitor { } extension DeclSyntaxProtocol where Self: WithModifiersSyntax & WithAttributesSyntax { - func shouldImport(log: Logger) -> Bool { - guard accessControlModifiers.contains(where: { $0.isPublic }) else { - log.trace("Skip import '\(self.qualifiedNameForDebug)': not public") + func shouldExtract(config: Configuration, log: Logger) -> Bool { + let meetsRequiredAccessLevel: Bool = + switch config.effectiveMinimumInputAccessLevelMode { + case .public: self.isPublic + case .package: self.isAtLeastPackage + case .internal: self.isAtLeastInternal + } + + guard meetsRequiredAccessLevel else { + log.debug("Skip import '\(self.qualifiedNameForDebug)': not at least \(config.effectiveMinimumInputAccessLevelMode)") return false } guard !attributes.contains(where: { $0.isJava }) else { - log.trace("Skip import '\(self.qualifiedNameForDebug)': is Java") + log.debug("Skip import '\(self.qualifiedNameForDebug)': is Java") return false } diff --git a/Sources/JavaKitConfigurationShared/Configuration.swift b/Sources/JavaKitConfigurationShared/Configuration.swift index c1ae7dd2..0ff089da 100644 --- a/Sources/JavaKitConfigurationShared/Configuration.swift +++ b/Sources/JavaKitConfigurationShared/Configuration.swift @@ -46,6 +46,10 @@ public struct Configuration: Codable { public var effectiveUnsignedNumbersMode: JExtractUnsignedIntegerMode { unsignedNumbersMode ?? .default } + public var minimumInputAccessLevelMode: JExtractMinimumAccessLevelMode? + public var effectiveMinimumInputAccessLevelMode: JExtractMinimumAccessLevelMode { + minimumInputAccessLevelMode ?? .default + } // ==== java 2 swift --------------------------------------------------------- diff --git a/Sources/JavaKitConfigurationShared/GenerationMode.swift b/Sources/JavaKitConfigurationShared/GenerationMode.swift index 190323a0..1feac411 100644 --- a/Sources/JavaKitConfigurationShared/GenerationMode.swift +++ b/Sources/JavaKitConfigurationShared/GenerationMode.swift @@ -59,7 +59,20 @@ extension JExtractUnsignedIntegerMode { } } - public static var `default`: JExtractUnsignedIntegerMode { + public static var `default`: Self { .annotate } } + +/// The minimum access level which +public enum JExtractMinimumAccessLevelMode: String, Codable { + case `public` + case `package` + case `internal` +} + +extension JExtractMinimumAccessLevelMode { + public static var `default`: Self { + .public + } +} diff --git a/Sources/SwiftJavaTool/Commands/JExtractCommand.swift b/Sources/SwiftJavaTool/Commands/JExtractCommand.swift index 105ace45..54a99708 100644 --- a/Sources/SwiftJavaTool/Commands/JExtractCommand.swift +++ b/Sources/SwiftJavaTool/Commands/JExtractCommand.swift @@ -64,6 +64,9 @@ extension SwiftJava { @Option(help: "The mode of generation to use for the output files. Used with jextract mode. By default, unsigned Swift types are imported as their bit-width compatible signed Java counterparts, and annotated using the '@Unsigned' annotation. You may choose the 'wrap-guava' mode in order to import types as class wrapper types (`UnsignedInteger` et al) defined by the Google Guava library's `com.google.common.primitives' package. that ensure complete type-safety with regards to unsigned values, however they incur an allocation and performance overhead.") var unsignedNumbers: JExtractUnsignedIntegerMode = .default + @Option(help: "The lowest access level of Swift declarations that should be extracted, defaults to 'public'.") + var minimumInputAccessLevel: JExtractMinimumAccessLevelMode = .default + @Option( help: """ A swift-java configuration file for a given Swift module name on which this module depends, @@ -85,6 +88,7 @@ extension SwiftJava.JExtractCommand { config.outputSwiftDirectory = outputSwift config.writeEmptyFiles = writeEmptyFiles config.unsignedNumbersMode = unsignedNumbers + config.minimumInputAccessLevelMode = minimumInputAccessLevel try checkModeCompatibility() @@ -143,3 +147,4 @@ struct IllegalModeCombinationError: Error { extension JExtractGenerationMode: ExpressibleByArgument {} extension JExtractUnsignedIntegerMode: ExpressibleByArgument {} +extension JExtractMinimumAccessLevelMode: ExpressibleByArgument {} diff --git a/Tests/JExtractSwiftTests/InternalExtractTests.swift b/Tests/JExtractSwiftTests/InternalExtractTests.swift new file mode 100644 index 00000000..78e71236 --- /dev/null +++ b/Tests/JExtractSwiftTests/InternalExtractTests.swift @@ -0,0 +1,49 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import JExtractSwiftLib +import JavaKitConfigurationShared +import Testing + +final class InternalExtractTests { + let text = + """ + internal func catchMeIfYouCan() + """ + + @Test("Import: internal decl if configured") + func data_swiftThunk() throws { + var config = Configuration() + config.minimumInputAccessLevelMode = .internal + + try assertOutput( + input: text, + config: config, + .ffm, .java, + expectedChunks: [ + """ + /** + * Downcall to Swift: + * {@snippet lang=swift : + * internal func catchMeIfYouCan() + * } + */ + public static void catchMeIfYouCan() { + swiftjava_SwiftModule_catchMeIfYouCan.call(); + } + """, + ] + ) + } +} \ No newline at end of file From b2f42a170154aa080256ca5a11a857197a52cf81 Mon Sep 17 00:00:00 2001 From: Mads Odgaard Date: Fri, 1 Aug 2025 17:34:31 +0200 Subject: [PATCH 332/426] [JExtract/JNI] Support optionals in JNI mode (#340) --- .../Sources/MySwiftLibrary/Optionals.swift | 75 ++++ .../com/example/swift/MySwiftClassTest.java | 4 + .../java/com/example/swift/OptionalsTest.java | 116 +++++ .../Convenience/JavaType+Extensions.swift | 75 ++++ ...t2JavaGenerator+JavaBindingsPrinting.swift | 20 +- ...ISwift2JavaGenerator+JavaTranslation.swift | 365 ++++++++++++++- ...wift2JavaGenerator+NativeTranslation.swift | 417 +++++++++++++++--- ...ift2JavaGenerator+SwiftThunkPrinting.swift | 21 +- Sources/JExtractSwiftLib/JNI/JNIType.swift | 98 ---- .../Documentation.docc/SupportedFeatures.md | 3 +- .../JNI/JNIClassTests.swift | 12 +- .../JNI/JNIClosureTests.swift | 4 +- .../JNI/JNIJavaKitTests.swift | 10 +- .../JNI/JNIModuleTests.swift | 3 +- .../JNI/JNIOptionalTests.swift | 253 +++++++++++ .../JNI/JNIStructTests.swift | 3 +- .../JNI/JNIVariablesTests.swift | 33 +- 17 files changed, 1300 insertions(+), 212 deletions(-) create mode 100644 Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/Optionals.swift create mode 100644 Samples/JExtractJNISampleApp/src/test/java/com/example/swift/OptionalsTest.java delete mode 100644 Sources/JExtractSwiftLib/JNI/JNIType.swift create mode 100644 Tests/JExtractSwiftTests/JNI/JNIOptionalTests.swift diff --git a/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/Optionals.swift b/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/Optionals.swift new file mode 100644 index 00000000..673ecb0b --- /dev/null +++ b/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/Optionals.swift @@ -0,0 +1,75 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import JavaKit + +public func optionalBool(input: Optional) -> Bool? { + return input +} + +public func optionalByte(input: Optional) -> Int8? { + return input +} + +public func optionalChar(input: Optional) -> UInt16? { + return input +} + +public func optionalShort(input: Optional) -> Int16? { + return input +} + +public func optionalInt(input: Optional) -> Int32? { + return input +} + +public func optionalLong(input: Optional) -> Int64? { + return input +} + +public func optionalFloat(input: Optional) -> Float? { + return input +} + +public func optionalDouble(input: Optional) -> Double? { + return input +} + +public func optionalString(input: Optional) -> String? { + return input +} + +public func optionalClass(input: Optional) -> MySwiftClass? { + return input +} + +public func optionalJavaKitLong(input: Optional) -> Int64? { + if let input { + return input.longValue() + } else { + return nil + } +} + +public func multipleOptionals( + input1: Optional, + input2: Optional, + input3: Optional, + input4: Optional, + input5: Optional, + input6: Optional, + input7: Optional +) -> Int64? { + return 1 +} diff --git a/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/MySwiftClassTest.java b/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/MySwiftClassTest.java index f034b904..e7de03ad 100644 --- a/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/MySwiftClassTest.java +++ b/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/MySwiftClassTest.java @@ -17,6 +17,10 @@ import org.junit.jupiter.api.Test; import org.swift.swiftkit.core.ConfinedSwiftMemorySession; +import java.util.Optional; +import java.util.OptionalInt; +import java.util.OptionalLong; + import static org.junit.jupiter.api.Assertions.*; public class MySwiftClassTest { diff --git a/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/OptionalsTest.java b/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/OptionalsTest.java new file mode 100644 index 00000000..f7262ad4 --- /dev/null +++ b/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/OptionalsTest.java @@ -0,0 +1,116 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package com.example.swift; + +import org.junit.jupiter.api.Test; +import org.swift.swiftkit.core.ConfinedSwiftMemorySession; + +import java.util.Optional; +import java.util.OptionalDouble; +import java.util.OptionalInt; +import java.util.OptionalLong; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class OptionalsTest { + @Test + void optionalBool() { + assertEquals(Optional.empty(), MySwiftLibrary.optionalBool(Optional.empty())); + assertEquals(Optional.of(true), MySwiftLibrary.optionalBool(Optional.of(true))); + } + + @Test + void optionalByte() { + assertEquals(Optional.empty(), MySwiftLibrary.optionalByte(Optional.empty())); + assertEquals(Optional.of((byte) 1) , MySwiftLibrary.optionalByte(Optional.of((byte) 1))); + } + + @Test + void optionalChar() { + assertEquals(Optional.empty(), MySwiftLibrary.optionalChar(Optional.empty())); + assertEquals(Optional.of((char) 42), MySwiftLibrary.optionalChar(Optional.of((char) 42))); + } + + @Test + void optionalShort() { + assertEquals(Optional.empty(), MySwiftLibrary.optionalShort(Optional.empty())); + assertEquals(Optional.of((short) -250), MySwiftLibrary.optionalShort(Optional.of((short) -250))); + } + + @Test + void optionalInt() { + assertEquals(OptionalInt.empty(), MySwiftLibrary.optionalInt(OptionalInt.empty())); + assertEquals(OptionalInt.of(999), MySwiftLibrary.optionalInt(OptionalInt.of(999))); + } + + @Test + void optionalLong() { + assertEquals(OptionalLong.empty(), MySwiftLibrary.optionalLong(OptionalLong.empty())); + assertEquals(OptionalLong.of(999), MySwiftLibrary.optionalLong(OptionalLong.of(999))); + } + + @Test + void optionalFloat() { + assertEquals(Optional.empty(), MySwiftLibrary.optionalFloat(Optional.empty())); + assertEquals(Optional.of(3.14f), MySwiftLibrary.optionalFloat(Optional.of(3.14f))); + } + + @Test + void optionalDouble() { + assertEquals(OptionalDouble.empty(), MySwiftLibrary.optionalDouble(OptionalDouble.empty())); + assertEquals(OptionalDouble.of(2.718), MySwiftLibrary.optionalDouble(OptionalDouble.of(2.718))); + } + + @Test + void optionalString() { + assertEquals(Optional.empty(), MySwiftLibrary.optionalString(Optional.empty())); + assertEquals(Optional.of("Hello Swift!"), MySwiftLibrary.optionalString(Optional.of("Hello Swift!"))); + } + + @Test + void optionalClass() { + try (var arena = new ConfinedSwiftMemorySession()) { + MySwiftClass c = MySwiftClass.init(arena); + assertEquals(Optional.empty(), MySwiftLibrary.optionalClass(Optional.empty(), arena)); + Optional optionalClass = MySwiftLibrary.optionalClass(Optional.of(c), arena); + assertTrue(optionalClass.isPresent()); + assertEquals(c.getX(), optionalClass.get().getX()); + } + } + + @Test + void optionalJavaKitLong() { + assertEquals(OptionalLong.empty(), MySwiftLibrary.optionalJavaKitLong(Optional.empty())); + assertEquals(OptionalLong.of(99L), MySwiftLibrary.optionalJavaKitLong(Optional.of(99L))); + } + + @Test + void multipleOptionals() { + try (var arena = new ConfinedSwiftMemorySession()) { + MySwiftClass c = MySwiftClass.init(arena); + OptionalLong result = MySwiftLibrary.multipleOptionals( + Optional.of((byte) 1), + Optional.of((short) 42), + OptionalInt.of(50), + OptionalLong.of(1000L), + Optional.of("42"), + Optional.of(c), + Optional.of(true) + ); + assertEquals(result, OptionalLong.of(1L)); + } + } +} \ No newline at end of file diff --git a/Sources/JExtractSwiftLib/Convenience/JavaType+Extensions.swift b/Sources/JExtractSwiftLib/Convenience/JavaType+Extensions.swift index f9a67419..cb849e79 100644 --- a/Sources/JExtractSwiftLib/Convenience/JavaType+Extensions.swift +++ b/Sources/JExtractSwiftLib/Convenience/JavaType+Extensions.swift @@ -36,4 +36,79 @@ extension JavaType { case .void: fatalError("There is no type signature for 'void'") } } + + /// Returns the next integral type with space for self and an additional byte. + var nextIntergralTypeWithSpaceForByte: (javaType: JavaType, swiftType: SwiftKnownTypeDeclKind, valueBytes: Int)? { + switch self { + case .boolean, .byte: (.short, .int16, 1) + case .char, .short: (.int, .int32, 2) + case .int: (.long, .int64, 4) + default: nil + } + } + + var optionalType: String? { + switch self { + case .boolean: "Optional" + case .byte: "Optional" + case .char: "Optional" + case .short: "Optional" + case .int: "OptionalInt" + case .long: "OptionalLong" + case .float: "Optional" + case .double: "OptionalDouble" + case .javaLangString: "Optional" + default: nil + } + } + + var optionalWrapperType: String? { + switch self { + case .boolean, .byte, .char, .short, .float, .javaLangString: "Optional" + case .int: "OptionalInt" + case .long: "OptionalLong" + case .double: "OptionalDouble" + default: nil + } + } + + var optionalPlaceholderValue: String? { + switch self { + case .boolean: "false" + case .byte: "(byte) 0" + case .char: "(char) 0" + case .short: "(short) 0" + case .int: "0" + case .long: "0L" + case .float: "0f" + case .double: "0.0" + case .array, .class: "null" + case .void: nil + } + } + + var jniCallMethodAName: String { + switch self { + case .boolean: "CallBooleanMethodA" + case .byte: "CallByteMethodA" + case .char: "CallCharMethodA" + case .short: "CallShortMethodA" + case .int: "CallIntMethodA" + case .long: "CallLongMethodA" + case .float: "CallFloatMethodA" + case .double: "CallDoubleMethodA" + case .void: "CallVoidMethodA" + default: "CallObjectMethodA" + } + } + + /// Returns whether this type returns `JavaValue` from JavaKit + var implementsJavaValue: Bool { + return switch self { + case .boolean, .byte, .char, .short, .int, .long, .float, .double, .void, .javaLangString: + true + default: + false + } + } } diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift index b91588df..0daf14de 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift @@ -12,6 +12,7 @@ // //===----------------------------------------------------------------------===// +import JavaTypes // MARK: Defaults @@ -20,6 +21,7 @@ extension JNISwift2JavaGenerator { static let defaultJavaImports: Array = [ "org.swift.swiftkit.core.*", "org.swift.swiftkit.core.util.*", + "java.util.*", // NonNull, Unsigned and friends "org.swift.swiftkit.core.annotations.*", @@ -279,11 +281,15 @@ extension JNISwift2JavaGenerator { let translatedDecl = translatedDecl(for: decl)! // Will always call with valid decl let nativeSignature = translatedDecl.nativeFunctionSignature let resultType = nativeSignature.result.javaType - var parameters = nativeSignature.parameters - if let selfParameter = nativeSignature.selfParameter { - parameters.append(selfParameter) + var parameters = nativeSignature.parameters.flatMap(\.parameters) + if let selfParameter = nativeSignature.selfParameter?.parameters { + parameters += selfParameter } - let renderedParameters = parameters.map { "\($0.javaType) \($0.name)"}.joined(separator: ", ") + parameters += nativeSignature.result.outParameters + + let renderedParameters = parameters.map { javaParameter in + "\(javaParameter.type) \(javaParameter.name)" + }.joined(separator: ", ") printer.print("private static native \(resultType) \(translatedDecl.nativeFunctionName)(\(renderedParameters));") } @@ -308,6 +314,12 @@ extension JNISwift2JavaGenerator { arguments.append(lowered) } + // Indirect return receivers + for outParameter in translatedFunctionSignature.resultType.outParameters { + printer.print("\(outParameter.type) \(outParameter.name) = \(outParameter.allocation.render());") + arguments.append(outParameter.name) + } + //=== Part 3: Downcall. // TODO: If we always generate a native method and a "public" method, we can actually choose our own thunk names // using the registry? diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift index 5908cfb1..0db77ece 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift @@ -190,14 +190,26 @@ extension JNISwift2JavaGenerator { let nominalTypeName = nominalType.nominalTypeDecl.name if let knownType = nominalType.nominalTypeDecl.knownTypeKind { - guard let javaType = JNIJavaTypeTranslator.translate(knownType: knownType, config: self.config) else { - throw JavaTranslationError.unsupportedSwiftType(swiftType) + switch knownType { + case .optional: + guard let genericArgs = nominalType.genericArguments, genericArgs.count == 1 else { + throw JavaTranslationError.unsupportedSwiftType(swiftType) + } + return try translateOptionalParameter( + wrappedType: genericArgs[0], + parameterName: parameterName + ) + + default: + guard let javaType = JNIJavaTypeTranslator.translate(knownType: knownType, config: self.config) else { + throw JavaTranslationError.unsupportedSwiftType(swiftType) + } + + return TranslatedParameter( + parameter: JavaParameter(name: parameterName, type: javaType, annotations: parameterAnnotations), + conversion: .placeholder + ) } - - return TranslatedParameter( - parameter: JavaParameter(name: parameterName, type: javaType, annotations: parameterAnnotations), - conversion: .placeholder - ) } if nominalType.isJavaKitWrapper { @@ -237,13 +249,22 @@ extension JNISwift2JavaGenerator { conversion: .placeholder ) - case .metatype, .optional, .tuple, .existential, .opaque, .genericParameter: + case .optional(let wrapped): + return try translateOptionalParameter( + wrappedType: wrapped, + parameterName: parameterName + ) + + case .metatype, .tuple, .existential, .opaque, .genericParameter: throw JavaTranslationError.unsupportedSwiftType(swiftType) } } - func unsignedResultConversion(_ from: SwiftType, to javaType: JavaType, - mode: JExtractUnsignedIntegerMode) -> JavaNativeConversionStep { + func unsignedResultConversion( + _ from: SwiftType, + to javaType: JavaType, + mode: JExtractUnsignedIntegerMode + ) -> JavaNativeConversionStep { switch mode { case .annotate: return .placeholder // no conversions @@ -253,6 +274,75 @@ extension JNISwift2JavaGenerator { } } + func translateOptionalParameter( + wrappedType swiftType: SwiftType, + parameterName: String + ) throws -> TranslatedParameter { + let parameterAnnotations: [JavaAnnotation] = getTypeAnnotations(swiftType: swiftType, config: config) + + switch swiftType { + case .nominal(let nominalType): + let nominalTypeName = nominalType.nominalTypeDecl.name + + if let knownType = nominalType.nominalTypeDecl.knownTypeKind { + guard let javaType = JNIJavaTypeTranslator.translate(knownType: knownType, config: self.config) else { + throw JavaTranslationError.unsupportedSwiftType(swiftType) + } + + guard let translatedClass = javaType.optionalType, let placeholderValue = javaType.optionalPlaceholderValue else { + throw JavaTranslationError.unsupportedSwiftType(swiftType) + } + + return TranslatedParameter( + parameter: JavaParameter( + name: parameterName, + type: JavaType(className: translatedClass), + annotations: parameterAnnotations + ), + conversion: .commaSeparated([ + .isOptionalPresent, + .method(.placeholder, function: "orElse", arguments: [.constant(placeholderValue)]) + ]) + ) + } + + if nominalType.isJavaKitWrapper { + guard let javaType = nominalTypeName.parseJavaClassFromJavaKitName(in: self.javaClassLookupTable) else { + throw JavaTranslationError.wrappedJavaClassTranslationNotProvided(swiftType) + } + + return TranslatedParameter( + parameter: JavaParameter( + name: parameterName, + type: .class(package: nil, name: "Optional<\(javaType)>"), + annotations: parameterAnnotations + ), + conversion: .method( + .placeholder, + function: "orElse", + arguments: [.constant("null")] + ) + ) + } + + // Assume JExtract imported class + return TranslatedParameter( + parameter: JavaParameter( + name: parameterName, + type: .class(package: nil, name: "Optional<\(nominalTypeName)>"), + annotations: parameterAnnotations + ), + conversion: .method( + .method(.placeholder, function: "map", arguments: [.constant("\(nominalType)::$memoryAddress")]), + function: "orElse", + arguments: [.constant("0L")] + ) + ) + default: + throw JavaTranslationError.unsupportedSwiftType(swiftType) + } + } + func translate(swiftResult: SwiftResult) throws -> TranslatedResult { let swiftType = swiftResult.type @@ -262,15 +352,25 @@ extension JNISwift2JavaGenerator { switch swiftType { case .nominal(let nominalType): if let knownType = nominalType.nominalTypeDecl.knownTypeKind { - guard let javaType = JNIJavaTypeTranslator.translate(knownType: knownType, config: self.config) else { - throw JavaTranslationError.unsupportedSwiftType(swiftType) + switch knownType { + case .optional: + guard let genericArgs = nominalType.genericArguments, genericArgs.count == 1 else { + throw JavaTranslationError.unsupportedSwiftType(swiftType) + } + return try translateOptionalResult(wrappedType: genericArgs[0]) + + default: + guard let javaType = JNIJavaTypeTranslator.translate(knownType: knownType, config: self.config) else { + throw JavaTranslationError.unsupportedSwiftType(swiftType) + } + + return TranslatedResult( + javaType: javaType, + annotations: resultAnnotations, + outParameters: [], + conversion: .placeholder + ) } - - return TranslatedResult( - javaType: javaType, - annotations: resultAnnotations, - conversion: .placeholder - ) } if nominalType.isJavaKitWrapper { @@ -282,13 +382,94 @@ extension JNISwift2JavaGenerator { return TranslatedResult( javaType: javaType, annotations: resultAnnotations, + outParameters: [], conversion: .constructSwiftValue(.placeholder, javaType) ) case .tuple([]): - return TranslatedResult(javaType: .void, conversion: .placeholder) + return TranslatedResult(javaType: .void, outParameters: [], conversion: .placeholder) + + case .optional(let wrapped): + return try translateOptionalResult(wrappedType: wrapped) - case .metatype, .optional, .tuple, .function, .existential, .opaque, .genericParameter: + case .metatype, .tuple, .function, .existential, .opaque, .genericParameter: + throw JavaTranslationError.unsupportedSwiftType(swiftType) + } + } + + func translateOptionalResult( + wrappedType swiftType: SwiftType + ) throws -> TranslatedResult { + let parameterAnnotations: [JavaAnnotation] = getTypeAnnotations(swiftType: swiftType, config: config) + + switch swiftType { + case .nominal(let nominalType): + let nominalTypeName = nominalType.nominalTypeDecl.name + + if let knownType = nominalType.nominalTypeDecl.knownTypeKind { + guard let javaType = JNIJavaTypeTranslator.translate(knownType: knownType, config: self.config) else { + throw JavaTranslationError.unsupportedSwiftType(swiftType) + } + + guard let returnType = javaType.optionalType, let optionalClass = javaType.optionalWrapperType else { + throw JavaTranslationError.unsupportedSwiftType(swiftType) + } + + // Check if we can fit the value and a discriminator byte in a primitive. + // so the return JNI value will be (value, discriminator) + if let nextIntergralTypeWithSpaceForByte = javaType.nextIntergralTypeWithSpaceForByte { + return TranslatedResult( + javaType: .class(package: nil, name: returnType), + annotations: parameterAnnotations, + outParameters: [], + conversion: .combinedValueToOptional( + .placeholder, + nextIntergralTypeWithSpaceForByte.javaType, + valueType: javaType, + valueSizeInBytes: nextIntergralTypeWithSpaceForByte.valueBytes, + optionalType: optionalClass + ) + ) + } else { + // Otherwise, we return the result as normal, but + // use an indirect return for the discriminator. + return TranslatedResult( + javaType: .class(package: nil, name: returnType), + annotations: parameterAnnotations, + outParameters: [ + OutParameter(name: "result_discriminator$", type: .array(.byte), allocation: .newArray(.byte, size: 1)) + ], + conversion: .toOptionalFromIndirectReturn( + discriminatorName: "result_discriminator$", + optionalClass: optionalClass, + javaType: javaType, + toValue: .placeholder + ) + ) + } + } + + guard !nominalType.isJavaKitWrapper else { + throw JavaTranslationError.unsupportedSwiftType(swiftType) + } + + // We assume this is a JExtract class. + let returnType = JavaType.class(package: nil, name: "Optional<\(nominalTypeName)>") + return TranslatedResult( + javaType: returnType, + annotations: parameterAnnotations, + outParameters: [ + OutParameter(name: "result_discriminator$", type: .array(.byte), allocation: .newArray(.byte, size: 1)) + ], + conversion: .toOptionalFromIndirectReturn( + discriminatorName: "result_discriminator$", + optionalClass: "Optional", + javaType: .long, + toValue: .constructSwiftValue(.placeholder, .class(package: nil, name: nominalTypeName)) + ) + ) + + default: throw JavaTranslationError.unsupportedSwiftType(swiftType) } } @@ -348,10 +529,33 @@ extension JNISwift2JavaGenerator { /// Java annotations that should be propagated from the result type onto the method var annotations: [JavaAnnotation] = [] + let outParameters: [OutParameter] + /// Represents how to convert the Java native result into a user-facing result. let conversion: JavaNativeConversionStep } + struct OutParameter { + enum Allocation { + case newArray(JavaType, size: Int) + + func render() -> String { + switch self { + case .newArray(let javaType, let size): + "new \(javaType)[\(size)]" + } + } + } + + let name: String + let type: JavaType + let allocation: Allocation + + var javaParameter: JavaParameter { + JavaParameter(name: self.name, type: self.type) + } + } + /// Represent a Swift closure type in the user facing Java API. /// /// Closures are translated to named functional interfaces in Java. @@ -367,6 +571,11 @@ extension JNISwift2JavaGenerator { /// The value being converted case placeholder + case constant(String) + + // Convert the results of the inner steps to a comma separated list. + indirect case commaSeparated([JavaNativeConversionStep]) + /// `value.$memoryAddress()` indirect case valueMemoryAddress(JavaNativeConversionStep) @@ -375,6 +584,43 @@ extension JNISwift2JavaGenerator { indirect case call(JavaNativeConversionStep, function: String) + indirect case method(JavaNativeConversionStep, function: String, arguments: [JavaNativeConversionStep] = []) + + case isOptionalPresent + + indirect case combinedValueToOptional(JavaNativeConversionStep, JavaType, valueType: JavaType, valueSizeInBytes: Int, optionalType: String) + + indirect case ternary(JavaNativeConversionStep, thenExp: JavaNativeConversionStep, elseExp: JavaNativeConversionStep) + + indirect case equals(JavaNativeConversionStep, JavaNativeConversionStep) + + indirect case subscriptOf(JavaNativeConversionStep, arguments: [JavaNativeConversionStep]) + + static func toOptionalFromIndirectReturn( + discriminatorName: String, + optionalClass: String, + javaType: JavaType, + toValue valueConversion: JavaNativeConversionStep + ) -> JavaNativeConversionStep { + .aggregate( + name: "result$", + type: javaType, + [ + .ternary( + .equals( + .subscriptOf(.constant(discriminatorName), arguments: [.constant("0")]), + .constant("1") + ), + thenExp: .method(.constant(optionalClass), function: "of", arguments: [valueConversion]), + elseExp: .method(.constant(optionalClass), function: "empty") + ) + ] + ) + } + + /// Perform multiple conversions using the same input. + case aggregate(name: String, type: JavaType, [JavaNativeConversionStep]) + /// Returns the conversion string applied to the placeholder. func render(_ printer: inout CodePrinter, _ placeholder: String) -> String { // NOTE: 'printer' is used if the conversion wants to cause side-effects. @@ -383,6 +629,12 @@ extension JNISwift2JavaGenerator { case .placeholder: return placeholder + case .constant(let value): + return value + + case .commaSeparated(let list): + return list.map({ $0.render(&printer, placeholder)}).joined(separator: ", ") + case .valueMemoryAddress: return "\(placeholder).$memoryAddress()" @@ -394,13 +646,63 @@ extension JNISwift2JavaGenerator { let inner = inner.render(&printer, placeholder) return "\(function)(\(inner))" + + case .isOptionalPresent: + return "(byte) (\(placeholder).isPresent() ? 1 : 0)" + + case .method(let inner, let methodName, let arguments): + let inner = inner.render(&printer, placeholder) + let args = arguments.map { $0.render(&printer, placeholder) } + let argsStr = args.joined(separator: ", ") + return "\(inner).\(methodName)(\(argsStr))" + + case .combinedValueToOptional(let combined, let combinedType, let valueType, let valueSizeInBytes, let optionalType): + let combined = combined.render(&printer, placeholder) + printer.print( + """ + \(combinedType) combined$ = \(combined); + byte discriminator$ = (byte) (combined$ & 0xFF); + """ + ) + + if valueType == .boolean { + printer.print("boolean value$ = ((byte) (combined$ >> 8)) != 0;") + } else { + printer.print("\(valueType) value$ = (\(valueType)) (combined$ >> \(valueSizeInBytes * 8));") + } + + return "discriminator$ == 1 ? \(optionalType).of(value$) : \(optionalType).empty()" + + case .ternary(let cond, let thenExp, let elseExp): + let cond = cond.render(&printer, placeholder) + let thenExp = thenExp.render(&printer, placeholder) + let elseExp = elseExp.render(&printer, placeholder) + return "(\(cond)) ? \(thenExp) : \(elseExp)" + + case .equals(let lhs, let rhs): + let lhs = lhs.render(&printer, placeholder) + let rhs = rhs.render(&printer, placeholder) + return "\(lhs) == \(rhs)" + + case .subscriptOf(let inner, let arguments): + let inner = inner.render(&printer, placeholder) + let arguments = arguments.map { $0.render(&printer, placeholder) } + return "\(inner)[\(arguments.joined(separator: ", "))]" + + case .aggregate(let name, let type, let steps): + precondition(!steps.isEmpty, "Aggregate must contain steps") + printer.print("\(type) \(name) = \(placeholder);") + let steps = steps.map { + $0.render(&printer, name) + } + return steps.last! } } /// Whether the conversion uses SwiftArena. var requiresSwiftArena: Bool { switch self { - case .placeholder: + case .placeholder, .constant, .isOptionalPresent: return false case .constructSwiftValue: @@ -409,6 +711,27 @@ extension JNISwift2JavaGenerator { case .valueMemoryAddress(let inner): return inner.requiresSwiftArena + case .commaSeparated(let list): + return list.contains(where: { $0.requiresSwiftArena }) + + case .method(let inner, _, let args): + return inner.requiresSwiftArena || args.contains(where: \.requiresSwiftArena) + + case .combinedValueToOptional(let inner, _, _, _, _): + return inner.requiresSwiftArena + + case .ternary(let cond, let thenExp, let elseExp): + return cond.requiresSwiftArena || thenExp.requiresSwiftArena || elseExp.requiresSwiftArena + + case .equals(let lhs, let rhs): + return lhs.requiresSwiftArena || rhs.requiresSwiftArena + + case .subscriptOf(let inner, _): + return inner.requiresSwiftArena + + case .aggregate(_, _, let steps): + return steps.contains(where: \.requiresSwiftArena) + case .call(let inner, _): return inner.requiresSwiftArena } diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift index 9f1113fc..e7f7efbe 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift @@ -72,16 +72,30 @@ extension JNISwift2JavaGenerator { let nominalTypeName = nominalType.nominalTypeDecl.name if let knownType = nominalType.nominalTypeDecl.knownTypeKind { - guard let javaType = JNIJavaTypeTranslator.translate(knownType: knownType, config: self.config), - javaType.implementsJavaValue else { - throw JavaTranslationError.unsupportedSwiftType(swiftParameter.type) - } + switch knownType { + case .optional: + guard let genericArgs = nominalType.genericArguments, genericArgs.count == 1 else { + throw JavaTranslationError.unsupportedSwiftType(swiftParameter.type) + } + return try translateOptionalParameter( + wrappedType: genericArgs[0], + parameterName: parameterName + ) + + default: + guard let javaType = JNIJavaTypeTranslator.translate(knownType: knownType, config: self.config), + javaType.implementsJavaValue else { + throw JavaTranslationError.unsupportedSwiftType(swiftParameter.type) + } + + return NativeParameter( + parameters: [ + JavaParameter(name: parameterName, type: javaType) + ], + conversion: .initFromJNI(.placeholder, swiftType: swiftParameter.type) + ) - return NativeParameter( - name: parameterName, - javaType: javaType, - conversion: .initFromJNI(.placeholder, swiftType: swiftParameter.type) - ) + } } if nominalType.isJavaKitWrapper { @@ -90,23 +104,33 @@ extension JNISwift2JavaGenerator { } return NativeParameter( - name: parameterName, - javaType: javaType, - conversion: .initializeJavaKitWrapper(wrapperName: nominalTypeName) + parameters: [ + JavaParameter(name: parameterName, type: javaType) + ], + conversion: .initializeJavaKitWrapper( + .unwrapOptional( + .placeholder, + name: parameterName, + fatalErrorMessage: "\(parameterName) was null in call to \\(#function), but Swift requires non-optional!" + ), + wrapperName: nominalTypeName + ) ) } // JExtract classes are passed as the pointer. return NativeParameter( - name: parameterName, - javaType: .long, + parameters: [ + JavaParameter(name: parameterName, type: .long) + ], conversion: .pointee(.extractSwiftValue(.placeholder, swiftType: swiftParameter.type)) ) case .tuple([]): return NativeParameter( - name: parameterName, - javaType: .void, + parameters: [ + JavaParameter(name: parameterName, type: .void) + ], conversion: .placeholder ) @@ -124,19 +148,162 @@ extension JNISwift2JavaGenerator { let result = try translateClosureResult(fn.resultType) return NativeParameter( - name: parameterName, - javaType: .class(package: javaPackage, name: "\(parentName).\(methodName).\(parameterName)"), + parameters: [ + JavaParameter(name: parameterName, type: .class(package: javaPackage, name: "\(parentName).\(methodName).\(parameterName)")) + ], conversion: .closureLowering( parameters: parameters, result: result ) ) - case .metatype, .optional, .tuple, .existential, .opaque, .genericParameter: + case .optional(let wrapped): + return try translateOptionalParameter( + wrappedType: wrapped, + parameterName: parameterName + ) + + case .metatype, .tuple, .existential, .opaque, .genericParameter: throw JavaTranslationError.unsupportedSwiftType(swiftParameter.type) } } + func translateOptionalParameter( + wrappedType swiftType: SwiftType, + parameterName: String + ) throws -> NativeParameter { + let discriminatorName = "\(parameterName)_discriminator" + let valueName = "\(parameterName)_value" + + switch swiftType { + case .nominal(let nominalType): + let nominalTypeName = nominalType.nominalTypeDecl.name + + if let knownType = nominalType.nominalTypeDecl.knownTypeKind { + guard let javaType = JNIJavaTypeTranslator.translate(knownType: knownType, config: self.config), + javaType.implementsJavaValue else { + throw JavaTranslationError.unsupportedSwiftType(swiftType) + } + + return NativeParameter( + parameters: [ + JavaParameter(name: discriminatorName, type: .byte), + JavaParameter(name: valueName, type: javaType) + ], + conversion: .optionalLowering( + .initFromJNI(.placeholder, swiftType: swiftType), + discriminatorName: discriminatorName, + valueName: valueName + ) + ) + } + + if nominalType.isJavaKitWrapper { + guard let javaType = nominalTypeName.parseJavaClassFromJavaKitName(in: self.javaClassLookupTable) else { + throw JavaTranslationError.wrappedJavaClassTranslationNotProvided(swiftType) + } + + return NativeParameter( + parameters: [ + JavaParameter(name: parameterName, type: javaType) + ], + conversion: .optionalMap(.initializeJavaKitWrapper(.placeholder, wrapperName: nominalTypeName)) + ) + } + + // Assume JExtract wrapped class + return NativeParameter( + parameters: [JavaParameter(name: parameterName, type: .long)], + conversion: .pointee( + .optionalChain( + .extractSwiftValue( + .placeholder, + swiftType: swiftType, + allowNil: true + ) + ) + ) + ) + + default: + throw JavaTranslationError.unsupportedSwiftType(swiftType) + } + } + + func translateOptionalResult( + wrappedType swiftType: SwiftType + ) throws -> NativeResult { + switch swiftType { + case .nominal(let nominalType): + if let knownType = nominalType.nominalTypeDecl.knownTypeKind { + guard let javaType = JNIJavaTypeTranslator.translate(knownType: knownType, config: self.config), + javaType.implementsJavaValue else { + throw JavaTranslationError.unsupportedSwiftType(swiftType) + } + + // Check if we can fit the value and a discriminator byte in a primitive. + // so the return JNI value will be (value, discriminator) + if let nextIntergralTypeWithSpaceForByte = javaType.nextIntergralTypeWithSpaceForByte { + return NativeResult( + javaType: nextIntergralTypeWithSpaceForByte.javaType, + conversion: .getJNIValue( + .optionalRaisingWidenIntegerType( + .placeholder, + valueType: javaType, + combinedSwiftType: nextIntergralTypeWithSpaceForByte.swiftType, + valueSizeInBytes: nextIntergralTypeWithSpaceForByte.valueBytes + ) + ), + outParameters: [] + ) + } else { + // Use indirect byte array to store discriminator + let discriminatorName = "result_discriminator$" + + return NativeResult( + javaType: javaType, + conversion: .optionalRaisingIndirectReturn( + .getJNIValue(.placeholder), + returnType: javaType, + discriminatorParameterName: discriminatorName, + placeholderValue: .member( + .constant("\(swiftType)"), + member: "jniPlaceholderValue" + ) + ), + outParameters: [ + JavaParameter(name: discriminatorName, type: .array(.byte)) + ] + ) + } + } + + guard !nominalType.isJavaKitWrapper else { + // TODO: Should be the same as above + throw JavaTranslationError.unsupportedSwiftType(swiftType) + } + + // Assume JExtract imported class + let discriminatorName = "result_discriminator$" + + return NativeResult( + javaType: .long, + conversion: .optionalRaisingIndirectReturn( + .getJNIValue(.allocateSwiftValue(name: "_result", swiftType: swiftType)), + returnType: .long, + discriminatorParameterName: discriminatorName, + placeholderValue: .constant("0") + ), + outParameters: [ + JavaParameter(name: discriminatorName, type: .array(.byte)) + ] + ) + + default: + throw JavaTranslationError.unsupportedSwiftType(swiftType) + } + } + func translateClosureResult( _ type: SwiftType ) throws -> NativeResult { @@ -151,7 +318,8 @@ extension JNISwift2JavaGenerator { // Only support primitives for now. return NativeResult( javaType: javaType, - conversion: .initFromJNI(.placeholder, swiftType: type) + conversion: .initFromJNI(.placeholder, swiftType: type), + outParameters: [] ) } @@ -161,7 +329,8 @@ extension JNISwift2JavaGenerator { case .tuple([]): return NativeResult( javaType: .void, - conversion: .placeholder + conversion: .placeholder, + outParameters: [] ) case .function, .metatype, .optional, .tuple, .existential, .opaque, .genericParameter: @@ -183,8 +352,9 @@ extension JNISwift2JavaGenerator { // Only support primitives for now. return NativeParameter( - name: parameterName, - javaType: javaType, + parameters: [ + JavaParameter(name: parameterName, type: javaType) + ], conversion: .getJValue(.placeholder) ) } @@ -203,17 +373,24 @@ extension JNISwift2JavaGenerator { switch swiftResult.type { case .nominal(let nominalType): if let knownType = nominalType.nominalTypeDecl.knownTypeKind { - guard let javaType = JNIJavaTypeTranslator.translate(knownType: knownType, config: self.config) else { - throw JavaTranslationError.unsupportedSwiftType(swiftResult.type) + switch knownType { + case .optional: + guard let genericArgs = nominalType.genericArguments, genericArgs.count == 1 else { + throw JavaTranslationError.unsupportedSwiftType(swiftResult.type) + } + return try translateOptionalResult(wrappedType: genericArgs[0]) + + default: + guard let javaType = JNIJavaTypeTranslator.translate(knownType: knownType, config: self.config), javaType.implementsJavaValue else { + throw JavaTranslationError.unsupportedSwiftType(swiftResult.type) + } + + return NativeResult( + javaType: javaType, + conversion: .getJNIValue(.placeholder), + outParameters: [] + ) } - guard javaType.implementsJavaValue else { - throw JavaTranslationError.unsupportedSwiftType(swiftResult.type) - } - - return NativeResult( - javaType: javaType, - conversion: .getJNIValue(.placeholder) - ) } if nominalType.isJavaKitWrapper { @@ -222,20 +399,23 @@ extension JNISwift2JavaGenerator { return NativeResult( javaType: .long, - conversion: .getJNIValue(.allocateSwiftValue(name: "result", swiftType: swiftResult.type)) + conversion: .getJNIValue(.allocateSwiftValue(name: "result", swiftType: swiftResult.type)), + outParameters: [] ) case .tuple([]): return NativeResult( javaType: .void, - conversion: .placeholder + conversion: .placeholder, + outParameters: [] ) - case .metatype, .optional, .tuple, .function, .existential, .opaque, .genericParameter: + case .optional(let wrapped): + return try translateOptionalResult(wrappedType: wrapped) + + case .metatype, .tuple, .function, .existential, .opaque, .genericParameter: throw JavaTranslationError.unsupportedSwiftType(swiftResult.type) } - - } } @@ -246,12 +426,9 @@ extension JNISwift2JavaGenerator { } struct NativeParameter { - let name: String - let javaType: JavaType - - var jniType: JNIType { - javaType.jniType - } + /// One Swift parameter can be lowered to multiple parameters. + /// E.g. 'Optional' as (descriptor, value) pair. + var parameters: [JavaParameter] /// Represents how to convert the JNI parameter to a Swift parameter let conversion: NativeSwiftConversionStep @@ -260,6 +437,9 @@ extension JNISwift2JavaGenerator { struct NativeResult { let javaType: JavaType let conversion: NativeSwiftConversionStep + + /// Out parameters for populating the indirect return values. + var outParameters: [JavaParameter] } /// Describes how to convert values between Java types and Swift through JNI @@ -267,6 +447,8 @@ extension JNISwift2JavaGenerator { /// The value being converted case placeholder + case constant(String) + /// `value.getJNIValue(in:)` indirect case getJNIValue(NativeSwiftConversionStep) @@ -277,7 +459,11 @@ extension JNISwift2JavaGenerator { indirect case initFromJNI(NativeSwiftConversionStep, swiftType: SwiftType) /// Extracts a swift type at a pointer given by a long. - indirect case extractSwiftValue(NativeSwiftConversionStep, swiftType: SwiftType) + indirect case extractSwiftValue( + NativeSwiftConversionStep, + swiftType: SwiftType, + allowNil: Bool = false + ) /// Allocate memory for a Swift value and outputs the pointer case allocateSwiftValue(name: String, swiftType: SwiftType) @@ -288,7 +474,23 @@ extension JNISwift2JavaGenerator { indirect case closureLowering(parameters: [NativeParameter], result: NativeResult) - case initializeJavaKitWrapper(wrapperName: String) + indirect case initializeJavaKitWrapper(NativeSwiftConversionStep, wrapperName: String) + + indirect case optionalLowering(NativeSwiftConversionStep, discriminatorName: String, valueName: String) + + indirect case optionalChain(NativeSwiftConversionStep) + + indirect case optionalRaisingWidenIntegerType(NativeSwiftConversionStep, valueType: JavaType, combinedSwiftType: SwiftKnownTypeDeclKind, valueSizeInBytes: Int) + + indirect case optionalRaisingIndirectReturn(NativeSwiftConversionStep, returnType: JavaType, discriminatorParameterName: String, placeholderValue: NativeSwiftConversionStep) + + indirect case method(NativeSwiftConversionStep, function: String, arguments: [(String?, NativeSwiftConversionStep)] = []) + + indirect case member(NativeSwiftConversionStep, member: String) + + indirect case optionalMap(NativeSwiftConversionStep) + + indirect case unwrapOptional(NativeSwiftConversionStep, name: String, fatalErrorMessage: String) /// Returns the conversion string applied to the placeholder. func render(_ printer: inout CodePrinter, _ placeholder: String) -> String { @@ -298,6 +500,9 @@ extension JNISwift2JavaGenerator { case .placeholder: return placeholder + case .constant(let value): + return value + case .getJNIValue(let inner): let inner = inner.render(&printer, placeholder) return "\(inner).getJNIValue(in: environment!)" @@ -310,18 +515,28 @@ extension JNISwift2JavaGenerator { let inner = inner.render(&printer, placeholder) return "\(swiftType)(fromJNI: \(inner), in: environment!)" - case .extractSwiftValue(let inner, let swiftType): + case .extractSwiftValue(let inner, let swiftType, let allowNil): let inner = inner.render(&printer, placeholder) + let pointerName = "\(inner)$" + if !allowNil { + printer.print(#"assert(\#(inner) != 0, "\#(inner) memory address was null")"#) + } printer.print( """ - assert(\(inner) != 0, "\(inner) memory address was null") let \(inner)Bits$ = Int(Int64(fromJNI: \(inner), in: environment!)) - guard let \(inner)$ = UnsafeMutablePointer<\(swiftType)>(bitPattern: \(inner)Bits$) else { - fatalError("\(inner) memory address was null in call to \\(#function)!") - } + let \(pointerName) = UnsafeMutablePointer<\(swiftType)>(bitPattern: \(inner)Bits$) """ ) - return "\(inner)$" + if !allowNil { + printer.print( + """ + guard let \(pointerName) else { + fatalError("\(inner) memory address was null in call to \\(#function)!") + } + """ + ) + } + return pointerName case .allocateSwiftValue(let name, let swiftType): let pointerName = "\(name)$" @@ -344,15 +559,17 @@ extension JNISwift2JavaGenerator { let methodSignature = MethodSignature( resultType: nativeResult.javaType, - parameterTypes: parameters.map(\.javaType) + parameterTypes: parameters.flatMap { $0.parameters.map(\.type) } ) - let closureParameters = !parameters.isEmpty ? "\(parameters.map(\.name).joined(separator: ", ")) in" : "" + let names = parameters.flatMap { $0.parameters.map(\.name) } + let closureParameters = !parameters.isEmpty ? "\(names.joined(separator: ", ")) in" : "" printer.print("{ \(closureParameters)") printer.indent() + // TODO: Add support for types that are lowered to multiple parameters in closures let arguments = parameters.map { - $0.conversion.render(&printer, $0.name) + $0.conversion.render(&printer, $0.parameters.first!.name) } printer.print( @@ -363,7 +580,7 @@ extension JNISwift2JavaGenerator { """ ) - let upcall = "environment!.interface.\(nativeResult.javaType.jniType.callMethodAName)(environment, \(placeholder), methodID$, arguments$)" + let upcall = "environment!.interface.\(nativeResult.javaType.jniCallMethodAName)(environment, \(placeholder), methodID$, arguments$)" let result = nativeResult.conversion.render(&printer, upcall) if nativeResult.javaType.isVoid { @@ -377,8 +594,92 @@ extension JNISwift2JavaGenerator { return printer.finalize() - case .initializeJavaKitWrapper(let wrapperName): - return "\(wrapperName)(javaThis: \(placeholder), environment: environment!)" + case .initializeJavaKitWrapper(let inner, let wrapperName): + let inner = inner.render(&printer, placeholder) + return "\(wrapperName)(javaThis: \(inner), environment: environment!)" + + case .optionalLowering(let valueConversion, let discriminatorName, let valueName): + let value = valueConversion.render(&printer, valueName) + return "\(discriminatorName) == 1 ? \(value) : nil" + + case .optionalChain(let inner): + let inner = inner.render(&printer, placeholder) + return "\(inner)?" + + case .optionalRaisingWidenIntegerType(let inner, let valueType, let combinedSwiftType, let valueSizeInBytes): + let inner = inner.render(&printer, placeholder) + let value = valueType == .boolean ? "$0 ? 1 : 0" : "$0" + let combinedSwiftTypeName = combinedSwiftType.moduleAndName.name + printer.print( + """ + let value$ = \(inner).map { + \(combinedSwiftTypeName)(\(value)) << \(valueSizeInBytes * 8) | \(combinedSwiftTypeName)(1) + } ?? 0 + """ + ) + return "value$" + + case .optionalRaisingIndirectReturn(let inner, let returnType, let discriminatorParameterName, let placeholderValue): + printer.print("let result$: \(returnType.jniTypeName)") + printer.printBraceBlock("if let innerResult$ = \(placeholder)") { printer in + let inner = inner.render(&printer, "innerResult$") + printer.print( + """ + result$ = \(inner) + var flag$ = Int8(1) + environment.interface.SetByteArrayRegion(environment, \(discriminatorParameterName), 0, 1, &flag$) + """ + ) + } + printer.printBraceBlock("else") { printer in + let placeholderValue = placeholderValue.render(&printer, placeholder) + printer.print( + """ + result$ = \(placeholderValue) + var flag$ = Int8(0) + environment.interface.SetByteArrayRegion(environment, \(discriminatorParameterName), 0, 1, &flag$) + """ + ) + } + + return "result$" + + case .method(let inner, let methodName, let arguments): + let inner = inner.render(&printer, placeholder) + let args = arguments.map { name, value in + let value = value.render(&printer, placeholder) + if let name { + return "\(name): \(value)" + } else { + return value + } + } + let argsStr = args.joined(separator: ", ") + return "\(inner).\(methodName)(\(argsStr))" + + case .member(let inner, let member): + let inner = inner.render(&printer, placeholder) + return "\(inner).\(member)" + + case .optionalMap(let inner): + var printer = CodePrinter() + printer.printBraceBlock("\(placeholder).map") { printer in + let inner = inner.render(&printer, "$0") + printer.print("return \(inner)") + } + return printer.finalize() + + case .unwrapOptional(let inner, let name, let fatalErrorMessage): + let unwrappedName = "\(name)_unwrapped$" + let inner = inner.render(&printer, placeholder) + printer.print( + """ + guard let \(unwrappedName) = \(inner) else { + fatalError("\(fatalErrorMessage)") + } + """ + ) + return unwrappedName } } } diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift index 8b910ffb..ca580e60 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift @@ -125,18 +125,20 @@ extension JNISwift2JavaGenerator { } let nativeSignature = translatedDecl.nativeFunctionSignature - var parameters = nativeSignature.parameters + var parameters = nativeSignature.parameters.flatMap(\.parameters) if let selfParameter = nativeSignature.selfParameter { - parameters.append(selfParameter) + parameters += selfParameter.parameters } + parameters += nativeSignature.result.outParameters + printCDecl( &printer, javaMethodName: translatedDecl.nativeFunctionName, parentName: translatedDecl.parentName, - parameters: parameters.map { JavaParameter(name: $0.name, type: $0.javaType) }, - resultType: nativeSignature.result.javaType.jniType + parameters: parameters, + resultType: nativeSignature.result.javaType ) { printer in self.printFunctionDowncall(&printer, decl) } @@ -155,8 +157,9 @@ extension JNISwift2JavaGenerator { // Regular parameters. var arguments = [String]() - for parameter in nativeSignature.parameters { - let lowered = parameter.conversion.render(&printer, parameter.name) + for (idx, parameter) in nativeSignature.parameters.enumerated() { + let javaParameterName = translatedDecl.translatedFunctionSignature.parameters[idx].parameter.name + let lowered = parameter.conversion.render(&printer, javaParameterName) arguments.append(lowered) } @@ -230,7 +233,7 @@ extension JNISwift2JavaGenerator { javaMethodName: String, parentName: String, parameters: [JavaParameter], - resultType: JNIType, + resultType: JavaType, _ body: (inout CodePrinter) -> Void ) { let jniSignature = parameters.reduce(into: "") { signature, parameter in @@ -246,7 +249,7 @@ extension JNISwift2JavaGenerator { + jniSignature.escapedJNIIdentifier let translatedParameters = parameters.map { - "\($0.name): \($0.type.jniType)" + "\($0.name): \($0.type.jniTypeName)" } let thunkParameters = @@ -254,7 +257,7 @@ extension JNISwift2JavaGenerator { "environment: UnsafeMutablePointer!", "thisClass: jclass" ] + translatedParameters - let thunkReturnType = resultType != .void ? " -> \(resultType)" : "" + let thunkReturnType = resultType != .void ? " -> \(resultType.jniTypeName)" : "" // TODO: Think about function overloads printer.printBraceBlock( diff --git a/Sources/JExtractSwiftLib/JNI/JNIType.swift b/Sources/JExtractSwiftLib/JNI/JNIType.swift deleted file mode 100644 index cdedb0a1..00000000 --- a/Sources/JExtractSwiftLib/JNI/JNIType.swift +++ /dev/null @@ -1,98 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2025 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of Swift.org project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -import JavaTypes - -/// Represents types that are able to be passed over a JNI boundary. -/// -/// - SeeAlso: https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/types.html -enum JNIType { - case jboolean - case jfloat - case jdouble - case jbyte - case jchar - case jshort - case jint - case jlong - case void - case jstring - case jclass - case jthrowable - case jobject - case jbooleanArray - case jbyteArray - case jcharArray - case jshortArray - case jintArray - case jlongArray - case jfloatArray - case jdoubleArray - case jobjectArray - - var callMethodAName: String { - switch self { - case .jboolean: "CallBooleanMethodA" - case .jbyte: "CallByteMethodA" - case .jchar: "CallCharMethodA" - case .jshort: "CallShortMethodA" - case .jint: "CallIntMethodA" - case .jlong: "CallLongMethodA" - case .jfloat: "CallFloatMethodA" - case .jdouble: "CallDoubleMethodA" - case .void: "CallVoidMethodA" - case .jobject, .jstring, .jclass, .jthrowable: "CallObjectMethodA" - case .jbooleanArray, .jbyteArray, .jcharArray, .jshortArray, .jintArray, .jlongArray, .jfloatArray, .jdoubleArray, .jobjectArray: "CallObjectMethodA" - } - } -} - -extension JavaType { - var jniType: JNIType { - switch self { - case .boolean: .jboolean - case .byte: .jbyte - case .char: .jchar - case .short: .jshort - case .int: .jint - case .long: .jlong - case .float: .jfloat - case .double: .jdouble - case .void: .void - case .array(.boolean): .jbooleanArray - case .array(.byte): .jbyteArray - case .array(.char): .jcharArray - case .array(.short): .jshortArray - case .array(.int): .jintArray - case .array(.long): .jlongArray - case .array(.float): .jfloatArray - case .array(.double): .jdoubleArray - case .array: .jobjectArray - case .javaLangString: .jstring - case .javaLangClass: .jclass - case .javaLangThrowable: .jthrowable - case .class: .jobject - } - } - - /// Returns whether this type returns `JavaValue` from JavaKit - var implementsJavaValue: Bool { - return switch self { - case .boolean, .byte, .char, .short, .int, .long, .float, .double, .void, .javaLangString: - true - default: - false - } - } -} diff --git a/Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md b/Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md index b3d02276..130c333b 100644 --- a/Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md +++ b/Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md @@ -63,7 +63,8 @@ SwiftJava's `swift-java jextract` tool automates generating Java bindings from S | `Foundation.Data`, `any Foundation.DataProtocol` | ✅ | ❌ | | Tuples: `(Int, String)`, `(A, B, C)` | ❌ | ❌ | | Protocols: `protocol`, existential parameters `any Collection` | ❌ | ❌ | -| Optional types: `Int?`, `AnyObject?` | ❌ | ❌ | +| Optional parameters: `func f(i: Int?, class: MyClass?)` | ✅ | ✅ | +| Optional return types: `func f() -> Int?`, `func g() -> MyClass?` | ❌ | ✅ | | Primitive types: `Bool`, `Int`, `Int8`, `Int16`, `Int32`, `Int64`, `Float`, `Double` | ✅ | ✅ | | Parameters: JavaKit wrapped types `JavaLong`, `JavaInteger` | ❌ | ✅ | | Return values: JavaKit wrapped types `JavaLong`, `JavaInteger` | ❌ | ❌ | diff --git a/Tests/JExtractSwiftTests/JNI/JNIClassTests.swift b/Tests/JExtractSwiftTests/JNI/JNIClassTests.swift index 483d53f5..5b015f89 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIClassTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIClassTests.swift @@ -283,7 +283,8 @@ struct JNIClassTests { func Java_com_example_swift_MyClass__00024doSomething__JJ(environment: UnsafeMutablePointer!, thisClass: jclass, x: jlong, self: jlong) { assert(self != 0, "self memory address was null") let selfBits$ = Int(Int64(fromJNI: self, in: environment!)) - guard let self$ = UnsafeMutablePointer(bitPattern: selfBits$) else { + let self$ = UnsafeMutablePointer(bitPattern: selfBits$) + guard let self$ else { fatalError("self memory address was null in call to \\(#function)!") } self$.pointee.doSomething(x: Int64(fromJNI: x, in: environment!)) @@ -331,7 +332,8 @@ struct JNIClassTests { func Java_com_example_swift_MyClass__00024copy__J(environment: UnsafeMutablePointer!, thisClass: jclass, self: jlong) -> jlong { assert(self != 0, "self memory address was null") let selfBits$ = Int(Int64(fromJNI: self, in: environment!)) - guard let self$ = UnsafeMutablePointer(bitPattern: selfBits$) else { + let self$ = UnsafeMutablePointer(bitPattern: selfBits$) + guard let self$ else { fatalError("self memory address was null in call to \\(#function)!") } let result$ = UnsafeMutablePointer.allocate(capacity: 1) @@ -382,12 +384,14 @@ struct JNIClassTests { func Java_com_example_swift_MyClass__00024isEqual__JJ(environment: UnsafeMutablePointer!, thisClass: jclass, other: jlong, self: jlong) -> jboolean { assert(other != 0, "other memory address was null") let otherBits$ = Int(Int64(fromJNI: other, in: environment!)) - guard let other$ = UnsafeMutablePointer(bitPattern: otherBits$) else { + let other$ = UnsafeMutablePointer(bitPattern: otherBits$) + guard let other$ else { fatalError("other memory address was null in call to \\(#function)!") } assert(self != 0, "self memory address was null") let selfBits$ = Int(Int64(fromJNI: self, in: environment!)) - guard let self$ = UnsafeMutablePointer(bitPattern: selfBits$) else { + let self$ = UnsafeMutablePointer(bitPattern: selfBits$) + guard let self$ else { fatalError("self memory address was null in call to \\(#function)!") } return self$.pointee.isEqual(to: other$.pointee).getJNIValue(in: environment!) diff --git a/Tests/JExtractSwiftTests/JNI/JNIClosureTests.swift b/Tests/JExtractSwiftTests/JNI/JNIClosureTests.swift index 47d7e35d..9a388da1 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIClosureTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIClosureTests.swift @@ -61,7 +61,7 @@ struct JNIClosureTests { expectedChunks: [ """ @_cdecl("Java_com_example_swift_SwiftModule__00024emptyClosure__Lcom_example_swift_SwiftModule_00024emptyClosure_00024closure_2") - func Java_com_example_swift_SwiftModule__00024emptyClosure__Lcom_example_swift_SwiftModule_00024emptyClosure_00024closure_2(environment: UnsafeMutablePointer!, thisClass: jclass, closure: jobject) { + func Java_com_example_swift_SwiftModule__00024emptyClosure__Lcom_example_swift_SwiftModule_00024emptyClosure_00024closure_2(environment: UnsafeMutablePointer!, thisClass: jclass, closure: jobject?) { SwiftModule.emptyClosure(closure: { let class$ = environment!.interface.GetObjectClass(environment, closure) let methodID$ = environment!.interface.GetMethodID(environment, class$, "apply", "()V")! @@ -113,7 +113,7 @@ struct JNIClosureTests { expectedChunks: [ """ @_cdecl("Java_com_example_swift_SwiftModule__00024closureWithArgumentsAndReturn__Lcom_example_swift_SwiftModule_00024closureWithArgumentsAndReturn_00024closure_2") - func Java_com_example_swift_SwiftModule__00024closureWithArgumentsAndReturn__Lcom_example_swift_SwiftModule_00024closureWithArgumentsAndReturn_00024closure_2(environment: UnsafeMutablePointer!, thisClass: jclass, closure: jobject) { + func Java_com_example_swift_SwiftModule__00024closureWithArgumentsAndReturn__Lcom_example_swift_SwiftModule_00024closureWithArgumentsAndReturn_00024closure_2(environment: UnsafeMutablePointer!, thisClass: jclass, closure: jobject?) { SwiftModule.closureWithArgumentsAndReturn(closure: { _0, _1 in let class$ = environment!.interface.GetObjectClass(environment, closure) let methodID$ = environment!.interface.GetMethodID(environment, class$, "apply", "(JZ)J")! diff --git a/Tests/JExtractSwiftTests/JNI/JNIJavaKitTests.swift b/Tests/JExtractSwiftTests/JNI/JNIJavaKitTests.swift index 0283780a..1f19c8f9 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIJavaKitTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIJavaKitTests.swift @@ -64,8 +64,14 @@ struct JNIJavaKitTests { expectedChunks: [ """ @_cdecl("Java_com_example_swift_SwiftModule__00024function__Ljava_lang_Long_2Ljava_lang_Integer_2J") - func Java_com_example_swift_SwiftModule__00024function__Ljava_lang_Long_2Ljava_lang_Integer_2J(environment: UnsafeMutablePointer!, thisClass: jclass, javaLong: jobject, javaInteger: jobject, int: jlong) { - SwiftModule.function(javaLong: JavaLong(javaThis: javaLong, environment: environment!), javaInteger: JavaInteger(javaThis: javaInteger, environment: environment!), int: Int64(fromJNI: int, in: environment!)) + func Java_com_example_swift_SwiftModule__00024function__Ljava_lang_Long_2Ljava_lang_Integer_2J(environment: UnsafeMutablePointer!, thisClass: jclass, javaLong: jobject?, javaInteger: jobject?, int: jlong) { + guard let javaLong_unwrapped$ = javaLong else { + fatalError("javaLong was null in call to \\(#function), but Swift requires non-optional!") + } + guard let javaInteger_unwrapped$ = javaInteger else { + fatalError("javaInteger was null in call to \\(#function), but Swift requires non-optional!") + } + SwiftModule.function(javaLong: JavaLong(javaThis: javaLong_unwrapped$, environment: environment!), javaInteger: JavaInteger(javaThis: javaInteger_unwrapped$, environment: environment!), int: Int64(fromJNI: int, in: environment!)) } """ ] diff --git a/Tests/JExtractSwiftTests/JNI/JNIModuleTests.swift b/Tests/JExtractSwiftTests/JNI/JNIModuleTests.swift index be9cf0ce..198276ba 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIModuleTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIModuleTests.swift @@ -45,6 +45,7 @@ struct JNIModuleTests { import org.swift.swiftkit.core.*; import org.swift.swiftkit.core.util.*; + import java.util.*; import org.swift.swiftkit.core.annotations.*; public final class SwiftModule { @@ -176,7 +177,7 @@ struct JNIModuleTests { expectedChunks: [ """ @_cdecl("Java_com_example_swift_SwiftModule__00024copy__Ljava_lang_String_2") - func Java_com_example_swift_SwiftModule__00024copy__Ljava_lang_String_2(environment: UnsafeMutablePointer!, thisClass: jclass, string: jstring) -> jstring { + func Java_com_example_swift_SwiftModule__00024copy__Ljava_lang_String_2(environment: UnsafeMutablePointer!, thisClass: jclass, string: jstring?) -> jstring? { return SwiftModule.copy(String(fromJNI: string, in: environment!)).getJNIValue(in: environment!) } """, diff --git a/Tests/JExtractSwiftTests/JNI/JNIOptionalTests.swift b/Tests/JExtractSwiftTests/JNI/JNIOptionalTests.swift new file mode 100644 index 00000000..cd04660b --- /dev/null +++ b/Tests/JExtractSwiftTests/JNI/JNIOptionalTests.swift @@ -0,0 +1,253 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import JExtractSwiftLib +import Testing + +@Suite +struct JNIOptionalTests { + let source = + """ + class MyClass { } + + public func optionalSugar(_ arg: Int64?) -> Int32? + public func optionalExplicit(_ arg: Optional) -> Optional + public func optionalClass(_ arg: MyClass?) -> MyClass? + public func optionalJavaKitClass(_ arg: JavaLong?) + """ + + let classLookupTable = [ + "JavaLong": "java.lang.Long", + ] + + @Test + func optionalSugar_javaBindings() throws { + try assertOutput( + input: source, + .jni, + .java, + javaClassLookupTable: classLookupTable, + expectedChunks: [ + """ + /** + * Downcall to Swift: + * {@snippet lang=swift : + * public func optionalSugar(_ arg: Int64?) -> Int32? + * } + */ + public static OptionalInt optionalSugar(OptionalLong arg) { + long combined$ = SwiftModule.$optionalSugar((byte) (arg.isPresent() ? 1 : 0), arg.orElse(0L)); + byte discriminator$ = (byte) (combined$ & 0xFF); + int value$ = (int) (combined$ >> 32); + return discriminator$ == 1 ? OptionalInt.of(value$) : OptionalInt.empty(); + } + """, + """ + private static native long $optionalSugar(byte arg_discriminator, long arg_value); + """ + ] + ) + } + + @Test + func optionalSugar_swiftThunks() throws { + try assertOutput( + input: source, + .jni, + .swift, + detectChunkByInitialLines: 1, + javaClassLookupTable: classLookupTable, + expectedChunks: [ + """ + @_cdecl("Java_com_example_swift_SwiftModule__00024optionalSugar__BJ") + func Java_com_example_swift_SwiftModule__00024optionalSugar__BJ(environment: UnsafeMutablePointer!, thisClass: jclass, arg_discriminator: jbyte, arg_value: jlong) -> jlong { + let value$ = SwiftModule.optionalSugar(arg_discriminator == 1 ? Int64(fromJNI: arg_value, in: environment!) : nil).map { + Int64($0) << 32 | Int64(1) + } ?? 0 + return value$.getJNIValue(in: environment!) + } + """ + ] + ) + } + + @Test + func optionalExplicit_javaBindings() throws { + try assertOutput( + input: source, + .jni, + .java, + javaClassLookupTable: classLookupTable, + expectedChunks: [ + """ + /** + * Downcall to Swift: + * {@snippet lang=swift : + * public func optionalExplicit(_ arg: Optional) -> Optional + * } + */ + public static Optional optionalExplicit(Optional arg) { + byte[] result_discriminator$ = new byte[1]; + java.lang.String result$ = SwiftModule.$optionalExplicit((byte) (arg.isPresent() ? 1 : 0), arg.orElse(null), result_discriminator$); + return (result_discriminator$[0] == 1) ? Optional.of(result$) : Optional.empty(); + } + """, + """ + private static native java.lang.String $optionalExplicit(byte arg_discriminator, java.lang.String arg_value, byte[] result_discriminator$); + """ + ] + ) + } + + @Test + func optionalExplicit_swiftThunks() throws { + try assertOutput( + input: source, + .jni, + .swift, + detectChunkByInitialLines: 1, + javaClassLookupTable: classLookupTable, + expectedChunks: [ + """ + @_cdecl("Java_com_example_swift_SwiftModule__00024optionalExplicit__BLjava_lang_String_2_3B") + func Java_com_example_swift_SwiftModule__00024optionalExplicit__BLjava_lang_String_2_3B(environment: UnsafeMutablePointer!, thisClass: jclass, arg_discriminator: jbyte, arg_value: jstring?, result_discriminator$: jbyteArray?) -> jstring? { + let result$: jstring? + if let innerResult$ = SwiftModule.optionalExplicit(arg_discriminator == 1 ? String(fromJNI: arg_value, in: environment!) : nil) { + result$ = innerResult$.getJNIValue(in: environment!) + var flag$ = Int8(1) + environment.interface.SetByteArrayRegion(environment, result_discriminator$, 0, 1, &flag$) + } // render(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+NativeTranslation.swift:624 + else { + result$ = String.jniPlaceholderValue + var flag$ = Int8(0) + environment.interface.SetByteArrayRegion(environment, result_discriminator$, 0, 1, &flag$) + } // render(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+NativeTranslation.swift:634 + return result$ + } + """ + ] + ) + } + + @Test + func optionalClass_javaBindings() throws { + try assertOutput( + input: source, + .jni, + .java, + javaClassLookupTable: classLookupTable, + expectedChunks: [ + """ + /** + * Downcall to Swift: + * {@snippet lang=swift : + * public func optionalClass(_ arg: MyClass?) -> MyClass? + * } + */ + public static Optional optionalClass(Optional arg, SwiftArena swiftArena$) { + byte[] result_discriminator$ = new byte[1]; + long result$ = SwiftModule.$optionalClass(arg.map(MyClass::$memoryAddress).orElse(0L), result_discriminator$); + return (result_discriminator$[0] == 1) ? Optional.of(new MyClass(result$, swiftArena$)) : Optional.empty(); + } + """, + """ + private static native long $optionalClass(long arg, byte[] result_discriminator$); + """ + ] + ) + } + + @Test + func optionalClass_swiftThunks() throws { + try assertOutput( + input: source, + .jni, + .swift, + detectChunkByInitialLines: 1, + javaClassLookupTable: classLookupTable, + expectedChunks: [ + """ + @_cdecl("Java_com_example_swift_SwiftModule__00024optionalClass__J_3B") + func Java_com_example_swift_SwiftModule__00024optionalClass__J_3B(environment: UnsafeMutablePointer!, thisClass: jclass, arg: jlong, result_discriminator$: jbyteArray?) -> jlong { + let argBits$ = Int(Int64(fromJNI: arg, in: environment!)) + let arg$ = UnsafeMutablePointer(bitPattern: argBits$) + let result$: jlong + if let innerResult$ = SwiftModule.optionalClass(arg$?.pointee) { + let _result$ = UnsafeMutablePointer.allocate(capacity: 1) + _result$.initialize(to: innerResult$) + let _resultBits$ = Int64(Int(bitPattern: _result$)) + result$ = _resultBits$.getJNIValue(in: environment!) + var flag$ = Int8(1) + environment.interface.SetByteArrayRegion(environment, result_discriminator$, 0, 1, &flag$) + } // render(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+NativeTranslation.swift:624 + else { + result$ = 0 + var flag$ = Int8(0) + environment.interface.SetByteArrayRegion(environment, result_discriminator$, 0, 1, &flag$) + } // render(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+NativeTranslation.swift:634 + return result$ + } + """ + ] + ) + } + + @Test + func optionalJavaKitClass_javaBindings() throws { + try assertOutput( + input: source, + .jni, + .java, + javaClassLookupTable: classLookupTable, + expectedChunks: [ + """ + /** + * Downcall to Swift: + * {@snippet lang=swift : + * public func optionalJavaKitClass(_ arg: JavaLong?) + * } + */ + public static void optionalJavaKitClass(Optional arg) { + SwiftModule.$optionalJavaKitClass(arg.orElse(null)); + } + """, + """ + private static native void $optionalJavaKitClass(java.lang.Long arg); + """ + ] + ) + } + + @Test + func optionalJavaKitClass_swiftThunks() throws { + try assertOutput( + input: source, + .jni, + .swift, + detectChunkByInitialLines: 1, + javaClassLookupTable: classLookupTable, + expectedChunks: [ + """ + @_cdecl("Java_com_example_swift_SwiftModule__00024optionalJavaKitClass__Ljava_lang_Long_2") + func Java_com_example_swift_SwiftModule__00024optionalJavaKitClass__Ljava_lang_Long_2(environment: UnsafeMutablePointer!, thisClass: jclass, arg: jobject?) { + SwiftModule.optionalJavaKitClass(arg.map { + return JavaLong(javaThis: $0, environment: environment!) + } // render(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+NativeTranslation.swift:666 + ) + } + """ + ] + ) + } +} diff --git a/Tests/JExtractSwiftTests/JNI/JNIStructTests.swift b/Tests/JExtractSwiftTests/JNI/JNIStructTests.swift index 09a8626d..01a2e3c0 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIStructTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIStructTests.swift @@ -205,7 +205,8 @@ struct JNIStructTests { func Java_com_example_swift_MyStruct__00024doSomething__JJ(environment: UnsafeMutablePointer!, thisClass: jclass, x: jlong, self: jlong) { assert(self != 0, "self memory address was null") let selfBits$ = Int(Int64(fromJNI: self, in: environment!)) - guard let self$ = UnsafeMutablePointer(bitPattern: selfBits$) else { + let self$ = UnsafeMutablePointer(bitPattern: selfBits$) + guard let self$ else { fatalError("self memory address was null in call to \\(#function)!") } self$.pointee.doSomething(x: Int64(fromJNI: x, in: environment!)) diff --git a/Tests/JExtractSwiftTests/JNI/JNIVariablesTests.swift b/Tests/JExtractSwiftTests/JNI/JNIVariablesTests.swift index 9d2fcb22..933e4f08 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIVariablesTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIVariablesTests.swift @@ -71,7 +71,8 @@ struct JNIVariablesTests { func Java_com_example_swift_MyClass__00024getConstant__J(environment: UnsafeMutablePointer!, thisClass: jclass, self: jlong) -> jlong { assert(self != 0, "self memory address was null") let selfBits$ = Int(Int64(fromJNI: self, in: environment!)) - guard let self$ = UnsafeMutablePointer(bitPattern: selfBits$) else { + let self$ = UnsafeMutablePointer(bitPattern: selfBits$) + guard let self$ else { fatalError("self memory address was null in call to \\(#function)!") } return self$.pointee.constant.getJNIValue(in: environment!) @@ -134,7 +135,8 @@ struct JNIVariablesTests { func Java_com_example_swift_MyClass__00024getMutable__J(environment: UnsafeMutablePointer!, thisClass: jclass, self: jlong) -> jlong { assert(self != 0, "self memory address was null") let selfBits$ = Int(Int64(fromJNI: self, in: environment!)) - guard let self$ = UnsafeMutablePointer(bitPattern: selfBits$) else { + let self$ = UnsafeMutablePointer(bitPattern: selfBits$) + guard let self$ else { fatalError("self memory address was null in call to \\(#function)!") } return self$.pointee.mutable.getJNIValue(in: environment!) @@ -145,7 +147,8 @@ struct JNIVariablesTests { func Java_com_example_swift_MyClass__00024setMutable__JJ(environment: UnsafeMutablePointer!, thisClass: jclass, newValue: jlong, self: jlong) { assert(self != 0, "self memory address was null") let selfBits$ = Int(Int64(fromJNI: self, in: environment!)) - guard let self$ = UnsafeMutablePointer(bitPattern: selfBits$) else { + let self$ = UnsafeMutablePointer(bitPattern: selfBits$) + guard let self$ else { fatalError("self memory address was null in call to \\(#function)!") } self$.pointee.mutable = Int64(fromJNI: newValue, in: environment!) @@ -194,7 +197,8 @@ struct JNIVariablesTests { func Java_com_example_swift_MyClass__00024getComputed__J(environment: UnsafeMutablePointer!, thisClass: jclass, self: jlong) -> jlong { assert(self != 0, "self memory address was null") let selfBits$ = Int(Int64(fromJNI: self, in: environment!)) - guard let self$ = UnsafeMutablePointer(bitPattern: selfBits$) else { + let self$ = UnsafeMutablePointer(bitPattern: selfBits$) + guard let self$ else { fatalError("self memory address was null in call to \\(#function)!") } return self$.pointee.computed.getJNIValue(in: environment!) @@ -243,7 +247,8 @@ struct JNIVariablesTests { func Java_com_example_swift_MyClass__00024getComputedThrowing__J(environment: UnsafeMutablePointer!, thisClass: jclass, self: jlong) -> jlong { assert(self != 0, "self memory address was null") let selfBits$ = Int(Int64(fromJNI: self, in: environment!)) - guard let self$ = UnsafeMutablePointer(bitPattern: selfBits$) else { + let self$ = UnsafeMutablePointer(bitPattern: selfBits$) + guard let self$ else { fatalError("self memory address was null in call to \\(#function)!") } do { @@ -311,7 +316,8 @@ struct JNIVariablesTests { func Java_com_example_swift_MyClass__00024getGetterAndSetter__J(environment: UnsafeMutablePointer!, thisClass: jclass, self: jlong) -> jlong { assert(self != 0, "self memory address was null") let selfBits$ = Int(Int64(fromJNI: self, in: environment!)) - guard let self$ = UnsafeMutablePointer(bitPattern: selfBits$) else { + let self$ = UnsafeMutablePointer(bitPattern: selfBits$) + guard let self$ else { fatalError("self memory address was null in call to \\(#function)!") } return self$.pointee.getterAndSetter.getJNIValue(in: environment!) @@ -322,7 +328,8 @@ struct JNIVariablesTests { func Java_com_example_swift_MyClass__00024setGetterAndSetter__JJ(environment: UnsafeMutablePointer!, thisClass: jclass, newValue: jlong, self: jlong) { assert(self != 0, "self memory address was null") let selfBits$ = Int(Int64(fromJNI: self, in: environment!)) - guard let self$ = UnsafeMutablePointer(bitPattern: selfBits$) else { + let self$ = UnsafeMutablePointer(bitPattern: selfBits$) + guard let self$ else { fatalError("self memory address was null in call to \\(#function)!") } self$.pointee.getterAndSetter = Int64(fromJNI: newValue, in: environment!) @@ -385,7 +392,8 @@ struct JNIVariablesTests { func Java_com_example_swift_MyClass__00024isSomeBoolean__J(environment: UnsafeMutablePointer!, thisClass: jclass, self: jlong) -> jboolean { assert(self != 0, "self memory address was null") let selfBits$ = Int(Int64(fromJNI: self, in: environment!)) - guard let self$ = UnsafeMutablePointer(bitPattern: selfBits$) else { + let self$ = UnsafeMutablePointer(bitPattern: selfBits$) + guard let self$ else { fatalError("self memory address was null in call to \\(#function)!") } return self$.pointee.someBoolean.getJNIValue(in: environment!) @@ -396,7 +404,8 @@ struct JNIVariablesTests { func Java_com_example_swift_MyClass__00024setSomeBoolean__ZJ(environment: UnsafeMutablePointer!, thisClass: jclass, newValue: jboolean, self: jlong) { assert(self != 0, "self memory address was null") let selfBits$ = Int(Int64(fromJNI: self, in: environment!)) - guard let self$ = UnsafeMutablePointer(bitPattern: selfBits$) else { + let self$ = UnsafeMutablePointer(bitPattern: selfBits$) + guard let self$ else { fatalError("self memory address was null in call to \\(#function)!") } self$.pointee.someBoolean = Bool(fromJNI: newValue, in: environment!) @@ -459,7 +468,8 @@ struct JNIVariablesTests { func Java_com_example_swift_MyClass__00024isBoolean__J(environment: UnsafeMutablePointer!, thisClass: jclass, self: jlong) -> jboolean { assert(self != 0, "self memory address was null") let selfBits$ = Int(Int64(fromJNI: self, in: environment!)) - guard let self$ = UnsafeMutablePointer(bitPattern: selfBits$) else { + let self$ = UnsafeMutablePointer(bitPattern: selfBits$) + guard let self$ else { fatalError("self memory address was null in call to \\(#function)!") } return self$.pointee.isBoolean.getJNIValue(in: environment!) @@ -470,7 +480,8 @@ struct JNIVariablesTests { func Java_com_example_swift_MyClass__00024setBoolean__ZJ(environment: UnsafeMutablePointer!, thisClass: jclass, newValue: jboolean, self: jlong) { assert(self != 0, "self memory address was null") let selfBits$ = Int(Int64(fromJNI: self, in: environment!)) - guard let self$ = UnsafeMutablePointer(bitPattern: selfBits$) else { + let self$ = UnsafeMutablePointer(bitPattern: selfBits$) + guard let self$ else { fatalError("self memory address was null in call to \\(#function)!") } self$.pointee.isBoolean = Bool(fromJNI: newValue, in: environment!) From 68f695a60c456ecdf91863dd563bc29f2f09dc62 Mon Sep 17 00:00:00 2001 From: "Sven A. Schmidt" Date: Sat, 2 Aug 2025 14:59:06 +0200 Subject: [PATCH 333/426] Update Package.swift (#345) --- Package.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Package.swift b/Package.swift index 51608c31..bac55bd6 100644 --- a/Package.swift +++ b/Package.swift @@ -32,7 +32,7 @@ func findJavaHome() -> String { } - if ProcessInfo.processInfo.environment["SPI_BUILD"] == "1" { + if ProcessInfo.processInfo.environment["SPI_PROCESSING"] == "1" { // just ignore that we're missing a JAVA_HOME when building in Swift Package Index return "" } From a3791cf7c94146a34f96fd9ad53efef9d58c2a1b Mon Sep 17 00:00:00 2001 From: Alsey Coleman Miller Date: Sat, 2 Aug 2025 22:36:21 -0400 Subject: [PATCH 334/426] [JavaKit] Add `JNIEnvPointer` and `JNINativeInterface_` for Android (#311) * [JavaKit] Add `JNIEnvPointer` for Android * [JavaKit] Fix `JNINativeInterface_` for Android --- Sources/JavaKit/JavaEnvironment.swift | 4 +++ .../JavaKitVM/JavaVirtualMachine.swift | 25 +++++++++++++++---- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/Sources/JavaKit/JavaEnvironment.swift b/Sources/JavaKit/JavaEnvironment.swift index 4895b32c..422262da 100644 --- a/Sources/JavaKit/JavaEnvironment.swift +++ b/Sources/JavaKit/JavaEnvironment.swift @@ -14,6 +14,10 @@ import JavaRuntime +#if canImport(Android) +typealias JNINativeInterface_ = JNINativeInterface +#endif + extension UnsafeMutablePointer { public var interface: JNINativeInterface_ { self.pointee!.pointee } } diff --git a/Sources/JavaKit/JavaKitVM/JavaVirtualMachine.swift b/Sources/JavaKit/JavaKitVM/JavaVirtualMachine.swift index 0800a89e..edbddbb7 100644 --- a/Sources/JavaKit/JavaKitVM/JavaVirtualMachine.swift +++ b/Sources/JavaKit/JavaKitVM/JavaVirtualMachine.swift @@ -19,6 +19,11 @@ import Foundation #endif public typealias JavaVMPointer = UnsafeMutablePointer +#if canImport(Android) +typealias JNIEnvPointer = UnsafeMutablePointer +#else +typealias JNIEnvPointer = UnsafeMutableRawPointer +#endif public final class JavaVirtualMachine: @unchecked Sendable { /// The JNI version that we depend on. @@ -61,7 +66,7 @@ public final class JavaVirtualMachine: @unchecked Sendable { ) throws { self.classpath = classpath var jvm: JavaVMPointer? = nil - var environment: UnsafeMutableRawPointer? = nil + var environment: JNIEnvPointer? = nil var vmArgs = JavaVMInitArgs() vmArgs.version = JavaVirtualMachine.jniVersion vmArgs.ignoreUnrecognized = jboolean(ignoreUnrecognized ? JNI_TRUE : JNI_FALSE) @@ -161,12 +166,18 @@ extension JavaVirtualMachine { return environment.assumingMemoryBound(to: JNIEnv?.self) } +#if canImport(Android) + var jniEnv = environment?.assumingMemoryBound(to: JNIEnv?.self) +#else + var jniEnv = environment +#endif + // Attach the current thread to the JVM. let attachResult: jint if asDaemon { - attachResult = jvm.pointee!.pointee.AttachCurrentThreadAsDaemon(jvm, &environment, nil) + attachResult = jvm.pointee!.pointee.AttachCurrentThreadAsDaemon(jvm, &jniEnv, nil) } else { - attachResult = jvm.pointee!.pointee.AttachCurrentThread(jvm, &environment, nil) + attachResult = jvm.pointee!.pointee.AttachCurrentThread(jvm, &jniEnv, nil) } // If we failed to attach, report that. @@ -175,9 +186,13 @@ extension JavaVirtualMachine { throw attachError } - JavaVirtualMachine.destroyTLS.set(environment!) + JavaVirtualMachine.destroyTLS.set(jniEnv!) - return environment!.assumingMemoryBound(to: JNIEnv?.self) +#if canImport(Android) + return jniEnv! +#else + return jniEnv!.assumingMemoryBound(to: JNIEnv?.self) +#endif } /// Detach the current thread from the Java Virtual Machine. All Java From 1ac73e4518f988741c62dba7c7c17a4655fd6e00 Mon Sep 17 00:00:00 2001 From: "Sven A. Schmidt" Date: Mon, 4 Aug 2025 16:57:47 +0200 Subject: [PATCH 335/426] Update Package.swift (#347) --- Package.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Package.swift b/Package.swift index bac55bd6..65737b2b 100644 --- a/Package.swift +++ b/Package.swift @@ -32,8 +32,8 @@ func findJavaHome() -> String { } - if ProcessInfo.processInfo.environment["SPI_PROCESSING"] == "1" { - // just ignore that we're missing a JAVA_HOME when building in Swift Package Index + if ProcessInfo.processInfo.environment["SPI_PROCESSING"] == "1" && ProcessInfo.processInfo.environment["SPI_BUILD"] == nil { + // Just ignore that we're missing a JAVA_HOME when building in Swift Package Index during general processing where no Java is needed. However, do _not_ suppress the error during SPI's compatibility build stage where Java is required. return "" } fatalError("Please set the JAVA_HOME environment variable to point to where Java is installed.") From 8d41e6e263b568a9a3adacee0077ac1dfc03762a Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Tue, 5 Aug 2025 17:09:16 -0700 Subject: [PATCH 336/426] [JExtract] Fix importing extensions (#351) --- .../JExtractSwiftLib/Swift2JavaVisitor.swift | 4 +- .../ExtensionImportTests.swift | 48 +++++++++++++++++++ 2 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 Tests/JExtractSwiftTests/ExtensionImportTests.swift diff --git a/Sources/JExtractSwiftLib/Swift2JavaVisitor.swift b/Sources/JExtractSwiftLib/Swift2JavaVisitor.swift index 3efddbfc..a933ff3e 100644 --- a/Sources/JExtractSwiftLib/Swift2JavaVisitor.swift +++ b/Sources/JExtractSwiftLib/Swift2JavaVisitor.swift @@ -2,7 +2,7 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Copyright (c) 2024-2025 Apple Inc. and the Swift.org project authors // Licensed under Apache License v2.0 // // See LICENSE.txt for license information @@ -84,7 +84,7 @@ final class Swift2JavaVisitor { } func visit(extensionDecl node: ExtensionDeclSyntax, in parent: ImportedNominalType?) { - guard parent != nil else { + guard parent == nil else { // 'extension' in a nominal type is invalid. Ignore return } diff --git a/Tests/JExtractSwiftTests/ExtensionImportTests.swift b/Tests/JExtractSwiftTests/ExtensionImportTests.swift new file mode 100644 index 00000000..2bad2c7b --- /dev/null +++ b/Tests/JExtractSwiftTests/ExtensionImportTests.swift @@ -0,0 +1,48 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import JExtractSwiftLib +import Testing + +final class ExtensionImportTests { + let interfaceFile = + """ + extension MyStruct { + public func methodInExtension() {} + } + + public struct MyStruct {} + """ + + @Test("Import extensions: Swift thunks") + func data_swiftThunk() throws { + try assertOutput( + input: interfaceFile, .ffm, .swift, + expectedChunks: [ + """ + @_cdecl("swiftjava_getType_SwiftModule_MyStruct") + public func swiftjava_getType_SwiftModule_MyStruct() -> UnsafeMutableRawPointer /* Any.Type */ { + return unsafeBitCast(MyStruct.self, to: UnsafeMutableRawPointer.self) + } + """, + """ + @_cdecl("swiftjava_SwiftModule_MyStruct_methodInExtension") + public func swiftjava_SwiftModule_MyStruct_methodInExtension(_ self: UnsafeRawPointer) { + self.assumingMemoryBound(to: MyStruct.self).pointee.methodInExtension() + } + """ + ] + ) + } +} From 1e4c6ebd9aa7bd3bd095c9bd8b1f26634a016001 Mon Sep 17 00:00:00 2001 From: David Ko Date: Wed, 6 Aug 2025 19:12:49 -0400 Subject: [PATCH 337/426] replace Java2Swift.config with swift-java.config (#350) --- .../Documentation.docc/SwiftJavaCommandLineTool.md | 2 +- Sources/SwiftJavaTool/Commands/JExtractCommand.swift | 2 +- Sources/SwiftJavaTool/Commands/WrapJavaCommand.swift | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Sources/SwiftJavaDocumentation/Documentation.docc/SwiftJavaCommandLineTool.md b/Sources/SwiftJavaDocumentation/Documentation.docc/SwiftJavaCommandLineTool.md index f83458d4..e8a3dfed 100644 --- a/Sources/SwiftJavaDocumentation/Documentation.docc/SwiftJavaCommandLineTool.md +++ b/Sources/SwiftJavaDocumentation/Documentation.docc/SwiftJavaCommandLineTool.md @@ -57,7 +57,7 @@ OPTIONS: The name of the Swift module into which the resulting Swift types will be generated. --depends-on A swift-java configuration file for a given Swift module name on which this module depends, - e.g., JavaKitJar=Sources/JavaKitJar/Java2Swift.config. There should be one of these options + e.g., JavaKitJar=Sources/JavaKitJar/swift-java.config. There should be one of these options for each Swift module that this module depends on (transitively) that contains wrapped Java sources. --swift-native-implementation The names of Java classes whose declared native methods will be implemented in Swift. diff --git a/Sources/SwiftJavaTool/Commands/JExtractCommand.swift b/Sources/SwiftJavaTool/Commands/JExtractCommand.swift index 54a99708..88fbf7f3 100644 --- a/Sources/SwiftJavaTool/Commands/JExtractCommand.swift +++ b/Sources/SwiftJavaTool/Commands/JExtractCommand.swift @@ -70,7 +70,7 @@ extension SwiftJava { @Option( help: """ A swift-java configuration file for a given Swift module name on which this module depends, - e.g., Sources/JavaKitJar/Java2Swift.config. There should be one of these options + e.g., Sources/JavaKitJar/swift-java.config. There should be one of these options for each Swift module that this module depends on (transitively) that contains wrapped Java sources. """ ) diff --git a/Sources/SwiftJavaTool/Commands/WrapJavaCommand.swift b/Sources/SwiftJavaTool/Commands/WrapJavaCommand.swift index 4c5bd97b..3e4a62af 100644 --- a/Sources/SwiftJavaTool/Commands/WrapJavaCommand.swift +++ b/Sources/SwiftJavaTool/Commands/WrapJavaCommand.swift @@ -40,7 +40,7 @@ extension SwiftJava { @Option( help: """ A swift-java configuration file for a given Swift module name on which this module depends, - e.g., JavaKitJar=Sources/JavaKitJar/Java2Swift.config. There should be one of these options + e.g., JavaKitJar=Sources/JavaKitJar/swift-java.config. There should be one of these options for each Swift module that this module depends on (transitively) that contains wrapped Java sources. """ ) From f87fe2811359b70d5f1e6a2dc916e06b6802bd72 Mon Sep 17 00:00:00 2001 From: Mads Odgaard Date: Fri, 8 Aug 2025 00:13:13 +0200 Subject: [PATCH 338/426] [JExtract/JNI] Add `auto` arena to SwiftKitCore and add memory management options (#353) --- .../com/example/swift/HelloJava2SwiftJNI.java | 4 +- .../com/example/swift/MySwiftClassTest.java | 30 ++++---- .../com/example/swift/MySwiftStructTest.java | 7 +- .../java/com/example/swift/OptionalsTest.java | 6 +- ...t2JavaGenerator+JavaBindingsPrinting.swift | 32 ++++++-- .../Configuration.swift | 5 ++ .../GenerationMode.swift | 22 ++++++ .../Commands/JExtractCommand.swift | 9 +++ .../swiftkit/core/AutoSwiftMemorySession.java | 56 ++++++++++++++ .../core/ConfinedSwiftMemorySession.java | 6 +- .../swift/swiftkit/core/JNISwiftInstance.java | 9 +-- .../org/swift/swiftkit/core/SwiftArena.java | 13 +++- .../swiftkit/core/SwiftMemoryManagement.java | 19 +++++ .../swiftkit/core/ref/PhantomCleanable.java | 35 +++++++++ .../swift/swiftkit/core/ref/SwiftCleaner.java | 67 ++++++++++++++++ .../org/swift/swiftkit/AutoArenaTest.java | 57 ++++++++++++++ .../MemoryManagementModeTests.swift | 77 +++++++++++++++++++ 17 files changed, 411 insertions(+), 43 deletions(-) create mode 100644 SwiftKitCore/src/main/java/org/swift/swiftkit/core/AutoSwiftMemorySession.java create mode 100644 SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftMemoryManagement.java create mode 100644 SwiftKitCore/src/main/java/org/swift/swiftkit/core/ref/PhantomCleanable.java create mode 100644 SwiftKitCore/src/main/java/org/swift/swiftkit/core/ref/SwiftCleaner.java create mode 100644 SwiftKitCore/src/test/java/org/swift/swiftkit/AutoArenaTest.java create mode 100644 Tests/JExtractSwiftTests/MemoryManagementModeTests.swift diff --git a/Samples/JExtractJNISampleApp/src/main/java/com/example/swift/HelloJava2SwiftJNI.java b/Samples/JExtractJNISampleApp/src/main/java/com/example/swift/HelloJava2SwiftJNI.java index 21cad317..3109f64e 100644 --- a/Samples/JExtractJNISampleApp/src/main/java/com/example/swift/HelloJava2SwiftJNI.java +++ b/Samples/JExtractJNISampleApp/src/main/java/com/example/swift/HelloJava2SwiftJNI.java @@ -18,8 +18,8 @@ // Import javakit/swiftkit support libraries +import org.swift.swiftkit.core.SwiftArena; import org.swift.swiftkit.core.SwiftLibraries; -import org.swift.swiftkit.core.ConfinedSwiftMemorySession; public class HelloJava2SwiftJNI { @@ -41,7 +41,7 @@ static void examples() { MySwiftClass.method(); - try (var arena = new ConfinedSwiftMemorySession()) { + try (var arena = SwiftArena.ofConfined()) { MySwiftClass myClass = MySwiftClass.init(10, 5, arena); MySwiftClass myClass2 = MySwiftClass.init(arena); diff --git a/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/MySwiftClassTest.java b/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/MySwiftClassTest.java index e7de03ad..2e9a7e62 100644 --- a/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/MySwiftClassTest.java +++ b/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/MySwiftClassTest.java @@ -15,7 +15,7 @@ package com.example.swift; import org.junit.jupiter.api.Test; -import org.swift.swiftkit.core.ConfinedSwiftMemorySession; +import org.swift.swiftkit.core.SwiftArena; import java.util.Optional; import java.util.OptionalInt; @@ -26,7 +26,7 @@ public class MySwiftClassTest { @Test void init_noParameters() { - try (var arena = new ConfinedSwiftMemorySession()) { + try (var arena = SwiftArena.ofConfined()) { MySwiftClass c = MySwiftClass.init(arena); assertNotNull(c); } @@ -34,7 +34,7 @@ void init_noParameters() { @Test void init_withParameters() { - try (var arena = new ConfinedSwiftMemorySession()) { + try (var arena = SwiftArena.ofConfined()) { MySwiftClass c = MySwiftClass.init(1337, 42, arena); assertNotNull(c); } @@ -42,7 +42,7 @@ void init_withParameters() { @Test void sum() { - try (var arena = new ConfinedSwiftMemorySession()) { + try (var arena = SwiftArena.ofConfined()) { MySwiftClass c = MySwiftClass.init(20, 10, arena); assertEquals(30, c.sum()); } @@ -50,7 +50,7 @@ void sum() { @Test void xMultiplied() { - try (var arena = new ConfinedSwiftMemorySession()) { + try (var arena = SwiftArena.ofConfined()) { MySwiftClass c = MySwiftClass.init(20, 10, arena); assertEquals(200, c.xMultiplied(10)); } @@ -58,7 +58,7 @@ void xMultiplied() { @Test void throwingFunction() { - try (var arena = new ConfinedSwiftMemorySession()) { + try (var arena = SwiftArena.ofConfined()) { MySwiftClass c = MySwiftClass.init(20, 10, arena); Exception exception = assertThrows(Exception.class, () -> c.throwingFunction()); @@ -68,7 +68,7 @@ void throwingFunction() { @Test void constant() { - try (var arena = new ConfinedSwiftMemorySession()) { + try (var arena = SwiftArena.ofConfined()) { MySwiftClass c = MySwiftClass.init(20, 10, arena); assertEquals(100, c.getConstant()); } @@ -76,7 +76,7 @@ void constant() { @Test void mutable() { - try (var arena = new ConfinedSwiftMemorySession()) { + try (var arena = SwiftArena.ofConfined()) { MySwiftClass c = MySwiftClass.init(20, 10, arena); assertEquals(0, c.getMutable()); c.setMutable(42); @@ -86,7 +86,7 @@ void mutable() { @Test void product() { - try (var arena = new ConfinedSwiftMemorySession()) { + try (var arena = SwiftArena.ofConfined()) { MySwiftClass c = MySwiftClass.init(20, 10, arena); assertEquals(200, c.getProduct()); } @@ -94,7 +94,7 @@ void product() { @Test void throwingVariable() { - try (var arena = new ConfinedSwiftMemorySession()) { + try (var arena = SwiftArena.ofConfined()) { MySwiftClass c = MySwiftClass.init(20, 10, arena); Exception exception = assertThrows(Exception.class, () -> c.getThrowingVariable()); @@ -105,7 +105,7 @@ void throwingVariable() { @Test void mutableDividedByTwo() { - try (var arena = new ConfinedSwiftMemorySession()) { + try (var arena = SwiftArena.ofConfined()) { MySwiftClass c = MySwiftClass.init(20, 10, arena); assertEquals(0, c.getMutableDividedByTwo()); c.setMutable(20); @@ -117,7 +117,7 @@ void mutableDividedByTwo() { @Test void isWarm() { - try (var arena = new ConfinedSwiftMemorySession()) { + try (var arena = SwiftArena.ofConfined()) { MySwiftClass c = MySwiftClass.init(20, 10, arena); assertFalse(c.isWarm()); } @@ -125,7 +125,7 @@ void isWarm() { @Test void sumWithX() { - try (var arena = new ConfinedSwiftMemorySession()) { + try (var arena = SwiftArena.ofConfined()) { MySwiftClass c1 = MySwiftClass.init(20, 10, arena); MySwiftClass c2 = MySwiftClass.init(50, 10, arena); assertEquals(70, c1.sumX(c2)); @@ -134,7 +134,7 @@ void sumWithX() { @Test void copy() { - try (var arena = new ConfinedSwiftMemorySession()) { + try (var arena = SwiftArena.ofConfined()) { MySwiftClass c1 = MySwiftClass.init(20, 10, arena); MySwiftClass c2 = c1.copy(arena); @@ -146,7 +146,7 @@ void copy() { @Test void addXWithJavaLong() { - try (var arena = new ConfinedSwiftMemorySession()) { + try (var arena = SwiftArena.ofConfined()) { MySwiftClass c1 = MySwiftClass.init(20, 10, arena); Long javaLong = 50L; assertEquals(70, c1.addXWithJavaLong(javaLong)); diff --git a/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/MySwiftStructTest.java b/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/MySwiftStructTest.java index 9eeaf029..c2c1170b 100644 --- a/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/MySwiftStructTest.java +++ b/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/MySwiftStructTest.java @@ -16,13 +16,14 @@ import org.junit.jupiter.api.Test; import org.swift.swiftkit.core.ConfinedSwiftMemorySession; +import org.swift.swiftkit.core.SwiftArena; import static org.junit.jupiter.api.Assertions.*; public class MySwiftStructTest { @Test void init() { - try (var arena = new ConfinedSwiftMemorySession()) { + try (var arena = SwiftArena.ofConfined()) { MySwiftStruct s = MySwiftStruct.init(1337, 42, arena); assertEquals(1337, s.getCapacity()); assertEquals(42, s.getLen()); @@ -31,7 +32,7 @@ void init() { @Test void getAndSetLen() { - try (var arena = new ConfinedSwiftMemorySession()) { + try (var arena = SwiftArena.ofConfined()) { MySwiftStruct s = MySwiftStruct.init(1337, 42, arena); s.setLen(100); assertEquals(100, s.getLen()); @@ -40,7 +41,7 @@ void getAndSetLen() { @Test void increaseCap() { - try (var arena = new ConfinedSwiftMemorySession()) { + try (var arena = SwiftArena.ofConfined()) { MySwiftStruct s = MySwiftStruct.init(1337, 42, arena); long newCap = s.increaseCap(10); assertEquals(1347, newCap); diff --git a/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/OptionalsTest.java b/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/OptionalsTest.java index f7262ad4..d60ff6d5 100644 --- a/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/OptionalsTest.java +++ b/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/OptionalsTest.java @@ -15,7 +15,7 @@ package com.example.swift; import org.junit.jupiter.api.Test; -import org.swift.swiftkit.core.ConfinedSwiftMemorySession; +import org.swift.swiftkit.core.SwiftArena; import java.util.Optional; import java.util.OptionalDouble; @@ -82,7 +82,7 @@ void optionalString() { @Test void optionalClass() { - try (var arena = new ConfinedSwiftMemorySession()) { + try (var arena = SwiftArena.ofConfined()) { MySwiftClass c = MySwiftClass.init(arena); assertEquals(Optional.empty(), MySwiftLibrary.optionalClass(Optional.empty(), arena)); Optional optionalClass = MySwiftLibrary.optionalClass(Optional.of(c), arena); @@ -99,7 +99,7 @@ void optionalJavaKitLong() { @Test void multipleOptionals() { - try (var arena = new ConfinedSwiftMemorySession()) { + try (var arena = SwiftArena.ofConfined()) { MySwiftClass c = MySwiftClass.init(arena); OptionalLong result = MySwiftLibrary.multipleOptionals( Optional.of((byte) 1), diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift index 0daf14de..0920a89b 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift @@ -247,29 +247,47 @@ extension JNISwift2JavaGenerator { guard let translatedDecl = translatedDecl(for: decl) else { fatalError("Decl was not translated, \(decl)") } + let translatedSignature = translatedDecl.translatedFunctionSignature var modifiers = ["public"] + if decl.isStatic || decl.isInitializer || !decl.hasParent { modifiers.append("static") } - let translatedSignature = translatedDecl.translatedFunctionSignature let resultType = translatedSignature.resultType.javaType - var parameters = translatedDecl.translatedFunctionSignature.parameters.map({ $0.parameter.renderParameter() }) - if translatedSignature.requiresSwiftArena { - parameters.append("SwiftArena swiftArena$") - } + var parameters = translatedDecl.translatedFunctionSignature.parameters.map { $0.parameter.renderParameter() } let throwsClause = decl.isThrowing ? " throws Exception" : "" var annotationsStr = translatedSignature.annotations.map({ $0.render() }).joined(separator: "\n") if !annotationsStr.isEmpty { annotationsStr += "\n" } - let modifiersStr = modifiers.joined(separator: " ") let parametersStr = parameters.joined(separator: ", ") + // Print default global arena variation + if config.effectiveMemoryManagementMode.requiresGlobalArena && translatedSignature.requiresSwiftArena { + printDeclDocumentation(&printer, decl) + printer.printBraceBlock( + "\(annotationsStr)\(modifiers.joined(separator: " ")) \(resultType) \(translatedDecl.name)(\(parametersStr))\(throwsClause)" + ) { printer in + let globalArenaName = "SwiftMemoryManagement.GLOBAL_SWIFT_JAVA_ARENA" + let arguments = translatedDecl.translatedFunctionSignature.parameters.map(\.parameter.name) + [globalArenaName] + let call = "\(translatedDecl.name)(\(arguments.joined(separator: ", ")))" + if translatedDecl.translatedFunctionSignature.resultType.javaType.isVoid { + printer.print("\(call);") + } else { + printer.print("return \(call);") + } + } + printer.println() + } + + if translatedSignature.requiresSwiftArena { + parameters.append("SwiftArena swiftArena$") + } printDeclDocumentation(&printer, decl) printer.printBraceBlock( - "\(annotationsStr)\(modifiersStr) \(resultType) \(translatedDecl.name)(\(parametersStr))\(throwsClause)" + "\(annotationsStr)\(modifiers.joined(separator: " ")) \(resultType) \(translatedDecl.name)(\(parameters.joined(separator: ", ")))\(throwsClause)" ) { printer in printDowncall(&printer, decl) } diff --git a/Sources/JavaKitConfigurationShared/Configuration.swift b/Sources/JavaKitConfigurationShared/Configuration.swift index 0ff089da..2d9b4311 100644 --- a/Sources/JavaKitConfigurationShared/Configuration.swift +++ b/Sources/JavaKitConfigurationShared/Configuration.swift @@ -51,6 +51,11 @@ public struct Configuration: Codable { minimumInputAccessLevelMode ?? .default } + public var memoryManagementMode: JExtractMemoryManagementMode? + public var effectiveMemoryManagementMode: JExtractMemoryManagementMode { + memoryManagementMode ?? .default + } + // ==== java 2 swift --------------------------------------------------------- /// The Java class path that should be passed along to the swift-java tool. diff --git a/Sources/JavaKitConfigurationShared/GenerationMode.swift b/Sources/JavaKitConfigurationShared/GenerationMode.swift index 1feac411..22fdd5f5 100644 --- a/Sources/JavaKitConfigurationShared/GenerationMode.swift +++ b/Sources/JavaKitConfigurationShared/GenerationMode.swift @@ -76,3 +76,25 @@ extension JExtractMinimumAccessLevelMode { .public } } + + +/// Configures how memory should be managed by the user +public enum JExtractMemoryManagementMode: String, Codable { + /// Force users to provide an explicit `SwiftArena` to all calls that require them. + case explicit + + /// Provide both explicit `SwiftArena` support + /// and a default global automatic `SwiftArena` that will deallocate memory when the GC decides to. + case allowGlobalAutomatic + + public static var `default`: Self { + .explicit + } + + public var requiresGlobalArena: Bool { + switch self { + case .explicit: false + case .allowGlobalAutomatic: true + } + } +} diff --git a/Sources/SwiftJavaTool/Commands/JExtractCommand.swift b/Sources/SwiftJavaTool/Commands/JExtractCommand.swift index 88fbf7f3..b32f34a0 100644 --- a/Sources/SwiftJavaTool/Commands/JExtractCommand.swift +++ b/Sources/SwiftJavaTool/Commands/JExtractCommand.swift @@ -67,6 +67,9 @@ extension SwiftJava { @Option(help: "The lowest access level of Swift declarations that should be extracted, defaults to 'public'.") var minimumInputAccessLevel: JExtractMinimumAccessLevelMode = .default + @Option(help: "The memory management mode to use for the generated code. By default, the user must explicitly provide `SwiftArena` to all calls that require it. By choosing `allow-automatic`, user can omit this parameter and a global GC-based arena will be used. `force-automatic` removes all explicit memory management.") + var memoryManagementMode: JExtractMemoryManagementMode = .default + @Option( help: """ A swift-java configuration file for a given Swift module name on which this module depends, @@ -89,6 +92,7 @@ extension SwiftJava.JExtractCommand { config.writeEmptyFiles = writeEmptyFiles config.unsignedNumbersMode = unsignedNumbers config.minimumInputAccessLevelMode = minimumInputAccessLevel + config.memoryManagementMode = memoryManagementMode try checkModeCompatibility() @@ -117,6 +121,10 @@ extension SwiftJava.JExtractCommand { case .wrapGuava: () // OK } + } else if self.mode == .ffm { + guard self.memoryManagementMode == .explicit else { + throw IllegalModeCombinationError("FFM mode does not support '\(self.memoryManagementMode)' memory management mode! \(Self.helpMessage)") + } } } } @@ -148,3 +156,4 @@ struct IllegalModeCombinationError: Error { extension JExtractGenerationMode: ExpressibleByArgument {} extension JExtractUnsignedIntegerMode: ExpressibleByArgument {} extension JExtractMinimumAccessLevelMode: ExpressibleByArgument {} +extension JExtractMemoryManagementMode: ExpressibleByArgument {} diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/AutoSwiftMemorySession.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/AutoSwiftMemorySession.java new file mode 100644 index 00000000..36e73209 --- /dev/null +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/AutoSwiftMemorySession.java @@ -0,0 +1,56 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package org.swift.swiftkit.core; + + +import org.swift.swiftkit.core.ref.SwiftCleaner; + +import java.util.Objects; +import java.util.concurrent.ThreadFactory; + +/** + * A memory session which manages registered objects via the Garbage Collector. + * + *

When registered Java wrapper classes around native Swift instances {@link SwiftInstance}, + * are eligible for collection, this will trigger the cleanup of the native resources as well. + * + *

This memory session is LESS reliable than using a {@link ConfinedSwiftMemorySession} because + * the timing of when the native resources are cleaned up is somewhat undefined, and rely on the + * system GC. Meaning, that if an object nas been promoted to an old generation, there may be a + * long time between the resource no longer being referenced "in Java" and its native memory being released, + * and also the deinit of the Swift type being run. + * + *

This can be problematic for Swift applications which rely on quick release of resources, and may expect + * the deinits to run in expected and "quick" succession. + * + *

Whenever possible, prefer using an explicitly managed {@link SwiftArena}, such as {@link SwiftArena#ofConfined()}. + */ +final class AutoSwiftMemorySession implements SwiftArena { + private final SwiftCleaner swiftCleaner; + + public AutoSwiftMemorySession(ThreadFactory cleanerThreadFactory) { + this.swiftCleaner = SwiftCleaner.create(cleanerThreadFactory); + } + + @Override + public void register(SwiftInstance instance) { + Objects.requireNonNull(instance, "value"); + + // We make sure we don't capture `instance` in the + // cleanup action, so we can ignore the warning below. + var cleanupAction = instance.$createCleanup(); + swiftCleaner.register(instance, cleanupAction); + } +} \ No newline at end of file diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/ConfinedSwiftMemorySession.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/ConfinedSwiftMemorySession.java index 7c6e80fb..4383a6fe 100644 --- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/ConfinedSwiftMemorySession.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/ConfinedSwiftMemorySession.java @@ -28,17 +28,13 @@ public class ConfinedSwiftMemorySession implements ClosableSwiftArena { final ConfinedResourceList resources; - public ConfinedSwiftMemorySession() { - this(Thread.currentThread()); - } - public ConfinedSwiftMemorySession(Thread owner) { this.owner = owner; this.state = new AtomicInteger(ACTIVE); this.resources = new ConfinedResourceList(); } - public void checkValid() throws RuntimeException { + void checkValid() throws RuntimeException { if (this.owner != null && this.owner != Thread.currentThread()) { throw new WrongThreadException(String.format("ConfinedSwift arena is confined to %s but was closed from %s!", this.owner, Thread.currentThread())); } else if (this.state.get() < ACTIVE) { diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/JNISwiftInstance.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/JNISwiftInstance.java index 6b30ed2f..95f1e5a0 100644 --- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/JNISwiftInstance.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/JNISwiftInstance.java @@ -56,13 +56,8 @@ protected JNISwiftInstance(long selfPointer, SwiftArena arena) { @Override public SwiftInstanceCleanup $createCleanup() { - final AtomicBoolean statusDestroyedFlag = $statusDestroyedFlag(); - Runnable markAsDestroyed = new Runnable() { - @Override - public void run() { - statusDestroyedFlag.set(true); - } - }; + var statusDestroyedFlag = $statusDestroyedFlag(); + Runnable markAsDestroyed = () -> statusDestroyedFlag.set(true); return new JNISwiftInstanceCleanup(this.$createDestroyFunction(), markAsDestroyed); } diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftArena.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftArena.java index ed16d250..3b6c4626 100644 --- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftArena.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftArena.java @@ -14,6 +14,8 @@ package org.swift.swiftkit.core; +import java.util.concurrent.ThreadFactory; + /** * A Swift arena manages Swift allocated memory for classes, structs, enums etc. * When an arena is closed, it will destroy all managed swift objects in a way appropriate to their type. @@ -21,12 +23,21 @@ *

A confined arena has an associated owner thread that confines some operations to * associated owner thread such as {@link ClosableSwiftArena#close()}. */ -public interface SwiftArena { +public interface SwiftArena { /** * Register a Swift object. * Its memory should be considered managed by this arena, and be destroyed when the arena is closed. */ void register(SwiftInstance instance); + + static ClosableSwiftArena ofConfined() { + return new ConfinedSwiftMemorySession(Thread.currentThread()); + } + + static SwiftArena ofAuto() { + ThreadFactory cleanerThreadFactory = r -> new Thread(r, "AutoSwiftArenaCleanerThread"); + return new AutoSwiftMemorySession(cleanerThreadFactory); + } } /** diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftMemoryManagement.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftMemoryManagement.java new file mode 100644 index 00000000..2b9a1209 --- /dev/null +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftMemoryManagement.java @@ -0,0 +1,19 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package org.swift.swiftkit.core; + +public class SwiftMemoryManagement { + public static final SwiftArena GLOBAL_SWIFT_JAVA_ARENA = SwiftArena.ofAuto(); +} diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/ref/PhantomCleanable.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/ref/PhantomCleanable.java new file mode 100644 index 00000000..2efcdae7 --- /dev/null +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/ref/PhantomCleanable.java @@ -0,0 +1,35 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package org.swift.swiftkit.core.ref; + +import java.lang.ref.PhantomReference; + +public class PhantomCleanable extends PhantomReference { + private final Runnable cleanupAction; + private final SwiftCleaner swiftCleaner; + + public PhantomCleanable(Object referent, SwiftCleaner swiftCleaner, Runnable cleanupAction) { + super(referent, swiftCleaner.referenceQueue); + this.cleanupAction = cleanupAction; + this.swiftCleaner = swiftCleaner; + swiftCleaner.list.add(this); + } + + public void cleanup() { + if (swiftCleaner.list.remove(this)) { + cleanupAction.run(); + } + } +} diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/ref/SwiftCleaner.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/ref/SwiftCleaner.java new file mode 100644 index 00000000..2a5b49f5 --- /dev/null +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/ref/SwiftCleaner.java @@ -0,0 +1,67 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package org.swift.swiftkit.core.ref; + +import java.lang.ref.ReferenceQueue; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import java.util.Objects; +import java.util.concurrent.ThreadFactory; + +public class SwiftCleaner implements Runnable { + final ReferenceQueue referenceQueue; + final List list; + + private SwiftCleaner() { + this.referenceQueue = new ReferenceQueue<>(); + this.list = Collections.synchronizedList(new LinkedList<>()); + } + + public static SwiftCleaner create(ThreadFactory threadFactory) { + SwiftCleaner swiftCleaner = new SwiftCleaner(); + swiftCleaner.start(threadFactory); + return swiftCleaner; + } + + void start(ThreadFactory threadFactory) { + // This makes sure the linked list is not empty when the thread starts, + // and the thread will run at least until the cleaner itself can be GCed. + new PhantomCleanable(this, this, () -> {}); + + Thread thread = threadFactory.newThread(this); + thread.setDaemon(true); + thread.start(); + } + + public void register(Object resourceHolder, Runnable cleaningAction) { + Objects.requireNonNull(resourceHolder, "resourceHolder"); + Objects.requireNonNull(cleaningAction, "cleaningAction"); + new PhantomCleanable(resourceHolder, this, cleaningAction); + } + + @Override + public void run() { + while (!list.isEmpty()) { + try { + PhantomCleanable removed = (PhantomCleanable) referenceQueue.remove(60 * 1000L); + removed.cleanup(); + } catch (Throwable e) { + // ignore exceptions from the cleanup action + // (including interruption of cleanup thread) + } + } + } +} diff --git a/SwiftKitCore/src/test/java/org/swift/swiftkit/AutoArenaTest.java b/SwiftKitCore/src/test/java/org/swift/swiftkit/AutoArenaTest.java new file mode 100644 index 00000000..b414962f --- /dev/null +++ b/SwiftKitCore/src/test/java/org/swift/swiftkit/AutoArenaTest.java @@ -0,0 +1,57 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package org.swift.swiftkit; + +import org.junit.jupiter.api.Test; +import org.swift.swiftkit.core.JNISwiftInstance; +import org.swift.swiftkit.core.SwiftArena; + +public class AutoArenaTest { + + @Test + @SuppressWarnings("removal") // System.runFinalization() will be removed + public void cleaner_releases_native_resource() { + SwiftArena arena = SwiftArena.ofAuto(); + + // This object is registered to the arena. + var object = new FakeSwiftInstance(arena); + var statusDestroyedFlag = object.$statusDestroyedFlag(); + + // Release the object and hope it gets GC-ed soon + + // noinspection UnusedAssignment + object = null; + + var i = 1_000; + while (!statusDestroyedFlag.get()) { + System.runFinalization(); + System.gc(); + + if (i-- < 1) { + throw new RuntimeException("Reference was not cleaned up! Did Cleaner not pick up the release?"); + } + } + } + + private static class FakeSwiftInstance extends JNISwiftInstance { + public FakeSwiftInstance(SwiftArena arena) { + super(1, arena); + } + + protected Runnable $createDestroyFunction() { + return () -> {}; + } + } +} diff --git a/Tests/JExtractSwiftTests/MemoryManagementModeTests.swift b/Tests/JExtractSwiftTests/MemoryManagementModeTests.swift new file mode 100644 index 00000000..4edf59c2 --- /dev/null +++ b/Tests/JExtractSwiftTests/MemoryManagementModeTests.swift @@ -0,0 +1,77 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import JExtractSwiftLib +import JavaKitConfigurationShared +import Testing + +@Suite +struct MemoryManagementModeTests { + let text = + """ + class MyClass {} + + public func f() -> MyClass + """ + + @Test + func explicit() throws { + var config = Configuration() + config.memoryManagementMode = .explicit + + try assertOutput( + input: text, + config: config, + .jni, .java, + expectedChunks: [ + """ + /** + * Downcall to Swift: + * {@snippet lang=swift : + * public func f() -> MyClass + * } + */ + public static MyClass f(SwiftArena swiftArena$) { + return new MyClass(SwiftModule.$f(), swiftArena$); + } + """, + ] + ) + } + + @Test + func allowGlobalAutomatic() throws { + var config = Configuration() + config.memoryManagementMode = .allowGlobalAutomatic + + try assertOutput( + input: text, + config: config, + .jni, .java, + detectChunkByInitialLines: 1, + expectedChunks: [ + """ + public static MyClass f() { + return f(SwiftMemoryManagement.GLOBAL_SWIFT_JAVA_ARENA); + } + """, + """ + public static MyClass f(SwiftArena swiftArena$) { + return new MyClass(SwiftModule.$f(), swiftArena$); + } + """, + ] + ) + } +} From d5f9c9059665550d4b696f2a345ba085bfdd11e9 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Fri, 8 Aug 2025 07:13:28 +0900 Subject: [PATCH 339/426] Update Dockerfile (#349) --- docker/Dockerfile | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index 06b17a87..c3568b54 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -18,9 +18,13 @@ ENV LC_ALL=en_US.UTF-8 ENV LANG=en_US.UTF-8 ENV LANGUAGE=en_US.UTF-8 -COPY install_jdk.sh . - # JDK dependency -RUN bash -xc 'JDK_VENDOR=corretto ./install_jdk.sh' -ENV JAVA_HOME="/usr/lib/jvm/default-jdk" -ENV PATH="$PATH:/usr/lib/jvm/default-jdk/bin" +RUN curl -s "https://get.sdkman.io" | bash +RUN bash -c "source /root/.sdkman/bin/sdkman-init.sh && sdk install java 24.0.1-amzn" + +RUN curl -O https://download.swift.org/swiftly/linux/swiftly-$(uname -m).tar.gz && \ + tar zxf swiftly-$(uname -m).tar.gz && \ + ./swiftly init --quiet-shell-followup --assume-yes && \ + . "${SWIFTLY_HOME_DIR:-$HOME/.local/share/swiftly}/env.sh" && \ + hash -r + From 5dd3f36fa086339e1ff90bcad7cb433d0560a125 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Wed, 13 Aug 2025 11:54:56 +0900 Subject: [PATCH 340/426] gh: test with nightly swift builds (#357) --- .github/workflows/pull_request.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index b2338ed2..89ca4289 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -157,7 +157,7 @@ jobs: strategy: fail-fast: false matrix: - swift_version: ['6.1.2'] + swift_version: ['6.1.2', 'nightly'] os_version: ['jammy'] jdk_vendor: ['corretto'] sample_app: [ # TODO: use a reusable-workflow to generate those names @@ -185,7 +185,7 @@ jobs: strategy: fail-fast: false matrix: - swift_version: ['6.1.2'] + swift_version: ['6.1.2'] # no nightly checks for macOS os_version: ['macos'] jdk_vendor: ['corretto'] sample_app: [ # TODO: use a reusable-workflow to generate those names From 69e487ba1871ff9f2f384ae9e0a547616dff128d Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Thu, 14 Aug 2025 18:28:23 +0900 Subject: [PATCH 341/426] jextract: hide memory location wrapping constructor, give it proper name (#360) --- .../JExtractSwiftLib/FFM/ConversionStep.swift | 2 +- ...wift2JavaGenerator+JavaBindingsPrinting.swift | 13 +++++++++++-- .../FFMSwift2JavaGenerator+JavaTranslation.swift | 5 ++++- .../FFM/FFMSwift2JavaGenerator.swift | 15 ++++++++++++++- ...wift2JavaGenerator+JavaBindingsPrinting.swift | 15 ++++++++++++++- .../JNISwift2JavaGenerator+JavaTranslation.swift | 13 ++++++++++--- Tests/JExtractSwiftTests/DataImportTests.swift | 7 ++++--- Tests/JExtractSwiftTests/JNI/JNIClassTests.swift | 16 +++++++++++----- .../JNI/JNIOptionalTests.swift | 2 +- .../JExtractSwiftTests/JNI/JNIStructTests.swift | 12 +++++++++--- .../MemoryManagementModeTests.swift | 4 ++-- Tests/JExtractSwiftTests/MethodImportTests.swift | 6 +++--- 12 files changed, 84 insertions(+), 26 deletions(-) diff --git a/Sources/JExtractSwiftLib/FFM/ConversionStep.swift b/Sources/JExtractSwiftLib/FFM/ConversionStep.swift index 656d9dd9..f59f739d 100644 --- a/Sources/JExtractSwiftLib/FFM/ConversionStep.swift +++ b/Sources/JExtractSwiftLib/FFM/ConversionStep.swift @@ -123,7 +123,7 @@ enum ConversionStep: Equatable { // of splatting out text. let renderedArgumentList = renderedArguments.joined(separator: ", ") return "\(raw: type.description)(\(raw: renderedArgumentList))" - + case .tuplify(let elements): let renderedElements: [String] = elements.enumerated().map { (index, element) in element.asExprSyntax(placeholder: "\(placeholder)_\(index)", bodyItems: &bodyItems)!.description diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift index b8749299..84a90275 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift @@ -407,6 +407,7 @@ extension FFMSwift2JavaGenerator { "arena$" } + // FIXME: use trailing$ convention let varName = outParameter.name.isEmpty ? "_result" : "_result_" + outParameter.name printer.print( @@ -463,7 +464,7 @@ extension FFMSwift2JavaGenerator.JavaConversionStep { switch self { case .placeholder, .explodedName, .constant, .readMemorySegment: return false - case .constructSwiftValue: + case .constructSwiftValue, .wrapMemoryAddressUnsafe: return true case .call(let inner, _, _), .cast(let inner, _), .construct(let inner, _), @@ -482,7 +483,11 @@ extension FFMSwift2JavaGenerator.JavaConversionStep { return false case .readMemorySegment: return true - case .cast(let inner, _), .construct(let inner, _), .constructSwiftValue(let inner, _), .swiftValueSelfSegment(let inner): + case .cast(let inner, _), + .construct(let inner, _), + .constructSwiftValue(let inner, _), + .swiftValueSelfSegment(let inner), + .wrapMemoryAddressUnsafe(let inner, _): return inner.requiresSwiftArena case .call(let inner, _, let withArena): return withArena || inner.requiresTemporaryArena @@ -522,6 +527,10 @@ extension FFMSwift2JavaGenerator.JavaConversionStep { let inner = inner.render(&printer, placeholder) return "new \(javaType.className!)(\(inner), swiftArena$)" + case .wrapMemoryAddressUnsafe(let inner, let javaType): + let inner = inner.render(&printer, placeholder) + return "\(javaType.className!).wrapMemoryAddressUnsafe(\(inner), swiftArena$)" + case .construct(let inner, let javaType): let inner = inner.render(&printer, placeholder) return "new \(javaType)(\(inner))" diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift index f8b2e7e8..06a4d171 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift @@ -684,7 +684,7 @@ extension FFMSwift2JavaGenerator { outParameters: [ JavaParameter(name: "", type: javaType) ], - conversion: .constructSwiftValue(.placeholder, javaType) + conversion: .wrapMemoryAddressUnsafe(.placeholder, javaType) ) case .tuple: @@ -732,6 +732,9 @@ extension FFMSwift2JavaGenerator { // Call 'new \(Type)(\(placeholder), swiftArena$)'. indirect case constructSwiftValue(JavaConversionStep, JavaType) + /// Call the `MyType.wrapMemoryAddressUnsafe` in order to wrap a memory address using the Java binding type + indirect case wrapMemoryAddressUnsafe(JavaConversionStep, JavaType) + // Construct the type using the placeholder as arguments. indirect case construct(JavaConversionStep, JavaType) diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift index 3e60db14..c66b0029 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift @@ -216,9 +216,22 @@ extension FFMSwift2JavaGenerator { printer.print( """ - public \(decl.swiftNominal.name)(MemorySegment segment, AllocatingSwiftArena arena) { + private \(decl.swiftNominal.name)(MemorySegment segment, AllocatingSwiftArena arena) { super(segment, arena); } + + /** + * Assume that the passed {@code MemorySegment} represents a memory address of a {@link \(decl.swiftNominal.name)}. + *

+ * Warnings: + *

    + *
  • No checks are performed about the compatibility of the pointed at memory and the actual \(decl.swiftNominal.name) types.
  • + *
  • This operation does not copy, or retain, the pointed at pointer, so its lifetime must be ensured manually to be valid when wrapping.
  • + *
+ */ + public static \(decl.swiftNominal.name) wrapMemoryAddressUnsafe(MemorySegment selfPointer, AllocatingSwiftArena swiftArena) { + return new \(decl.swiftNominal.name)(selfPointer, swiftArena); + } """ ) diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift index 0920a89b..d3452cef 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift @@ -117,9 +117,22 @@ extension JNISwift2JavaGenerator { printer.print( """ - public \(decl.swiftNominal.name)(long selfPointer, SwiftArena swiftArena) { + private \(decl.swiftNominal.name)(long selfPointer, SwiftArena swiftArena) { super(selfPointer, swiftArena); } + + /** + * Assume that the passed {@code long} represents a memory address of a {@link \(decl.swiftNominal.name)}. + *

+ * Warnings: + *

    + *
  • No checks are performed about the compatibility of the pointed at memory and the actual \(decl.swiftNominal.name) types.
  • + *
  • This operation does not copy, or retain, the pointed at pointer, so its lifetime must be ensured manually to be valid when wrapping.
  • + *
+ */ + public static \(decl.swiftNominal.name) wrapMemoryAddressUnsafe(long selfPointer, SwiftArena swiftArena) { + return new \(decl.swiftNominal.name)(selfPointer, swiftArena); + } """ ) diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift index 0db77ece..64ae23b7 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift @@ -383,7 +383,7 @@ extension JNISwift2JavaGenerator { javaType: javaType, annotations: resultAnnotations, outParameters: [], - conversion: .constructSwiftValue(.placeholder, javaType) + conversion: .wrapMemoryAddressUnsafe(.placeholder, javaType) ) case .tuple([]): @@ -465,7 +465,7 @@ extension JNISwift2JavaGenerator { discriminatorName: "result_discriminator$", optionalClass: "Optional", javaType: .long, - toValue: .constructSwiftValue(.placeholder, .class(package: nil, name: nominalTypeName)) + toValue: .wrapMemoryAddressUnsafe(.placeholder, .class(package: nil, name: nominalTypeName)) ) ) @@ -582,6 +582,9 @@ extension JNISwift2JavaGenerator { /// Call `new \(Type)(\(placeholder), swiftArena$)` indirect case constructSwiftValue(JavaNativeConversionStep, JavaType) + /// Call the `MyType.wrapMemoryAddressUnsafe` in order to wrap a memory address using the Java binding type + indirect case wrapMemoryAddressUnsafe(JavaNativeConversionStep, JavaType) + indirect case call(JavaNativeConversionStep, function: String) indirect case method(JavaNativeConversionStep, function: String, arguments: [JavaNativeConversionStep] = []) @@ -641,6 +644,10 @@ extension JNISwift2JavaGenerator { case .constructSwiftValue(let inner, let javaType): let inner = inner.render(&printer, placeholder) return "new \(javaType.className!)(\(inner), swiftArena$)" + + case .wrapMemoryAddressUnsafe(let inner, let javaType): + let inner = inner.render(&printer, placeholder) + return "\(javaType.className!).wrapMemoryAddressUnsafe(\(inner), swiftArena$)" case .call(let inner, let function): let inner = inner.render(&printer, placeholder) @@ -705,7 +712,7 @@ extension JNISwift2JavaGenerator { case .placeholder, .constant, .isOptionalPresent: return false - case .constructSwiftValue: + case .constructSwiftValue, .wrapMemoryAddressUnsafe: return true case .valueMemoryAddress(let inner): diff --git a/Tests/JExtractSwiftTests/DataImportTests.swift b/Tests/JExtractSwiftTests/DataImportTests.swift index 7416779d..cf4ed387 100644 --- a/Tests/JExtractSwiftTests/DataImportTests.swift +++ b/Tests/JExtractSwiftTests/DataImportTests.swift @@ -86,7 +86,7 @@ final class DataImportTests { ] ) } - + @Test("Import Data: JavaBindings") func data_javaBindings() throws { @@ -167,7 +167,7 @@ final class DataImportTests { public static Data returnData(AllocatingSwiftArena swiftArena$) { MemorySegment _result = swiftArena$.allocate(Data.$LAYOUT); swiftjava_SwiftModule_returnData.call(_result); - return new Data(_result, swiftArena$); + return Data.wrapMemoryAddressUnsafe(_result, swiftArena$); } """, @@ -210,7 +210,7 @@ final class DataImportTests { public static Data init(java.lang.foreign.MemorySegment bytes, long count, AllocatingSwiftArena swiftArena$) { MemorySegment _result = swiftArena$.allocate(Data.$LAYOUT); swiftjava_SwiftModule_Data_init_bytes_count.call(bytes, count, _result); - return new Data(_result, swiftArena$); + return Data.wrapMemoryAddressUnsafe(_result, swiftArena$); } """, @@ -408,4 +408,5 @@ final class DataImportTests { ] ) } + } diff --git a/Tests/JExtractSwiftTests/JNI/JNIClassTests.swift b/Tests/JExtractSwiftTests/JNI/JNIClassTests.swift index 5b015f89..1e33efcb 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIClassTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIClassTests.swift @@ -66,11 +66,17 @@ struct JNIClassTests { System.loadLibrary(LIB_NAME); return true; } - - public MyClass(long selfPointer, SwiftArena swiftArena) { + """, + """ + private MyClass(long selfPointer, SwiftArena swiftArena) { super(selfPointer, swiftArena); } """, + """ + public static MyClass wrapMemoryAddressUnsafe(long selfPointer, SwiftArena swiftArena) { + return new MyClass(selfPointer, swiftArena); + } + """ ]) try assertOutput( input: source, @@ -164,7 +170,7 @@ struct JNIClassTests { * } */ public static MyClass init(long x, long y, SwiftArena swiftArena$) { - return new MyClass(MyClass.$init(x, y), swiftArena$); + return MyClass.wrapMemoryAddressUnsafe(MyClass.$init(x, y), swiftArena$); } """, """ @@ -175,7 +181,7 @@ struct JNIClassTests { * } */ public static MyClass init(SwiftArena swiftArena$) { - return new MyClass(MyClass.$init(), swiftArena$); + return MyClass.wrapMemoryAddressUnsafe(MyClass.$init(), swiftArena$); } """, """ @@ -309,7 +315,7 @@ struct JNIClassTests { * } */ public MyClass copy(SwiftArena swiftArena$) { - return new MyClass(MyClass.$copy(this.$memoryAddress()), swiftArena$); + return MyClass.wrapMemoryAddressUnsafe(MyClass.$copy(this.$memoryAddress()), swiftArena$); } """, """ diff --git a/Tests/JExtractSwiftTests/JNI/JNIOptionalTests.swift b/Tests/JExtractSwiftTests/JNI/JNIOptionalTests.swift index cd04660b..f9c70ba4 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIOptionalTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIOptionalTests.swift @@ -158,7 +158,7 @@ struct JNIOptionalTests { public static Optional optionalClass(Optional arg, SwiftArena swiftArena$) { byte[] result_discriminator$ = new byte[1]; long result$ = SwiftModule.$optionalClass(arg.map(MyClass::$memoryAddress).orElse(0L), result_discriminator$); - return (result_discriminator$[0] == 1) ? Optional.of(new MyClass(result$, swiftArena$)) : Optional.empty(); + return (result_discriminator$[0] == 1) ? Optional.of(MyClass.wrapMemoryAddressUnsafe(result$, swiftArena$)) : Optional.empty(); } """, """ diff --git a/Tests/JExtractSwiftTests/JNI/JNIStructTests.swift b/Tests/JExtractSwiftTests/JNI/JNIStructTests.swift index 01a2e3c0..59d7ee6b 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIStructTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIStructTests.swift @@ -56,10 +56,16 @@ struct JNIStructTests { System.loadLibrary(LIB_NAME); return true; } - - public MyStruct(long selfPointer, SwiftArena swiftArena) { + """, + """ + private MyStruct(long selfPointer, SwiftArena swiftArena) { super(selfPointer, swiftArena); } + """, + """ + public static MyStruct wrapMemoryAddressUnsafe(long selfPointer, SwiftArena swiftArena) { + return new MyStruct(selfPointer, swiftArena); + } """ ]) try assertOutput( @@ -110,7 +116,7 @@ struct JNIStructTests { * } */ public static MyStruct init(long x, long y, SwiftArena swiftArena$) { - return new MyStruct(MyStruct.$init(x, y), swiftArena$); + return MyStruct.wrapMemoryAddressUnsafe(MyStruct.$init(x, y), swiftArena$); } """, """ diff --git a/Tests/JExtractSwiftTests/MemoryManagementModeTests.swift b/Tests/JExtractSwiftTests/MemoryManagementModeTests.swift index 4edf59c2..e64d4397 100644 --- a/Tests/JExtractSwiftTests/MemoryManagementModeTests.swift +++ b/Tests/JExtractSwiftTests/MemoryManagementModeTests.swift @@ -43,7 +43,7 @@ struct MemoryManagementModeTests { * } */ public static MyClass f(SwiftArena swiftArena$) { - return new MyClass(SwiftModule.$f(), swiftArena$); + return MyClass.wrapMemoryAddressUnsafe(SwiftModule.$f(), swiftArena$); } """, ] @@ -68,7 +68,7 @@ struct MemoryManagementModeTests { """, """ public static MyClass f(SwiftArena swiftArena$) { - return new MyClass(SwiftModule.$f(), swiftArena$); + return MyClass.wrapMemoryAddressUnsafe(SwiftModule.$f(), swiftArena$); } """, ] diff --git a/Tests/JExtractSwiftTests/MethodImportTests.swift b/Tests/JExtractSwiftTests/MethodImportTests.swift index fd885f1b..3aa7d394 100644 --- a/Tests/JExtractSwiftTests/MethodImportTests.swift +++ b/Tests/JExtractSwiftTests/MethodImportTests.swift @@ -227,7 +227,7 @@ final class MethodImportTests { public static MySwiftClass globalReturnClass(AllocatingSwiftArena swiftArena$) { MemorySegment _result = swiftArena$.allocate(MySwiftClass.$LAYOUT); swiftjava___FakeModule_globalReturnClass.call(_result); - return new MySwiftClass(_result, swiftArena$); + return MySwiftClass.wrapMemoryAddressUnsafe(_result, swiftArena$); } """ ) @@ -404,7 +404,7 @@ final class MethodImportTests { public static MySwiftClass init(long len, long cap, AllocatingSwiftArena swiftArena$) { MemorySegment _result = swiftArena$.allocate(MySwiftClass.$LAYOUT); swiftjava___FakeModule_MySwiftClass_init_len_cap.call(len, cap, _result) - return new MySwiftClass(_result, swiftArena$); + return MySwiftClass.wrapMemoryAddressUnsafe(_result, swiftArena$); } """ ) @@ -449,7 +449,7 @@ final class MethodImportTests { public static MySwiftStruct init(long len, long cap, AllocatingSwiftArena swiftArena$) { MemorySegment _result = swiftArena$.allocate(MySwiftStruct.$LAYOUT); swiftjava___FakeModule_MySwiftStruct_init_len_cap.call(len, cap, _result) - return new MySwiftStruct(_result, swiftArena$); + return MySwiftStruct.wrapMemoryAddressUnsafe(_result, swiftArena$); } """ ) From a720622d62b3c7f2178f8b8f61e2594fb3cd1958 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Fri, 15 Aug 2025 11:15:43 +0900 Subject: [PATCH 342/426] fix javadoc formatting (#361) --- ...t2JavaGenerator+JavaBindingsPrinting.swift | 10 +-- .../JNI/JNIClassTests.swift | 40 +++++------ .../JNI/JNIClosureTests.swift | 20 +++--- .../JNI/JNIJavaKitTests.swift | 10 +-- .../JNI/JNIModuleTests.swift | 60 ++++++++-------- .../JNI/JNIOptionalTests.swift | 68 +++++++++---------- .../JNI/JNIStructTests.swift | 20 +++--- .../JNI/JNIUnsignedNumberTests.swift | 40 +++++------ .../MemoryManagementModeTests.swift | 16 ++--- 9 files changed, 142 insertions(+), 142 deletions(-) diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift index d3452cef..6d82175f 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift @@ -369,11 +369,11 @@ extension JNISwift2JavaGenerator { printer.print( """ /** - * Downcall to Swift: - * {@snippet lang=swift : - * \(decl.signatureString) - * } - */ + * Downcall to Swift: + * {@snippet lang=swift : + * \(decl.signatureString) + * } + */ """ ) } diff --git a/Tests/JExtractSwiftTests/JNI/JNIClassTests.swift b/Tests/JExtractSwiftTests/JNI/JNIClassTests.swift index 1e33efcb..30bb7433 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIClassTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIClassTests.swift @@ -164,22 +164,22 @@ struct JNIClassTests { expectedChunks: [ """ /** - * Downcall to Swift: - * {@snippet lang=swift : - * public init(x: Int64, y: Int64) - * } - */ + * Downcall to Swift: + * {@snippet lang=swift : + * public init(x: Int64, y: Int64) + * } + */ public static MyClass init(long x, long y, SwiftArena swiftArena$) { return MyClass.wrapMemoryAddressUnsafe(MyClass.$init(x, y), swiftArena$); } """, """ /** - * Downcall to Swift: - * {@snippet lang=swift : - * public init() - * } - */ + * Downcall to Swift: + * {@snippet lang=swift : + * public init() + * } + */ public static MyClass init(SwiftArena swiftArena$) { return MyClass.wrapMemoryAddressUnsafe(MyClass.$init(), swiftArena$); } @@ -309,11 +309,11 @@ struct JNIClassTests { expectedChunks: [ """ /** - * Downcall to Swift: - * {@snippet lang=swift : - * public func copy() -> MyClass - * } - */ + * Downcall to Swift: + * {@snippet lang=swift : + * public func copy() -> MyClass + * } + */ public MyClass copy(SwiftArena swiftArena$) { return MyClass.wrapMemoryAddressUnsafe(MyClass.$copy(this.$memoryAddress()), swiftArena$); } @@ -361,11 +361,11 @@ struct JNIClassTests { expectedChunks: [ """ /** - * Downcall to Swift: - * {@snippet lang=swift : - * public func isEqual(to other: MyClass) -> Bool - * } - */ + * Downcall to Swift: + * {@snippet lang=swift : + * public func isEqual(to other: MyClass) -> Bool + * } + */ public boolean isEqual(MyClass other) { return MyClass.$isEqual(other.$memoryAddress(), this.$memoryAddress()); } diff --git a/Tests/JExtractSwiftTests/JNI/JNIClosureTests.swift b/Tests/JExtractSwiftTests/JNI/JNIClosureTests.swift index 9a388da1..b374d24e 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIClosureTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIClosureTests.swift @@ -36,11 +36,11 @@ struct JNIClosureTests { """, """ /** - * Downcall to Swift: - * {@snippet lang=swift : - * public func emptyClosure(closure: () -> ()) - * } - */ + * Downcall to Swift: + * {@snippet lang=swift : + * public func emptyClosure(closure: () -> ()) + * } + */ public static void emptyClosure(com.example.swift.SwiftModule.emptyClosure.closure closure) { SwiftModule.$emptyClosure(closure); } @@ -88,11 +88,11 @@ struct JNIClosureTests { """, """ /** - * Downcall to Swift: - * {@snippet lang=swift : - * public func closureWithArgumentsAndReturn(closure: (Int64, Bool) -> Int64) - * } - */ + * Downcall to Swift: + * {@snippet lang=swift : + * public func closureWithArgumentsAndReturn(closure: (Int64, Bool) -> Int64) + * } + */ public static void closureWithArgumentsAndReturn(com.example.swift.SwiftModule.closureWithArgumentsAndReturn.closure closure) { SwiftModule.$closureWithArgumentsAndReturn(closure); } diff --git a/Tests/JExtractSwiftTests/JNI/JNIJavaKitTests.swift b/Tests/JExtractSwiftTests/JNI/JNIJavaKitTests.swift index 1f19c8f9..ac6b8384 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIJavaKitTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIJavaKitTests.swift @@ -37,11 +37,11 @@ struct JNIJavaKitTests { expectedChunks: [ """ /** - * Downcall to Swift: - * {@snippet lang=swift : - * public func function(javaLong: JavaLong, javaInteger: JavaInteger, int: Int64) - * } - */ + * Downcall to Swift: + * {@snippet lang=swift : + * public func function(javaLong: JavaLong, javaInteger: JavaInteger, int: Int64) + * } + */ public static void function(java.lang.Long javaLong, java.lang.Integer javaInteger, long int) { SwiftModule.$function(javaLong, javaInteger, int); } diff --git a/Tests/JExtractSwiftTests/JNI/JNIModuleTests.swift b/Tests/JExtractSwiftTests/JNI/JNIModuleTests.swift index 198276ba..ad55f491 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIModuleTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIModuleTests.swift @@ -67,11 +67,11 @@ struct JNIModuleTests { expectedChunks: [ """ /** - * Downcall to Swift: - * {@snippet lang=swift : - * public func helloWorld() - * } - */ + * Downcall to Swift: + * {@snippet lang=swift : + * public func helloWorld() + * } + */ public static void helloWorld() { SwiftModule.$helloWorld(); } @@ -81,11 +81,11 @@ struct JNIModuleTests { """, """ /** - * Downcall to Swift: - * {@snippet lang=swift : - * public func takeIntegers(i1: Int8, i2: Int16, i3: Int32, i4: Int64) -> UInt16 - * } - */ + * Downcall to Swift: + * {@snippet lang=swift : + * public func takeIntegers(i1: Int8, i2: Int16, i3: Int32, i4: Int64) -> UInt16 + * } + */ @Unsigned public static char takeIntegers(byte i1, short i2, int i3, long i4) { return SwiftModule.$takeIntegers(i1, i2, i3, i4); @@ -96,11 +96,11 @@ struct JNIModuleTests { """, """ /** - * Downcall to Swift: - * {@snippet lang=swift : - * public func otherPrimitives(b: Bool, f: Float, d: Double) - * } - */ + * Downcall to Swift: + * {@snippet lang=swift : + * public func otherPrimitives(b: Bool, f: Float, d: Double) + * } + */ public static void otherPrimitives(boolean b, float f, double d) { SwiftModule.$otherPrimitives(b, f, d); } @@ -151,11 +151,11 @@ struct JNIModuleTests { expectedChunks: [ """ /** - * Downcall to Swift: - * {@snippet lang=swift : - * public func copy(_ string: String) -> String - * } - */ + * Downcall to Swift: + * {@snippet lang=swift : + * public func copy(_ string: String) -> String + * } + */ public static java.lang.String copy(java.lang.String string) { return SwiftModule.$copy(string); } @@ -194,11 +194,11 @@ struct JNIModuleTests { expectedChunks: [ """ /** - * Downcall to Swift: - * {@snippet lang=swift : - * public func methodA() throws - * } - */ + * Downcall to Swift: + * {@snippet lang=swift : + * public func methodA() throws + * } + */ public static void methodA() throws Exception { SwiftModule.$methodA(); } @@ -208,11 +208,11 @@ struct JNIModuleTests { """, """ /** - * Downcall to Swift: - * {@snippet lang=swift : - * public func methodB() throws -> Int64 - * } - */ + * Downcall to Swift: + * {@snippet lang=swift : + * public func methodB() throws -> Int64 + * } + */ public static long methodB() throws Exception { return SwiftModule.$methodB(); } diff --git a/Tests/JExtractSwiftTests/JNI/JNIOptionalTests.swift b/Tests/JExtractSwiftTests/JNI/JNIOptionalTests.swift index f9c70ba4..2186e227 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIOptionalTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIOptionalTests.swift @@ -46,12 +46,12 @@ struct JNIOptionalTests { * public func optionalSugar(_ arg: Int64?) -> Int32? * } */ - public static OptionalInt optionalSugar(OptionalLong arg) { - long combined$ = SwiftModule.$optionalSugar((byte) (arg.isPresent() ? 1 : 0), arg.orElse(0L)); - byte discriminator$ = (byte) (combined$ & 0xFF); - int value$ = (int) (combined$ >> 32); - return discriminator$ == 1 ? OptionalInt.of(value$) : OptionalInt.empty(); - } + public static OptionalInt optionalSugar(OptionalLong arg) { + long combined$ = SwiftModule.$optionalSugar((byte) (arg.isPresent() ? 1 : 0), arg.orElse(0L)); + byte discriminator$ = (byte) (combined$ & 0xFF); + int value$ = (int) (combined$ >> 32); + return discriminator$ == 1 ? OptionalInt.of(value$) : OptionalInt.empty(); + } """, """ private static native long $optionalSugar(byte arg_discriminator, long arg_value); @@ -92,16 +92,16 @@ struct JNIOptionalTests { expectedChunks: [ """ /** - * Downcall to Swift: - * {@snippet lang=swift : - * public func optionalExplicit(_ arg: Optional) -> Optional - * } - */ - public static Optional optionalExplicit(Optional arg) { - byte[] result_discriminator$ = new byte[1]; - java.lang.String result$ = SwiftModule.$optionalExplicit((byte) (arg.isPresent() ? 1 : 0), arg.orElse(null), result_discriminator$); - return (result_discriminator$[0] == 1) ? Optional.of(result$) : Optional.empty(); - } + * Downcall to Swift: + * {@snippet lang=swift : + * public func optionalExplicit(_ arg: Optional) -> Optional + * } + */ + public static Optional optionalExplicit(Optional arg) { + byte[] result_discriminator$ = new byte[1]; + java.lang.String result$ = SwiftModule.$optionalExplicit((byte) (arg.isPresent() ? 1 : 0), arg.orElse(null), result_discriminator$); + return (result_discriminator$[0] == 1) ? Optional.of(result$) : Optional.empty(); + } """, """ private static native java.lang.String $optionalExplicit(byte arg_discriminator, java.lang.String arg_value, byte[] result_discriminator$); @@ -150,16 +150,16 @@ struct JNIOptionalTests { expectedChunks: [ """ /** - * Downcall to Swift: - * {@snippet lang=swift : - * public func optionalClass(_ arg: MyClass?) -> MyClass? - * } - */ - public static Optional optionalClass(Optional arg, SwiftArena swiftArena$) { - byte[] result_discriminator$ = new byte[1]; - long result$ = SwiftModule.$optionalClass(arg.map(MyClass::$memoryAddress).orElse(0L), result_discriminator$); - return (result_discriminator$[0] == 1) ? Optional.of(MyClass.wrapMemoryAddressUnsafe(result$, swiftArena$)) : Optional.empty(); - } + * Downcall to Swift: + * {@snippet lang=swift : + * public func optionalClass(_ arg: MyClass?) -> MyClass? + * } + */ + public static Optional optionalClass(Optional arg, SwiftArena swiftArena$) { + byte[] result_discriminator$ = new byte[1]; + long result$ = SwiftModule.$optionalClass(arg.map(MyClass::$memoryAddress).orElse(0L), result_discriminator$); + return (result_discriminator$[0] == 1) ? Optional.of(MyClass.wrapMemoryAddressUnsafe(result$, swiftArena$)) : Optional.empty(); + } """, """ private static native long $optionalClass(long arg, byte[] result_discriminator$); @@ -213,14 +213,14 @@ struct JNIOptionalTests { expectedChunks: [ """ /** - * Downcall to Swift: - * {@snippet lang=swift : - * public func optionalJavaKitClass(_ arg: JavaLong?) - * } - */ - public static void optionalJavaKitClass(Optional arg) { - SwiftModule.$optionalJavaKitClass(arg.orElse(null)); - } + * Downcall to Swift: + * {@snippet lang=swift : + * public func optionalJavaKitClass(_ arg: JavaLong?) + * } + */ + public static void optionalJavaKitClass(Optional arg) { + SwiftModule.$optionalJavaKitClass(arg.orElse(null)); + } """, """ private static native void $optionalJavaKitClass(java.lang.Long arg); diff --git a/Tests/JExtractSwiftTests/JNI/JNIStructTests.swift b/Tests/JExtractSwiftTests/JNI/JNIStructTests.swift index 59d7ee6b..7f54fa7e 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIStructTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIStructTests.swift @@ -110,11 +110,11 @@ struct JNIStructTests { expectedChunks: [ """ /** - * Downcall to Swift: - * {@snippet lang=swift : - * public init(x: Int64, y: Int64) - * } - */ + * Downcall to Swift: + * {@snippet lang=swift : + * public init(x: Int64, y: Int64) + * } + */ public static MyStruct init(long x, long y, SwiftArena swiftArena$) { return MyStruct.wrapMemoryAddressUnsafe(MyStruct.$init(x, y), swiftArena$); } @@ -182,11 +182,11 @@ struct JNIStructTests { expectedChunks: [ """ /** - * Downcall to Swift: - * {@snippet lang=swift : - * public func doSomething(x: Int64) - * } - */ + * Downcall to Swift: + * {@snippet lang=swift : + * public func doSomething(x: Int64) + * } + */ public void doSomething(long x) { MyStruct.$doSomething(x, this.$memoryAddress()); } diff --git a/Tests/JExtractSwiftTests/JNI/JNIUnsignedNumberTests.swift b/Tests/JExtractSwiftTests/JNI/JNIUnsignedNumberTests.swift index f4dbffed..bfae447a 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIUnsignedNumberTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIUnsignedNumberTests.swift @@ -27,11 +27,11 @@ final class JNIUnsignedNumberTests { expectedChunks: [ """ /** - * Downcall to Swift: - * {@snippet lang=swift : - * public func unsignedChar(_ arg: UInt16) - * } - */ + * Downcall to Swift: + * {@snippet lang=swift : + * public func unsignedChar(_ arg: UInt16) + * } + */ public static void unsignedChar(@Unsigned char arg) { SwiftModule.$unsignedChar(arg); } @@ -57,11 +57,11 @@ final class JNIUnsignedNumberTests { expectedChunks: [ """ /** - * Downcall to Swift: - * {@snippet lang=swift : - * public func unsignedInt(_ arg: UInt32) - * } - */ + * Downcall to Swift: + * {@snippet lang=swift : + * public func unsignedInt(_ arg: UInt32) + * } + */ public static void unsignedInt(@Unsigned int arg) { SwiftModule.$unsignedInt(arg); } @@ -83,11 +83,11 @@ final class JNIUnsignedNumberTests { expectedChunks: [ """ /** - * Downcall to Swift: - * {@snippet lang=swift : - * public func returnUnsignedInt() -> UInt32 - * } - */ + * Downcall to Swift: + * {@snippet lang=swift : + * public func returnUnsignedInt() -> UInt32 + * } + */ @Unsigned public static int returnUnsignedInt() { return SwiftModule.$returnUnsignedInt(); @@ -137,11 +137,11 @@ final class JNIUnsignedNumberTests { expectedChunks: [ """ /** - * Downcall to Swift: - * {@snippet lang=swift : - * public func unsignedLong(first: UInt64, second: UInt32) -> UInt32 - * } - */ + * Downcall to Swift: + * {@snippet lang=swift : + * public func unsignedLong(first: UInt64, second: UInt32) -> UInt32 + * } + */ @Unsigned public static int unsignedLong(@Unsigned long first, @Unsigned int second) { return SwiftModule.$unsignedLong(first, second); diff --git a/Tests/JExtractSwiftTests/MemoryManagementModeTests.swift b/Tests/JExtractSwiftTests/MemoryManagementModeTests.swift index e64d4397..3ce839b9 100644 --- a/Tests/JExtractSwiftTests/MemoryManagementModeTests.swift +++ b/Tests/JExtractSwiftTests/MemoryManagementModeTests.swift @@ -37,14 +37,14 @@ struct MemoryManagementModeTests { expectedChunks: [ """ /** - * Downcall to Swift: - * {@snippet lang=swift : - * public func f() -> MyClass - * } - */ - public static MyClass f(SwiftArena swiftArena$) { - return MyClass.wrapMemoryAddressUnsafe(SwiftModule.$f(), swiftArena$); - } + * Downcall to Swift: + * {@snippet lang=swift : + * public func f() -> MyClass + * } + */ + public static MyClass f(SwiftArena swiftArena$) { + return MyClass.wrapMemoryAddressUnsafe(SwiftModule.$f(), swiftArena$); + } """, ] ) From 94cb7ecdf905ff1450de1d44b6f145460807020e Mon Sep 17 00:00:00 2001 From: Mads Odgaard Date: Fri, 15 Aug 2025 04:59:20 +0200 Subject: [PATCH 343/426] Add "..." wildcard syntax to output assertions in JExtract tests (#362) Co-authored-by: Konrad `ktoso` Malawski --- .../Asserts/TextAssertions.swift | 65 +++++++++++++---- .../JNI/JNIVariablesTests.swift | 72 ++++--------------- 2 files changed, 64 insertions(+), 73 deletions(-) diff --git a/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift b/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift index e975d223..1f768fb2 100644 --- a/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift +++ b/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift @@ -124,18 +124,49 @@ func assertOutput( continue } - for (no, (g, e)) in zip(gotLines.dropFirst(matchingOutputOffset), expectedLines).enumerated() { - if g.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines).count == 0 - || e.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines).count == 0 { - continue - } + var currentExpectedLine: Int = 0 + var currentGotLine: Int = matchingOutputOffset + + outer: while currentExpectedLine < expectedLines.count { + let expectedLine = expectedLines[currentExpectedLine].trimmingCharacters(in: CharacterSet.whitespacesAndNewlines) - let ge = g.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines) - let ee = e.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines) - if ge.commonPrefix(with: ee) != ee { - diffLineNumbers.append(no + matchingOutputOffset) + if expectedLine == "..." { + // Ignore the rest of output, if last line is placeholder. + guard currentExpectedLine != (expectedLines.count - 1) else { + break + } - #expect(ge == ee, sourceLocation: sourceLocation) + let nextLine = expectedLines[currentExpectedLine + 1].trimmingCharacters(in: .whitespacesAndNewlines) + while currentGotLine < gotLines.count { + let gottenLine = gotLines[currentGotLine].trimmingCharacters(in: CharacterSet.whitespacesAndNewlines) + if gottenLine.commonPrefix(with: nextLine) == nextLine { + currentExpectedLine += 2 + break + } else if nextLine == "..." { + // Skip any following "..." + currentExpectedLine += 1 + break + } else { + currentGotLine += 1 + } + + if currentGotLine == gotLines.count { + diffLineNumbers.append(currentExpectedLine + matchingOutputOffset + 1) + Issue.record("Expected to find '\(nextLine)' after wildcard, but end of file reached.", sourceLocation: sourceLocation) + break outer + } + } + + currentGotLine += 1 + } else { + let gottenLine = gotLines[currentGotLine].trimmingCharacters(in: CharacterSet.whitespacesAndNewlines) + if gottenLine.commonPrefix(with: expectedLine) != expectedLine { + diffLineNumbers.append(currentExpectedLine + matchingOutputOffset) + + #expect(gottenLine == expectedLine, sourceLocation: sourceLocation) + } + currentGotLine += 1 + currentExpectedLine += 1 } } @@ -155,9 +186,17 @@ func assertOutput( print("==== ---------------------------------------------------------------") print("Got output:") let printFromLineNo = matchingOutputOffset - let printToLineNo = matchingOutputOffset + expectedLines.count - for (n, g) in gotLines.enumerated() where n >= printFromLineNo && n <= printToLineNo { - print("\(n): \(g)".red(if: diffLineNumbers.contains(n))) + for (n, g) in gotLines.enumerated() where n >= printFromLineNo { + let baseLine = "\(n): \(g)" + var line = baseLine + if diffLineNumbers.contains(n) { + line += "\n" + let leadingCount = "\(n): ".count + let message = "\(String(repeating: " ", count: leadingCount))\(String(repeating: "^", count: 8)) EXPECTED MATCH OR SEARCHING FROM HERE " + line += "\(message)\(String(repeating: "^", count: max(0, line.count - message.count)))" + line = line.red + } + print(line) } print("==== ---------------------------------------------------------------\n") } diff --git a/Tests/JExtractSwiftTests/JNI/JNIVariablesTests.swift b/Tests/JExtractSwiftTests/JNI/JNIVariablesTests.swift index 933e4f08..c9d313a5 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIVariablesTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIVariablesTests.swift @@ -69,12 +69,7 @@ struct JNIVariablesTests { """ @_cdecl("Java_com_example_swift_MyClass__00024getConstant__J") func Java_com_example_swift_MyClass__00024getConstant__J(environment: UnsafeMutablePointer!, thisClass: jclass, self: jlong) -> jlong { - assert(self != 0, "self memory address was null") - let selfBits$ = Int(Int64(fromJNI: self, in: environment!)) - let self$ = UnsafeMutablePointer(bitPattern: selfBits$) - guard let self$ else { - fatalError("self memory address was null in call to \\(#function)!") - } + ... return self$.pointee.constant.getJNIValue(in: environment!) } """ @@ -134,11 +129,12 @@ struct JNIVariablesTests { @_cdecl("Java_com_example_swift_MyClass__00024getMutable__J") func Java_com_example_swift_MyClass__00024getMutable__J(environment: UnsafeMutablePointer!, thisClass: jclass, self: jlong) -> jlong { assert(self != 0, "self memory address was null") - let selfBits$ = Int(Int64(fromJNI: self, in: environment!)) + ... let self$ = UnsafeMutablePointer(bitPattern: selfBits$) guard let self$ else { fatalError("self memory address was null in call to \\(#function)!") } + ... return self$.pointee.mutable.getJNIValue(in: environment!) } """, @@ -146,11 +142,7 @@ struct JNIVariablesTests { @_cdecl("Java_com_example_swift_MyClass__00024setMutable__JJ") func Java_com_example_swift_MyClass__00024setMutable__JJ(environment: UnsafeMutablePointer!, thisClass: jclass, newValue: jlong, self: jlong) { assert(self != 0, "self memory address was null") - let selfBits$ = Int(Int64(fromJNI: self, in: environment!)) - let self$ = UnsafeMutablePointer(bitPattern: selfBits$) - guard let self$ else { - fatalError("self memory address was null in call to \\(#function)!") - } + ... self$.pointee.mutable = Int64(fromJNI: newValue, in: environment!) } """ @@ -195,12 +187,7 @@ struct JNIVariablesTests { """ @_cdecl("Java_com_example_swift_MyClass__00024getComputed__J") func Java_com_example_swift_MyClass__00024getComputed__J(environment: UnsafeMutablePointer!, thisClass: jclass, self: jlong) -> jlong { - assert(self != 0, "self memory address was null") - let selfBits$ = Int(Int64(fromJNI: self, in: environment!)) - let self$ = UnsafeMutablePointer(bitPattern: selfBits$) - guard let self$ else { - fatalError("self memory address was null in call to \\(#function)!") - } + ... return self$.pointee.computed.getJNIValue(in: environment!) } """, @@ -245,12 +232,7 @@ struct JNIVariablesTests { """ @_cdecl("Java_com_example_swift_MyClass__00024getComputedThrowing__J") func Java_com_example_swift_MyClass__00024getComputedThrowing__J(environment: UnsafeMutablePointer!, thisClass: jclass, self: jlong) -> jlong { - assert(self != 0, "self memory address was null") - let selfBits$ = Int(Int64(fromJNI: self, in: environment!)) - let self$ = UnsafeMutablePointer(bitPattern: selfBits$) - guard let self$ else { - fatalError("self memory address was null in call to \\(#function)!") - } + ... do { return try self$.pointee.computedThrowing.getJNIValue(in: environment!) } catch { @@ -314,24 +296,14 @@ struct JNIVariablesTests { """ @_cdecl("Java_com_example_swift_MyClass__00024getGetterAndSetter__J") func Java_com_example_swift_MyClass__00024getGetterAndSetter__J(environment: UnsafeMutablePointer!, thisClass: jclass, self: jlong) -> jlong { - assert(self != 0, "self memory address was null") - let selfBits$ = Int(Int64(fromJNI: self, in: environment!)) - let self$ = UnsafeMutablePointer(bitPattern: selfBits$) - guard let self$ else { - fatalError("self memory address was null in call to \\(#function)!") - } + ... return self$.pointee.getterAndSetter.getJNIValue(in: environment!) } """, """ @_cdecl("Java_com_example_swift_MyClass__00024setGetterAndSetter__JJ") func Java_com_example_swift_MyClass__00024setGetterAndSetter__JJ(environment: UnsafeMutablePointer!, thisClass: jclass, newValue: jlong, self: jlong) { - assert(self != 0, "self memory address was null") - let selfBits$ = Int(Int64(fromJNI: self, in: environment!)) - let self$ = UnsafeMutablePointer(bitPattern: selfBits$) - guard let self$ else { - fatalError("self memory address was null in call to \\(#function)!") - } + ... self$.pointee.getterAndSetter = Int64(fromJNI: newValue, in: environment!) } """ @@ -390,24 +362,14 @@ struct JNIVariablesTests { """ @_cdecl("Java_com_example_swift_MyClass__00024isSomeBoolean__J") func Java_com_example_swift_MyClass__00024isSomeBoolean__J(environment: UnsafeMutablePointer!, thisClass: jclass, self: jlong) -> jboolean { - assert(self != 0, "self memory address was null") - let selfBits$ = Int(Int64(fromJNI: self, in: environment!)) - let self$ = UnsafeMutablePointer(bitPattern: selfBits$) - guard let self$ else { - fatalError("self memory address was null in call to \\(#function)!") - } + ... return self$.pointee.someBoolean.getJNIValue(in: environment!) } """, """ @_cdecl("Java_com_example_swift_MyClass__00024setSomeBoolean__ZJ") func Java_com_example_swift_MyClass__00024setSomeBoolean__ZJ(environment: UnsafeMutablePointer!, thisClass: jclass, newValue: jboolean, self: jlong) { - assert(self != 0, "self memory address was null") - let selfBits$ = Int(Int64(fromJNI: self, in: environment!)) - let self$ = UnsafeMutablePointer(bitPattern: selfBits$) - guard let self$ else { - fatalError("self memory address was null in call to \\(#function)!") - } + ... self$.pointee.someBoolean = Bool(fromJNI: newValue, in: environment!) } """ @@ -466,24 +428,14 @@ struct JNIVariablesTests { """ @_cdecl("Java_com_example_swift_MyClass__00024isBoolean__J") func Java_com_example_swift_MyClass__00024isBoolean__J(environment: UnsafeMutablePointer!, thisClass: jclass, self: jlong) -> jboolean { - assert(self != 0, "self memory address was null") - let selfBits$ = Int(Int64(fromJNI: self, in: environment!)) - let self$ = UnsafeMutablePointer(bitPattern: selfBits$) - guard let self$ else { - fatalError("self memory address was null in call to \\(#function)!") - } + ... return self$.pointee.isBoolean.getJNIValue(in: environment!) } """, """ @_cdecl("Java_com_example_swift_MyClass__00024setBoolean__ZJ") func Java_com_example_swift_MyClass__00024setBoolean__ZJ(environment: UnsafeMutablePointer!, thisClass: jclass, newValue: jboolean, self: jlong) { - assert(self != 0, "self memory address was null") - let selfBits$ = Int(Int64(fromJNI: self, in: environment!)) - let self$ = UnsafeMutablePointer(bitPattern: selfBits$) - guard let self$ else { - fatalError("self memory address was null in call to \\(#function)!") - } + ... self$.pointee.isBoolean = Bool(fromJNI: newValue, in: environment!) } """ From c3ecd548a85e8b1f2d809399e7b5f10e4215c9e3 Mon Sep 17 00:00:00 2001 From: David Ko Date: Thu, 14 Aug 2025 23:00:24 -0400 Subject: [PATCH 344/426] Add function documentation (#363) Co-authored-by: Konrad `ktoso` Malawski --- .gitignore | 3 +++ .../Commands/ResolveCommand.swift | 25 ++++++++++++++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 28dfbae2..d4e1c5ec 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ .DS_Store .build .idea +.vscode Packages xcuserdata/ DerivedData/ @@ -16,6 +17,7 @@ bin/ BuildLogic/out/ .index-build .build-vscode +**/.vscode # Ignore gradle build artifacts .gradle @@ -45,3 +47,4 @@ Package.resolved */**/*.swiftdeps */**/*.swiftdeps~ */**/.docc-build/ + diff --git a/Sources/SwiftJavaTool/Commands/ResolveCommand.swift b/Sources/SwiftJavaTool/Commands/ResolveCommand.swift index 3eb01fe7..c492e788 100644 --- a/Sources/SwiftJavaTool/Commands/ResolveCommand.swift +++ b/Sources/SwiftJavaTool/Commands/ResolveCommand.swift @@ -89,6 +89,15 @@ extension SwiftJava.ResolveCommand { resolvedClasspath: dependenciesClasspath) } + + /// Resolves Java dependencies from swift-java.config and returns classpath information. + /// + /// - Parameters: + /// - swiftModule: module name from --swift-module. e.g.: --swift-module MySwiftModule + /// - dependencies: parsed maven-style dependency descriptors (groupId:artifactId:version) + /// from Sources/MySwiftModule/swift-java.config "dependencies" array. + /// + /// - Throws: func resolveDependencies( swiftModule: String, dependencies: [JavaDependencyDescriptor] ) async throws -> ResolvedDependencyClasspath { @@ -108,6 +117,11 @@ extension SwiftJava.ResolveCommand { return ResolvedDependencyClasspath(for: dependencies, classpath: dependenciesClasspath) } + + /// Resolves maven-style dependencies from swift-java.config under temporary project directory. + /// + /// - Parameter dependencies: maven-style dependencies to resolve + /// - Returns: Colon-separated classpath func resolveDependencies(dependencies: [JavaDependencyDescriptor]) async -> String { let workDir = URL(fileURLWithPath: FileManager.default.currentDirectoryPath) .appendingPathComponent(".build") @@ -158,6 +172,7 @@ extension SwiftJava.ResolveCommand { } } + /// Creates Gradle project files (build.gradle, settings.gradle.kts) in temporary directory. func printGradleProject(directory: URL, dependencies: [JavaDependencyDescriptor]) throws { let buildGradle = directory .appendingPathComponent("build.gradle", isDirectory: false) @@ -189,7 +204,14 @@ extension SwiftJava.ResolveCommand { """ try settingsGradleText.write(to: settingsGradle, atomically: true, encoding: .utf8) } - + + /// Creates {MySwiftModule}.swift.classpath in the --output-directory. + /// + /// - Parameters: + /// - swiftModule: Swift module name for classpath filename (--swift-module value) + /// - outputDirectory: Directory path for classpath file (--output-directory value) + /// - resolvedClasspath: Complete dependency classpath information + /// mutating func writeSwiftJavaClasspathFile( swiftModule: String, outputDirectory: String, @@ -218,6 +240,7 @@ extension SwiftJava.ResolveCommand { return camelCased } + // copy gradlew & gradle.bat from root, throws error if there is no gradle setup. func copyGradlew(to resolverWorkDirectory: URL) throws { var searchDir = URL(fileURLWithPath: FileManager.default.currentDirectoryPath) From 91d21328c7d9776108e979a82f8faf786f44b54d Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Fri, 15 Aug 2025 12:36:46 +0900 Subject: [PATCH 345/426] gh action: also run test jobs with nightly (#358) --- .github/actions/prepare_env/action.yml | 3 +++ .github/workflows/pull_request.yml | 6 +++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/actions/prepare_env/action.yml b/.github/actions/prepare_env/action.yml index 0e4a1ca3..3fdd5d4b 100644 --- a/.github/actions/prepare_env/action.yml +++ b/.github/actions/prepare_env/action.yml @@ -4,6 +4,9 @@ description: 'Prepare the CI environment by installing Swift and selected JDK et runs: using: composite steps: + - name: Check Swift version + shell: bash + run: swift -version - name: Set up JDK ${{ matrix.jdk_version }} uses: actions/setup-java@v4 with: diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 89ca4289..b2d8ee7c 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -45,7 +45,7 @@ jobs: strategy: fail-fast: true matrix: - swift_version: ['6.1.2'] + swift_version: ['6.1.2', 'nightly'] os_version: ['jammy'] jdk_vendor: ['corretto'] container: @@ -115,7 +115,7 @@ jobs: strategy: fail-fast: false matrix: - swift_version: ['6.1.2'] + swift_version: ['6.1.2', 'nightly'] os_version: ['jammy'] jdk_vendor: ['corretto'] container: @@ -185,7 +185,7 @@ jobs: strategy: fail-fast: false matrix: - swift_version: ['6.1.2'] # no nightly checks for macOS + swift_version: ['6.1.2'] # no nightly testing on macOS os_version: ['macos'] jdk_vendor: ['corretto'] sample_app: [ # TODO: use a reusable-workflow to generate those names From e29deed3ad7bf0de7463509adb51b425f4ed510a Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Fri, 15 Aug 2025 20:15:39 +0900 Subject: [PATCH 346/426] Allow config if to auto load native libraries with -Dswift-java.auto-load-libraries=false (#364) --- .../FFM/FFMSwift2JavaGenerator.swift | 13 ++++---- .../swift/swiftkit/core/SwiftLibraries.java | 31 +++++++++---------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift index c66b0029..9c9154a4 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift @@ -194,8 +194,8 @@ extension FFMSwift2JavaGenerator { @SuppressWarnings("unused") private static final boolean INITIALIZED_LIBS = initializeLibs(); static boolean initializeLibs() { - System.loadLibrary(SwiftLibraries.STDLIB_DYLIB_NAME); - System.loadLibrary("SwiftKitSwift"); + System.loadLibrary(SwiftLibraries.LIB_NAME_SWIFT_CORE); + System.loadLibrary(SwiftLibraries.LIB_NAME_SWIFTKITSWIFT); System.loadLibrary(LIB_NAME); return true; } @@ -343,10 +343,11 @@ extension FFMSwift2JavaGenerator { """ static final SymbolLookup SYMBOL_LOOKUP = getSymbolLookup(); private static SymbolLookup getSymbolLookup() { - // Ensure Swift and our Lib are loaded during static initialization of the class. - SwiftLibraries.loadLibrary("swiftCore"); - SwiftLibraries.loadLibrary("SwiftKitSwift"); - SwiftLibraries.loadLibrary(LIB_NAME); + if (SwiftLibraries.AUTO_LOAD_LIBS) { + System.loadLibrary(SwiftLibraries.LIB_NAME_SWIFT_CORE); + System.loadLibrary(SwiftLibraries.LIB_NAME_SWIFTKITSWIFT); + System.loadLibrary(LIB_NAME); + } if (PlatformUtils.isMacOS()) { return SymbolLookup.libraryLookup(System.mapLibraryName(LIB_NAME), LIBRARY_ARENA) diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftLibraries.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftLibraries.java index 3230e52a..a093cc50 100644 --- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftLibraries.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftLibraries.java @@ -24,18 +24,28 @@ public final class SwiftLibraries { - public static final String STDLIB_DYLIB_NAME = "swiftCore"; - public static final String SWIFTKITSWIFT_DYLIB_NAME = "SwiftKitSwift"; + // Library names of core Swift and SwiftKit + public static final String LIB_NAME_SWIFT_CORE = "swiftCore"; + public static final String LIB_NAME_SWIFT_CONCURRENCY = "swift_Concurrency"; + public static final String LIB_NAME_SWIFTKITSWIFT = "SwiftKitSwift"; - private static final String STDLIB_MACOS_DYLIB_PATH = "/usr/lib/swift/libswiftCore.dylib"; + /** + * Allows for configuration if jextracted types should automatically attempt to load swiftCore and the library type is from. + *

+ * If all libraries you need to load are available in paths passed to {@code -Djava.library.path} this should work correctly, + * however if attempting to load libraries from e.g. the jar as a resource, you may want to disable this. + */ + public static final boolean AUTO_LOAD_LIBS = System.getProperty("swift-java.auto-load-libraries") == null ? + true + : Boolean.getBoolean("swiftkit.auto-load-libraries"); @SuppressWarnings("unused") private static final boolean INITIALIZED_LIBS = loadLibraries(false); public static boolean loadLibraries(boolean loadSwiftKit) { - System.loadLibrary(STDLIB_DYLIB_NAME); + System.loadLibrary(LIB_NAME_SWIFTKITSWIFT); if (loadSwiftKit) { - System.loadLibrary(SWIFTKITSWIFT_DYLIB_NAME); + System.loadLibrary(LIB_NAME_SWIFTKITSWIFT); } return true; } @@ -43,17 +53,6 @@ public static boolean loadLibraries(boolean loadSwiftKit) { // ==== ------------------------------------------------------------------------------------------------------------ // Loading libraries - public static void loadLibrary(String libname) { - // TODO: avoid concurrent loadResource calls; one load is enough esp since we cause File IO when we do that - try { - // try to load a dylib from our classpath, e.g. when we included it in our jar - loadResourceLibrary(libname); - } catch (UnsatisfiedLinkError | RuntimeException e) { - // fallback to plain system path loading - System.loadLibrary(libname); - } - } - public static void loadResourceLibrary(String libname) { String resourceName = PlatformUtils.dynamicLibraryName(libname); if (CallTraces.TRACE_DOWNCALLS) { From 66f7a15b6ec915faf0fc3755649356fd935fc987 Mon Sep 17 00:00:00 2001 From: "Sven A. Schmidt" Date: Fri, 15 Aug 2025 14:29:19 +0200 Subject: [PATCH 347/426] Update .spi.yml (#367) --- .spi.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.spi.yml b/.spi.yml index 58345f25..e7159a31 100644 --- a/.spi.yml +++ b/.spi.yml @@ -6,3 +6,5 @@ builder: JavaKit, SwiftKitSwift ] + # Drop this version pinning once 6.2 is released and docs are built with 6.2 by default to prevent it staying on 6.2 forever. + swift_version: 6.2 From f8de1460314bd68727fcb3e6a888acd0d4698ac4 Mon Sep 17 00:00:00 2001 From: Mads Odgaard Date: Sat, 16 Aug 2025 16:46:00 +0200 Subject: [PATCH 348/426] [JExtract/JNI] Import enums (#346) --- .../Sources/MySwiftLibrary/Alignment.swift | 18 + .../Sources/MySwiftLibrary/Vehicle.swift | 63 ++++ .../Sources/MySwiftLibrary/swift-java.config | 1 + .../java/com/example/swift/EnumBenchmark.java | 60 ++++ .../com/example/swift/AlignmentEnumTest.java | 41 +++ .../com/example/swift/VehicleEnumTest.java | 206 ++++++++++++ .../Convenience/String+Extensions.swift | 8 + .../Convenience/SwiftSyntax+Extensions.swift | 2 + ...Swift2JavaGenerator+FunctionLowering.swift | 4 + ...MSwift2JavaGenerator+JavaTranslation.swift | 2 +- Sources/JExtractSwiftLib/ImportedDecls.swift | 53 +++ Sources/JExtractSwiftLib/JNI/JNICaching.swift | 31 ++ ...t2JavaGenerator+JavaBindingsPrinting.swift | 116 ++++++- ...ISwift2JavaGenerator+JavaTranslation.swift | 302 ++++++++++++++--- ...wift2JavaGenerator+NativeTranslation.swift | 49 ++- ...ift2JavaGenerator+SwiftThunkPrinting.swift | 159 ++++++++- .../JNI/JNISwift2JavaGenerator.swift | 1 + .../JExtractSwiftLib/Swift2JavaVisitor.swift | 88 ++++- .../SwiftTypes/SwiftEnumCaseParameter.swift | 32 ++ .../SwiftTypes/SwiftFunctionSignature.swift | 28 +- .../SwiftNominalTypeDeclaration.swift | 8 + .../SwiftTypes/SwiftParameter.swift | 10 + .../SwiftTypes/SwiftType.swift | 13 + .../JavaKit/Helpers/_JNIMethodIDCache.swift | 59 ++++ Sources/JavaTypes/Mangling.swift | 7 +- .../Documentation.docc/SupportedFeatures.md | 113 ++++++- .../JExtractSwiftTests/JNI/JNIEnumTests.swift | 313 ++++++++++++++++++ .../JNI/JNIOptionalTests.swift | 34 +- 28 files changed, 1702 insertions(+), 119 deletions(-) create mode 100644 Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/Alignment.swift create mode 100644 Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/Vehicle.swift create mode 100644 Samples/JExtractJNISampleApp/src/jmh/java/com/example/swift/EnumBenchmark.java create mode 100644 Samples/JExtractJNISampleApp/src/test/java/com/example/swift/AlignmentEnumTest.java create mode 100644 Samples/JExtractJNISampleApp/src/test/java/com/example/swift/VehicleEnumTest.java create mode 100644 Sources/JExtractSwiftLib/JNI/JNICaching.swift create mode 100644 Sources/JExtractSwiftLib/SwiftTypes/SwiftEnumCaseParameter.swift create mode 100644 Sources/JavaKit/Helpers/_JNIMethodIDCache.swift create mode 100644 Tests/JExtractSwiftTests/JNI/JNIEnumTests.swift diff --git a/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/Alignment.swift b/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/Alignment.swift new file mode 100644 index 00000000..760c564b --- /dev/null +++ b/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/Alignment.swift @@ -0,0 +1,18 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +public enum Alignment: String { + case horizontal + case vertical +} diff --git a/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/Vehicle.swift b/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/Vehicle.swift new file mode 100644 index 00000000..9d9155ad --- /dev/null +++ b/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/Vehicle.swift @@ -0,0 +1,63 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +public enum Vehicle { + case bicycle + case car(String, trailer: String?) + case motorbike(String, horsePower: Int64, helmets: Int32?) + indirect case transformer(front: Vehicle, back: Vehicle) + case boat(passengers: Int32?, length: Int16?) + + public init?(name: String) { + switch name { + case "bicycle": self = .bicycle + case "car": self = .car("Unknown", trailer: nil) + case "motorbike": self = .motorbike("Unknown", horsePower: 0, helmets: nil) + case "boat": self = .boat(passengers: nil, length: nil) + default: return nil + } + } + + public var name: String { + switch self { + case .bicycle: "bicycle" + case .car: "car" + case .motorbike: "motorbike" + case .transformer: "transformer" + case .boat: "boat" + } + } + + public func isFasterThan(other: Vehicle) -> Bool { + switch (self, other) { + case (.bicycle, .bicycle), (.bicycle, .car), (.bicycle, .motorbike), (.bicycle, .transformer): false + case (.car, .bicycle): true + case (.car, .motorbike), (.car, .transformer), (.car, .car): false + case (.motorbike, .bicycle), (.motorbike, .car): true + case (.motorbike, .motorbike), (.motorbike, .transformer): false + case (.transformer, .bicycle), (.transformer, .car), (.transformer, .motorbike): true + case (.transformer, .transformer): false + default: false + } + } + + public mutating func upgrade() { + switch self { + case .bicycle: self = .car("Unknown", trailer: nil) + case .car: self = .motorbike("Unknown", horsePower: 0, helmets: nil) + case .motorbike: self = .transformer(front: .car("BMW", trailer: nil), back: self) + case .transformer, .boat: break + } + } +} diff --git a/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/swift-java.config b/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/swift-java.config index bb637f34..be44c2fd 100644 --- a/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/swift-java.config +++ b/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/swift-java.config @@ -1,4 +1,5 @@ { "javaPackage": "com.example.swift", "mode": "jni", + "logLevel": ["debug"] } diff --git a/Samples/JExtractJNISampleApp/src/jmh/java/com/example/swift/EnumBenchmark.java b/Samples/JExtractJNISampleApp/src/jmh/java/com/example/swift/EnumBenchmark.java new file mode 100644 index 00000000..d3de624b --- /dev/null +++ b/Samples/JExtractJNISampleApp/src/jmh/java/com/example/swift/EnumBenchmark.java @@ -0,0 +1,60 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package com.example.swift; + +import org.openjdk.jmh.annotations.*; +import org.openjdk.jmh.infra.Blackhole; +import org.swift.swiftkit.core.ClosableSwiftArena; +import org.swift.swiftkit.core.ConfinedSwiftMemorySession; +import org.swift.swiftkit.core.SwiftArena; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.OptionalInt; +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.AverageTime) +@Warmup(iterations = 5, time = 200, timeUnit = TimeUnit.MILLISECONDS) +@Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@Fork(value = 3, jvmArgsAppend = { "--enable-native-access=ALL-UNNAMED" }) +public class EnumBenchmark { + + @State(Scope.Benchmark) + public static class BenchmarkState { + ClosableSwiftArena arena; + Vehicle vehicle; + + @Setup(Level.Trial) + public void beforeAll() { + arena = SwiftArena.ofConfined(); + vehicle = Vehicle.motorbike("Yamaha", 900, OptionalInt.empty(), arena); + } + + @TearDown(Level.Trial) + public void afterAll() { + arena.close(); + } + } + + @Benchmark + public Vehicle.Motorbike getAssociatedValues(BenchmarkState state, Blackhole bh) { + Vehicle.Motorbike motorbike = state.vehicle.getAsMotorbike().orElseThrow(); + bh.consume(motorbike.arg0()); + bh.consume(motorbike.horsePower()); + return motorbike; + } +} \ No newline at end of file diff --git a/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/AlignmentEnumTest.java b/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/AlignmentEnumTest.java new file mode 100644 index 00000000..6be85c75 --- /dev/null +++ b/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/AlignmentEnumTest.java @@ -0,0 +1,41 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package com.example.swift; + +import org.junit.jupiter.api.Test; +import org.swift.swiftkit.core.ConfinedSwiftMemorySession; +import org.swift.swiftkit.core.SwiftArena; + +import java.util.Optional; + +import static org.junit.jupiter.api.Assertions.*; + +public class AlignmentEnumTest { + @Test + void rawValue() { + try (var arena = SwiftArena.ofConfined()) { + Optional invalid = Alignment.init("invalid", arena); + assertFalse(invalid.isPresent()); + + Optional horizontal = Alignment.init("horizontal", arena); + assertTrue(horizontal.isPresent()); + assertEquals("horizontal", horizontal.get().getRawValue()); + + Optional vertical = Alignment.init("vertical", arena); + assertTrue(vertical.isPresent()); + assertEquals("vertical", vertical.get().getRawValue()); + } + } +} \ No newline at end of file diff --git a/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/VehicleEnumTest.java b/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/VehicleEnumTest.java new file mode 100644 index 00000000..c533603a --- /dev/null +++ b/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/VehicleEnumTest.java @@ -0,0 +1,206 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package com.example.swift; + +import org.junit.jupiter.api.Test; +import org.swift.swiftkit.core.ConfinedSwiftMemorySession; +import org.swift.swiftkit.core.SwiftArena; + +import java.lang.foreign.Arena; +import java.util.Optional; +import java.util.OptionalInt; + +import static org.junit.jupiter.api.Assertions.*; + +public class VehicleEnumTest { + @Test + void bicycle() { + try (var arena = SwiftArena.ofConfined()) { + Vehicle vehicle = Vehicle.bicycle(arena); + assertNotNull(vehicle); + } + } + + @Test + void car() { + try (var arena = SwiftArena.ofConfined()) { + Vehicle vehicle = Vehicle.car("Porsche 911", Optional.empty(), arena); + assertNotNull(vehicle); + } + } + + @Test + void motorbike() { + try (var arena = SwiftArena.ofConfined()) { + Vehicle vehicle = Vehicle.motorbike("Yamaha", 750, OptionalInt.empty(), arena); + assertNotNull(vehicle); + } + } + + @Test + void initName() { + try (var arena = SwiftArena.ofConfined()) { + assertFalse(Vehicle.init("bus", arena).isPresent()); + Optional vehicle = Vehicle.init("car", arena); + assertTrue(vehicle.isPresent()); + assertNotNull(vehicle.get()); + } + } + + @Test + void nameProperty() { + try (var arena = SwiftArena.ofConfined()) { + Vehicle vehicle = Vehicle.bicycle(arena); + assertEquals("bicycle", vehicle.getName()); + } + } + + @Test + void isFasterThan() { + try (var arena = SwiftArena.ofConfined()) { + Vehicle bicycle = Vehicle.bicycle(arena); + Vehicle car = Vehicle.car("Porsche 911", Optional.empty(), arena); + assertFalse(bicycle.isFasterThan(car)); + assertTrue(car.isFasterThan(bicycle)); + } + } + + @Test + void upgrade() { + try (var arena = SwiftArena.ofConfined()) { + Vehicle vehicle = Vehicle.bicycle(arena); + assertEquals("bicycle", vehicle.getName()); + vehicle.upgrade(); + assertEquals("car", vehicle.getName()); + vehicle.upgrade(); + assertEquals("motorbike", vehicle.getName()); + } + } + + @Test + void getAsBicycle() { + try (var arena = SwiftArena.ofConfined()) { + Vehicle vehicle = Vehicle.bicycle(arena); + Vehicle.Bicycle bicycle = vehicle.getAsBicycle().orElseThrow(); + assertNotNull(bicycle); + } + } + + @Test + void getAsCar() { + try (var arena = SwiftArena.ofConfined()) { + Vehicle vehicle = Vehicle.car("BMW", Optional.empty(), arena); + Vehicle.Car car = vehicle.getAsCar().orElseThrow(); + assertEquals("BMW", car.arg0()); + + vehicle = Vehicle.car("BMW", Optional.of("Long trailer"), arena); + car = vehicle.getAsCar().orElseThrow(); + assertEquals("Long trailer", car.trailer().orElseThrow()); + } + } + + @Test + void getAsMotorbike() { + try (var arena = SwiftArena.ofConfined()) { + Vehicle vehicle = Vehicle.motorbike("Yamaha", 750, OptionalInt.empty(), arena); + Vehicle.Motorbike motorbike = vehicle.getAsMotorbike().orElseThrow(); + assertEquals("Yamaha", motorbike.arg0()); + assertEquals(750, motorbike.horsePower()); + assertEquals(OptionalInt.empty(), motorbike.helmets()); + + vehicle = Vehicle.motorbike("Yamaha", 750, OptionalInt.of(2), arena); + motorbike = vehicle.getAsMotorbike().orElseThrow(); + assertEquals(OptionalInt.of(2), motorbike.helmets()); + } + } + + @Test + void getAsTransformer() { + try (var arena = SwiftArena.ofConfined()) { + Vehicle vehicle = Vehicle.transformer(Vehicle.bicycle(arena), Vehicle.car("BMW", Optional.empty(), arena), arena); + Vehicle.Transformer transformer = vehicle.getAsTransformer(arena).orElseThrow(); + assertTrue(transformer.front().getAsBicycle().isPresent()); + assertEquals("BMW", transformer.back().getAsCar().orElseThrow().arg0()); + } + } + + @Test + void getAsBoat() { + try (var arena = SwiftArena.ofConfined()) { + Vehicle vehicle = Vehicle.boat(OptionalInt.of(10), Optional.of((short) 1), arena); + Vehicle.Boat boat = vehicle.getAsBoat().orElseThrow(); + assertEquals(OptionalInt.of(10), boat.passengers()); + assertEquals(Optional.of((short) 1), boat.length()); + } + } + + @Test + void associatedValuesAreCopied() { + try (var arena = SwiftArena.ofConfined()) { + Vehicle vehicle = Vehicle.car("BMW", Optional.empty(), arena); + Vehicle.Car car = vehicle.getAsCar().orElseThrow(); + assertEquals("BMW", car.arg0()); + vehicle.upgrade(); + Vehicle.Motorbike motorbike = vehicle.getAsMotorbike().orElseThrow(); + assertNotNull(motorbike); + // Motorbike should still remain + assertEquals("BMW", car.arg0()); + } + } + + @Test + void getDiscriminator() { + try (var arena = SwiftArena.ofConfined()) { + assertEquals(Vehicle.Discriminator.BICYCLE, Vehicle.bicycle(arena).getDiscriminator()); + assertEquals(Vehicle.Discriminator.CAR, Vehicle.car("BMW", Optional.empty(), arena).getDiscriminator()); + assertEquals(Vehicle.Discriminator.MOTORBIKE, Vehicle.motorbike("Yamaha", 750, OptionalInt.empty(), arena).getDiscriminator()); + assertEquals(Vehicle.Discriminator.TRANSFORMER, Vehicle.transformer(Vehicle.bicycle(arena), Vehicle.bicycle(arena), arena).getDiscriminator()); + } + } + + @Test + void getCase() { + try (var arena = SwiftArena.ofConfined()) { + Vehicle vehicle = Vehicle.bicycle(arena); + Vehicle.Case caseElement = vehicle.getCase(arena); + assertInstanceOf(Vehicle.Bicycle.class, caseElement); + } + } + + @Test + void switchGetCase() { + try (var arena = SwiftArena.ofConfined()) { + Vehicle vehicle = Vehicle.car("BMW", Optional.empty(), arena); + switch (vehicle.getCase(arena)) { + case Vehicle.Bicycle b: + fail("Was bicycle"); + break; + case Vehicle.Car car: + assertEquals("BMW", car.arg0()); + break; + case Vehicle.Motorbike motorbike: + fail("Was motorbike"); + break; + case Vehicle.Transformer transformer: + fail("Was transformer"); + break; + case Vehicle.Boat b: + fail("Was boat"); + break; + } + } + } + +} \ No newline at end of file diff --git a/Sources/JExtractSwiftLib/Convenience/String+Extensions.swift b/Sources/JExtractSwiftLib/Convenience/String+Extensions.swift index 0f5cfeac..25c46366 100644 --- a/Sources/JExtractSwiftLib/Convenience/String+Extensions.swift +++ b/Sources/JExtractSwiftLib/Convenience/String+Extensions.swift @@ -24,6 +24,14 @@ extension String { return "\(f.uppercased())\(String(dropFirst()))" } + var firstCharacterLowercased: String { + guard let f = first else { + return self + } + + return "\(f.lowercased())\(String(dropFirst()))" + } + /// Returns whether the string is of the format `isX` var hasJavaBooleanNamingConvention: Bool { guard self.hasPrefix("is"), self.count > 2 else { diff --git a/Sources/JExtractSwiftLib/Convenience/SwiftSyntax+Extensions.swift b/Sources/JExtractSwiftLib/Convenience/SwiftSyntax+Extensions.swift index e71300af..3719d99d 100644 --- a/Sources/JExtractSwiftLib/Convenience/SwiftSyntax+Extensions.swift +++ b/Sources/JExtractSwiftLib/Convenience/SwiftSyntax+Extensions.swift @@ -253,6 +253,8 @@ extension DeclSyntaxProtocol { } )) .triviaSanitizedDescription + case .enumCaseDecl(let node): + node.triviaSanitizedDescription default: fatalError("unimplemented \(self.kind)") } diff --git a/Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift b/Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift index 085a6331..0a61708e 100644 --- a/Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift +++ b/Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift @@ -835,6 +835,10 @@ extension LoweredFunctionSignature { case .setter: assert(paramExprs.count == 1) resultExpr = "\(callee) = \(paramExprs[0])" + + case .enumCase: + // This should not be called, but let's fatalError. + fatalError("Enum cases are not supported with FFM.") } // Lower the result. diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift index 06a4d171..57f947a8 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift @@ -146,7 +146,7 @@ extension FFMSwift2JavaGenerator { let javaName = switch decl.apiKind { case .getter: decl.javaGetterName case .setter: decl.javaSetterName - case .function, .initializer: decl.name + case .function, .initializer, .enumCase: decl.name } // Signature. diff --git a/Sources/JExtractSwiftLib/ImportedDecls.swift b/Sources/JExtractSwiftLib/ImportedDecls.swift index 4c4d9c0f..5655af00 100644 --- a/Sources/JExtractSwiftLib/ImportedDecls.swift +++ b/Sources/JExtractSwiftLib/ImportedDecls.swift @@ -22,6 +22,7 @@ package enum SwiftAPIKind { case initializer case getter case setter + case enumCase } /// Describes a Swift nominal type (e.g., a class, struct, enum) that has been @@ -32,6 +33,7 @@ package class ImportedNominalType: ImportedDecl { package var initializers: [ImportedFunc] = [] package var methods: [ImportedFunc] = [] package var variables: [ImportedFunc] = [] + package var cases: [ImportedEnumCase] = [] init(swiftNominal: SwiftNominalTypeDeclaration) { self.swiftNominal = swiftNominal @@ -46,6 +48,56 @@ package class ImportedNominalType: ImportedDecl { } } +public final class ImportedEnumCase: ImportedDecl, CustomStringConvertible { + /// The case name + public var name: String + + /// The enum parameters + var parameters: [SwiftEnumCaseParameter] + + var swiftDecl: any DeclSyntaxProtocol + + var enumType: SwiftNominalType + + /// A function that represents the Swift static "initializer" for cases + var caseFunction: ImportedFunc + + init( + name: String, + parameters: [SwiftEnumCaseParameter], + swiftDecl: any DeclSyntaxProtocol, + enumType: SwiftNominalType, + caseFunction: ImportedFunc + ) { + self.name = name + self.parameters = parameters + self.swiftDecl = swiftDecl + self.enumType = enumType + self.caseFunction = caseFunction + } + + public var description: String { + """ + ImportedEnumCase { + name: \(name), + parameters: \(parameters), + swiftDecl: \(swiftDecl), + enumType: \(enumType), + caseFunction: \(caseFunction) + } + """ + } +} + +extension ImportedEnumCase: Hashable { + public func hash(into hasher: inout Hasher) { + hasher.combine(ObjectIdentifier(self)) + } + public static func == (lhs: ImportedEnumCase, rhs: ImportedEnumCase) -> Bool { + return lhs === rhs + } +} + public final class ImportedFunc: ImportedDecl, CustomStringConvertible { /// Swift module name (e.g. the target name where a type or function was declared) public var module: String @@ -113,6 +165,7 @@ public final class ImportedFunc: ImportedDecl, CustomStringConvertible { let prefix = switch self.apiKind { case .getter: "getter:" case .setter: "setter:" + case .enumCase: "case:" case .function, .initializer: "" } diff --git a/Sources/JExtractSwiftLib/JNI/JNICaching.swift b/Sources/JExtractSwiftLib/JNI/JNICaching.swift new file mode 100644 index 00000000..cdb13e3f --- /dev/null +++ b/Sources/JExtractSwiftLib/JNI/JNICaching.swift @@ -0,0 +1,31 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +enum JNICaching { + static func cacheName(for type: ImportedNominalType) -> String { + cacheName(for: type.swiftNominal.name) + } + + static func cacheName(for type: SwiftNominalType) -> String { + cacheName(for: type.nominalTypeDecl.name) + } + + private static func cacheName(for name: String) -> String { + "_JNI_\(name)" + } + + static func cacheMemberName(for enumCase: ImportedEnumCase) -> String { + "\(enumCase.enumType.nominalTypeDecl.name.firstCharacterLowercased)\(enumCase.name.firstCharacterUppercased)Cache" + } +} diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift index 6d82175f..9351252e 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift @@ -138,6 +138,11 @@ extension JNISwift2JavaGenerator { printer.println() + if decl.swiftNominal.kind == .enum { + printEnumHelpers(&printer, decl) + printer.println() + } + for initializer in decl.initializers { printFunctionDowncallMethods(&printer, initializer) printer.println() @@ -200,6 +205,85 @@ extension JNISwift2JavaGenerator { } } + private func printEnumHelpers(_ printer: inout CodePrinter, _ decl: ImportedNominalType) { + printEnumDiscriminator(&printer, decl) + printer.println() + printEnumCaseInterface(&printer, decl) + printer.println() + printEnumStaticInitializers(&printer, decl) + printer.println() + printEnumCases(&printer, decl) + } + + private func printEnumDiscriminator(_ printer: inout CodePrinter, _ decl: ImportedNominalType) { + printer.printBraceBlock("public enum Discriminator") { printer in + printer.print( + decl.cases.map { $0.name.uppercased() }.joined(separator: ",\n") + ) + } + + // TODO: Consider whether all of these "utility" functions can be printed using our existing printing logic. + printer.printBraceBlock("public Discriminator getDiscriminator()") { printer in + printer.print("return Discriminator.values()[$getDiscriminator(this.$memoryAddress())];") + } + printer.print("private static native int $getDiscriminator(long self);") + } + + private func printEnumCaseInterface(_ printer: inout CodePrinter, _ decl: ImportedNominalType) { + printer.print("public sealed interface Case {}") + printer.println() + + let requiresSwiftArena = decl.cases.compactMap { + self.translatedEnumCase(for: $0) + }.contains(where: \.requiresSwiftArena) + + printer.printBraceBlock("public Case getCase(\(requiresSwiftArena ? "SwiftArena swiftArena$" : ""))") { printer in + printer.print("Discriminator discriminator = this.getDiscriminator();") + printer.printBraceBlock("switch (discriminator)") { printer in + for enumCase in decl.cases { + guard let translatedCase = self.translatedEnumCase(for: enumCase) else { + continue + } + let arenaArgument = translatedCase.requiresSwiftArena ? "swiftArena$" : "" + printer.print("case \(enumCase.name.uppercased()): return this.getAs\(enumCase.name.firstCharacterUppercased)(\(arenaArgument)).orElseThrow();") + } + } + printer.print(#"throw new RuntimeException("Unknown discriminator value " + discriminator);"#) + } + } + + private func printEnumStaticInitializers(_ printer: inout CodePrinter, _ decl: ImportedNominalType) { + for enumCase in decl.cases { + printFunctionDowncallMethods(&printer, enumCase.caseFunction) + } + } + + private func printEnumCases(_ printer: inout CodePrinter, _ decl: ImportedNominalType) { + for enumCase in decl.cases { + guard let translatedCase = self.translatedEnumCase(for: enumCase) else { + return + } + + let members = translatedCase.translatedValues.map { + $0.parameter.renderParameter() + } + + let caseName = enumCase.name.firstCharacterUppercased + + // Print record + printer.printBraceBlock("public record \(caseName)(\(members.joined(separator: ", "))) implements Case") { printer in + let nativeParameters = zip(translatedCase.translatedValues, translatedCase.parameterConversions).flatMap { value, conversion in + ["\(conversion.native.javaType) \(value.parameter.name)"] + } + + printer.print("record $NativeParameters(\(nativeParameters.joined(separator: ", "))) {}") + } + + self.printJavaBindingWrapperMethod(&printer, translatedCase.getAsCaseFunction) + printer.println() + } + } + private func printFunctionDowncallMethods( _ printer: inout CodePrinter, _ decl: ImportedFunc @@ -260,17 +344,23 @@ extension JNISwift2JavaGenerator { guard let translatedDecl = translatedDecl(for: decl) else { fatalError("Decl was not translated, \(decl)") } - let translatedSignature = translatedDecl.translatedFunctionSignature + printJavaBindingWrapperMethod(&printer, translatedDecl, importedFunc: decl) + } + private func printJavaBindingWrapperMethod( + _ printer: inout CodePrinter, + _ translatedDecl: TranslatedFunctionDecl, + importedFunc: ImportedFunc? = nil + ) { var modifiers = ["public"] - - if decl.isStatic || decl.isInitializer || !decl.hasParent { + if translatedDecl.isStatic { modifiers.append("static") } + let translatedSignature = translatedDecl.translatedFunctionSignature let resultType = translatedSignature.resultType.javaType var parameters = translatedDecl.translatedFunctionSignature.parameters.map { $0.parameter.renderParameter() } - let throwsClause = decl.isThrowing ? " throws Exception" : "" + let throwsClause = translatedDecl.isThrowing ? " throws Exception" : "" var annotationsStr = translatedSignature.annotations.map({ $0.render() }).joined(separator: "\n") if !annotationsStr.isEmpty { annotationsStr += "\n" } @@ -279,7 +369,9 @@ extension JNISwift2JavaGenerator { // Print default global arena variation if config.effectiveMemoryManagementMode.requiresGlobalArena && translatedSignature.requiresSwiftArena { - printDeclDocumentation(&printer, decl) + if let importedFunc { + printDeclDocumentation(&printer, importedFunc) + } printer.printBraceBlock( "\(annotationsStr)\(modifiers.joined(separator: " ")) \(resultType) \(translatedDecl.name)(\(parametersStr))\(throwsClause)" ) { printer in @@ -298,18 +390,19 @@ extension JNISwift2JavaGenerator { if translatedSignature.requiresSwiftArena { parameters.append("SwiftArena swiftArena$") } - printDeclDocumentation(&printer, decl) + if let importedFunc { + printDeclDocumentation(&printer, importedFunc) + } printer.printBraceBlock( "\(annotationsStr)\(modifiers.joined(separator: " ")) \(resultType) \(translatedDecl.name)(\(parameters.joined(separator: ", ")))\(throwsClause)" ) { printer in - printDowncall(&printer, decl) + printDowncall(&printer, translatedDecl) } - printNativeFunction(&printer, decl) + printNativeFunction(&printer, translatedDecl) } - private func printNativeFunction(_ printer: inout CodePrinter, _ decl: ImportedFunc) { - let translatedDecl = translatedDecl(for: decl)! // Will always call with valid decl + private func printNativeFunction(_ printer: inout CodePrinter, _ translatedDecl: TranslatedFunctionDecl) { let nativeSignature = translatedDecl.nativeFunctionSignature let resultType = nativeSignature.result.javaType var parameters = nativeSignature.parameters.flatMap(\.parameters) @@ -327,9 +420,8 @@ extension JNISwift2JavaGenerator { private func printDowncall( _ printer: inout CodePrinter, - _ decl: ImportedFunc + _ translatedDecl: TranslatedFunctionDecl ) { - let translatedDecl = translatedDecl(for: decl)! // We will only call this method if we can translate the decl. let translatedFunctionSignature = translatedDecl.translatedFunctionSignature // Regular parameters. diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift index 64ae23b7..0e169ec6 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift @@ -41,12 +41,121 @@ extension JNISwift2JavaGenerator { return translated } + func translatedEnumCase( + for decl: ImportedEnumCase + ) -> TranslatedEnumCase? { + if let cached = translatedEnumCases[decl] { + return cached + } + + let translated: TranslatedEnumCase? + do { + let translation = JavaTranslation( + config: config, + swiftModuleName: swiftModuleName, + javaPackage: self.javaPackage, + javaClassLookupTable: self.javaClassLookupTable + ) + translated = try translation.translate(enumCase: decl) + } catch { + self.logger.debug("Failed to translate: '\(decl.swiftDecl.qualifiedNameForDebug)'; \(error)") + translated = nil + } + + translatedEnumCases[decl] = translated + return translated + } + struct JavaTranslation { let config: Configuration let swiftModuleName: String let javaPackage: String let javaClassLookupTable: JavaClassLookupTable + func translate(enumCase: ImportedEnumCase) throws -> TranslatedEnumCase { + let nativeTranslation = NativeJavaTranslation( + config: self.config, + javaPackage: self.javaPackage, + javaClassLookupTable: self.javaClassLookupTable + ) + + let methodName = "" // TODO: Used for closures, replace with better name? + let parentName = "" // TODO: Used for closures, replace with better name? + + let translatedValues = try self.translateParameters( + enumCase.parameters.map { ($0.name, $0.type) }, + methodName: methodName, + parentName: parentName + ) + + let conversions = try enumCase.parameters.enumerated().map { idx, parameter in + let resultName = parameter.name ?? "arg\(idx)" + let result = SwiftResult(convention: .direct, type: parameter.type) + var translatedResult = try self.translate(swiftResult: result, resultName: resultName) + translatedResult.conversion = .replacingPlaceholder(translatedResult.conversion, placeholder: "$nativeParameters.\(resultName)") + let nativeResult = try nativeTranslation.translate(swiftResult: result, resultName: resultName) + return (translated: translatedResult, native: nativeResult) + } + + let caseName = enumCase.name.firstCharacterUppercased + let enumName = enumCase.enumType.nominalTypeDecl.name + let nativeParametersType = JavaType.class(package: nil, name: "\(caseName).$NativeParameters") + let getAsCaseName = "getAs\(caseName)" + // If the case has no parameters, we can skip the native call. + let constructRecordConversion = JavaNativeConversionStep.method(.constant("Optional"), function: "of", arguments: [ + .constructJavaClass( + .commaSeparated(conversions.map(\.translated.conversion)), + .class(package: nil,name: caseName) + ) + ]) + let getAsCaseFunction = TranslatedFunctionDecl( + name: getAsCaseName, + isStatic: false, + isThrowing: false, + nativeFunctionName: "$\(getAsCaseName)", + parentName: enumName, + functionTypes: [], + translatedFunctionSignature: TranslatedFunctionSignature( + selfParameter: TranslatedParameter( + parameter: JavaParameter(name: "self", type: .long), + conversion: .aggregate( + [ + .ifStatement(.constant("getDiscriminator() != Discriminator.\(caseName.uppercased())"), thenExp: .constant("return Optional.empty();")), + .valueMemoryAddress(.placeholder) + ] + ) + ), + parameters: [], + resultType: TranslatedResult( + javaType: .class(package: nil, name: "Optional<\(caseName)>"), + outParameters: conversions.flatMap(\.translated.outParameters), + conversion: enumCase.parameters.isEmpty ? constructRecordConversion : .aggregate(variable: ("$nativeParameters", nativeParametersType), [constructRecordConversion]) + ) + ), + nativeFunctionSignature: NativeFunctionSignature( + selfParameter: NativeParameter( + parameters: [JavaParameter(name: "self", type: .long)], + conversion: .extractSwiftValue(.placeholder, swiftType: .nominal(enumCase.enumType), allowNil: false) + ), + parameters: [], + result: NativeResult( + javaType: nativeParametersType, + conversion: .placeholder, + outParameters: conversions.flatMap(\.native.outParameters) + ) + ) + ) + + return TranslatedEnumCase( + name: enumCase.name.firstCharacterUppercased, + enumName: enumCase.enumType.nominalTypeDecl.name, + original: enumCase, + translatedValues: translatedValues, + parameterConversions: conversions, + getAsCaseFunction: getAsCaseFunction + ) + } + func translate(_ decl: ImportedFunc) throws -> TranslatedFunctionDecl { let nativeTranslation = NativeJavaTranslation( config: self.config, @@ -61,7 +170,7 @@ extension JNISwift2JavaGenerator { let javaName = switch decl.apiKind { case .getter: decl.javaGetterName case .setter: decl.javaSetterName - case .function, .initializer: decl.name + case .function, .initializer, .enumCase: decl.name } // Swift -> Java @@ -98,6 +207,8 @@ extension JNISwift2JavaGenerator { return TranslatedFunctionDecl( name: javaName, + isStatic: decl.isStatic || !decl.hasParent || decl.isInitializer, + isThrowing: decl.isThrowing, nativeFunctionName: "$\(javaName)", parentName: parentName, functionTypes: funcTypes, @@ -136,31 +247,47 @@ extension JNISwift2JavaGenerator { methodName: String, parentName: String ) throws -> TranslatedFunctionSignature { - let parameters = try functionSignature.parameters.enumerated().map { idx, param in - let parameterName = param.parameterName ?? "arg\(idx))" + let parameters = try translateParameters( + functionSignature.parameters.map { ($0.parameterName, $0.type )}, + methodName: methodName, + parentName: parentName + ) + + // 'self' + let selfParameter = try self.translateSelfParameter(functionSignature.selfParameter, methodName: methodName, parentName: parentName) + + let resultType = try translate(swiftResult: functionSignature.result) + + return TranslatedFunctionSignature( + selfParameter: selfParameter, + parameters: parameters, + resultType: resultType + ) + } + + func translateParameters( + _ parameters: [(name: String?, type: SwiftType)], + methodName: String, + parentName: String + ) throws -> [TranslatedParameter] { + try parameters.enumerated().map { idx, param in + let parameterName = param.name ?? "arg\(idx)" return try translateParameter(swiftType: param.type, parameterName: parameterName, methodName: methodName, parentName: parentName) } + } + func translateSelfParameter(_ selfParameter: SwiftSelfParameter?, methodName: String, parentName: String) throws -> TranslatedParameter? { // 'self' - let selfParameter: TranslatedParameter? - if case .instance(let swiftSelf) = functionSignature.selfParameter { - selfParameter = try self.translateParameter( + if case .instance(let swiftSelf) = selfParameter { + return try self.translateParameter( swiftType: swiftSelf.type, parameterName: swiftSelf.parameterName ?? "self", methodName: methodName, parentName: parentName ) } else { - selfParameter = nil + return nil } - - let resultType = try translate(swiftResult: functionSignature.result) - - return TranslatedFunctionSignature( - selfParameter: selfParameter, - parameters: parameters, - resultType: resultType - ) } func translateParameter( @@ -343,7 +470,7 @@ extension JNISwift2JavaGenerator { } } - func translate(swiftResult: SwiftResult) throws -> TranslatedResult { + func translate(swiftResult: SwiftResult, resultName: String = "result") throws -> TranslatedResult { let swiftType = swiftResult.type // If the result type should cause any annotations on the method, include them here. @@ -357,7 +484,7 @@ extension JNISwift2JavaGenerator { guard let genericArgs = nominalType.genericArguments, genericArgs.count == 1 else { throw JavaTranslationError.unsupportedSwiftType(swiftType) } - return try translateOptionalResult(wrappedType: genericArgs[0]) + return try translateOptionalResult(wrappedType: genericArgs[0], resultName: resultName) default: guard let javaType = JNIJavaTypeTranslator.translate(knownType: knownType, config: self.config) else { @@ -390,7 +517,7 @@ extension JNISwift2JavaGenerator { return TranslatedResult(javaType: .void, outParameters: [], conversion: .placeholder) case .optional(let wrapped): - return try translateOptionalResult(wrappedType: wrapped) + return try translateOptionalResult(wrappedType: wrapped, resultName: resultName) case .metatype, .tuple, .function, .existential, .opaque, .genericParameter: throw JavaTranslationError.unsupportedSwiftType(swiftType) @@ -398,8 +525,11 @@ extension JNISwift2JavaGenerator { } func translateOptionalResult( - wrappedType swiftType: SwiftType + wrappedType swiftType: SwiftType, + resultName: String = "result" ) throws -> TranslatedResult { + let discriminatorName = "\(resultName)$_discriminator$" + let parameterAnnotations: [JavaAnnotation] = getTypeAnnotations(swiftType: swiftType, config: config) switch swiftType { @@ -425,6 +555,7 @@ extension JNISwift2JavaGenerator { conversion: .combinedValueToOptional( .placeholder, nextIntergralTypeWithSpaceForByte.javaType, + resultName: resultName, valueType: javaType, valueSizeInBytes: nextIntergralTypeWithSpaceForByte.valueBytes, optionalType: optionalClass @@ -437,13 +568,14 @@ extension JNISwift2JavaGenerator { javaType: .class(package: nil, name: returnType), annotations: parameterAnnotations, outParameters: [ - OutParameter(name: "result_discriminator$", type: .array(.byte), allocation: .newArray(.byte, size: 1)) + OutParameter(name: discriminatorName, type: .array(.byte), allocation: .newArray(.byte, size: 1)) ], conversion: .toOptionalFromIndirectReturn( - discriminatorName: "result_discriminator$", + discriminatorName: .combinedName(component: "discriminator$"), optionalClass: optionalClass, javaType: javaType, - toValue: .placeholder + toValue: .placeholder, + resultName: resultName ) ) } @@ -459,13 +591,14 @@ extension JNISwift2JavaGenerator { javaType: returnType, annotations: parameterAnnotations, outParameters: [ - OutParameter(name: "result_discriminator$", type: .array(.byte), allocation: .newArray(.byte, size: 1)) + OutParameter(name: discriminatorName, type: .array(.byte), allocation: .newArray(.byte, size: 1)) ], conversion: .toOptionalFromIndirectReturn( - discriminatorName: "result_discriminator$", + discriminatorName: .combinedName(component: "discriminator$"), optionalClass: "Optional", javaType: .long, - toValue: .wrapMemoryAddressUnsafe(.placeholder, .class(package: nil, name: nominalTypeName)) + toValue: .wrapMemoryAddressUnsafe(.placeholder, .class(package: nil, name: nominalTypeName)), + resultName: resultName ) ) @@ -475,10 +608,38 @@ extension JNISwift2JavaGenerator { } } + struct TranslatedEnumCase { + /// The corresponding Java case class (CamelCased) + let name: String + + /// The name of the translated enum + let enumName: String + + /// The oringinal enum case. + let original: ImportedEnumCase + + /// A list of the translated associated values + let translatedValues: [TranslatedParameter] + + /// A list of parameter conversions + let parameterConversions: [(translated: TranslatedResult, native: NativeResult)] + + let getAsCaseFunction: TranslatedFunctionDecl + + /// Returns whether the parameters require an arena + var requiresSwiftArena: Bool { + parameterConversions.contains(where: \.translated.conversion.requiresSwiftArena) + } + } + struct TranslatedFunctionDecl { /// Java function name let name: String + let isStatic: Bool + + let isThrowing: Bool + /// The name of the native function let nativeFunctionName: String @@ -532,7 +693,7 @@ extension JNISwift2JavaGenerator { let outParameters: [OutParameter] /// Represents how to convert the Java native result into a user-facing result. - let conversion: JavaNativeConversionStep + var conversion: JavaNativeConversionStep } struct OutParameter { @@ -573,6 +734,9 @@ extension JNISwift2JavaGenerator { case constant(String) + /// `input_component` + case combinedName(component: String) + // Convert the results of the inner steps to a comma separated list. indirect case commaSeparated([JavaNativeConversionStep]) @@ -582,6 +746,9 @@ extension JNISwift2JavaGenerator { /// Call `new \(Type)(\(placeholder), swiftArena$)` indirect case constructSwiftValue(JavaNativeConversionStep, JavaType) + /// Call `new \(Type)(\(placeholder))` + indirect case constructJavaClass(JavaNativeConversionStep, JavaType) + /// Call the `MyType.wrapMemoryAddressUnsafe` in order to wrap a memory address using the Java binding type indirect case wrapMemoryAddressUnsafe(JavaNativeConversionStep, JavaType) @@ -591,7 +758,7 @@ extension JNISwift2JavaGenerator { case isOptionalPresent - indirect case combinedValueToOptional(JavaNativeConversionStep, JavaType, valueType: JavaType, valueSizeInBytes: Int, optionalType: String) + indirect case combinedValueToOptional(JavaNativeConversionStep, JavaType, resultName: String, valueType: JavaType, valueSizeInBytes: Int, optionalType: String) indirect case ternary(JavaNativeConversionStep, thenExp: JavaNativeConversionStep, elseExp: JavaNativeConversionStep) @@ -600,18 +767,18 @@ extension JNISwift2JavaGenerator { indirect case subscriptOf(JavaNativeConversionStep, arguments: [JavaNativeConversionStep]) static func toOptionalFromIndirectReturn( - discriminatorName: String, + discriminatorName: JavaNativeConversionStep, optionalClass: String, javaType: JavaType, - toValue valueConversion: JavaNativeConversionStep + toValue valueConversion: JavaNativeConversionStep, + resultName: String ) -> JavaNativeConversionStep { .aggregate( - name: "result$", - type: javaType, + variable: (name: "\(resultName)$", type: javaType), [ .ternary( .equals( - .subscriptOf(.constant(discriminatorName), arguments: [.constant("0")]), + .subscriptOf(discriminatorName, arguments: [.constant("0")]), .constant("1") ), thenExp: .method(.constant(optionalClass), function: "of", arguments: [valueConversion]), @@ -622,7 +789,12 @@ extension JNISwift2JavaGenerator { } /// Perform multiple conversions using the same input. - case aggregate(name: String, type: JavaType, [JavaNativeConversionStep]) + case aggregate(variable: (name: String, type: JavaType)? = nil, [JavaNativeConversionStep]) + + indirect case ifStatement(JavaNativeConversionStep, thenExp: JavaNativeConversionStep, elseExp: JavaNativeConversionStep? = nil) + + /// Access a member of the value + indirect case replacingPlaceholder(JavaNativeConversionStep, placeholder: String) /// Returns the conversion string applied to the placeholder. func render(_ printer: inout CodePrinter, _ placeholder: String) -> String { @@ -635,6 +807,9 @@ extension JNISwift2JavaGenerator { case .constant(let value): return value + case .combinedName(let component): + return "\(placeholder)_\(component)" + case .commaSeparated(let list): return list.map({ $0.render(&printer, placeholder)}).joined(separator: ", ") @@ -649,6 +824,10 @@ extension JNISwift2JavaGenerator { let inner = inner.render(&printer, placeholder) return "\(javaType.className!).wrapMemoryAddressUnsafe(\(inner), swiftArena$)" + case .constructJavaClass(let inner, let javaType): + let inner = inner.render(&printer, placeholder) + return "new \(javaType.className!)(\(inner))" + case .call(let inner, let function): let inner = inner.render(&printer, placeholder) return "\(function)(\(inner))" @@ -663,22 +842,22 @@ extension JNISwift2JavaGenerator { let argsStr = args.joined(separator: ", ") return "\(inner).\(methodName)(\(argsStr))" - case .combinedValueToOptional(let combined, let combinedType, let valueType, let valueSizeInBytes, let optionalType): + case .combinedValueToOptional(let combined, let combinedType, let resultName, let valueType, let valueSizeInBytes, let optionalType): let combined = combined.render(&printer, placeholder) printer.print( """ - \(combinedType) combined$ = \(combined); - byte discriminator$ = (byte) (combined$ & 0xFF); + \(combinedType) \(resultName)_combined$ = \(combined); + byte \(resultName)_discriminator$ = (byte) (\(resultName)_combined$ & 0xFF); """ ) if valueType == .boolean { - printer.print("boolean value$ = ((byte) (combined$ >> 8)) != 0;") + printer.print("boolean \(resultName)_value$ = ((byte) (\(resultName)_combined$ >> 8)) != 0;") } else { - printer.print("\(valueType) value$ = (\(valueType)) (combined$ >> \(valueSizeInBytes * 8));") + printer.print("\(valueType) \(resultName)_value$ = (\(valueType)) (\(resultName)_combined$ >> \(valueSizeInBytes * 8));") } - return "discriminator$ == 1 ? \(optionalType).of(value$) : \(optionalType).empty()" + return "\(resultName)_discriminator$ == 1 ? \(optionalType).of(\(resultName)_value$) : \(optionalType).empty()" case .ternary(let cond, let thenExp, let elseExp): let cond = cond.render(&printer, placeholder) @@ -696,25 +875,50 @@ extension JNISwift2JavaGenerator { let arguments = arguments.map { $0.render(&printer, placeholder) } return "\(inner)[\(arguments.joined(separator: ", "))]" - case .aggregate(let name, let type, let steps): + case .aggregate(let variable, let steps): precondition(!steps.isEmpty, "Aggregate must contain steps") - printer.print("\(type) \(name) = \(placeholder);") + let toExplode: String + if let variable { + printer.print("\(variable.type) \(variable.name) = \(placeholder);") + toExplode = variable.name + } else { + toExplode = placeholder + } let steps = steps.map { - $0.render(&printer, name) + $0.render(&printer, toExplode) } return steps.last! + + case .ifStatement(let cond, let thenExp, let elseExp): + let cond = cond.render(&printer, placeholder) + printer.printBraceBlock("if (\(cond))") { printer in + printer.print(thenExp.render(&printer, placeholder)) + } + if let elseExp { + printer.printBraceBlock("else") { printer in + printer.print(elseExp.render(&printer, placeholder)) + } + } + + return "" + + case .replacingPlaceholder(let inner, let placeholder): + return inner.render(&printer, placeholder) } } /// Whether the conversion uses SwiftArena. var requiresSwiftArena: Bool { switch self { - case .placeholder, .constant, .isOptionalPresent: + case .placeholder, .constant, .isOptionalPresent, .combinedName: return false case .constructSwiftValue, .wrapMemoryAddressUnsafe: return true + case .constructJavaClass(let inner, _): + return inner.requiresSwiftArena + case .valueMemoryAddress(let inner): return inner.requiresSwiftArena @@ -724,7 +928,7 @@ extension JNISwift2JavaGenerator { case .method(let inner, _, let args): return inner.requiresSwiftArena || args.contains(where: \.requiresSwiftArena) - case .combinedValueToOptional(let inner, _, _, _, _): + case .combinedValueToOptional(let inner, _, _, _, _, _): return inner.requiresSwiftArena case .ternary(let cond, let thenExp, let elseExp): @@ -736,11 +940,17 @@ extension JNISwift2JavaGenerator { case .subscriptOf(let inner, _): return inner.requiresSwiftArena - case .aggregate(_, _, let steps): + case .aggregate(_, let steps): return steps.contains(where: \.requiresSwiftArena) + case .ifStatement(let cond, let thenExp, let elseExp): + return cond.requiresSwiftArena || thenExp.requiresSwiftArena || (elseExp?.requiresSwiftArena ?? false) + case .call(let inner, _): - return inner.requiresSwiftArena + return inner.requiresSwiftArena + + case .replacingPlaceholder(let inner, _): + return inner.requiresSwiftArena } } } diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift index e7f7efbe..f2e9522b 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift @@ -61,6 +61,23 @@ extension JNISwift2JavaGenerator { ) } + func translateParameters( + _ parameters: [SwiftParameter], + translatedParameters: [TranslatedParameter], + methodName: String, + parentName: String + ) throws -> [NativeParameter] { + try zip(translatedParameters, parameters).map { translatedParameter, swiftParameter in + let parameterName = translatedParameter.parameter.name + return try translate( + swiftParameter: swiftParameter, + parameterName: parameterName, + methodName: methodName, + parentName: parentName + ) + } + } + func translate( swiftParameter: SwiftParameter, parameterName: String, @@ -231,8 +248,11 @@ extension JNISwift2JavaGenerator { } func translateOptionalResult( - wrappedType swiftType: SwiftType + wrappedType swiftType: SwiftType, + resultName: String = "result" ) throws -> NativeResult { + let discriminatorName = "\(resultName)_discriminator$" + switch swiftType { case .nominal(let nominalType): if let knownType = nominalType.nominalTypeDecl.knownTypeKind { @@ -249,6 +269,7 @@ extension JNISwift2JavaGenerator { conversion: .getJNIValue( .optionalRaisingWidenIntegerType( .placeholder, + resultName: resultName, valueType: javaType, combinedSwiftType: nextIntergralTypeWithSpaceForByte.swiftType, valueSizeInBytes: nextIntergralTypeWithSpaceForByte.valueBytes @@ -258,7 +279,6 @@ extension JNISwift2JavaGenerator { ) } else { // Use indirect byte array to store discriminator - let discriminatorName = "result_discriminator$" return NativeResult( javaType: javaType, @@ -284,8 +304,6 @@ extension JNISwift2JavaGenerator { } // Assume JExtract imported class - let discriminatorName = "result_discriminator$" - return NativeResult( javaType: .long, conversion: .optionalRaisingIndirectReturn( @@ -368,7 +386,8 @@ extension JNISwift2JavaGenerator { } func translate( - swiftResult: SwiftResult + swiftResult: SwiftResult, + resultName: String = "result" ) throws -> NativeResult { switch swiftResult.type { case .nominal(let nominalType): @@ -378,7 +397,7 @@ extension JNISwift2JavaGenerator { guard let genericArgs = nominalType.genericArguments, genericArgs.count == 1 else { throw JavaTranslationError.unsupportedSwiftType(swiftResult.type) } - return try translateOptionalResult(wrappedType: genericArgs[0]) + return try translateOptionalResult(wrappedType: genericArgs[0], resultName: resultName) default: guard let javaType = JNIJavaTypeTranslator.translate(knownType: knownType, config: self.config), javaType.implementsJavaValue else { @@ -399,7 +418,7 @@ extension JNISwift2JavaGenerator { return NativeResult( javaType: .long, - conversion: .getJNIValue(.allocateSwiftValue(name: "result", swiftType: swiftResult.type)), + conversion: .getJNIValue(.allocateSwiftValue(name: resultName, swiftType: swiftResult.type)), outParameters: [] ) @@ -411,7 +430,7 @@ extension JNISwift2JavaGenerator { ) case .optional(let wrapped): - return try translateOptionalResult(wrappedType: wrapped) + return try translateOptionalResult(wrappedType: wrapped, resultName: resultName) case .metatype, .tuple, .function, .existential, .opaque, .genericParameter: throw JavaTranslationError.unsupportedSwiftType(swiftResult.type) @@ -449,6 +468,9 @@ extension JNISwift2JavaGenerator { case constant(String) + /// `input_component` + case combinedName(component: String) + /// `value.getJNIValue(in:)` indirect case getJNIValue(NativeSwiftConversionStep) @@ -480,7 +502,7 @@ extension JNISwift2JavaGenerator { indirect case optionalChain(NativeSwiftConversionStep) - indirect case optionalRaisingWidenIntegerType(NativeSwiftConversionStep, valueType: JavaType, combinedSwiftType: SwiftKnownTypeDeclKind, valueSizeInBytes: Int) + indirect case optionalRaisingWidenIntegerType(NativeSwiftConversionStep, resultName: String, valueType: JavaType, combinedSwiftType: SwiftKnownTypeDeclKind, valueSizeInBytes: Int) indirect case optionalRaisingIndirectReturn(NativeSwiftConversionStep, returnType: JavaType, discriminatorParameterName: String, placeholderValue: NativeSwiftConversionStep) @@ -503,6 +525,9 @@ extension JNISwift2JavaGenerator { case .constant(let value): return value + case .combinedName(let component): + return "\(placeholder)_\(component)" + case .getJNIValue(let inner): let inner = inner.render(&printer, placeholder) return "\(inner).getJNIValue(in: environment!)" @@ -606,18 +631,18 @@ extension JNISwift2JavaGenerator { let inner = inner.render(&printer, placeholder) return "\(inner)?" - case .optionalRaisingWidenIntegerType(let inner, let valueType, let combinedSwiftType, let valueSizeInBytes): + case .optionalRaisingWidenIntegerType(let inner, let resultName, let valueType, let combinedSwiftType, let valueSizeInBytes): let inner = inner.render(&printer, placeholder) let value = valueType == .boolean ? "$0 ? 1 : 0" : "$0" let combinedSwiftTypeName = combinedSwiftType.moduleAndName.name printer.print( """ - let value$ = \(inner).map { + let \(resultName)_value$ = \(inner).map { \(combinedSwiftTypeName)(\(value)) << \(valueSizeInBytes * 8) | \(combinedSwiftTypeName)(1) } ?? 0 """ ) - return "value$" + return "\(resultName)_value$" case .optionalRaisingIndirectReturn(let inner, let returnType, let discriminatorParameterName, let placeholderValue): printer.print("let result$: \(returnType.jniTypeName)") diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift index ca580e60..6b8c435a 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift @@ -80,6 +80,15 @@ extension JNISwift2JavaGenerator { } } + private func printJNICache(_ printer: inout CodePrinter, _ type: ImportedNominalType) { + printer.printBraceBlock("enum \(JNICaching.cacheName(for: type))") { printer in + for enumCase in type.cases { + guard let translatedCase = translatedEnumCase(for: enumCase) else { continue } + printer.print("static let \(JNICaching.cacheMemberName(for: enumCase)) = \(renderEnumCaseCacheInit(translatedCase))") + } + } + } + private func printGlobalSwiftThunkSources(_ printer: inout CodePrinter) throws { printHeader(&printer) @@ -97,11 +106,24 @@ extension JNISwift2JavaGenerator { private func printNominalTypeThunks(_ printer: inout CodePrinter, _ type: ImportedNominalType) throws { printHeader(&printer) + printJNICache(&printer, type) + printer.println() + for initializer in type.initializers { printSwiftFunctionThunk(&printer, initializer) printer.println() } + if type.swiftNominal.kind == .enum { + printEnumDiscriminator(&printer, type) + printer.println() + + for enumCase in type.cases { + printEnumCase(&printer, enumCase) + printer.println() + } + } + for method in type.methods { printSwiftFunctionThunk(&printer, method) printer.println() @@ -115,6 +137,92 @@ extension JNISwift2JavaGenerator { printDestroyFunctionThunk(&printer, type) } + private func printEnumDiscriminator(_ printer: inout CodePrinter, _ type: ImportedNominalType) { + let selfPointerParam = JavaParameter(name: "selfPointer", type: .long) + printCDecl( + &printer, + javaMethodName: "$getDiscriminator", + parentName: type.swiftNominal.name, + parameters: [selfPointerParam], + resultType: .int + ) { printer in + let selfPointer = self.printSelfJLongToUnsafeMutablePointer( + &printer, + swiftParentName: type.swiftNominal.name, + selfPointerParam + ) + printer.printBraceBlock("switch (\(selfPointer).pointee)") { printer in + for (idx, enumCase) in type.cases.enumerated() { + printer.print("case .\(enumCase.name): return \(idx)") + } + } + } + } + + private func printEnumCase(_ printer: inout CodePrinter, _ enumCase: ImportedEnumCase) { + guard let translatedCase = self.translatedEnumCase(for: enumCase) else { + return + } + + // Print static case initializer + printSwiftFunctionThunk(&printer, enumCase.caseFunction) + printer.println() + + // Print getAsCase method + if !translatedCase.translatedValues.isEmpty { + printEnumGetAsCaseThunk(&printer, translatedCase) + } + } + + private func renderEnumCaseCacheInit(_ enumCase: TranslatedEnumCase) -> String { + let nativeParametersClassName = "\(javaPackagePath)/\(enumCase.enumName)$\(enumCase.name)$$NativeParameters" + let methodSignature = MethodSignature(resultType: .void, parameterTypes: enumCase.parameterConversions.map(\.native.javaType)) + let methods = #"[.init(name: "", signature: "\#(methodSignature.mangledName)")]"# + + return #"_JNIMethodIDCache(environment: try! JavaVirtualMachine.shared().environment(), className: "\#(nativeParametersClassName)", methods: \#(methods))"# + } + + private func printEnumGetAsCaseThunk( + _ printer: inout CodePrinter, + _ enumCase: TranslatedEnumCase + ) { + printCDecl( + &printer, + enumCase.getAsCaseFunction + ) { printer in + let selfPointer = enumCase.getAsCaseFunction.nativeFunctionSignature.selfParameter!.conversion.render(&printer, "self") + let caseNames = enumCase.original.parameters.enumerated().map { idx, parameter in + parameter.name ?? "_\(idx)" + } + let caseNamesWithLet = caseNames.map { "let \($0)" } + let methodSignature = MethodSignature(resultType: .void, parameterTypes: enumCase.parameterConversions.map(\.native.javaType)) + printer.print( + """ + guard case .\(enumCase.original.name)(\(caseNamesWithLet.joined(separator: ", "))) = \(selfPointer).pointee else { + fatalError("Expected enum case '\(enumCase.original.name)', but was '\\(\(selfPointer).pointee)'!") + } + let cache$ = \(JNICaching.cacheName(for: enumCase.original.enumType)).\(JNICaching.cacheMemberName(for: enumCase.original)) + let class$ = cache$.javaClass + let method$ = _JNIMethodIDCache.Method(name: "", signature: "\(methodSignature.mangledName)") + let constructorID$ = cache$[method$] + """ + ) + let upcallArguments = zip(enumCase.parameterConversions, caseNames).map { conversion, caseName in + // '0' is treated the same as a null pointer. + let nullConversion = !conversion.native.javaType.isPrimitive ? " ?? 0" : "" + let result = conversion.native.conversion.render(&printer, caseName) + return "\(result)\(nullConversion)" + } + printer.print( + """ + return withVaList([\(upcallArguments.joined(separator: ", "))]) { + return environment.interface.NewObjectV(environment, class$, constructorID$, $0) + } + """ + ) + } + } + private func printSwiftFunctionThunk( _ printer: inout CodePrinter, _ decl: ImportedFunc @@ -124,21 +232,9 @@ extension JNISwift2JavaGenerator { return } - let nativeSignature = translatedDecl.nativeFunctionSignature - var parameters = nativeSignature.parameters.flatMap(\.parameters) - - if let selfParameter = nativeSignature.selfParameter { - parameters += selfParameter.parameters - } - - parameters += nativeSignature.result.outParameters - printCDecl( &printer, - javaMethodName: translatedDecl.nativeFunctionName, - parentName: translatedDecl.parentName, - parameters: parameters, - resultType: nativeSignature.result.javaType + translatedDecl ) { printer in self.printFunctionDowncall(&printer, decl) } @@ -190,6 +286,18 @@ extension JNISwift2JavaGenerator { .joined(separator: ", ") result = "\(tryClause)\(callee).\(decl.name)(\(downcallArguments))" + case .enumCase: + let downcallArguments = zip( + decl.functionSignature.parameters, + arguments + ).map { originalParam, argument in + let label = originalParam.argumentLabel.map { "\($0): " } ?? "" + return "\(label)\(argument)" + } + + let associatedValues = !downcallArguments.isEmpty ? "(\(downcallArguments.joined(separator: ", ")))" : "" + result = "\(callee).\(decl.name)\(associatedValues)" + case .getter: result = "\(tryClause)\(callee).\(decl.name)" @@ -228,6 +336,31 @@ extension JNISwift2JavaGenerator { } } + private func printCDecl( + _ printer: inout CodePrinter, + _ translatedDecl: TranslatedFunctionDecl, + _ body: (inout CodePrinter) -> Void + ) { + let nativeSignature = translatedDecl.nativeFunctionSignature + var parameters = nativeSignature.parameters.flatMap(\.parameters) + + if let selfParameter = nativeSignature.selfParameter { + parameters += selfParameter.parameters + } + + parameters += nativeSignature.result.outParameters + + printCDecl( + &printer, + javaMethodName: translatedDecl.nativeFunctionName, + parentName: translatedDecl.parentName, + parameters: parameters, + resultType: nativeSignature.result.javaType + ) { printer in + body(&printer) + } + } + private func printCDecl( _ printer: inout CodePrinter, javaMethodName: String, diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator.swift index c5f3a5b6..60ec1b8b 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator.swift @@ -39,6 +39,7 @@ package class JNISwift2JavaGenerator: Swift2JavaGenerator { /// Cached Java translation result. 'nil' indicates failed translation. var translatedDecls: [ImportedFunc: TranslatedFunctionDecl] = [:] + var translatedEnumCases: [ImportedEnumCase: TranslatedEnumCase] = [:] /// Because we need to write empty files for SwiftPM, keep track which files we didn't write yet, /// and write an empty file for those. diff --git a/Sources/JExtractSwiftLib/Swift2JavaVisitor.swift b/Sources/JExtractSwiftLib/Swift2JavaVisitor.swift index a933ff3e..bc6ac032 100644 --- a/Sources/JExtractSwiftLib/Swift2JavaVisitor.swift +++ b/Sources/JExtractSwiftLib/Swift2JavaVisitor.swift @@ -46,7 +46,7 @@ final class Swift2JavaVisitor { case .structDecl(let node): self.visit(nominalDecl: node, in: parent) case .enumDecl(let node): - self.visit(nominalDecl: node, in: parent) + self.visit(enumDecl: node, in: parent) case .protocolDecl(let node): self.visit(nominalDecl: node, in: parent) case .extensionDecl(let node): @@ -65,6 +65,8 @@ final class Swift2JavaVisitor { case .subscriptDecl: // TODO: Implement break + case .enumCaseDecl(let node): + self.visit(enumCaseDecl: node, in: parent) default: break @@ -83,6 +85,12 @@ final class Swift2JavaVisitor { } } + func visit(enumDecl node: EnumDeclSyntax, in parent: ImportedNominalType?) { + self.visit(nominalDecl: node, in: parent) + + self.synthesizeRawRepresentableConformance(enumDecl: node, in: parent) + } + func visit(extensionDecl node: ExtensionDeclSyntax, in parent: ImportedNominalType?) { guard parent == nil else { // 'extension' in a nominal type is invalid. Ignore @@ -131,6 +139,49 @@ final class Swift2JavaVisitor { } } + func visit(enumCaseDecl node: EnumCaseDeclSyntax, in typeContext: ImportedNominalType?) { + guard let typeContext else { + self.log.info("Enum case must be within a current type; \(node)") + return + } + + do { + for caseElement in node.elements { + self.log.debug("Import case \(caseElement.name) of enum \(node.qualifiedNameForDebug)") + + let parameters = try caseElement.parameterClause?.parameters.map { + try SwiftEnumCaseParameter($0, lookupContext: translator.lookupContext) + } + + let signature = try SwiftFunctionSignature( + caseElement, + enclosingType: typeContext.swiftType, + lookupContext: translator.lookupContext + ) + + let caseFunction = ImportedFunc( + module: translator.swiftModuleName, + swiftDecl: node, + name: caseElement.name.text, + apiKind: .enumCase, + functionSignature: signature + ) + + let importedCase = ImportedEnumCase( + name: caseElement.name.text, + parameters: parameters ?? [], + swiftDecl: node, + enumType: SwiftNominalType(nominalTypeDecl: typeContext.swiftNominal), + caseFunction: caseFunction + ) + + typeContext.cases.append(importedCase) + } + } catch { + self.log.debug("Failed to import: \(node.qualifiedNameForDebug); \(error)") + } + } + func visit(variableDecl node: VariableDeclSyntax, in typeContext: ImportedNominalType?) { guard node.shouldExtract(config: config, log: log) else { return @@ -213,6 +264,32 @@ final class Swift2JavaVisitor { typeContext.initializers.append(imported) } + + private func synthesizeRawRepresentableConformance(enumDecl node: EnumDeclSyntax, in parent: ImportedNominalType?) { + guard let imported = translator.importedNominalType(node, parent: parent) else { + return + } + + if let firstInheritanceType = imported.swiftNominal.firstInheritanceType, + let inheritanceType = try? SwiftType( + firstInheritanceType, + lookupContext: translator.lookupContext + ), + inheritanceType.isRawTypeCompatible + { + if !imported.variables.contains(where: { $0.name == "rawValue" && $0.functionSignature.result.type != inheritanceType }) { + let decl: DeclSyntax = "public var rawValue: \(raw: inheritanceType.description) { get }" + self.visit(decl: decl, in: imported) + } + + imported.variables.first?.signatureString + + if !imported.initializers.contains(where: { $0.functionSignature.parameters.count == 1 && $0.functionSignature.parameters.first?.parameterName == "rawValue" && $0.functionSignature.parameters.first?.type == inheritanceType }) { + let decl: DeclSyntax = "public init?(rawValue: \(raw: inheritanceType))" + self.visit(decl: decl, in: imported) + } + } + } } extension DeclSyntaxProtocol where Self: WithModifiersSyntax & WithAttributesSyntax { @@ -233,15 +310,6 @@ extension DeclSyntaxProtocol where Self: WithModifiersSyntax & WithAttributesSyn return false } - if let node = self.as(InitializerDeclSyntax.self) { - let isFailable = node.optionalMark != nil - - if isFailable { - log.warning("Skip import '\(self.qualifiedNameForDebug)': failable initializer") - return false - } - } - return true } } diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftEnumCaseParameter.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftEnumCaseParameter.swift new file mode 100644 index 00000000..55682152 --- /dev/null +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftEnumCaseParameter.swift @@ -0,0 +1,32 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import SwiftSyntax + +struct SwiftEnumCaseParameter: Equatable { + var name: String? + var type: SwiftType +} + +extension SwiftEnumCaseParameter { + init( + _ node: EnumCaseParameterSyntax, + lookupContext: SwiftTypeLookupContext + ) throws { + self.init( + name: node.firstName?.identifier?.name, + type: try SwiftType(node.type, lookupContext: lookupContext) + ) + } +} diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftFunctionSignature.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftFunctionSignature.swift index 85b96110..a5b01bee 100644 --- a/Sources/JExtractSwiftLib/SwiftTypes/SwiftFunctionSignature.swift +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftFunctionSignature.swift @@ -71,11 +71,6 @@ extension SwiftFunctionSignature { throw SwiftFunctionTranslationError.missingEnclosingType(node) } - // We do not yet support failable initializers. - if node.optionalMark != nil { - throw SwiftFunctionTranslationError.failableInitializer(node) - } - let (genericParams, genericRequirements) = try Self.translateGenericParameters( parameterClause: node.genericParameterClause, whereClause: node.genericWhereClause, @@ -86,16 +81,37 @@ extension SwiftFunctionSignature { lookupContext: lookupContext ) + let type = node.optionalMark != nil ? .optional(enclosingType) : enclosingType + self.init( selfParameter: .initializer(enclosingType), parameters: parameters, - result: SwiftResult(convention: .direct, type: enclosingType), + result: SwiftResult(convention: .direct, type: type), effectSpecifiers: effectSpecifiers, genericParameters: genericParams, genericRequirements: genericRequirements ) } + init( + _ node: EnumCaseElementSyntax, + enclosingType: SwiftType, + lookupContext: SwiftTypeLookupContext + ) throws { + let parameters = try node.parameterClause?.parameters.map { param in + try SwiftParameter(param, lookupContext: lookupContext) + } + + self.init( + selfParameter: .initializer(enclosingType), + parameters: parameters ?? [], + result: SwiftResult(convention: .direct, type: enclosingType), + effectSpecifiers: [], + genericParameters: [], + genericRequirements: [] + ) + } + init( _ node: FunctionDeclSyntax, enclosingType: SwiftType?, diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftNominalTypeDeclaration.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftNominalTypeDeclaration.swift index cef4e731..335979a4 100644 --- a/Sources/JExtractSwiftLib/SwiftTypes/SwiftNominalTypeDeclaration.swift +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftNominalTypeDeclaration.swift @@ -85,6 +85,14 @@ package class SwiftNominalTypeDeclaration: SwiftTypeDeclaration { super.init(moduleName: moduleName, name: node.name.text) } + lazy var firstInheritanceType: TypeSyntax? = { + guard let firstInheritanceType = self.syntax?.inheritanceClause?.inheritedTypes.first else { + return nil + } + + return firstInheritanceType.type + }() + /// Returns true if this type conforms to `Sendable` and therefore is "threadsafe". lazy var isSendable: Bool = { // Check if Sendable is in the inheritance list diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftParameter.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftParameter.swift index 75d165e9..63f7d75b 100644 --- a/Sources/JExtractSwiftLib/SwiftTypes/SwiftParameter.swift +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftParameter.swift @@ -57,6 +57,16 @@ enum SwiftParameterConvention: Equatable { case `inout` } +extension SwiftParameter { + init(_ node: EnumCaseParameterSyntax, lookupContext: SwiftTypeLookupContext) throws { + self.convention = .byValue + self.type = try SwiftType(node.type, lookupContext: lookupContext) + self.argumentLabel = nil + self.parameterName = node.firstName?.identifier?.name + self.argumentLabel = node.firstName?.identifier?.name + } +} + extension SwiftParameter { init(_ node: FunctionParameterSyntax, lookupContext: SwiftTypeLookupContext) throws { // Determine the convention. The default is by-value, but there are diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftType.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftType.swift index 3cc14406..58bb65c3 100644 --- a/Sources/JExtractSwiftLib/SwiftTypes/SwiftType.swift +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftType.swift @@ -103,6 +103,19 @@ enum SwiftType: Equatable { default: false } } + + var isRawTypeCompatible: Bool { + switch self { + case .nominal(let nominal): + switch nominal.nominalTypeDecl.knownTypeKind { + case .int, .uint, .int8, .uint8, .int16, .uint16, .int32, .uint32, .int64, .uint64, .float, .double, .string: + true + default: + false + } + default: false + } + } } extension SwiftType: CustomStringConvertible { diff --git a/Sources/JavaKit/Helpers/_JNIMethodIDCache.swift b/Sources/JavaKit/Helpers/_JNIMethodIDCache.swift new file mode 100644 index 00000000..a67d225f --- /dev/null +++ b/Sources/JavaKit/Helpers/_JNIMethodIDCache.swift @@ -0,0 +1,59 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +/// A cache used to hold references for JNI method and classes. +/// +/// This type is used internally in by the outputted JExtract wrappers +/// to improve performance of any JNI lookups. +public final class _JNIMethodIDCache: Sendable { + public struct Method: Hashable { + public let name: String + public let signature: String + + public init(name: String, signature: String) { + self.name = name + self.signature = signature + } + } + + nonisolated(unsafe) let _class: jclass? + nonisolated(unsafe) let methods: [Method: jmethodID] + + public var javaClass: jclass { + self._class! + } + + public init(environment: UnsafeMutablePointer!, className: String, methods: [Method]) { + guard let clazz = environment.interface.FindClass(environment, className) else { + fatalError("Class \(className) could not be found!") + } + self._class = environment.interface.NewGlobalRef(environment, clazz)! + self.methods = methods.reduce(into: [:]) { (result, method) in + if let methodID = environment.interface.GetMethodID(environment, clazz, method.name, method.signature) { + result[method] = methodID + } else { + fatalError("Method \(method.signature) with signature \(method.signature) not found in class \(className)") + } + } + } + + + public subscript(_ method: Method) -> jmethodID? { + methods[method] + } + + public func cleanup(environment: UnsafeMutablePointer!) { + environment.interface.DeleteGlobalRef(environment, self._class) + } +} diff --git a/Sources/JavaTypes/Mangling.swift b/Sources/JavaTypes/Mangling.swift index 74e2e0b8..f0dbd484 100644 --- a/Sources/JavaTypes/Mangling.swift +++ b/Sources/JavaTypes/Mangling.swift @@ -36,7 +36,7 @@ extension JavaType { case .void: "V" case .array(let elementType): "[" + elementType.mangledName case .class(package: let package, name: let name): - "L\(package!).\(name);".replacingPeriodsWithSlashes() + "L\(package!).\(name.replacingPeriodsWithDollars());".replacingPeriodsWithSlashes() } } } @@ -145,4 +145,9 @@ extension StringProtocol { fileprivate func replacingSlashesWithPeriods() -> String { return String(self.map { $0 == "/" ? "." as Character : $0 }) } + + /// Return the string after replacing all of the periods (".") with slashes ("$"). + fileprivate func replacingPeriodsWithDollars() -> String { + return String(self.map { $0 == "." ? "$" as Character : $0 }) + } } diff --git a/Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md b/Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md index 130c333b..c5de6c45 100644 --- a/Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md +++ b/Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md @@ -49,7 +49,8 @@ SwiftJava's `swift-java jextract` tool automates generating Java bindings from S | Initializers: `class`, `struct` | ✅ | ✅ | | Optional Initializers / Throwing Initializers | ❌ | ❌ | | Deinitializers: `class`, `struct` | ✅ | ✅ | -| `enum`, `actor` | ❌ | ❌ | +| `enum` | ❌ | ✅ | +| `actor` | ❌ | ❌ | | Global Swift `func` | ✅ | ✅ | | Class/struct member `func` | ✅ | ✅ | | Throwing functions: `func x() throws` | ❌ | ✅ | @@ -157,3 +158,113 @@ you are expected to add a Guava dependency to your Java project. | `Double` | `double` | > Note: The `wrap-guava` mode is currently only available in FFM mode of jextract. + +### Enums + +> Note: Enums are currently only supported in JNI mode. + +Swift enums are extracted into a corresponding Java `class`. To support associated values +all cases are also extracted as Java `record`s. + +Consider the following Swift enum: +```swift +public enum Vehicle { + case car(String) + case bicycle(maker: String) +} +``` +You can then instantiate a case of `Vehicle` by using one of the static methods: +```java +try (var arena = SwiftArena.ofConfined()) { + Vehicle vehicle = Vehicle.car("BMW", arena); + Optional car = vehicle.getAsCar(); + assertEquals("BMW", car.orElseThrow().arg0()); +} +``` +As you can see above, to access the associated values of a case you can call one of the +`getAsX` methods that will return an Optional record with the associated values. +```java +try (var arena = SwiftArena.ofConfined()) { + Vehicle vehicle = Vehicle.bycicle("My Brand", arena); + Optional car = vehicle.getAsCar(); + assertFalse(car.isPresent()); + + Optional bicycle = vehicle.getAsBicycle(); + assertEquals("My Brand", bicycle.orElseThrow().maker()); +} +``` + +#### Switching and pattern matching + +If you only need to switch on the case and not access any associated values, +you can use the `getDiscriminator()` method: +```java +Vehicle vehicle = ...; +switch (vehicle.getDiscriminator()) { + case BICYCLE: + System.out.println("I am a bicycle!"); + break + case CAR: + System.out.println("I am a car!"); + break +} +``` +If you also want access to the associated values, you have various options +depending on the Java version you are using. +If you are running Java 21+ you can use [pattern matching for switch](https://openjdk.org/jeps/441): +```java +Vehicle vehicle = ...; +switch (vehicle.getCase()) { + case Vehicle.Bicycle b: + System.out.println("Bicycle maker: " + b.maker()); + break + case Vehicle.Car c: + System.out.println("Car: " + c.arg0()); + break +} +``` +For Java 16+ you can use [pattern matching for instanceof](https://openjdk.org/jeps/394) +```java +Vehicle vehicle = ...; +Vehicle.Case case = vehicle.getCase(); +if (case instanceof Vehicle.Bicycle b) { + System.out.println("Bicycle maker: " + b.maker()); +} else if(case instanceof Vehicle.Car c) { + System.out.println("Car: " + c.arg0()); +} +``` +For any previous Java versions you can resort to casting the `Case` to the expected type: +```java +Vehicle vehicle = ...; +Vehicle.Case case = vehicle.getCase(); +if (case instanceof Vehicle.Bicycle) { + Vehicle.Bicycle b = (Vehicle.Bicycle) case; + System.out.println("Bicycle maker: " + b.maker()); +} else if(case instanceof Vehicle.Car) { + Vehicle.Car c = (Vehicle.Car) case; + System.out.println("Car: " + c.arg0()); +} +``` + +#### RawRepresentable enums + +JExtract also supports extracting enums that conform to `RawRepresentable` +by giving access to an optional initializer and the `rawValue` variable. +Consider the following example: +```swift +public enum Alignment: String { + case horizontal + case vertical +} +``` +you can then initialize `Alignment` from a `String` and also retrieve back its `rawValue`: +```java +try (var arena = SwiftArena.ofConfined()) { + Optional alignment = Alignment.init("horizontal", arena); + assertEqual(HORIZONTAL, alignment.orElseThrow().getDiscriminator()); + assertEqual("horizontal", alignment.orElseThrow().getRawValue()); +} +``` + + + diff --git a/Tests/JExtractSwiftTests/JNI/JNIEnumTests.swift b/Tests/JExtractSwiftTests/JNI/JNIEnumTests.swift new file mode 100644 index 00000000..47765043 --- /dev/null +++ b/Tests/JExtractSwiftTests/JNI/JNIEnumTests.swift @@ -0,0 +1,313 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import JExtractSwiftLib +import Testing + +@Suite +struct JNIEnumTests { + let source = """ + public enum MyEnum { + case first + case second(String) + case third(x: Int64, y: Int32) + } + """ + + @Test + func generatesJavaClass() throws { + try assertOutput( + input: source, + .jni, .java, + expectedChunks: [ + """ + // Generated by jextract-swift + // Swift module: SwiftModule + + package com.example.swift; + + import org.swift.swiftkit.core.*; + import org.swift.swiftkit.core.util.*; + """, + """ + public final class MyEnum extends JNISwiftInstance { + static final String LIB_NAME = "SwiftModule"; + + @SuppressWarnings("unused") + private static final boolean INITIALIZED_LIBS = initializeLibs(); + static boolean initializeLibs() { + System.loadLibrary(LIB_NAME); + return true; + } + """, + """ + private MyEnum(long selfPointer, SwiftArena swiftArena) { + super(selfPointer, swiftArena); + } + """, + """ + public static MyEnum wrapMemoryAddressUnsafe(long selfPointer, SwiftArena swiftArena) { + return new MyEnum(selfPointer, swiftArena); + } + """, + """ + private static native void $destroy(long selfPointer); + """, + """ + @Override + protected Runnable $createDestroyFunction() { + long self$ = this.$memoryAddress(); + if (CallTraces.TRACE_DOWNCALLS) { + CallTraces.traceDowncall("MyEnum.$createDestroyFunction", + "this", this, + "self", self$); + } + return new Runnable() { + @Override + public void run() { + if (CallTraces.TRACE_DOWNCALLS) { + CallTraces.traceDowncall("MyEnum.$destroy", "self", self$); + } + MyEnum.$destroy(self$); + } + }; + """ + ]) + } + + @Test + func generatesDiscriminator_java() throws { + try assertOutput( + input: source, + .jni, .java, + detectChunkByInitialLines: 1, + expectedChunks: [ + """ + public enum Discriminator { + FIRST, + SECOND, + THIRD + } + """, + """ + public Discriminator getDiscriminator() { + return Discriminator.values()[$getDiscriminator(this.$memoryAddress())]; + } + """, + """ + private static native int $getDiscriminator(long self); + """ + ]) + } + + @Test + func generatesDiscriminator_swift() throws { + try assertOutput( + input: source, + .jni, .swift, + detectChunkByInitialLines: 1, + expectedChunks: [ + """ + @_cdecl("Java_com_example_swift_MyEnum__00024getDiscriminator__J") + func Java_com_example_swift_MyEnum__00024getDiscriminator__J(environment: UnsafeMutablePointer!, thisClass: jclass, selfPointer: jlong) -> jint { + ... + switch (self$.pointee) { + case .first: return 0 + case .second: return 1 + case .third: return 2 + } + } + """ + ]) + } + + @Test + func generatesCases_java() throws { + try assertOutput( + input: source, + .jni, .java, + detectChunkByInitialLines: 1, + expectedChunks: [ + """ + public sealed interface Case {} + """, + """ + public Case getCase() { + Discriminator discriminator = this.getDiscriminator(); + switch (discriminator) { + case FIRST: return this.getAsFirst().orElseThrow(); + case SECOND: return this.getAsSecond().orElseThrow(); + case THIRD: return this.getAsThird().orElseThrow(); + } + throw new RuntimeException("Unknown discriminator value " + discriminator); + } + """, + """ + public record First() implements Case { + record $NativeParameters() {} + } + """, + """ + public record Second(java.lang.String arg0) implements Case { + record $NativeParameters(java.lang.String arg0) {} + } + """, + """ + public record Third(long x, int y) implements Case { + record $NativeParameters(long x, int y) {} + } + """ + ]) + } + + @Test + func generatesCaseInitializers_java() throws { + try assertOutput( + input: source, + .jni, .java, + detectChunkByInitialLines: 1, + expectedChunks: [ + """ + public static MyEnum first(SwiftArena swiftArena$) { + return MyEnum.wrapMemoryAddressUnsafe(MyEnum.$first(), swiftArena$); + } + """, + """ + public static MyEnum second(java.lang.String arg0, SwiftArena swiftArena$) { + return MyEnum.wrapMemoryAddressUnsafe(MyEnum.$second(arg0), swiftArena$); + } + """, + """ + public static MyEnum third(long x, int y, SwiftArena swiftArena$) { + return MyEnum.wrapMemoryAddressUnsafe(MyEnum.$third(x, y), swiftArena$); + } + """ + ]) + } + + @Test + func generatesCaseInitializers_swift() throws { + try assertOutput( + input: source, + .jni, .swift, + detectChunkByInitialLines: 1, + expectedChunks: [ + """ + @_cdecl("Java_com_example_swift_MyEnum__00024first__") + func Java_com_example_swift_MyEnum__00024first__(environment: UnsafeMutablePointer!, thisClass: jclass) -> jlong { + let result$ = UnsafeMutablePointer.allocate(capacity: 1) + result$.initialize(to: MyEnum.first) + let resultBits$ = Int64(Int(bitPattern: result$)) + return resultBits$.getJNIValue(in: environment!) + } + """, + """ + @_cdecl("Java_com_example_swift_MyEnum__00024second__Ljava_lang_String_2") + func Java_com_example_swift_MyEnum__00024second__Ljava_lang_String_2(environment: UnsafeMutablePointer!, thisClass: jclass, arg0: jstring?) -> jlong { + let result$ = UnsafeMutablePointer.allocate(capacity: 1) + result$.initialize(to: MyEnum.second(String(fromJNI: arg0, in: environment!))) + let resultBits$ = Int64(Int(bitPattern: result$)) + return resultBits$.getJNIValue(in: environment!) + } + """, + """ + @_cdecl("Java_com_example_swift_MyEnum__00024third__JI") + func Java_com_example_swift_MyEnum__00024third__JI(environment: UnsafeMutablePointer!, thisClass: jclass, x: jlong, y: jint) -> jlong { + let result$ = UnsafeMutablePointer.allocate(capacity: 1) + result$.initialize(to: MyEnum.third(x: Int64(fromJNI: x, in: environment!), y: Int32(fromJNI: y, in: environment!))) + let resultBits$ = Int64(Int(bitPattern: result$)) + return resultBits$.getJNIValue(in: environment!) + } + """ + ]) + } + + @Test + func generatesGetAsCase_java() throws { + try assertOutput( + input: source, + .jni, .java, + detectChunkByInitialLines: 1, + expectedChunks: [ + """ + public Optional getAsFirst() { + if (getDiscriminator() != Discriminator.FIRST) { + return Optional.empty(); + } + return Optional.of(new First()); + } + """, + """ + public Optional getAsSecond() { + if (getDiscriminator() != Discriminator.SECOND) { + return Optional.empty(); + } + Second.$NativeParameters $nativeParameters = MyEnum.$getAsSecond(this.$memoryAddress()); + return Optional.of(new Second($nativeParameters.arg0)); + } + """, + """ + public Optional getAsThird() { + if (getDiscriminator() != Discriminator.THIRD) { + return Optional.empty(); + } + Third.$NativeParameters $nativeParameters = MyEnum.$getAsThird(this.$memoryAddress()); + return Optional.of(new Third($nativeParameters.x, $nativeParameters.y)); + } + """ + ]) + } + + @Test + func generatesGetAsCase_swift() throws { + try assertOutput( + input: source, + .jni, .swift, + detectChunkByInitialLines: 1, + expectedChunks: [ + """ + @_cdecl("Java_com_example_swift_MyEnum__00024getAsSecond__J") + func Java_com_example_swift_MyEnum__00024getAsSecond__J(environment: UnsafeMutablePointer!, thisClass: jclass, self: jlong) -> jobject? { + ... + guard case .second(let _0) = self$.pointee else { + fatalError("Expected enum case 'second', but was '\\(self$.pointee)'!") + } + let cache$ = _JNI_MyEnum.myEnumSecondCache + let class$ = cache$.javaClass + let method$ = _JNIMethodIDCache.Method(name: "", signature: "(Ljava/lang/String;)V") + let constructorID$ = cache$[method$] + return withVaList([_0.getJNIValue(in: environment!) ?? 0]) { + return environment.interface.NewObjectV(environment, class$, constructorID$, $0) + } + } + """, + """ + @_cdecl("Java_com_example_swift_MyEnum__00024getAsThird__J") + func Java_com_example_swift_MyEnum__00024getAsThird__J(environment: UnsafeMutablePointer!, thisClass: jclass, self: jlong) -> jobject? { + ... + guard case .third(let x, let y) = self$.pointee else { + fatalError("Expected enum case 'third', but was '\\(self$.pointee)'!") + } + let cache$ = _JNI_MyEnum.myEnumThirdCache + let class$ = cache$.javaClass + let method$ = _JNIMethodIDCache.Method(name: "", signature: "(JI)V") + let constructorID$ = cache$[method$] + return withVaList([x.getJNIValue(in: environment!), y.getJNIValue(in: environment!)]) { + return environment.interface.NewObjectV(environment, class$, constructorID$, $0) + } + } + """ + ]) + } +} diff --git a/Tests/JExtractSwiftTests/JNI/JNIOptionalTests.swift b/Tests/JExtractSwiftTests/JNI/JNIOptionalTests.swift index 2186e227..548a2eac 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIOptionalTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIOptionalTests.swift @@ -47,10 +47,10 @@ struct JNIOptionalTests { * } */ public static OptionalInt optionalSugar(OptionalLong arg) { - long combined$ = SwiftModule.$optionalSugar((byte) (arg.isPresent() ? 1 : 0), arg.orElse(0L)); - byte discriminator$ = (byte) (combined$ & 0xFF); - int value$ = (int) (combined$ >> 32); - return discriminator$ == 1 ? OptionalInt.of(value$) : OptionalInt.empty(); + long result_combined$ = SwiftModule.$optionalSugar((byte) (arg.isPresent() ? 1 : 0), arg.orElse(0L)); + byte result_discriminator$ = (byte) (result_combined$ & 0xFF); + int result_value$ = (int) (result_combined$ >> 32); + return result_discriminator$ == 1 ? OptionalInt.of(result_value$) : OptionalInt.empty(); } """, """ @@ -72,10 +72,10 @@ struct JNIOptionalTests { """ @_cdecl("Java_com_example_swift_SwiftModule__00024optionalSugar__BJ") func Java_com_example_swift_SwiftModule__00024optionalSugar__BJ(environment: UnsafeMutablePointer!, thisClass: jclass, arg_discriminator: jbyte, arg_value: jlong) -> jlong { - let value$ = SwiftModule.optionalSugar(arg_discriminator == 1 ? Int64(fromJNI: arg_value, in: environment!) : nil).map { + let result_value$ = SwiftModule.optionalSugar(arg_discriminator == 1 ? Int64(fromJNI: arg_value, in: environment!) : nil).map { Int64($0) << 32 | Int64(1) } ?? 0 - return value$.getJNIValue(in: environment!) + return result_value$.getJNIValue(in: environment!) } """ ] @@ -98,9 +98,9 @@ struct JNIOptionalTests { * } */ public static Optional optionalExplicit(Optional arg) { - byte[] result_discriminator$ = new byte[1]; - java.lang.String result$ = SwiftModule.$optionalExplicit((byte) (arg.isPresent() ? 1 : 0), arg.orElse(null), result_discriminator$); - return (result_discriminator$[0] == 1) ? Optional.of(result$) : Optional.empty(); + byte[] result$_discriminator$ = new byte[1]; + java.lang.String result$ = SwiftModule.$optionalExplicit((byte) (arg.isPresent() ? 1 : 0), arg.orElse(null), result$_discriminator$); + return (result$_discriminator$[0] == 1) ? Optional.of(result$) : Optional.empty(); } """, """ @@ -127,12 +127,12 @@ struct JNIOptionalTests { result$ = innerResult$.getJNIValue(in: environment!) var flag$ = Int8(1) environment.interface.SetByteArrayRegion(environment, result_discriminator$, 0, 1, &flag$) - } // render(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+NativeTranslation.swift:624 + } // render(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+NativeTranslation.swift:649 else { result$ = String.jniPlaceholderValue var flag$ = Int8(0) environment.interface.SetByteArrayRegion(environment, result_discriminator$, 0, 1, &flag$) - } // render(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+NativeTranslation.swift:634 + } // render(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+NativeTranslation.swift:659 return result$ } """ @@ -156,9 +156,9 @@ struct JNIOptionalTests { * } */ public static Optional optionalClass(Optional arg, SwiftArena swiftArena$) { - byte[] result_discriminator$ = new byte[1]; - long result$ = SwiftModule.$optionalClass(arg.map(MyClass::$memoryAddress).orElse(0L), result_discriminator$); - return (result_discriminator$[0] == 1) ? Optional.of(MyClass.wrapMemoryAddressUnsafe(result$, swiftArena$)) : Optional.empty(); + byte[] result$_discriminator$ = new byte[1]; + long result$ = SwiftModule.$optionalClass(arg.map(MyClass::$memoryAddress).orElse(0L), result$_discriminator$); + return (result$_discriminator$[0] == 1) ? Optional.of(MyClass.wrapMemoryAddressUnsafe(result$, swiftArena$)) : Optional.empty(); } """, """ @@ -190,12 +190,12 @@ struct JNIOptionalTests { result$ = _resultBits$.getJNIValue(in: environment!) var flag$ = Int8(1) environment.interface.SetByteArrayRegion(environment, result_discriminator$, 0, 1, &flag$) - } // render(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+NativeTranslation.swift:624 + } // render(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+NativeTranslation.swift:649 else { result$ = 0 var flag$ = Int8(0) environment.interface.SetByteArrayRegion(environment, result_discriminator$, 0, 1, &flag$) - } // render(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+NativeTranslation.swift:634 + } // render(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+NativeTranslation.swift:659 return result$ } """ @@ -243,7 +243,7 @@ struct JNIOptionalTests { func Java_com_example_swift_SwiftModule__00024optionalJavaKitClass__Ljava_lang_Long_2(environment: UnsafeMutablePointer!, thisClass: jclass, arg: jobject?) { SwiftModule.optionalJavaKitClass(arg.map { return JavaLong(javaThis: $0, environment: environment!) - } // render(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+NativeTranslation.swift:666 + } // render(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+NativeTranslation.swift:691 ) } """ From 612f04e48c430d4e38df21c51e95d52de31c08d3 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Wed, 20 Aug 2025 16:22:52 +0900 Subject: [PATCH 349/426] Disable SPI docs for jni dependent targets (#369) docc plugin can't handle targets which need additional libraries, so we're blocked on generating docs for them in SPI until https://github.com/swiftlang/swift-docc-plugin/issues/112 is resolved --- .spi.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.spi.yml b/.spi.yml index e7159a31..f4074e0e 100644 --- a/.spi.yml +++ b/.spi.yml @@ -2,9 +2,7 @@ version: 1 builder: configs: - documentation_targets: [ - SwiftJavaDocumentation, - JavaKit, - SwiftKitSwift + SwiftJavaDocumentation ] # Drop this version pinning once 6.2 is released and docs are built with 6.2 by default to prevent it staying on 6.2 forever. swift_version: 6.2 From 1d2014849d325ea4efc6141114d54ee36ce3fcd1 Mon Sep 17 00:00:00 2001 From: David Ko Date: Mon, 25 Aug 2025 04:11:55 -0400 Subject: [PATCH 350/426] Update on SwiftJavaDocumentation (#372) Co-authored-by: Konrad `ktoso` Malawski --- .../Documentation.docc/SupportedFeatures.md | 4 ++-- .../Documentation.docc/index.md | 18 +++++++++++++++--- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md b/Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md index c5de6c45..8d193149 100644 --- a/Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md +++ b/Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md @@ -33,10 +33,10 @@ Java `native` functions. JavaKit simplifies the type conversions | Java `abstract class` | TODO | | Java `enum` | ❌ | | Java methods: `static`, member | ✅ `@JavaMethod` | -| **This list is very work in progress** | | +| **This list is very work in progress** | | -### JExtract: Java -> Swift +### JExtract – calling Swift from Java SwiftJava's `swift-java jextract` tool automates generating Java bindings from Swift sources. diff --git a/Sources/SwiftJavaDocumentation/Documentation.docc/index.md b/Sources/SwiftJavaDocumentation/Documentation.docc/index.md index 7c695a71..460f396d 100644 --- a/Sources/SwiftJavaDocumentation/Documentation.docc/index.md +++ b/Sources/SwiftJavaDocumentation/Documentation.docc/index.md @@ -11,9 +11,21 @@ Please refer to articles about the specific direction of interoperability you ar ### Getting started -TODO: Some general intro +**SwiftJava** provides a set of tools and libraries to enable Java and Swift interoperability. It allows developers to generate bindings to either language from the other, by using either source generation (for Java consuming Swift code) or a combination of Swift macros and source generation (for Swift consuming Java libraries). -If you prefer a video introduction, you may want to this +The generated code is highly efficient and less error-prone than manually mapping, and also guarantees memory safety across the boundaries between the languages. + +Reasons why you might want to reach for Swift and Java interoperability include, but are not limited to, the following scenarios: +- Incremental adoption of Swift in an existing Java codebase +- Reuse existing libraries which exist in one ecosystem, but don't have a direct equivalent in the other + +SwiftJava is offering several core libraries which support language interoperability: +- `JavaKit` (Swift -> Java) - JNI-based support library and Swift macros +- `SwiftKit` (Java -> Swift) - Support library for Java calling Swift code (either using JNI or FFM) +- `swift-java` - command line tool; Supports source generation and also dependency management operations +- Build tool integration - SwiftPM Plugin + +If you prefer a video introduction, you may want to watch this [Explore Swift and Java interoperability](https://www.youtube.com/watch?v=QSHO-GUGidA) WWDC 2025 session, which is a quick overview of all the features and approaches offered by SwiftJava. @@ -25,7 +37,7 @@ which is a quick overview of all the features and approaches offered by SwiftJav - -### Source generation +### Source Generation - - From caa97a4e841ef9859fe93b8c754422e1cb73bd7a Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Tue, 26 Aug 2025 07:26:47 +0900 Subject: [PATCH 351/426] Reorganize and rename modules; Centralize around SwiftJava prefix and naming (#366) --- .github/workflows/pull_request.yml | 8 +- .../JavaApiCallBenchmarks.swift | 4 +- Benchmarks/Package.swift | 6 +- Package.swift | 137 ++++++++++-------- .../JExtractSwiftPlugin.swift | 2 +- .../JavaCompilerPlugin.swift | 2 +- .../PluginsShared/JavaKitConfigurationShared | 1 - .../SwiftJavaConfigurationShared | 1 + Plugins/SwiftJavaPlugin/SwiftJavaPlugin.swift | 2 +- README.md | 2 +- Samples/JavaDependencySampleApp/Package.swift | 16 +- .../Sources/JavaDependencySample/main.swift | 8 +- Samples/JavaKitSampleApp/Package.swift | 6 +- .../JavaKitExample/JavaKitExample.swift | 4 +- Samples/JavaProbablyPrime/Package.swift | 4 +- .../Sources/JavaProbablyPrime/prime.swift | 2 +- Samples/JavaSieve/Package.swift | 8 +- .../JavaSieve/Sources/JavaSieve/main.swift | 2 +- .../Package.swift | 6 +- .../Sources/MySwiftLibrary/MySwiftClass.swift | 0 .../MySwiftLibrary/MySwiftLibrary.swift | 0 .../MySwiftLibrary/MySwiftStruct.swift | 0 .../jni/JNIImplementations.swift | 4 +- .../Sources/MySwiftLibrary/swift-java.config | 0 .../build.gradle | 0 .../ci-validate.sh | 0 .../gradle.properties | 0 .../gradlew | 0 .../gradlew.bat | 0 .../swiftkit/ffm/JavaToSwiftBenchmark.java | 0 .../swiftkit/ffm/StringPassingBenchmark.java | 0 .../com/example/swift/HelloJava2Swift.java | 0 .../com/example/swift/DataImportTest.java | 0 .../com/example/swift/MySwiftClassTest.java | 0 .../com/example/swift/MySwiftLibraryTest.java | 0 .../com/example/swift/OptionalImportTest.java | 0 .../example/swift/UnsignedNumbersTest.java | 0 .../swift/swiftkitffm/MySwiftClassTest.java | 0 .../swift/swiftkitffm/MySwiftStructTest.java | 0 .../org/swift/swiftkitffm/SwiftArenaTest.java | 0 .../Package.swift | 4 +- .../Sources/MySwiftLibrary/Alignment.swift | 0 .../Sources/MySwiftLibrary/Closures.swift | 0 .../Sources/MySwiftLibrary/MySwiftClass.swift | 2 +- .../MySwiftLibrary/MySwiftLibrary.swift | 0 .../MySwiftLibrary/MySwiftStruct.swift | 0 .../Sources/MySwiftLibrary/Optionals.swift | 2 +- .../Sources/MySwiftLibrary/Vehicle.swift | 0 .../Sources/MySwiftLibrary/swift-java.config | 0 .../build.gradle | 0 .../ci-validate.sh | 0 .../gradle.properties | 0 .../gradlew | 0 .../gradlew.bat | 0 .../com/example/swift/HelloJava2SwiftJNI.java | 0 .../com/example/swift/AlignmentEnumTest.java | 0 .../java/com/example/swift/ClosuresTest.java | 0 .../com/example/swift/MySwiftClassTest.java | 0 .../com/example/swift/MySwiftLibraryTest.java | 0 .../com/example/swift/MySwiftStructTest.java | 0 .../java/com/example/swift/OptionalsTest.java | 0 .../com/example/swift/VehicleEnumTest.java | 0 Sources/{JavaRuntime => CJNI}/dummy.c | 0 .../JavaRuntime.h => CJNI/include/CJNI.h} | 6 +- Sources/CJNI/include/module.modulemap | 4 + .../Common/TypeAnnotations.swift | 2 +- .../Configuration+Extensions.swift | 4 +- .../Convenience/String+Extensions.swift | 2 +- ...MSwift2JavaGenerator+JavaTranslation.swift | 2 +- .../FFM/FFMSwift2JavaGenerator.swift | 2 +- .../JNI/JNIJavaTypeTranslator.swift | 2 +- ...ISwift2JavaGenerator+JavaTranslation.swift | 2 +- ...wift2JavaGenerator+NativeTranslation.swift | 2 +- ...ift2JavaGenerator+SwiftThunkPrinting.swift | 4 +- .../JNI/JNISwift2JavaGenerator.swift | 2 +- Sources/JExtractSwiftLib/Logger.swift | 4 +- Sources/JExtractSwiftLib/Swift2Java.swift | 4 +- .../Swift2JavaTranslator.swift | 2 +- .../JExtractSwiftLib/Swift2JavaVisitor.swift | 2 +- .../DependencyResolver.swift | 6 +- .../swift-java.config | 2 +- Sources/JavaRuntime/include/module.modulemap | 4 - .../generated/BufferedInputStream.swift | 4 +- .../JavaIO}/generated/Charset.swift | 4 +- .../JavaIO}/generated/Closeable.swift | 4 +- .../JavaIO}/generated/File.swift | 4 +- .../JavaIO}/generated/FileDescriptor.swift | 4 +- .../JavaIO}/generated/FileReader.swift | 4 +- .../JavaIO}/generated/Flushable.swift | 4 +- .../JavaIO}/generated/InputStream.swift | 4 +- .../JavaIO}/generated/InputStreamReader.swift | 4 +- .../JavaIO}/generated/OutputStream.swift | 4 +- .../JavaIO}/generated/Path.swift | 4 +- .../JavaIO}/generated/Readable.swift | 4 +- .../JavaIO}/generated/Reader.swift | 4 +- .../JavaIO}/generated/StringReader.swift | 4 +- .../JavaIO}/generated/WatchService.swift | 4 +- .../JavaIO}/generated/Writer.swift | 4 +- .../JavaIO}/swift-java.config | 0 .../Constructor+Utilities.swift | 0 .../Executable+Utilities.swift | 2 +- .../JavaLangReflect}/Field+Utilities.swift | 0 .../JavaClass+Reflection.swift | 2 +- .../JavaLangReflect}/Method+Utilities.swift | 0 .../generated/AccessibleObject.swift | 4 +- .../generated/AnnotatedType.swift | 4 +- .../generated/Annotation.swift | 4 +- .../generated/Constructor.swift | 4 +- .../generated/Executable.swift | 6 +- .../JavaLangReflect}/generated/Field.swift | 6 +- .../generated/GenericArrayType.swift | 4 +- .../generated/GenericDeclaration.swift | 4 +- .../JavaLangReflect}/generated/Method.swift | 4 +- .../generated/Parameter.swift | 6 +- .../generated/ParameterizedType.swift | 4 +- .../JavaLangReflect}/generated/Type.swift | 4 +- .../generated/TypeVariable.swift | 4 +- .../generated/WildcardType.swift | 4 +- .../JavaLangReflect}/swift-java.config | 0 .../JavaNet}/generated/URI.swift | 4 +- .../JavaNet}/generated/URL.swift | 4 +- .../JavaNet}/generated/URLClassLoader.swift | 6 +- .../JavaNet}/generated/URLConnection.swift | 4 +- .../JavaNet}/swift-java.config | 0 .../JavaUtil}/JavaEnumeration+Sequence.swift | 0 .../JavaUtil}/JavaIterator+Iterator.swift | 2 +- .../JavaUtil}/List+Sequence.swift | 0 .../JavaUtil}/generated/ArrayDeque.swift | 4 +- .../JavaUtil}/generated/ArrayList.swift | 4 +- .../JavaUtil}/generated/BitSet.swift | 4 +- .../JavaUtil}/generated/Enumeration.swift | 4 +- .../JavaUtil}/generated/HashMap.swift | 4 +- .../JavaUtil}/generated/HashSet.swift | 4 +- .../JavaUtil}/generated/JavaCollection.swift | 4 +- .../JavaUtil}/generated/JavaDictionary.swift | 4 +- .../JavaUtil}/generated/JavaIterator.swift | 4 +- .../JavaUtil}/generated/JavaSet.swift | 4 +- .../JavaUtil}/generated/LinkedList.swift | 4 +- .../JavaUtil}/generated/List.swift | 4 +- .../JavaUtil}/generated/ListIterator.swift | 4 +- .../JavaUtil}/generated/PriorityQueue.swift | 4 +- .../JavaUtil}/generated/Queue.swift | 4 +- .../JavaUtil}/generated/RandomAccess.swift | 4 +- .../JavaUtil}/generated/Stack.swift | 4 +- .../JavaUtil}/generated/TreeMap.swift | 4 +- .../JavaUtil}/generated/TreeSet.swift | 4 +- .../JavaUtil}/swift-java.config | 0 .../generated/JavaBiConsumer.swift | 4 +- .../generated/JavaBiFunction.swift | 4 +- .../generated/JavaBiPredicate.swift | 4 +- .../generated/JavaBinaryOperator.swift | 4 +- .../generated/JavaBooleanSupplier.swift | 4 +- .../generated/JavaConsumer.swift | 4 +- .../generated/JavaDoubleBinaryOperator.swift | 4 +- .../generated/JavaDoubleConsumer.swift | 4 +- .../generated/JavaDoubleFunction.swift | 4 +- .../generated/JavaDoublePredicate.swift | 4 +- .../generated/JavaDoubleSupplier.swift | 4 +- .../generated/JavaDoubleToIntFunction.swift | 4 +- .../generated/JavaDoubleToLongFunction.swift | 4 +- .../generated/JavaDoubleUnaryOperator.swift | 4 +- .../generated/JavaFunction.swift | 4 +- .../generated/JavaIntBinaryOperator.swift | 4 +- .../generated/JavaIntConsumer.swift | 4 +- .../generated/JavaIntFunction.swift | 4 +- .../generated/JavaIntPredicate.swift | 4 +- .../generated/JavaIntSupplier.swift | 4 +- .../generated/JavaIntToDoubleFunction.swift | 4 +- .../generated/JavaIntToLongFunction.swift | 4 +- .../generated/JavaIntUnaryOperator.swift | 4 +- .../generated/JavaLongBinaryOperator.swift | 4 +- .../generated/JavaLongConsumer.swift | 4 +- .../generated/JavaLongFunction.swift | 4 +- .../generated/JavaLongPredicate.swift | 4 +- .../generated/JavaLongSupplier.swift | 4 +- .../generated/JavaLongToDoubleFunction.swift | 4 +- .../generated/JavaLongToIntFunction.swift | 4 +- .../generated/JavaLongUnaryOperator.swift | 4 +- .../generated/JavaObjDoubleConsumer.swift | 4 +- .../generated/JavaObjIntConsumer.swift | 4 +- .../generated/JavaObjLongConsumer.swift | 4 +- .../generated/JavaPredicate.swift | 4 +- .../generated/JavaSupplier.swift | 4 +- .../generated/JavaToDoubleBiFunction.swift | 4 +- .../generated/JavaToDoubleFunction.swift | 4 +- .../generated/JavaToIntBiFunction.swift | 4 +- .../generated/JavaToIntFunction.swift | 4 +- .../generated/JavaToLongBiFunction.swift | 4 +- .../generated/JavaToLongFunction.swift | 4 +- .../generated/JavaUnaryOperator.swift | 4 +- .../JavaUtilFunction}/swift-java.config | 0 .../JavaUtilJar}/generated/Attributes.swift | 6 +- .../JavaUtilJar}/generated/JarEntry.swift | 4 +- .../JavaUtilJar}/generated/JarFile.swift | 6 +- .../generated/JarInputStream.swift | 4 +- .../generated/JarOutputStream.swift | 4 +- .../JavaUtilJar}/generated/Manifest.swift | 4 +- .../JavaUtilJar}/generated/ZipEntry.swift | 4 +- .../JavaUtilJar}/swift-java.config | 0 .../JavaStdlib/README_PACKAGE_CONVENTION.md | 13 ++ .../AnyJavaObject.swift | 2 +- .../BridgedValues/JavaValue+Array.swift | 0 .../BridgedValues/JavaValue+Bool.swift | 0 .../JavaValue+FloatingPoint.swift | 0 .../BridgedValues/JavaValue+Integers.swift | 0 .../BridgedValues/JavaValue+String.swift | 0 .../Documentation.docc/JavaKit.md | 2 +- .../Exceptions/Exception+Error.swift | 0 .../Exceptions/ExceptionHandling.swift | 0 .../Exceptions/Throwable+Error.swift | 0 .../SwiftJava/Helpers/_JNIMethodIDCache.swift | 59 ++++++++ .../JavaClass+Initialization.swift | 2 +- .../JavaEnvironment.swift | 2 +- .../JavaKitVM/JavaVirtualMachine.swift | 0 .../JavaKitVM/LockedState.swift | 0 .../JavaKitVM/ThreadLocalStorage.swift | 0 .../JavaObject+Inheritance.swift | 2 +- .../JavaObject+MethodCalls.swift | 2 +- .../JavaObjectHolder.swift | 2 +- .../JavaRuntime+Reexport.swift | 2 +- .../{JavaKit => SwiftJava}/JavaValue.swift | 2 +- Sources/{JavaKit => SwiftJava}/Macros.swift | 14 +- .../Optional+JavaObject.swift | 2 +- .../Optional+JavaOptional.swift | 0 .../generated/Appendable.swift | 2 +- .../generated/CharSequence.swift | 2 +- .../generated/Exception.swift | 2 +- .../generated/JavaArray.swift | 2 +- .../generated/JavaBoolean.swift | 2 +- .../generated/JavaByte.swift | 2 +- .../generated/JavaCharacter.swift | 2 +- .../generated/JavaClass.swift | 2 +- .../generated/JavaClassLoader.swift | 2 +- .../generated/JavaDouble.swift | 2 +- .../generated/JavaError.swift | 2 +- .../generated/JavaFloat.swift | 2 +- .../generated/JavaInteger.swift | 2 +- .../generated/JavaLong.swift | 2 +- .../generated/JavaNumber.swift | 2 +- .../generated/JavaObject.swift | 2 +- .../generated/JavaOptional.swift | 2 +- .../generated/JavaOptionalDouble.swift | 2 +- .../generated/JavaOptionalInt.swift | 2 +- .../generated/JavaOptionalLong.swift | 2 +- .../generated/JavaShort.swift | 2 +- .../generated/JavaString.swift | 2 +- .../generated/JavaVoid.swift | 2 +- .../generated/RuntimeException.swift | 2 +- .../generated/Throwable.swift | 2 +- .../{JavaKit => SwiftJava}/swift-java.config | 0 .../Configuration.swift | 0 .../GenerationMode.swift | 0 .../GradleDependencyParsing.swift | 0 .../SwiftJavaCommandLineTool.md | 8 +- .../GenerationMode.swift | 0 .../ImplementsJavaMacro.swift | 0 .../JavaClassMacro.swift | 0 .../JavaFieldMacro.swift | 0 .../JavaMethodMacro.swift | 0 .../MacroErrors.swift | 0 .../SwiftJNIMacrosPlugin.swift} | 2 +- .../SwiftSyntaxUtils.swift | 0 .../TerminalColors.swift | 0 .../Commands/ConfigureCommand.swift | 14 +- .../Commands/JExtractCommand.swift | 12 +- .../Commands/ResolveCommand.swift | 14 +- .../Commands/WrapJavaCommand.swift | 10 +- Sources/SwiftJavaTool/CommonOptions.swift | 12 +- .../SwiftJavaTool/Java/JavaClassLoader.swift | 8 +- Sources/SwiftJavaTool/String+Extensions.swift | 10 +- Sources/SwiftJavaTool/SwiftJava.swift | 14 +- .../SwiftJavaBaseAsyncParsableCommand.swift | 14 +- .../JavaClassTranslator.swift | 4 +- .../JavaTranslator+Configuration.swift | 2 +- .../JavaTranslator+Validation.swift | 0 .../JavaTranslator.swift | 12 +- .../MethodVariance.swift | 4 +- .../OptionalKind.swift | 0 .../StringExtras.swift | 0 .../TranslationError.swift | 2 +- .../swiftkit/ffm/FFMSwiftInstanceCleanup.java | 4 +- .../org/swift/swiftkit/ffm/SwiftRuntime.java | 27 ++++ .../Asserts/LoweringAssertions.swift | 2 +- .../Asserts/TextAssertions.swift | 2 +- .../FuncCallbackImportTests.swift | 2 +- .../FunctionDescriptorImportTests.swift | 2 +- .../InternalExtractTests.swift | 2 +- .../JNI/JNIUnsignedNumberTests.swift | 2 +- .../MemoryManagementModeTests.swift | 2 +- .../MethodImportTests.swift | 2 +- .../UnsignedNumberTests.swift | 2 +- .../GradleDependencyParsingTests.swift | 2 +- .../JavaClassMacroTests.swift | 2 +- .../BasicRuntimeTests.swift | 4 +- .../Java2SwiftTests.swift | 90 ++++++------ .../JavaTranslatorValidationTests.swift | 2 +- 296 files changed, 641 insertions(+), 527 deletions(-) delete mode 120000 Plugins/PluginsShared/JavaKitConfigurationShared create mode 120000 Plugins/PluginsShared/SwiftJavaConfigurationShared rename Samples/{SwiftKitSampleApp => SwiftJavaExtractFFMSampleApp}/Package.swift (93%) rename Samples/{SwiftKitSampleApp => SwiftJavaExtractFFMSampleApp}/Sources/MySwiftLibrary/MySwiftClass.swift (100%) rename Samples/{SwiftKitSampleApp => SwiftJavaExtractFFMSampleApp}/Sources/MySwiftLibrary/MySwiftLibrary.swift (100%) rename Samples/{SwiftKitSampleApp => SwiftJavaExtractFFMSampleApp}/Sources/MySwiftLibrary/MySwiftStruct.swift (100%) rename Samples/{SwiftKitSampleApp => SwiftJavaExtractFFMSampleApp}/Sources/MySwiftLibrary/jni/JNIImplementations.swift (97%) rename Samples/{SwiftKitSampleApp => SwiftJavaExtractFFMSampleApp}/Sources/MySwiftLibrary/swift-java.config (100%) rename Samples/{SwiftKitSampleApp => SwiftJavaExtractFFMSampleApp}/build.gradle (100%) rename Samples/{JExtractJNISampleApp => SwiftJavaExtractFFMSampleApp}/ci-validate.sh (100%) rename Samples/{JExtractJNISampleApp => SwiftJavaExtractFFMSampleApp}/gradle.properties (100%) rename Samples/{JExtractJNISampleApp => SwiftJavaExtractFFMSampleApp}/gradlew (100%) rename Samples/{JExtractJNISampleApp => SwiftJavaExtractFFMSampleApp}/gradlew.bat (100%) rename Samples/{SwiftKitSampleApp => SwiftJavaExtractFFMSampleApp}/src/jmh/java/org/swift/swiftkit/ffm/JavaToSwiftBenchmark.java (100%) rename Samples/{SwiftKitSampleApp => SwiftJavaExtractFFMSampleApp}/src/jmh/java/org/swift/swiftkit/ffm/StringPassingBenchmark.java (100%) rename Samples/{SwiftKitSampleApp => SwiftJavaExtractFFMSampleApp}/src/main/java/com/example/swift/HelloJava2Swift.java (100%) rename Samples/{SwiftKitSampleApp => SwiftJavaExtractFFMSampleApp}/src/test/java/com/example/swift/DataImportTest.java (100%) rename Samples/{SwiftKitSampleApp => SwiftJavaExtractFFMSampleApp}/src/test/java/com/example/swift/MySwiftClassTest.java (100%) rename Samples/{SwiftKitSampleApp => SwiftJavaExtractFFMSampleApp}/src/test/java/com/example/swift/MySwiftLibraryTest.java (100%) rename Samples/{SwiftKitSampleApp => SwiftJavaExtractFFMSampleApp}/src/test/java/com/example/swift/OptionalImportTest.java (100%) rename Samples/{SwiftKitSampleApp => SwiftJavaExtractFFMSampleApp}/src/test/java/com/example/swift/UnsignedNumbersTest.java (100%) rename Samples/{SwiftKitSampleApp => SwiftJavaExtractFFMSampleApp}/src/test/java/org/swift/swiftkitffm/MySwiftClassTest.java (100%) rename Samples/{SwiftKitSampleApp => SwiftJavaExtractFFMSampleApp}/src/test/java/org/swift/swiftkitffm/MySwiftStructTest.java (100%) rename Samples/{SwiftKitSampleApp => SwiftJavaExtractFFMSampleApp}/src/test/java/org/swift/swiftkitffm/SwiftArenaTest.java (100%) rename Samples/{JExtractJNISampleApp => SwiftJavaExtractJNISampleApp}/Package.swift (94%) rename Samples/{JExtractJNISampleApp => SwiftJavaExtractJNISampleApp}/Sources/MySwiftLibrary/Alignment.swift (100%) rename Samples/{JExtractJNISampleApp => SwiftJavaExtractJNISampleApp}/Sources/MySwiftLibrary/Closures.swift (100%) rename Samples/{JExtractJNISampleApp => SwiftJavaExtractJNISampleApp}/Sources/MySwiftLibrary/MySwiftClass.swift (99%) rename Samples/{JExtractJNISampleApp => SwiftJavaExtractJNISampleApp}/Sources/MySwiftLibrary/MySwiftLibrary.swift (100%) rename Samples/{JExtractJNISampleApp => SwiftJavaExtractJNISampleApp}/Sources/MySwiftLibrary/MySwiftStruct.swift (100%) rename Samples/{JExtractJNISampleApp => SwiftJavaExtractJNISampleApp}/Sources/MySwiftLibrary/Optionals.swift (99%) rename Samples/{JExtractJNISampleApp => SwiftJavaExtractJNISampleApp}/Sources/MySwiftLibrary/Vehicle.swift (100%) rename Samples/{JExtractJNISampleApp => SwiftJavaExtractJNISampleApp}/Sources/MySwiftLibrary/swift-java.config (100%) rename Samples/{JExtractJNISampleApp => SwiftJavaExtractJNISampleApp}/build.gradle (100%) rename Samples/{SwiftKitSampleApp => SwiftJavaExtractJNISampleApp}/ci-validate.sh (100%) rename Samples/{SwiftKitSampleApp => SwiftJavaExtractJNISampleApp}/gradle.properties (100%) rename Samples/{SwiftKitSampleApp => SwiftJavaExtractJNISampleApp}/gradlew (100%) rename Samples/{SwiftKitSampleApp => SwiftJavaExtractJNISampleApp}/gradlew.bat (100%) rename Samples/{JExtractJNISampleApp => SwiftJavaExtractJNISampleApp}/src/main/java/com/example/swift/HelloJava2SwiftJNI.java (100%) rename Samples/{JExtractJNISampleApp => SwiftJavaExtractJNISampleApp}/src/test/java/com/example/swift/AlignmentEnumTest.java (100%) rename Samples/{JExtractJNISampleApp => SwiftJavaExtractJNISampleApp}/src/test/java/com/example/swift/ClosuresTest.java (100%) rename Samples/{JExtractJNISampleApp => SwiftJavaExtractJNISampleApp}/src/test/java/com/example/swift/MySwiftClassTest.java (100%) rename Samples/{JExtractJNISampleApp => SwiftJavaExtractJNISampleApp}/src/test/java/com/example/swift/MySwiftLibraryTest.java (100%) rename Samples/{JExtractJNISampleApp => SwiftJavaExtractJNISampleApp}/src/test/java/com/example/swift/MySwiftStructTest.java (100%) rename Samples/{JExtractJNISampleApp => SwiftJavaExtractJNISampleApp}/src/test/java/com/example/swift/OptionalsTest.java (100%) rename Samples/{JExtractJNISampleApp => SwiftJavaExtractJNISampleApp}/src/test/java/com/example/swift/VehicleEnumTest.java (100%) rename Sources/{JavaRuntime => CJNI}/dummy.c (100%) rename Sources/{JavaRuntime/include/JavaRuntime.h => CJNI/include/CJNI.h} (85%) create mode 100644 Sources/CJNI/include/module.modulemap delete mode 100644 Sources/JavaRuntime/include/module.modulemap rename Sources/{JavaKitIO => JavaStdlib/JavaIO}/generated/BufferedInputStream.swift (96%) rename Sources/{JavaKitIO => JavaStdlib/JavaIO}/generated/Charset.swift (96%) rename Sources/{JavaKitIO => JavaStdlib/JavaIO}/generated/Closeable.swift (82%) rename Sources/{JavaKitIO => JavaStdlib/JavaIO}/generated/File.swift (98%) rename Sources/{JavaKitIO => JavaStdlib/JavaIO}/generated/FileDescriptor.swift (94%) rename Sources/{JavaKitIO => JavaStdlib/JavaIO}/generated/FileReader.swift (95%) rename Sources/{JavaKitIO => JavaStdlib/JavaIO}/generated/Flushable.swift (82%) rename Sources/{JavaKitIO => JavaStdlib/JavaIO}/generated/InputStream.swift (97%) rename Sources/{JavaKitIO => JavaStdlib/JavaIO}/generated/InputStreamReader.swift (96%) rename Sources/{JavaKitIO => JavaStdlib/JavaIO}/generated/OutputStream.swift (95%) rename Sources/{JavaKitIO => JavaStdlib/JavaIO}/generated/Path.swift (98%) rename Sources/{JavaKitIO => JavaStdlib/JavaIO}/generated/Readable.swift (77%) rename Sources/{JavaKitIO => JavaStdlib/JavaIO}/generated/Reader.swift (96%) rename Sources/{JavaKitIO => JavaStdlib/JavaIO}/generated/StringReader.swift (95%) rename Sources/{JavaKitIO => JavaStdlib/JavaIO}/generated/WatchService.swift (85%) rename Sources/{JavaKitIO => JavaStdlib/JavaIO}/generated/Writer.swift (97%) rename Sources/{JavaKitIO => JavaStdlib/JavaIO}/swift-java.config (100%) rename Sources/{JavaKitReflection => JavaStdlib/JavaLangReflect}/Constructor+Utilities.swift (100%) rename Sources/{JavaKitReflection => JavaStdlib/JavaLangReflect}/Executable+Utilities.swift (98%) rename Sources/{JavaKitReflection => JavaStdlib/JavaLangReflect}/Field+Utilities.swift (100%) rename Sources/{JavaKitReflection => JavaStdlib/JavaLangReflect}/JavaClass+Reflection.swift (98%) rename Sources/{JavaKitReflection => JavaStdlib/JavaLangReflect}/Method+Utilities.swift (100%) rename Sources/{JavaKitReflection => JavaStdlib/JavaLangReflect}/generated/AccessibleObject.swift (97%) rename Sources/{JavaKitReflection => JavaStdlib/JavaLangReflect}/generated/AnnotatedType.swift (96%) rename Sources/{JavaKitReflection => JavaStdlib/JavaLangReflect}/generated/Annotation.swift (91%) rename Sources/{JavaKitReflection => JavaStdlib/JavaLangReflect}/generated/Constructor.swift (98%) rename Sources/{JavaKitReflection => JavaStdlib/JavaLangReflect}/generated/Executable.swift (96%) rename Sources/{JavaKitReflection => JavaStdlib/JavaLangReflect}/generated/Field.swift (97%) rename Sources/{JavaKitReflection => JavaStdlib/JavaLangReflect}/generated/GenericArrayType.swift (89%) rename Sources/{JavaKitReflection => JavaStdlib/JavaLangReflect}/generated/GenericDeclaration.swift (96%) rename Sources/{JavaKitReflection => JavaStdlib/JavaLangReflect}/generated/Method.swift (98%) rename Sources/{JavaKitReflection => JavaStdlib/JavaLangReflect}/generated/Parameter.swift (95%) rename Sources/{JavaKitReflection => JavaStdlib/JavaLangReflect}/generated/ParameterizedType.swift (91%) rename Sources/{JavaKitReflection => JavaStdlib/JavaLangReflect}/generated/Type.swift (83%) rename Sources/{JavaKitReflection => JavaStdlib/JavaLangReflect}/generated/TypeVariable.swift (96%) rename Sources/{JavaKitReflection => JavaStdlib/JavaLangReflect}/generated/WildcardType.swift (90%) rename Sources/{JavaKitReflection => JavaStdlib/JavaLangReflect}/swift-java.config (100%) rename Sources/{JavaKitNetwork => JavaStdlib/JavaNet}/generated/URI.swift (98%) rename Sources/{JavaKitNetwork => JavaStdlib/JavaNet}/generated/URL.swift (97%) rename Sources/{JavaKitNetwork => JavaStdlib/JavaNet}/generated/URLClassLoader.swift (93%) rename Sources/{JavaKitNetwork => JavaStdlib/JavaNet}/generated/URLConnection.swift (99%) rename Sources/{JavaKitNetwork => JavaStdlib/JavaNet}/swift-java.config (100%) rename Sources/{JavaKitCollection => JavaStdlib/JavaUtil}/JavaEnumeration+Sequence.swift (100%) rename Sources/{JavaKitCollection => JavaStdlib/JavaUtil}/JavaIterator+Iterator.swift (97%) rename Sources/{JavaKitCollection => JavaStdlib/JavaUtil}/List+Sequence.swift (100%) rename Sources/{JavaKitCollection => JavaStdlib/JavaUtil}/generated/ArrayDeque.swift (98%) rename Sources/{JavaKitCollection => JavaStdlib/JavaUtil}/generated/ArrayList.swift (98%) rename Sources/{JavaKitCollection => JavaStdlib/JavaUtil}/generated/BitSet.swift (98%) rename Sources/{JavaKitCollection => JavaStdlib/JavaUtil}/generated/Enumeration.swift (90%) rename Sources/{JavaKitCollection => JavaStdlib/JavaUtil}/generated/HashMap.swift (98%) rename Sources/{JavaKitCollection => JavaStdlib/JavaUtil}/generated/HashSet.swift (97%) rename Sources/{JavaKitCollection => JavaStdlib/JavaUtil}/generated/JavaCollection.swift (97%) rename Sources/{JavaKitCollection => JavaStdlib/JavaUtil}/generated/JavaDictionary.swift (95%) rename Sources/{JavaKitCollection => JavaStdlib/JavaUtil}/generated/JavaIterator.swift (89%) rename Sources/{JavaKitCollection => JavaStdlib/JavaUtil}/generated/JavaSet.swift (99%) rename Sources/{JavaKitCollection => JavaStdlib/JavaUtil}/generated/LinkedList.swift (99%) rename Sources/{JavaKitCollection => JavaStdlib/JavaUtil}/generated/List.swift (99%) rename Sources/{JavaKitCollection => JavaStdlib/JavaUtil}/generated/ListIterator.swift (94%) rename Sources/{JavaKitCollection => JavaStdlib/JavaUtil}/generated/PriorityQueue.swift (97%) rename Sources/{JavaKitCollection => JavaStdlib/JavaUtil}/generated/Queue.swift (97%) rename Sources/{JavaKitCollection => JavaStdlib/JavaUtil}/generated/RandomAccess.swift (79%) rename Sources/{JavaKitCollection => JavaStdlib/JavaUtil}/generated/Stack.swift (93%) rename Sources/{JavaKitCollection => JavaStdlib/JavaUtil}/generated/TreeMap.swift (98%) rename Sources/{JavaKitCollection => JavaStdlib/JavaUtil}/generated/TreeSet.swift (97%) rename Sources/{JavaKitCollection => JavaStdlib/JavaUtil}/swift-java.config (100%) rename Sources/{JavaKitFunction => JavaStdlib/JavaUtilFunction}/generated/JavaBiConsumer.swift (91%) rename Sources/{JavaKitFunction => JavaStdlib/JavaUtilFunction}/generated/JavaBiFunction.swift (92%) rename Sources/{JavaKitFunction => JavaStdlib/JavaUtilFunction}/generated/JavaBiPredicate.swift (94%) rename Sources/{JavaKitFunction => JavaStdlib/JavaUtilFunction}/generated/JavaBinaryOperator.swift (93%) rename Sources/{JavaKitFunction => JavaStdlib/JavaUtilFunction}/generated/JavaBooleanSupplier.swift (85%) rename Sources/{JavaKitFunction => JavaStdlib/JavaUtilFunction}/generated/JavaConsumer.swift (90%) rename Sources/{JavaKitFunction => JavaStdlib/JavaUtilFunction}/generated/JavaDoubleBinaryOperator.swift (87%) rename Sources/{JavaKitFunction => JavaStdlib/JavaUtilFunction}/generated/JavaDoubleConsumer.swift (89%) rename Sources/{JavaKitFunction => JavaStdlib/JavaUtilFunction}/generated/JavaDoubleFunction.swift (86%) rename Sources/{JavaKitFunction => JavaStdlib/JavaUtilFunction}/generated/JavaDoublePredicate.swift (92%) rename Sources/{JavaKitFunction => JavaStdlib/JavaUtilFunction}/generated/JavaDoubleSupplier.swift (85%) rename Sources/{JavaKitFunction => JavaStdlib/JavaUtilFunction}/generated/JavaDoubleToIntFunction.swift (86%) rename Sources/{JavaKitFunction => JavaStdlib/JavaUtilFunction}/generated/JavaDoubleToLongFunction.swift (86%) rename Sources/{JavaKitFunction => JavaStdlib/JavaUtilFunction}/generated/JavaDoubleUnaryOperator.swift (94%) rename Sources/{JavaKitFunction => JavaStdlib/JavaUtilFunction}/generated/JavaFunction.swift (95%) rename Sources/{JavaKitFunction => JavaStdlib/JavaUtilFunction}/generated/JavaIntBinaryOperator.swift (87%) rename Sources/{JavaKitFunction => JavaStdlib/JavaUtilFunction}/generated/JavaIntConsumer.swift (88%) rename Sources/{JavaKitFunction => JavaStdlib/JavaUtilFunction}/generated/JavaIntFunction.swift (86%) rename Sources/{JavaKitFunction => JavaStdlib/JavaUtilFunction}/generated/JavaIntPredicate.swift (92%) rename Sources/{JavaKitFunction => JavaStdlib/JavaUtilFunction}/generated/JavaIntSupplier.swift (84%) rename Sources/{JavaKitFunction => JavaStdlib/JavaUtilFunction}/generated/JavaIntToDoubleFunction.swift (86%) rename Sources/{JavaKitFunction => JavaStdlib/JavaUtilFunction}/generated/JavaIntToLongFunction.swift (86%) rename Sources/{JavaKitFunction => JavaStdlib/JavaUtilFunction}/generated/JavaIntUnaryOperator.swift (93%) rename Sources/{JavaKitFunction => JavaStdlib/JavaUtilFunction}/generated/JavaLongBinaryOperator.swift (87%) rename Sources/{JavaKitFunction => JavaStdlib/JavaUtilFunction}/generated/JavaLongConsumer.swift (88%) rename Sources/{JavaKitFunction => JavaStdlib/JavaUtilFunction}/generated/JavaLongFunction.swift (86%) rename Sources/{JavaKitFunction => JavaStdlib/JavaUtilFunction}/generated/JavaLongPredicate.swift (92%) rename Sources/{JavaKitFunction => JavaStdlib/JavaUtilFunction}/generated/JavaLongSupplier.swift (84%) rename Sources/{JavaKitFunction => JavaStdlib/JavaUtilFunction}/generated/JavaLongToDoubleFunction.swift (86%) rename Sources/{JavaKitFunction => JavaStdlib/JavaUtilFunction}/generated/JavaLongToIntFunction.swift (86%) rename Sources/{JavaKitFunction => JavaStdlib/JavaUtilFunction}/generated/JavaLongUnaryOperator.swift (93%) rename Sources/{JavaKitFunction => JavaStdlib/JavaUtilFunction}/generated/JavaObjDoubleConsumer.swift (87%) rename Sources/{JavaKitFunction => JavaStdlib/JavaUtilFunction}/generated/JavaObjIntConsumer.swift (87%) rename Sources/{JavaKitFunction => JavaStdlib/JavaUtilFunction}/generated/JavaObjLongConsumer.swift (87%) rename Sources/{JavaKitFunction => JavaStdlib/JavaUtilFunction}/generated/JavaPredicate.swift (96%) rename Sources/{JavaKitFunction => JavaStdlib/JavaUtilFunction}/generated/JavaSupplier.swift (85%) rename Sources/{JavaKitFunction => JavaStdlib/JavaUtilFunction}/generated/JavaToDoubleBiFunction.swift (89%) rename Sources/{JavaKitFunction => JavaStdlib/JavaUtilFunction}/generated/JavaToDoubleFunction.swift (87%) rename Sources/{JavaKitFunction => JavaStdlib/JavaUtilFunction}/generated/JavaToIntBiFunction.swift (88%) rename Sources/{JavaKitFunction => JavaStdlib/JavaUtilFunction}/generated/JavaToIntFunction.swift (87%) rename Sources/{JavaKitFunction => JavaStdlib/JavaUtilFunction}/generated/JavaToLongBiFunction.swift (88%) rename Sources/{JavaKitFunction => JavaStdlib/JavaUtilFunction}/generated/JavaToLongFunction.swift (87%) rename Sources/{JavaKitFunction => JavaStdlib/JavaUtilFunction}/generated/JavaUnaryOperator.swift (95%) rename Sources/{JavaKitFunction => JavaStdlib/JavaUtilFunction}/swift-java.config (100%) rename Sources/{JavaKitJar => JavaStdlib/JavaUtilJar}/generated/Attributes.swift (98%) rename Sources/{JavaKitJar => JavaStdlib/JavaUtilJar}/generated/JarEntry.swift (98%) rename Sources/{JavaKitJar => JavaStdlib/JavaUtilJar}/generated/JarFile.swift (98%) rename Sources/{JavaKitJar => JavaStdlib/JavaUtilJar}/generated/JarInputStream.swift (98%) rename Sources/{JavaKitJar => JavaStdlib/JavaUtilJar}/generated/JarOutputStream.swift (98%) rename Sources/{JavaKitJar => JavaStdlib/JavaUtilJar}/generated/Manifest.swift (95%) rename Sources/{JavaKitJar => JavaStdlib/JavaUtilJar}/generated/ZipEntry.swift (99%) rename Sources/{JavaKitJar => JavaStdlib/JavaUtilJar}/swift-java.config (100%) create mode 100644 Sources/JavaStdlib/README_PACKAGE_CONVENTION.md rename Sources/{JavaKit => SwiftJava}/AnyJavaObject.swift (99%) rename Sources/{JavaKit => SwiftJava}/BridgedValues/JavaValue+Array.swift (100%) rename Sources/{JavaKit => SwiftJava}/BridgedValues/JavaValue+Bool.swift (100%) rename Sources/{JavaKit => SwiftJava}/BridgedValues/JavaValue+FloatingPoint.swift (100%) rename Sources/{JavaKit => SwiftJava}/BridgedValues/JavaValue+Integers.swift (100%) rename Sources/{JavaKit => SwiftJava}/BridgedValues/JavaValue+String.swift (100%) rename Sources/{JavaKit => SwiftJava}/Documentation.docc/JavaKit.md (99%) rename Sources/{JavaKit => SwiftJava}/Exceptions/Exception+Error.swift (100%) rename Sources/{JavaKit => SwiftJava}/Exceptions/ExceptionHandling.swift (100%) rename Sources/{JavaKit => SwiftJava}/Exceptions/Throwable+Error.swift (100%) create mode 100644 Sources/SwiftJava/Helpers/_JNIMethodIDCache.swift rename Sources/{JavaKit => SwiftJava}/JavaClass+Initialization.swift (98%) rename Sources/{JavaKit => SwiftJava}/JavaEnvironment.swift (97%) rename Sources/{JavaKit => SwiftJava}/JavaKitVM/JavaVirtualMachine.swift (100%) rename Sources/{JavaKit => SwiftJava}/JavaKitVM/LockedState.swift (100%) rename Sources/{JavaKit => SwiftJava}/JavaKitVM/ThreadLocalStorage.swift (100%) rename Sources/{JavaKit => SwiftJava}/JavaObject+Inheritance.swift (98%) rename Sources/{JavaKit => SwiftJava}/JavaObject+MethodCalls.swift (99%) rename Sources/{JavaKit => SwiftJava}/JavaObjectHolder.swift (98%) rename Sources/{JavaKit => SwiftJava}/JavaRuntime+Reexport.swift (94%) rename Sources/{JavaKit => SwiftJava}/JavaValue.swift (99%) rename Sources/{JavaKit => SwiftJava}/Macros.swift (90%) rename Sources/{JavaKit => SwiftJava}/Optional+JavaObject.swift (99%) rename Sources/{JavaKit => SwiftJava}/Optional+JavaOptional.swift (100%) rename Sources/{JavaKit => SwiftJava}/generated/Appendable.swift (95%) rename Sources/{JavaKit => SwiftJava}/generated/CharSequence.swift (96%) rename Sources/{JavaKit => SwiftJava}/generated/Exception.swift (96%) rename Sources/{JavaKit => SwiftJava}/generated/JavaArray.swift (99%) rename Sources/{JavaKit => SwiftJava}/generated/JavaBoolean.swift (98%) rename Sources/{JavaKit => SwiftJava}/generated/JavaByte.swift (99%) rename Sources/{JavaKit => SwiftJava}/generated/JavaCharacter.swift (99%) rename Sources/{JavaKit => SwiftJava}/generated/JavaClass.swift (99%) rename Sources/{JavaKit => SwiftJava}/generated/JavaClassLoader.swift (99%) rename Sources/{JavaKit => SwiftJava}/generated/JavaDouble.swift (99%) rename Sources/{JavaKit => SwiftJava}/generated/JavaError.swift (96%) rename Sources/{JavaKit => SwiftJava}/generated/JavaFloat.swift (99%) rename Sources/{JavaKit => SwiftJava}/generated/JavaInteger.swift (99%) rename Sources/{JavaKit => SwiftJava}/generated/JavaLong.swift (99%) rename Sources/{JavaKit => SwiftJava}/generated/JavaNumber.swift (96%) rename Sources/{JavaKit => SwiftJava}/generated/JavaObject.swift (97%) rename Sources/{JavaKit => SwiftJava}/generated/JavaOptional.swift (98%) rename Sources/{JavaKit => SwiftJava}/generated/JavaOptionalDouble.swift (98%) rename Sources/{JavaKit => SwiftJava}/generated/JavaOptionalInt.swift (97%) rename Sources/{JavaKit => SwiftJava}/generated/JavaOptionalLong.swift (97%) rename Sources/{JavaKit => SwiftJava}/generated/JavaShort.swift (99%) rename Sources/{JavaKit => SwiftJava}/generated/JavaString.swift (99%) rename Sources/{JavaKit => SwiftJava}/generated/JavaVoid.swift (92%) rename Sources/{JavaKit => SwiftJava}/generated/RuntimeException.swift (96%) rename Sources/{JavaKit => SwiftJava}/generated/Throwable.swift (98%) rename Sources/{JavaKit => SwiftJava}/swift-java.config (100%) rename Sources/{JavaKitConfigurationShared => SwiftJavaConfigurationShared}/Configuration.swift (100%) rename Sources/{JavaKitConfigurationShared => SwiftJavaConfigurationShared}/GenerationMode.swift (100%) rename Sources/{JavaKitConfigurationShared => SwiftJavaConfigurationShared}/GradleDependencyParsing.swift (100%) rename Sources/{JavaKitMacros => SwiftJavaMacros}/GenerationMode.swift (100%) rename Sources/{JavaKitMacros => SwiftJavaMacros}/ImplementsJavaMacro.swift (100%) rename Sources/{JavaKitMacros => SwiftJavaMacros}/JavaClassMacro.swift (100%) rename Sources/{JavaKitMacros => SwiftJavaMacros}/JavaFieldMacro.swift (100%) rename Sources/{JavaKitMacros => SwiftJavaMacros}/JavaMethodMacro.swift (100%) rename Sources/{JavaKitMacros => SwiftJavaMacros}/MacroErrors.swift (100%) rename Sources/{JavaKitMacros/JavaKitMacrosPlugin.swift => SwiftJavaMacros/SwiftJNIMacrosPlugin.swift} (93%) rename Sources/{JavaKitMacros => SwiftJavaMacros}/SwiftSyntaxUtils.swift (100%) rename Sources/{JavaKitShared => SwiftJavaShared}/TerminalColors.swift (100%) rename Sources/{SwiftJavaLib => SwiftJavaToolLib}/JavaClassTranslator.swift (99%) rename Sources/{SwiftJavaLib => SwiftJavaToolLib}/JavaTranslator+Configuration.swift (97%) rename Sources/{SwiftJavaLib => SwiftJavaToolLib}/JavaTranslator+Validation.swift (100%) rename Sources/{SwiftJavaLib => SwiftJavaToolLib}/JavaTranslator.swift (98%) rename Sources/{SwiftJavaLib => SwiftJavaToolLib}/MethodVariance.swift (98%) rename Sources/{SwiftJavaLib => SwiftJavaToolLib}/OptionalKind.swift (100%) rename Sources/{SwiftJavaLib => SwiftJavaToolLib}/StringExtras.swift (100%) rename Sources/{SwiftJavaLib => SwiftJavaToolLib}/TranslationError.swift (97%) rename Tests/{JavaKitConfigurationSharedTests => SwiftJavaConfigurationSharedTests}/GradleDependencyParsingTests.swift (97%) rename Tests/{JavaKitMacroTests => SwiftJavaMacrosTests}/JavaClassMacroTests.swift (99%) rename Tests/{JavaKitTests => SwiftJavaTests}/BasicRuntimeTests.swift (98%) rename Tests/{SwiftJavaTests => SwiftJavaToolLibTests}/Java2SwiftTests.swift (89%) rename Tests/{SwiftJavaTests => SwiftJavaToolLibTests}/JavaTranslatorValidationTests.swift (98%) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index b2d8ee7c..0a2b6949 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -166,8 +166,8 @@ jobs: 'JavaProbablyPrime', 'JavaSieve', 'SwiftAndJavaJarSampleLib', - 'SwiftKitSampleApp', - 'JExtractJNISampleApp', + 'SwiftJavaExtractFFMSampleApp', + 'SwiftJavaExtractJNISampleApp', ] container: image: ${{ (contains(matrix.swift_version, 'nightly') && 'swiftlang/swift') || 'swift' }}:${{ matrix.swift_version }}-${{ matrix.os_version }} @@ -194,8 +194,8 @@ jobs: 'JavaProbablyPrime', 'JavaSieve', 'SwiftAndJavaJarSampleLib', - 'SwiftKitSampleApp', - 'JExtractJNISampleApp', + 'SwiftJavaExtractFFMSampleApp', + 'SwiftJavaExtractJNISampleApp', ] steps: - uses: actions/checkout@v4 diff --git a/Benchmarks/Benchmarks/JavaApiCallBenchmarks/JavaApiCallBenchmarks.swift b/Benchmarks/Benchmarks/JavaApiCallBenchmarks/JavaApiCallBenchmarks.swift index 25c67074..d52d3133 100644 --- a/Benchmarks/Benchmarks/JavaApiCallBenchmarks/JavaApiCallBenchmarks.swift +++ b/Benchmarks/Benchmarks/JavaApiCallBenchmarks/JavaApiCallBenchmarks.swift @@ -14,8 +14,8 @@ import Benchmark import Foundation -import JavaKit -import JavaKitNetwork +import SwiftJava +import JavaNet @MainActor let benchmarks = { var jvm: JavaVirtualMachine { diff --git a/Benchmarks/Package.swift b/Benchmarks/Package.swift index b8fbe580..955378fc 100644 --- a/Benchmarks/Package.swift +++ b/Benchmarks/Package.swift @@ -51,9 +51,9 @@ let package = Package( .executableTarget( name: "JavaApiCallBenchmarks", dependencies: [ - .product(name: "JavaRuntime", package: "swift-java"), - .product(name: "JavaKit", package: "swift-java"), - .product(name: "JavaKitNetwork", package: "swift-java"), + .product(name: "CJNI", package: "swift-java"), + .product(name: "SwiftJava", package: "swift-java"), + .product(name: "JavaNet", package: "swift-java"), .product(name: "Benchmark", package: "package-benchmark"), ], path: "Benchmarks/JavaApiCallBenchmarks", diff --git a/Package.swift b/Package.swift index 65737b2b..a30b9510 100644 --- a/Package.swift +++ b/Package.swift @@ -94,45 +94,45 @@ let package = Package( .macOS(.v15) ], products: [ - // ==== JavaKit (i.e. calling Java directly Swift utilities) + // ==== SwiftJava (i.e. calling Java directly Swift utilities) .library( - name: "JavaKit", - targets: ["JavaKit"] + name: "SwiftJava", + targets: ["SwiftJava"] ), .library( - name: "JavaRuntime", - targets: ["JavaRuntime"] + name: "CJNI", + targets: ["CJNI"] ), .library( - name: "JavaKitCollection", - targets: ["JavaKitCollection"] + name: "JavaUtil", + targets: ["JavaUtil"] ), .library( - name: "JavaKitFunction", - targets: ["JavaKitFunction"] + name: "JavaUtilFunction", + targets: ["JavaUtilFunction"] ), .library( - name: "JavaKitJar", - targets: ["JavaKitJar"] + name: "JavaUtilJar", + targets: ["JavaUtilJar"] ), .library( - name: "JavaKitNetwork", - targets: ["JavaKitNetwork"] + name: "JavaNet", + targets: ["JavaNet"] ), .library( - name: "JavaKitIO", - targets: ["JavaKitIO"] + name: "JavaIO", + targets: ["JavaIO"] ), .library( - name: "JavaKitReflection", - targets: ["JavaKitReflection"] + name: "JavaLangReflect", + targets: ["JavaLangReflect"] ), .library( @@ -212,13 +212,13 @@ let package = Package( .target( name: "SwiftJavaDocumentation", dependencies: [ - "JavaKit", + "SwiftJava", "SwiftKitSwift", ] ), .macro( - name: "JavaKitMacros", + name: "SwiftJavaMacros", dependencies: [ .product(name: "SwiftSyntaxMacros", package: "swift-syntax"), .product(name: "SwiftCompilerPlugin", package: "swift-syntax"), @@ -235,12 +235,12 @@ let package = Package( ), .target( - name: "JavaKit", + name: "SwiftJava", dependencies: [ - "JavaRuntime", - "JavaKitMacros", + "CJNI", + "SwiftJavaMacros", "JavaTypes", - "JavaKitConfigurationShared", // for Configuration reading at runtime + "SwiftJavaConfigurationShared", // for Configuration reading at runtime ], exclude: ["swift-java.config"], swiftSettings: [ @@ -268,8 +268,9 @@ let package = Package( ] ), .target( - name: "JavaKitCollection", - dependencies: ["JavaKit"], + name: "JavaUtil", + dependencies: ["SwiftJava"], + path: "Sources/JavaStdlib/JavaUtil", exclude: ["swift-java.config"], swiftSettings: [ .swiftLanguageMode(.v5), @@ -277,8 +278,9 @@ let package = Package( ] ), .target( - name: "JavaKitFunction", - dependencies: ["JavaKit"], + name: "JavaUtilFunction", + dependencies: ["SwiftJava"], + path: "Sources/JavaStdlib/JavaUtilFunction", exclude: ["swift-java.config"], swiftSettings: [ .swiftLanguageMode(.v5), @@ -286,8 +288,9 @@ let package = Package( ] ), .target( - name: "JavaKitJar", - dependencies: ["JavaKit", "JavaKitCollection"], + name: "JavaUtilJar", + dependencies: ["SwiftJava", "JavaUtil"], + path: "Sources/JavaStdlib/JavaUtilJar", exclude: ["swift-java.config"], swiftSettings: [ .swiftLanguageMode(.v5), @@ -295,8 +298,9 @@ let package = Package( ] ), .target( - name: "JavaKitNetwork", - dependencies: ["JavaKit", "JavaKitCollection"], + name: "JavaNet", + dependencies: ["SwiftJava", "JavaUtil"], + path: "Sources/JavaStdlib/JavaNet", exclude: ["swift-java.config"], swiftSettings: [ .swiftLanguageMode(.v5), @@ -304,8 +308,9 @@ let package = Package( ] ), .target( - name: "JavaKitIO", - dependencies: ["JavaKit", "JavaKitCollection"], + name: "JavaIO", + dependencies: ["SwiftJava", "JavaUtil"], + path: "Sources/JavaStdlib/JavaIO", exclude: ["swift-java.config"], swiftSettings: [ .swiftLanguageMode(.v5), @@ -313,8 +318,9 @@ let package = Package( ] ), .target( - name: "JavaKitReflection", - dependencies: ["JavaKit", "JavaKitCollection"], + name: "JavaLangReflect", + dependencies: ["SwiftJava", "JavaUtil"], + path: "Sources/JavaStdlib/JavaLangReflect", exclude: ["swift-java.config"], swiftSettings: [ .swiftLanguageMode(.v5), @@ -353,7 +359,7 @@ let package = Package( ), .target( - name: "JavaRuntime", + name: "CJNI", swiftSettings: [ .swiftLanguageMode(.v5), .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) @@ -361,26 +367,26 @@ let package = Package( ), .target( - name: "JavaKitConfigurationShared" + name: "SwiftJavaConfigurationShared" ), .target( - name: "JavaKitShared" + name: "SwiftJavaShared" ), .target( - name: "SwiftJavaLib", + name: "SwiftJavaToolLib", dependencies: [ .product(name: "SwiftBasicFormat", package: "swift-syntax"), .product(name: "SwiftSyntax", package: "swift-syntax"), .product(name: "SwiftSyntaxBuilder", package: "swift-syntax"), - "JavaKit", - "JavaKitJar", - "JavaKitReflection", - "JavaKitNetwork", + "SwiftJava", + "JavaUtilJar", + "JavaLangReflect", + "JavaNet", "JavaTypes", - "JavaKitShared", - "JavaKitConfigurationShared", + "SwiftJavaShared", + "SwiftJavaConfigurationShared", // .product(name: "Subprocess", package: "swift-subprocess") "_Subprocess", ], @@ -399,13 +405,13 @@ let package = Package( .product(name: "SwiftSyntaxBuilder", package: "swift-syntax"), .product(name: "ArgumentParser", package: "swift-argument-parser"), .product(name: "SystemPackage", package: "swift-system"), - "JavaKit", - "JavaKitJar", - "JavaKitNetwork", - "SwiftJavaLib", + "SwiftJava", + "JavaUtilJar", + "JavaNet", + "SwiftJavaToolLib", "JExtractSwiftLib", - "JavaKitShared", - "JavaKitConfigurationShared", + "SwiftJavaShared", + "SwiftJavaConfigurationShared", ], swiftSettings: [ .swiftLanguageMode(.v5), @@ -427,8 +433,8 @@ let package = Package( .product(name: "SwiftSyntaxBuilder", package: "swift-syntax"), .product(name: "ArgumentParser", package: "swift-argument-parser"), "JavaTypes", - "JavaKitShared", - "JavaKitConfigurationShared", + "SwiftJavaShared", + "SwiftJavaConfigurationShared", ], swiftSettings: [ .swiftLanguageMode(.v5), @@ -445,8 +451,11 @@ let package = Package( ), .testTarget( - name: "JavaKitTests", - dependencies: ["JavaKit", "JavaKitNetwork"], + name: "SwiftJavaTests", + dependencies: [ + "SwiftJava", + "JavaNet" + ], swiftSettings: [ .swiftLanguageMode(.v5), .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) @@ -455,16 +464,18 @@ let package = Package( .testTarget( name: "JavaTypesTests", - dependencies: ["JavaTypes"], + dependencies: [ + "JavaTypes" + ], swiftSettings: [ .swiftLanguageMode(.v5) ] ), .testTarget( - name: "JavaKitMacroTests", + name: "SwiftJavaMacrosTests", dependencies: [ - "JavaKitMacros", + "SwiftJavaMacros", .product(name: "SwiftSyntaxMacrosTestSupport", package: "swift-syntax"), ], swiftSettings: [ @@ -473,8 +484,10 @@ let package = Package( ), .testTarget( - name: "SwiftJavaTests", - dependencies: ["SwiftJavaLib"], + name: "SwiftJavaToolLibTests", + dependencies: [ + "SwiftJavaToolLib" + ], swiftSettings: [ .swiftLanguageMode(.v5), .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) @@ -482,8 +495,8 @@ let package = Package( ), .testTarget( - name: "JavaKitConfigurationSharedTests", - dependencies: ["JavaKitConfigurationShared"], + name: "SwiftJavaConfigurationSharedTests", + dependencies: ["SwiftJavaConfigurationShared"], swiftSettings: [ .swiftLanguageMode(.v5), .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) diff --git a/Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift b/Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift index 2778cebe..49ed3c4d 100644 --- a/Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift +++ b/Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift @@ -43,7 +43,7 @@ struct JExtractSwiftBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin { let sourceDir = target.directory.string - // The name of the configuration file JavaKit.config from the target for + // The name of the configuration file SwiftJava.config from the target for // which we are generating Swift wrappers for Java classes. let configFile = URL(filePath: sourceDir).appending(path: "swift-java.config") let configuration = try readConfiguration(sourceDir: "\(sourceDir)") diff --git a/Plugins/JavaCompilerPlugin/JavaCompilerPlugin.swift b/Plugins/JavaCompilerPlugin/JavaCompilerPlugin.swift index 55955180..e12e13e8 100644 --- a/Plugins/JavaCompilerPlugin/JavaCompilerPlugin.swift +++ b/Plugins/JavaCompilerPlugin/JavaCompilerPlugin.swift @@ -32,7 +32,7 @@ struct JavaCompilerBuildToolPlugin: BuildToolPlugin { // so we cannot eliminate this deprecation warning. let sourceDir = target.directory.string - // The name of the configuration file JavaKit.config from the target for + // The name of the configuration file SwiftJava.config from the target for // which we are generating Swift wrappers for Java classes. let configFile = URL(filePath: sourceDir).appending(path: "swift-java.config") let config: Configuration? diff --git a/Plugins/PluginsShared/JavaKitConfigurationShared b/Plugins/PluginsShared/JavaKitConfigurationShared deleted file mode 120000 index d5c765df..00000000 --- a/Plugins/PluginsShared/JavaKitConfigurationShared +++ /dev/null @@ -1 +0,0 @@ -../../Sources/JavaKitConfigurationShared \ No newline at end of file diff --git a/Plugins/PluginsShared/SwiftJavaConfigurationShared b/Plugins/PluginsShared/SwiftJavaConfigurationShared new file mode 120000 index 00000000..2af5fd01 --- /dev/null +++ b/Plugins/PluginsShared/SwiftJavaConfigurationShared @@ -0,0 +1 @@ +../../Sources/SwiftJavaConfigurationShared \ No newline at end of file diff --git a/Plugins/SwiftJavaPlugin/SwiftJavaPlugin.swift b/Plugins/SwiftJavaPlugin/SwiftJavaPlugin.swift index cbbbe425..57641eff 100644 --- a/Plugins/SwiftJavaPlugin/SwiftJavaPlugin.swift +++ b/Plugins/SwiftJavaPlugin/SwiftJavaPlugin.swift @@ -34,7 +34,7 @@ struct SwiftJavaBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin { // so we cannot eliminate this deprecation warning. let sourceDir = target.directory.string - // The name of the configuration file JavaKit.config from the target for + // The name of the configuration file SwiftJava.config from the target for // which we are generating Swift wrappers for Java classes. let configFile = URL(filePath: sourceDir) .appending(path: SwiftJavaConfigFileName) diff --git a/README.md b/README.md index 940b478c..9f676905 100644 --- a/README.md +++ b/README.md @@ -184,7 +184,7 @@ To view the rendered docc documentation you can use the docc preview command: xcrun docc preview Sources/SwiftJavaDocumentation/Documentation.docc # OR JavaKit to view JavaKit documentation: -# xcrun docc preview Sources/JavaKit/Documentation.docc +# xcrun docc preview Sources/SwiftJNI/Documentation.docc # ======================================== # Starting Local Preview Server diff --git a/Samples/JavaDependencySampleApp/Package.swift b/Samples/JavaDependencySampleApp/Package.swift index 506b8c93..c5ae97c7 100644 --- a/Samples/JavaDependencySampleApp/Package.swift +++ b/Samples/JavaDependencySampleApp/Package.swift @@ -64,9 +64,9 @@ let package = Package( .executableTarget( name: "JavaDependencySample", dependencies: [ - .product(name: "JavaKit", package: "swift-java"), - .product(name: "JavaRuntime", package: "swift-java"), - .product(name: "JavaKitFunction", package: "swift-java"), + .product(name: "SwiftJava", package: "swift-java"), + .product(name: "CJNI", package: "swift-java"), + .product(name: "JavaUtilFunction", package: "swift-java"), "JavaCommonsCSV" ], exclude: ["swift-java.config"], @@ -82,11 +82,11 @@ let package = Package( .target( name: "JavaCommonsCSV", dependencies: [ - .product(name: "JavaKit", package: "swift-java"), - .product(name: "JavaKitFunction", package: "swift-java"), - .product(name: "JavaKitCollection", package: "swift-java"), - .product(name: "JavaKitIO", package: "swift-java"), - .product(name: "JavaKitNetwork", package: "swift-java"), + .product(name: "SwiftJava", package: "swift-java"), + .product(name: "JavaUtilFunction", package: "swift-java"), + .product(name: "JavaUtil", package: "swift-java"), + .product(name: "JavaIO", package: "swift-java"), + .product(name: "JavaNet", package: "swift-java"), ], exclude: ["swift-java.config"], swiftSettings: [ diff --git a/Samples/JavaDependencySampleApp/Sources/JavaDependencySample/main.swift b/Samples/JavaDependencySampleApp/Sources/JavaDependencySample/main.swift index c75cf553..13ea6eed 100644 --- a/Samples/JavaDependencySampleApp/Sources/JavaDependencySample/main.swift +++ b/Samples/JavaDependencySampleApp/Sources/JavaDependencySample/main.swift @@ -12,10 +12,10 @@ // //===----------------------------------------------------------------------===// -import JavaKit -import JavaKitFunction -import JavaKitIO -import JavaKitConfigurationShared +import SwiftJava +import JavaUtilFunction +import JavaIO +import SwiftJavaConfigurationShared import Foundation // Import the commons-csv library wrapper: diff --git a/Samples/JavaKitSampleApp/Package.swift b/Samples/JavaKitSampleApp/Package.swift index 1b545819..32451e92 100644 --- a/Samples/JavaKitSampleApp/Package.swift +++ b/Samples/JavaKitSampleApp/Package.swift @@ -65,9 +65,9 @@ let package = Package( .target( name: "JavaKitExample", dependencies: [ - .product(name: "JavaKit", package: "swift-java"), - .product(name: "JavaKitFunction", package: "swift-java"), - .product(name: "JavaKitJar", package: "swift-java"), + .product(name: "SwiftJava", package: "swift-java"), + .product(name: "JavaUtilFunction", package: "swift-java"), + .product(name: "JavaUtilJar", package: "swift-java"), ], swiftSettings: [ .swiftLanguageMode(.v5), diff --git a/Samples/JavaKitSampleApp/Sources/JavaKitExample/JavaKitExample.swift b/Samples/JavaKitSampleApp/Sources/JavaKitExample/JavaKitExample.swift index f074fee6..44f811d3 100644 --- a/Samples/JavaKitSampleApp/Sources/JavaKitExample/JavaKitExample.swift +++ b/Samples/JavaKitSampleApp/Sources/JavaKitExample/JavaKitExample.swift @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -import JavaKit -import JavaKitFunction +import SwiftJava +import JavaUtilFunction enum SwiftWrappedError: Error { case message(String) diff --git a/Samples/JavaProbablyPrime/Package.swift b/Samples/JavaProbablyPrime/Package.swift index 9f0ecff2..3ebf8fcb 100644 --- a/Samples/JavaProbablyPrime/Package.swift +++ b/Samples/JavaProbablyPrime/Package.swift @@ -29,8 +29,8 @@ let package = Package( .executableTarget( name: "JavaProbablyPrime", dependencies: [ - .product(name: "JavaKitCollection", package: "swift-java"), - .product(name: "JavaKit", package: "swift-java"), + .product(name: "JavaUtil", package: "swift-java"), + .product(name: "SwiftJava", package: "swift-java"), .product(name: "ArgumentParser", package: "swift-argument-parser"), ], swiftSettings: [ diff --git a/Samples/JavaProbablyPrime/Sources/JavaProbablyPrime/prime.swift b/Samples/JavaProbablyPrime/Sources/JavaProbablyPrime/prime.swift index 07f701bd..c070c87a 100644 --- a/Samples/JavaProbablyPrime/Sources/JavaProbablyPrime/prime.swift +++ b/Samples/JavaProbablyPrime/Sources/JavaProbablyPrime/prime.swift @@ -13,7 +13,7 @@ //===----------------------------------------------------------------------===// import ArgumentParser -import JavaKit +import SwiftJava @main struct ProbablyPrime: ParsableCommand { diff --git a/Samples/JavaSieve/Package.swift b/Samples/JavaSieve/Package.swift index ee61a021..c34d8331 100644 --- a/Samples/JavaSieve/Package.swift +++ b/Samples/JavaSieve/Package.swift @@ -54,8 +54,8 @@ let package = Package( .target( name: "JavaMath", dependencies: [ - .product(name: "JavaKit", package: "swift-java"), - .product(name: "JavaKitJar", package: "swift-java"), + .product(name: "SwiftJava", package: "swift-java"), + .product(name: "JavaUtilJar", package: "swift-java"), ], exclude: ["swift-java.config"], swiftSettings: [ @@ -72,8 +72,8 @@ let package = Package( name: "JavaSieve", dependencies: [ "JavaMath", - .product(name: "JavaKit", package: "swift-java"), - .product(name: "JavaKitCollection", package: "swift-java"), + .product(name: "SwiftJava", package: "swift-java"), + .product(name: "JavaUtil", package: "swift-java"), ], exclude: ["swift-java.config"], swiftSettings: [ diff --git a/Samples/JavaSieve/Sources/JavaSieve/main.swift b/Samples/JavaSieve/Sources/JavaSieve/main.swift index feec792d..470ee5c7 100644 --- a/Samples/JavaSieve/Sources/JavaSieve/main.swift +++ b/Samples/JavaSieve/Sources/JavaSieve/main.swift @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -import JavaKit +import SwiftJava import JavaMath let jvm = try JavaVirtualMachine.shared() diff --git a/Samples/SwiftKitSampleApp/Package.swift b/Samples/SwiftJavaExtractFFMSampleApp/Package.swift similarity index 93% rename from Samples/SwiftKitSampleApp/Package.swift rename to Samples/SwiftJavaExtractFFMSampleApp/Package.swift index 8501062b..30630a01 100644 --- a/Samples/SwiftKitSampleApp/Package.swift +++ b/Samples/SwiftJavaExtractFFMSampleApp/Package.swift @@ -41,7 +41,7 @@ let javaIncludePath = "\(javaHome)/include" #endif let package = Package( - name: "SwiftKitSampleApp", + name: "SwiftJavaExtractFFMSampleApp", platforms: [ .macOS(.v15), .iOS(.v18), @@ -63,8 +63,8 @@ let package = Package( .target( name: "MySwiftLibrary", dependencies: [ - .product(name: "JavaKit", package: "swift-java"), - .product(name: "JavaRuntime", package: "swift-java"), + .product(name: "SwiftJava", package: "swift-java"), + .product(name: "CJNI", package: "swift-java"), .product(name: "SwiftKitSwift", package: "swift-java"), ], exclude: [ diff --git a/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftClass.swift b/Samples/SwiftJavaExtractFFMSampleApp/Sources/MySwiftLibrary/MySwiftClass.swift similarity index 100% rename from Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftClass.swift rename to Samples/SwiftJavaExtractFFMSampleApp/Sources/MySwiftLibrary/MySwiftClass.swift diff --git a/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift b/Samples/SwiftJavaExtractFFMSampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift similarity index 100% rename from Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift rename to Samples/SwiftJavaExtractFFMSampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift diff --git a/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftStruct.swift b/Samples/SwiftJavaExtractFFMSampleApp/Sources/MySwiftLibrary/MySwiftStruct.swift similarity index 100% rename from Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftStruct.swift rename to Samples/SwiftJavaExtractFFMSampleApp/Sources/MySwiftLibrary/MySwiftStruct.swift diff --git a/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/jni/JNIImplementations.swift b/Samples/SwiftJavaExtractFFMSampleApp/Sources/MySwiftLibrary/jni/JNIImplementations.swift similarity index 97% rename from Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/jni/JNIImplementations.swift rename to Samples/SwiftJavaExtractFFMSampleApp/Sources/MySwiftLibrary/jni/JNIImplementations.swift index ef0e2e58..481265d5 100644 --- a/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/jni/JNIImplementations.swift +++ b/Samples/SwiftJavaExtractFFMSampleApp/Sources/MySwiftLibrary/jni/JNIImplementations.swift @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaClass("com.example.swift.HelloJava2Swift") open class HelloJava2Swift: JavaObject { diff --git a/Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/swift-java.config b/Samples/SwiftJavaExtractFFMSampleApp/Sources/MySwiftLibrary/swift-java.config similarity index 100% rename from Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/swift-java.config rename to Samples/SwiftJavaExtractFFMSampleApp/Sources/MySwiftLibrary/swift-java.config diff --git a/Samples/SwiftKitSampleApp/build.gradle b/Samples/SwiftJavaExtractFFMSampleApp/build.gradle similarity index 100% rename from Samples/SwiftKitSampleApp/build.gradle rename to Samples/SwiftJavaExtractFFMSampleApp/build.gradle diff --git a/Samples/JExtractJNISampleApp/ci-validate.sh b/Samples/SwiftJavaExtractFFMSampleApp/ci-validate.sh similarity index 100% rename from Samples/JExtractJNISampleApp/ci-validate.sh rename to Samples/SwiftJavaExtractFFMSampleApp/ci-validate.sh diff --git a/Samples/JExtractJNISampleApp/gradle.properties b/Samples/SwiftJavaExtractFFMSampleApp/gradle.properties similarity index 100% rename from Samples/JExtractJNISampleApp/gradle.properties rename to Samples/SwiftJavaExtractFFMSampleApp/gradle.properties diff --git a/Samples/JExtractJNISampleApp/gradlew b/Samples/SwiftJavaExtractFFMSampleApp/gradlew similarity index 100% rename from Samples/JExtractJNISampleApp/gradlew rename to Samples/SwiftJavaExtractFFMSampleApp/gradlew diff --git a/Samples/JExtractJNISampleApp/gradlew.bat b/Samples/SwiftJavaExtractFFMSampleApp/gradlew.bat similarity index 100% rename from Samples/JExtractJNISampleApp/gradlew.bat rename to Samples/SwiftJavaExtractFFMSampleApp/gradlew.bat diff --git a/Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/ffm/JavaToSwiftBenchmark.java b/Samples/SwiftJavaExtractFFMSampleApp/src/jmh/java/org/swift/swiftkit/ffm/JavaToSwiftBenchmark.java similarity index 100% rename from Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/ffm/JavaToSwiftBenchmark.java rename to Samples/SwiftJavaExtractFFMSampleApp/src/jmh/java/org/swift/swiftkit/ffm/JavaToSwiftBenchmark.java diff --git a/Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/ffm/StringPassingBenchmark.java b/Samples/SwiftJavaExtractFFMSampleApp/src/jmh/java/org/swift/swiftkit/ffm/StringPassingBenchmark.java similarity index 100% rename from Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/ffm/StringPassingBenchmark.java rename to Samples/SwiftJavaExtractFFMSampleApp/src/jmh/java/org/swift/swiftkit/ffm/StringPassingBenchmark.java diff --git a/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java b/Samples/SwiftJavaExtractFFMSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java similarity index 100% rename from Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java rename to Samples/SwiftJavaExtractFFMSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java diff --git a/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/DataImportTest.java b/Samples/SwiftJavaExtractFFMSampleApp/src/test/java/com/example/swift/DataImportTest.java similarity index 100% rename from Samples/SwiftKitSampleApp/src/test/java/com/example/swift/DataImportTest.java rename to Samples/SwiftJavaExtractFFMSampleApp/src/test/java/com/example/swift/DataImportTest.java diff --git a/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/MySwiftClassTest.java b/Samples/SwiftJavaExtractFFMSampleApp/src/test/java/com/example/swift/MySwiftClassTest.java similarity index 100% rename from Samples/SwiftKitSampleApp/src/test/java/com/example/swift/MySwiftClassTest.java rename to Samples/SwiftJavaExtractFFMSampleApp/src/test/java/com/example/swift/MySwiftClassTest.java diff --git a/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/MySwiftLibraryTest.java b/Samples/SwiftJavaExtractFFMSampleApp/src/test/java/com/example/swift/MySwiftLibraryTest.java similarity index 100% rename from Samples/SwiftKitSampleApp/src/test/java/com/example/swift/MySwiftLibraryTest.java rename to Samples/SwiftJavaExtractFFMSampleApp/src/test/java/com/example/swift/MySwiftLibraryTest.java diff --git a/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/OptionalImportTest.java b/Samples/SwiftJavaExtractFFMSampleApp/src/test/java/com/example/swift/OptionalImportTest.java similarity index 100% rename from Samples/SwiftKitSampleApp/src/test/java/com/example/swift/OptionalImportTest.java rename to Samples/SwiftJavaExtractFFMSampleApp/src/test/java/com/example/swift/OptionalImportTest.java diff --git a/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/UnsignedNumbersTest.java b/Samples/SwiftJavaExtractFFMSampleApp/src/test/java/com/example/swift/UnsignedNumbersTest.java similarity index 100% rename from Samples/SwiftKitSampleApp/src/test/java/com/example/swift/UnsignedNumbersTest.java rename to Samples/SwiftJavaExtractFFMSampleApp/src/test/java/com/example/swift/UnsignedNumbersTest.java diff --git a/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkitffm/MySwiftClassTest.java b/Samples/SwiftJavaExtractFFMSampleApp/src/test/java/org/swift/swiftkitffm/MySwiftClassTest.java similarity index 100% rename from Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkitffm/MySwiftClassTest.java rename to Samples/SwiftJavaExtractFFMSampleApp/src/test/java/org/swift/swiftkitffm/MySwiftClassTest.java diff --git a/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkitffm/MySwiftStructTest.java b/Samples/SwiftJavaExtractFFMSampleApp/src/test/java/org/swift/swiftkitffm/MySwiftStructTest.java similarity index 100% rename from Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkitffm/MySwiftStructTest.java rename to Samples/SwiftJavaExtractFFMSampleApp/src/test/java/org/swift/swiftkitffm/MySwiftStructTest.java diff --git a/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkitffm/SwiftArenaTest.java b/Samples/SwiftJavaExtractFFMSampleApp/src/test/java/org/swift/swiftkitffm/SwiftArenaTest.java similarity index 100% rename from Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkitffm/SwiftArenaTest.java rename to Samples/SwiftJavaExtractFFMSampleApp/src/test/java/org/swift/swiftkitffm/SwiftArenaTest.java diff --git a/Samples/JExtractJNISampleApp/Package.swift b/Samples/SwiftJavaExtractJNISampleApp/Package.swift similarity index 94% rename from Samples/JExtractJNISampleApp/Package.swift rename to Samples/SwiftJavaExtractJNISampleApp/Package.swift index 8c7ce856..0d2d2fa8 100644 --- a/Samples/JExtractJNISampleApp/Package.swift +++ b/Samples/SwiftJavaExtractJNISampleApp/Package.swift @@ -60,8 +60,8 @@ let package = Package( .target( name: "MySwiftLibrary", dependencies: [ - .product(name: "JavaKit", package: "swift-java"), - .product(name: "JavaRuntime", package: "swift-java"), + .product(name: "SwiftJava", package: "swift-java"), + .product(name: "CJNI", package: "swift-java"), .product(name: "SwiftKitSwift", package: "swift-java"), ], exclude: [ diff --git a/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/Alignment.swift b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/Alignment.swift similarity index 100% rename from Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/Alignment.swift rename to Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/Alignment.swift diff --git a/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/Closures.swift b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/Closures.swift similarity index 100% rename from Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/Closures.swift rename to Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/Closures.swift diff --git a/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftClass.swift b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftClass.swift similarity index 99% rename from Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftClass.swift rename to Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftClass.swift index 9a78c3c2..4b334a5e 100644 --- a/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftClass.swift +++ b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftClass.swift @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -import JavaKit +import SwiftJava public class MySwiftClass { public let x: Int64 diff --git a/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift similarity index 100% rename from Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift rename to Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift diff --git a/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftStruct.swift b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftStruct.swift similarity index 100% rename from Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftStruct.swift rename to Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftStruct.swift diff --git a/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/Optionals.swift b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/Optionals.swift similarity index 99% rename from Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/Optionals.swift rename to Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/Optionals.swift index 673ecb0b..3e122102 100644 --- a/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/Optionals.swift +++ b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/Optionals.swift @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -import JavaKit +import SwiftJava public func optionalBool(input: Optional) -> Bool? { return input diff --git a/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/Vehicle.swift b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/Vehicle.swift similarity index 100% rename from Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/Vehicle.swift rename to Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/Vehicle.swift diff --git a/Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/swift-java.config b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/swift-java.config similarity index 100% rename from Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/swift-java.config rename to Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/swift-java.config diff --git a/Samples/JExtractJNISampleApp/build.gradle b/Samples/SwiftJavaExtractJNISampleApp/build.gradle similarity index 100% rename from Samples/JExtractJNISampleApp/build.gradle rename to Samples/SwiftJavaExtractJNISampleApp/build.gradle diff --git a/Samples/SwiftKitSampleApp/ci-validate.sh b/Samples/SwiftJavaExtractJNISampleApp/ci-validate.sh similarity index 100% rename from Samples/SwiftKitSampleApp/ci-validate.sh rename to Samples/SwiftJavaExtractJNISampleApp/ci-validate.sh diff --git a/Samples/SwiftKitSampleApp/gradle.properties b/Samples/SwiftJavaExtractJNISampleApp/gradle.properties similarity index 100% rename from Samples/SwiftKitSampleApp/gradle.properties rename to Samples/SwiftJavaExtractJNISampleApp/gradle.properties diff --git a/Samples/SwiftKitSampleApp/gradlew b/Samples/SwiftJavaExtractJNISampleApp/gradlew similarity index 100% rename from Samples/SwiftKitSampleApp/gradlew rename to Samples/SwiftJavaExtractJNISampleApp/gradlew diff --git a/Samples/SwiftKitSampleApp/gradlew.bat b/Samples/SwiftJavaExtractJNISampleApp/gradlew.bat similarity index 100% rename from Samples/SwiftKitSampleApp/gradlew.bat rename to Samples/SwiftJavaExtractJNISampleApp/gradlew.bat diff --git a/Samples/JExtractJNISampleApp/src/main/java/com/example/swift/HelloJava2SwiftJNI.java b/Samples/SwiftJavaExtractJNISampleApp/src/main/java/com/example/swift/HelloJava2SwiftJNI.java similarity index 100% rename from Samples/JExtractJNISampleApp/src/main/java/com/example/swift/HelloJava2SwiftJNI.java rename to Samples/SwiftJavaExtractJNISampleApp/src/main/java/com/example/swift/HelloJava2SwiftJNI.java diff --git a/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/AlignmentEnumTest.java b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/AlignmentEnumTest.java similarity index 100% rename from Samples/JExtractJNISampleApp/src/test/java/com/example/swift/AlignmentEnumTest.java rename to Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/AlignmentEnumTest.java diff --git a/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/ClosuresTest.java b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/ClosuresTest.java similarity index 100% rename from Samples/JExtractJNISampleApp/src/test/java/com/example/swift/ClosuresTest.java rename to Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/ClosuresTest.java diff --git a/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/MySwiftClassTest.java b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/MySwiftClassTest.java similarity index 100% rename from Samples/JExtractJNISampleApp/src/test/java/com/example/swift/MySwiftClassTest.java rename to Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/MySwiftClassTest.java diff --git a/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/MySwiftLibraryTest.java b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/MySwiftLibraryTest.java similarity index 100% rename from Samples/JExtractJNISampleApp/src/test/java/com/example/swift/MySwiftLibraryTest.java rename to Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/MySwiftLibraryTest.java diff --git a/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/MySwiftStructTest.java b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/MySwiftStructTest.java similarity index 100% rename from Samples/JExtractJNISampleApp/src/test/java/com/example/swift/MySwiftStructTest.java rename to Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/MySwiftStructTest.java diff --git a/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/OptionalsTest.java b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/OptionalsTest.java similarity index 100% rename from Samples/JExtractJNISampleApp/src/test/java/com/example/swift/OptionalsTest.java rename to Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/OptionalsTest.java diff --git a/Samples/JExtractJNISampleApp/src/test/java/com/example/swift/VehicleEnumTest.java b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/VehicleEnumTest.java similarity index 100% rename from Samples/JExtractJNISampleApp/src/test/java/com/example/swift/VehicleEnumTest.java rename to Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/VehicleEnumTest.java diff --git a/Sources/JavaRuntime/dummy.c b/Sources/CJNI/dummy.c similarity index 100% rename from Sources/JavaRuntime/dummy.c rename to Sources/CJNI/dummy.c diff --git a/Sources/JavaRuntime/include/JavaRuntime.h b/Sources/CJNI/include/CJNI.h similarity index 85% rename from Sources/JavaRuntime/include/JavaRuntime.h rename to Sources/CJNI/include/CJNI.h index 02bf548e..bef6e7ff 100644 --- a/Sources/JavaRuntime/include/JavaRuntime.h +++ b/Sources/CJNI/include/CJNI.h @@ -12,9 +12,9 @@ // //===----------------------------------------------------------------------===// -#ifndef Swift_JavaRuntime_h -#define Swift_JavaRuntime_h +#ifndef Swift_CJNI_h +#define Swift_CJNI_h #include -#endif /* Swift_JavaRuntime_h */ +#endif /* Swift_CJNI_h */ diff --git a/Sources/CJNI/include/module.modulemap b/Sources/CJNI/include/module.modulemap new file mode 100644 index 00000000..c71f30c2 --- /dev/null +++ b/Sources/CJNI/include/module.modulemap @@ -0,0 +1,4 @@ +module CJNI { + umbrella header "CJNI.h" + export * +} diff --git a/Sources/JExtractSwiftLib/Common/TypeAnnotations.swift b/Sources/JExtractSwiftLib/Common/TypeAnnotations.swift index 70a86e82..0896e4be 100644 --- a/Sources/JExtractSwiftLib/Common/TypeAnnotations.swift +++ b/Sources/JExtractSwiftLib/Common/TypeAnnotations.swift @@ -13,7 +13,7 @@ //===----------------------------------------------------------------------===// import JavaTypes -import JavaKitConfigurationShared +import SwiftJavaConfigurationShared /// Determine if the given type needs any extra annotations that should be included /// in Java sources when the corresponding Java type is rendered. diff --git a/Sources/JExtractSwiftLib/Configuration+Extensions.swift b/Sources/JExtractSwiftLib/Configuration+Extensions.swift index d85cf447..042d8610 100644 --- a/Sources/JExtractSwiftLib/Configuration+Extensions.swift +++ b/Sources/JExtractSwiftLib/Configuration+Extensions.swift @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -import JavaKitConfigurationShared // TODO: this should become SwiftJavaConfigurationShared -import JavaTypes // TODO: this should become SwiftJavaConfigurationShared +import SwiftJavaConfigurationShared +import JavaTypes extension Configuration { public var effectiveUnsignedNumericsMode: UnsignedNumericsMode { diff --git a/Sources/JExtractSwiftLib/Convenience/String+Extensions.swift b/Sources/JExtractSwiftLib/Convenience/String+Extensions.swift index 25c46366..82ce5c1c 100644 --- a/Sources/JExtractSwiftLib/Convenience/String+Extensions.swift +++ b/Sources/JExtractSwiftLib/Convenience/String+Extensions.swift @@ -66,7 +66,7 @@ extension String { .joined() } - /// Looks up self as a JavaKit wrapped class name and converts it + /// Looks up self as a SwiftJava wrapped class name and converts it /// into a `JavaType.class` if it exists in `lookupTable`. func parseJavaClassFromJavaKitName(in lookupTable: [String: String]) -> JavaType? { guard let canonicalJavaName = lookupTable[self] else { diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift index 57f947a8..00fa60e7 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift @@ -13,7 +13,7 @@ //===----------------------------------------------------------------------===// import JavaTypes -import JavaKitConfigurationShared +import SwiftJavaConfigurationShared extension FFMSwift2JavaGenerator { func translatedDecl( diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift index 9c9154a4..c9a5028b 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift @@ -15,7 +15,7 @@ import JavaTypes import SwiftSyntax import SwiftSyntaxBuilder -import JavaKitConfigurationShared +import SwiftJavaConfigurationShared import struct Foundation.URL package class FFMSwift2JavaGenerator: Swift2JavaGenerator { diff --git a/Sources/JExtractSwiftLib/JNI/JNIJavaTypeTranslator.swift b/Sources/JExtractSwiftLib/JNI/JNIJavaTypeTranslator.swift index fe10ef72..983396ac 100644 --- a/Sources/JExtractSwiftLib/JNI/JNIJavaTypeTranslator.swift +++ b/Sources/JExtractSwiftLib/JNI/JNIJavaTypeTranslator.swift @@ -13,7 +13,7 @@ //===----------------------------------------------------------------------===// import JavaTypes -import JavaKitConfigurationShared +import SwiftJavaConfigurationShared enum JNIJavaTypeTranslator { diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift index 0e169ec6..073883a2 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift @@ -13,7 +13,7 @@ //===----------------------------------------------------------------------===// import JavaTypes -import JavaKitConfigurationShared +import SwiftJavaConfigurationShared extension JNISwift2JavaGenerator { func translatedDecl( diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift index f2e9522b..03273e68 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift @@ -13,7 +13,7 @@ //===----------------------------------------------------------------------===// import JavaTypes -import JavaKitConfigurationShared +import SwiftJavaConfigurationShared extension JNISwift2JavaGenerator { diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift index 6b8c435a..53679783 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift @@ -408,8 +408,8 @@ extension JNISwift2JavaGenerator { """ // Generated by swift-java - import JavaKit - import JavaRuntime + import SwiftJava + import CJNI """ ) diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator.swift index 60ec1b8b..f9b99f6b 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator.swift @@ -13,7 +13,7 @@ //===----------------------------------------------------------------------===// import JavaTypes -import JavaKitConfigurationShared +import SwiftJavaConfigurationShared /// A table that where keys are Swift class names and the values are /// the fully qualified canoical names. diff --git a/Sources/JExtractSwiftLib/Logger.swift b/Sources/JExtractSwiftLib/Logger.swift index 5bffdc8c..6ef04651 100644 --- a/Sources/JExtractSwiftLib/Logger.swift +++ b/Sources/JExtractSwiftLib/Logger.swift @@ -15,7 +15,7 @@ import Foundation import SwiftSyntax import ArgumentParser -import JavaKitConfigurationShared +import SwiftJavaConfigurationShared // Placeholder for some better logger, we could depend on swift-log public struct Logger { @@ -114,7 +114,7 @@ public struct Logger { } extension Logger { - public typealias Level = JavaKitConfigurationShared.LogLevel + public typealias Level = SwiftJavaConfigurationShared.LogLevel } extension Logger.Level: ExpressibleByArgument { diff --git a/Sources/JExtractSwiftLib/Swift2Java.swift b/Sources/JExtractSwiftLib/Swift2Java.swift index 5a73e328..e6271993 100644 --- a/Sources/JExtractSwiftLib/Swift2Java.swift +++ b/Sources/JExtractSwiftLib/Swift2Java.swift @@ -15,8 +15,8 @@ import Foundation import SwiftSyntax import SwiftSyntaxBuilder -import JavaKitShared -import JavaKitConfigurationShared // TODO: this should become SwiftJavaConfigurationShared +import SwiftJavaShared +import SwiftJavaConfigurationShared public struct SwiftToJava { let config: Configuration diff --git a/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift b/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift index 300b979f..02049ed4 100644 --- a/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift +++ b/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift @@ -16,7 +16,7 @@ import Foundation import JavaTypes import SwiftBasicFormat import SwiftParser -import JavaKitConfigurationShared +import SwiftJavaConfigurationShared import SwiftSyntax /// Takes swift interfaces and translates them into Java used to access those. diff --git a/Sources/JExtractSwiftLib/Swift2JavaVisitor.swift b/Sources/JExtractSwiftLib/Swift2JavaVisitor.swift index bc6ac032..9b183cb6 100644 --- a/Sources/JExtractSwiftLib/Swift2JavaVisitor.swift +++ b/Sources/JExtractSwiftLib/Swift2JavaVisitor.swift @@ -15,7 +15,7 @@ import Foundation import SwiftParser import SwiftSyntax -import JavaKitConfigurationShared +import SwiftJavaConfigurationShared final class Swift2JavaVisitor { let translator: Swift2JavaTranslator diff --git a/Sources/JavaKitDependencyResolver/DependencyResolver.swift b/Sources/JavaKitDependencyResolver/DependencyResolver.swift index 697e3d2a..1ecc8dc5 100644 --- a/Sources/JavaKitDependencyResolver/DependencyResolver.swift +++ b/Sources/JavaKitDependencyResolver/DependencyResolver.swift @@ -12,10 +12,10 @@ // //===----------------------------------------------------------------------===// -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI -@JavaInterface("org.swift.javakit.dependencies.DependencyResolver") +@JavaInterface("org.swift.jni.dependencies.DependencyResolver") public struct DependencyResolver { } diff --git a/Sources/JavaKitDependencyResolver/swift-java.config b/Sources/JavaKitDependencyResolver/swift-java.config index 6ea5aa87..3803b5f0 100644 --- a/Sources/JavaKitDependencyResolver/swift-java.config +++ b/Sources/JavaKitDependencyResolver/swift-java.config @@ -1,5 +1,5 @@ { "dependencies": [ - ":JavaKit", + ":SwiftJNI", ] } diff --git a/Sources/JavaRuntime/include/module.modulemap b/Sources/JavaRuntime/include/module.modulemap deleted file mode 100644 index 2c0d4a98..00000000 --- a/Sources/JavaRuntime/include/module.modulemap +++ /dev/null @@ -1,4 +0,0 @@ -module JavaRuntime { - umbrella header "JavaRuntime.h" - export * -} diff --git a/Sources/JavaKitIO/generated/BufferedInputStream.swift b/Sources/JavaStdlib/JavaIO/generated/BufferedInputStream.swift similarity index 96% rename from Sources/JavaKitIO/generated/BufferedInputStream.swift rename to Sources/JavaStdlib/JavaIO/generated/BufferedInputStream.swift index 8ea95eeb..b4a13494 100644 --- a/Sources/JavaKitIO/generated/BufferedInputStream.swift +++ b/Sources/JavaStdlib/JavaIO/generated/BufferedInputStream.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaClass("java.io.BufferedInputStream") open class BufferedInputStream: InputStream { diff --git a/Sources/JavaKitIO/generated/Charset.swift b/Sources/JavaStdlib/JavaIO/generated/Charset.swift similarity index 96% rename from Sources/JavaKitIO/generated/Charset.swift rename to Sources/JavaStdlib/JavaIO/generated/Charset.swift index fda054ef..f3b9126c 100644 --- a/Sources/JavaKitIO/generated/Charset.swift +++ b/Sources/JavaStdlib/JavaIO/generated/Charset.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaClass("java.nio.charset.Charset") open class Charset: JavaObject { diff --git a/Sources/JavaKitIO/generated/Closeable.swift b/Sources/JavaStdlib/JavaIO/generated/Closeable.swift similarity index 82% rename from Sources/JavaKitIO/generated/Closeable.swift rename to Sources/JavaStdlib/JavaIO/generated/Closeable.swift index 6da8e2a9..9e68c58b 100644 --- a/Sources/JavaKitIO/generated/Closeable.swift +++ b/Sources/JavaStdlib/JavaIO/generated/Closeable.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaInterface("java.io.Closeable") public struct Closeable { diff --git a/Sources/JavaKitIO/generated/File.swift b/Sources/JavaStdlib/JavaIO/generated/File.swift similarity index 98% rename from Sources/JavaKitIO/generated/File.swift rename to Sources/JavaStdlib/JavaIO/generated/File.swift index 5cbdb70e..11831b5e 100644 --- a/Sources/JavaKitIO/generated/File.swift +++ b/Sources/JavaStdlib/JavaIO/generated/File.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaClass("java.io.File") open class File: JavaObject { diff --git a/Sources/JavaKitIO/generated/FileDescriptor.swift b/Sources/JavaStdlib/JavaIO/generated/FileDescriptor.swift similarity index 94% rename from Sources/JavaKitIO/generated/FileDescriptor.swift rename to Sources/JavaStdlib/JavaIO/generated/FileDescriptor.swift index 81490e46..36f1686c 100644 --- a/Sources/JavaKitIO/generated/FileDescriptor.swift +++ b/Sources/JavaStdlib/JavaIO/generated/FileDescriptor.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaClass("java.io.FileDescriptor") open class FileDescriptor: JavaObject { diff --git a/Sources/JavaKitIO/generated/FileReader.swift b/Sources/JavaStdlib/JavaIO/generated/FileReader.swift similarity index 95% rename from Sources/JavaKitIO/generated/FileReader.swift rename to Sources/JavaStdlib/JavaIO/generated/FileReader.swift index 5254bdd0..ed0898c7 100644 --- a/Sources/JavaKitIO/generated/FileReader.swift +++ b/Sources/JavaStdlib/JavaIO/generated/FileReader.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaClass("java.io.FileReader") open class FileReader: InputStreamReader { diff --git a/Sources/JavaKitIO/generated/Flushable.swift b/Sources/JavaStdlib/JavaIO/generated/Flushable.swift similarity index 82% rename from Sources/JavaKitIO/generated/Flushable.swift rename to Sources/JavaStdlib/JavaIO/generated/Flushable.swift index daf621f6..59854369 100644 --- a/Sources/JavaKitIO/generated/Flushable.swift +++ b/Sources/JavaStdlib/JavaIO/generated/Flushable.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaInterface("java.io.Flushable") public struct Flushable { diff --git a/Sources/JavaKitIO/generated/InputStream.swift b/Sources/JavaStdlib/JavaIO/generated/InputStream.swift similarity index 97% rename from Sources/JavaKitIO/generated/InputStream.swift rename to Sources/JavaStdlib/JavaIO/generated/InputStream.swift index 971a610b..d521f265 100644 --- a/Sources/JavaKitIO/generated/InputStream.swift +++ b/Sources/JavaStdlib/JavaIO/generated/InputStream.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaClass("java.io.InputStream", implements: Closeable.self) open class InputStream: JavaObject { diff --git a/Sources/JavaKitIO/generated/InputStreamReader.swift b/Sources/JavaStdlib/JavaIO/generated/InputStreamReader.swift similarity index 96% rename from Sources/JavaKitIO/generated/InputStreamReader.swift rename to Sources/JavaStdlib/JavaIO/generated/InputStreamReader.swift index 2766aeba..faa04eda 100644 --- a/Sources/JavaKitIO/generated/InputStreamReader.swift +++ b/Sources/JavaStdlib/JavaIO/generated/InputStreamReader.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaClass("java.io.InputStreamReader") open class InputStreamReader: Reader { diff --git a/Sources/JavaKitIO/generated/OutputStream.swift b/Sources/JavaStdlib/JavaIO/generated/OutputStream.swift similarity index 95% rename from Sources/JavaKitIO/generated/OutputStream.swift rename to Sources/JavaStdlib/JavaIO/generated/OutputStream.swift index e169bfd0..1d3ec356 100644 --- a/Sources/JavaKitIO/generated/OutputStream.swift +++ b/Sources/JavaStdlib/JavaIO/generated/OutputStream.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaClass("java.io.OutputStream", implements: Closeable.self, Flushable.self) open class OutputStream: JavaObject { diff --git a/Sources/JavaKitIO/generated/Path.swift b/Sources/JavaStdlib/JavaIO/generated/Path.swift similarity index 98% rename from Sources/JavaKitIO/generated/Path.swift rename to Sources/JavaStdlib/JavaIO/generated/Path.swift index e93d0381..87956f10 100644 --- a/Sources/JavaKitIO/generated/Path.swift +++ b/Sources/JavaStdlib/JavaIO/generated/Path.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaInterface("java.nio.file.Path") public struct Path { diff --git a/Sources/JavaKitIO/generated/Readable.swift b/Sources/JavaStdlib/JavaIO/generated/Readable.swift similarity index 77% rename from Sources/JavaKitIO/generated/Readable.swift rename to Sources/JavaStdlib/JavaIO/generated/Readable.swift index 16825989..25f48221 100644 --- a/Sources/JavaKitIO/generated/Readable.swift +++ b/Sources/JavaStdlib/JavaIO/generated/Readable.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaInterface("java.lang.Readable") public struct Readable { diff --git a/Sources/JavaKitIO/generated/Reader.swift b/Sources/JavaStdlib/JavaIO/generated/Reader.swift similarity index 96% rename from Sources/JavaKitIO/generated/Reader.swift rename to Sources/JavaStdlib/JavaIO/generated/Reader.swift index 2f6cdfe2..e133f741 100644 --- a/Sources/JavaKitIO/generated/Reader.swift +++ b/Sources/JavaStdlib/JavaIO/generated/Reader.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaClass("java.io.Reader", implements: Readable.self, Closeable.self) open class Reader: JavaObject { diff --git a/Sources/JavaKitIO/generated/StringReader.swift b/Sources/JavaStdlib/JavaIO/generated/StringReader.swift similarity index 95% rename from Sources/JavaKitIO/generated/StringReader.swift rename to Sources/JavaStdlib/JavaIO/generated/StringReader.swift index e2af1166..aa3efd38 100644 --- a/Sources/JavaKitIO/generated/StringReader.swift +++ b/Sources/JavaStdlib/JavaIO/generated/StringReader.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaClass("java.io.StringReader") open class StringReader: Reader { diff --git a/Sources/JavaKitIO/generated/WatchService.swift b/Sources/JavaStdlib/JavaIO/generated/WatchService.swift similarity index 85% rename from Sources/JavaKitIO/generated/WatchService.swift rename to Sources/JavaStdlib/JavaIO/generated/WatchService.swift index 20bca06f..0b44c4fe 100644 --- a/Sources/JavaKitIO/generated/WatchService.swift +++ b/Sources/JavaStdlib/JavaIO/generated/WatchService.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaInterface("java.nio.file.WatchService", extends: Closeable.self) public struct WatchService { diff --git a/Sources/JavaKitIO/generated/Writer.swift b/Sources/JavaStdlib/JavaIO/generated/Writer.swift similarity index 97% rename from Sources/JavaKitIO/generated/Writer.swift rename to Sources/JavaStdlib/JavaIO/generated/Writer.swift index 5e3fdff2..7712a1c0 100644 --- a/Sources/JavaKitIO/generated/Writer.swift +++ b/Sources/JavaStdlib/JavaIO/generated/Writer.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaClass("java.io.Writer", implements: Appendable.self, Closeable.self, Flushable.self) open class Writer: JavaObject { diff --git a/Sources/JavaKitIO/swift-java.config b/Sources/JavaStdlib/JavaIO/swift-java.config similarity index 100% rename from Sources/JavaKitIO/swift-java.config rename to Sources/JavaStdlib/JavaIO/swift-java.config diff --git a/Sources/JavaKitReflection/Constructor+Utilities.swift b/Sources/JavaStdlib/JavaLangReflect/Constructor+Utilities.swift similarity index 100% rename from Sources/JavaKitReflection/Constructor+Utilities.swift rename to Sources/JavaStdlib/JavaLangReflect/Constructor+Utilities.swift diff --git a/Sources/JavaKitReflection/Executable+Utilities.swift b/Sources/JavaStdlib/JavaLangReflect/Executable+Utilities.swift similarity index 98% rename from Sources/JavaKitReflection/Executable+Utilities.swift rename to Sources/JavaStdlib/JavaLangReflect/Executable+Utilities.swift index 2b0a8a2d..bf70f114 100644 --- a/Sources/JavaKitReflection/Executable+Utilities.swift +++ b/Sources/JavaStdlib/JavaLangReflect/Executable+Utilities.swift @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -import JavaKit +import SwiftJava extension Executable { /// Whether this executable throws any checked exception. diff --git a/Sources/JavaKitReflection/Field+Utilities.swift b/Sources/JavaStdlib/JavaLangReflect/Field+Utilities.swift similarity index 100% rename from Sources/JavaKitReflection/Field+Utilities.swift rename to Sources/JavaStdlib/JavaLangReflect/Field+Utilities.swift diff --git a/Sources/JavaKitReflection/JavaClass+Reflection.swift b/Sources/JavaStdlib/JavaLangReflect/JavaClass+Reflection.swift similarity index 98% rename from Sources/JavaKitReflection/JavaClass+Reflection.swift rename to Sources/JavaStdlib/JavaLangReflect/JavaClass+Reflection.swift index 1f2120e0..29e24be5 100644 --- a/Sources/JavaKitReflection/JavaClass+Reflection.swift +++ b/Sources/JavaStdlib/JavaLangReflect/JavaClass+Reflection.swift @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -import JavaKit +import SwiftJava // TODO: We should be able to autogenerate this as an extension based on // knowing that JavaClass was defined elsewhere. diff --git a/Sources/JavaKitReflection/Method+Utilities.swift b/Sources/JavaStdlib/JavaLangReflect/Method+Utilities.swift similarity index 100% rename from Sources/JavaKitReflection/Method+Utilities.swift rename to Sources/JavaStdlib/JavaLangReflect/Method+Utilities.swift diff --git a/Sources/JavaKitReflection/generated/AccessibleObject.swift b/Sources/JavaStdlib/JavaLangReflect/generated/AccessibleObject.swift similarity index 97% rename from Sources/JavaKitReflection/generated/AccessibleObject.swift rename to Sources/JavaStdlib/JavaLangReflect/generated/AccessibleObject.swift index 84dcc4c2..c118f78b 100644 --- a/Sources/JavaKitReflection/generated/AccessibleObject.swift +++ b/Sources/JavaStdlib/JavaLangReflect/generated/AccessibleObject.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaClass("java.lang.reflect.AccessibleObject") open class AccessibleObject: JavaObject { diff --git a/Sources/JavaKitReflection/generated/AnnotatedType.swift b/Sources/JavaStdlib/JavaLangReflect/generated/AnnotatedType.swift similarity index 96% rename from Sources/JavaKitReflection/generated/AnnotatedType.swift rename to Sources/JavaStdlib/JavaLangReflect/generated/AnnotatedType.swift index ca9b9994..cc5b418c 100644 --- a/Sources/JavaKitReflection/generated/AnnotatedType.swift +++ b/Sources/JavaStdlib/JavaLangReflect/generated/AnnotatedType.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaInterface("java.lang.reflect.AnnotatedType") public struct AnnotatedType { diff --git a/Sources/JavaKitReflection/generated/Annotation.swift b/Sources/JavaStdlib/JavaLangReflect/generated/Annotation.swift similarity index 91% rename from Sources/JavaKitReflection/generated/Annotation.swift rename to Sources/JavaStdlib/JavaLangReflect/generated/Annotation.swift index 269c0f9e..66ab49cc 100644 --- a/Sources/JavaKitReflection/generated/Annotation.swift +++ b/Sources/JavaStdlib/JavaLangReflect/generated/Annotation.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaInterface("java.lang.annotation.Annotation") public struct Annotation { diff --git a/Sources/JavaKitReflection/generated/Constructor.swift b/Sources/JavaStdlib/JavaLangReflect/generated/Constructor.swift similarity index 98% rename from Sources/JavaKitReflection/generated/Constructor.swift rename to Sources/JavaStdlib/JavaLangReflect/generated/Constructor.swift index 263d767d..76f49f11 100644 --- a/Sources/JavaKitReflection/generated/Constructor.swift +++ b/Sources/JavaStdlib/JavaLangReflect/generated/Constructor.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaClass("java.lang.reflect.Constructor") open class Constructor: Executable { diff --git a/Sources/JavaKitReflection/generated/Executable.swift b/Sources/JavaStdlib/JavaLangReflect/generated/Executable.swift similarity index 96% rename from Sources/JavaKitReflection/generated/Executable.swift rename to Sources/JavaStdlib/JavaLangReflect/generated/Executable.swift index 6a1f5b75..31799784 100644 --- a/Sources/JavaKitReflection/generated/Executable.swift +++ b/Sources/JavaStdlib/JavaLangReflect/generated/Executable.swift @@ -1,7 +1,7 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaKitCollection -import JavaRuntime +import SwiftJava +import JavaUtil +import CJNI @JavaClass("java.lang.reflect.Executable", implements: GenericDeclaration.self) open class Executable: AccessibleObject { diff --git a/Sources/JavaKitReflection/generated/Field.swift b/Sources/JavaStdlib/JavaLangReflect/generated/Field.swift similarity index 97% rename from Sources/JavaKitReflection/generated/Field.swift rename to Sources/JavaStdlib/JavaLangReflect/generated/Field.swift index c67e56ff..2c4a49e9 100644 --- a/Sources/JavaKitReflection/generated/Field.swift +++ b/Sources/JavaStdlib/JavaLangReflect/generated/Field.swift @@ -1,7 +1,7 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaKitCollection -import JavaRuntime +import SwiftJava +import JavaUtil +import CJNI @JavaClass("java.lang.reflect.Field") open class Field: AccessibleObject { diff --git a/Sources/JavaKitReflection/generated/GenericArrayType.swift b/Sources/JavaStdlib/JavaLangReflect/generated/GenericArrayType.swift similarity index 89% rename from Sources/JavaKitReflection/generated/GenericArrayType.swift rename to Sources/JavaStdlib/JavaLangReflect/generated/GenericArrayType.swift index 6f96a0d2..75ad2c75 100644 --- a/Sources/JavaKitReflection/generated/GenericArrayType.swift +++ b/Sources/JavaStdlib/JavaLangReflect/generated/GenericArrayType.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaInterface("java.lang.reflect.GenericArrayType", extends: Type.self) public struct GenericArrayType { diff --git a/Sources/JavaKitReflection/generated/GenericDeclaration.swift b/Sources/JavaStdlib/JavaLangReflect/generated/GenericDeclaration.swift similarity index 96% rename from Sources/JavaKitReflection/generated/GenericDeclaration.swift rename to Sources/JavaStdlib/JavaLangReflect/generated/GenericDeclaration.swift index 7a86bd8a..bec84aa5 100644 --- a/Sources/JavaKitReflection/generated/GenericDeclaration.swift +++ b/Sources/JavaStdlib/JavaLangReflect/generated/GenericDeclaration.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaInterface("java.lang.reflect.GenericDeclaration") public struct GenericDeclaration { diff --git a/Sources/JavaKitReflection/generated/Method.swift b/Sources/JavaStdlib/JavaLangReflect/generated/Method.swift similarity index 98% rename from Sources/JavaKitReflection/generated/Method.swift rename to Sources/JavaStdlib/JavaLangReflect/generated/Method.swift index 46183f4f..4489cf24 100644 --- a/Sources/JavaKitReflection/generated/Method.swift +++ b/Sources/JavaStdlib/JavaLangReflect/generated/Method.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaClass("java.lang.reflect.Method") open class Method: Executable { diff --git a/Sources/JavaKitReflection/generated/Parameter.swift b/Sources/JavaStdlib/JavaLangReflect/generated/Parameter.swift similarity index 95% rename from Sources/JavaKitReflection/generated/Parameter.swift rename to Sources/JavaStdlib/JavaLangReflect/generated/Parameter.swift index 30f2d628..6dea46fd 100644 --- a/Sources/JavaKitReflection/generated/Parameter.swift +++ b/Sources/JavaStdlib/JavaLangReflect/generated/Parameter.swift @@ -1,7 +1,7 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaKitCollection -import JavaRuntime +import SwiftJava +import JavaUtil +import CJNI @JavaClass("java.lang.reflect.Parameter") open class Parameter: JavaObject { diff --git a/Sources/JavaKitReflection/generated/ParameterizedType.swift b/Sources/JavaStdlib/JavaLangReflect/generated/ParameterizedType.swift similarity index 91% rename from Sources/JavaKitReflection/generated/ParameterizedType.swift rename to Sources/JavaStdlib/JavaLangReflect/generated/ParameterizedType.swift index 3e413714..a427a2a5 100644 --- a/Sources/JavaKitReflection/generated/ParameterizedType.swift +++ b/Sources/JavaStdlib/JavaLangReflect/generated/ParameterizedType.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaInterface("java.lang.reflect.ParameterizedType", extends: Type.self) public struct ParameterizedType { diff --git a/Sources/JavaKitReflection/generated/Type.swift b/Sources/JavaStdlib/JavaLangReflect/generated/Type.swift similarity index 83% rename from Sources/JavaKitReflection/generated/Type.swift rename to Sources/JavaStdlib/JavaLangReflect/generated/Type.swift index ea6376cb..05e8687e 100644 --- a/Sources/JavaKitReflection/generated/Type.swift +++ b/Sources/JavaStdlib/JavaLangReflect/generated/Type.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaInterface("java.lang.reflect.Type") public struct Type { diff --git a/Sources/JavaKitReflection/generated/TypeVariable.swift b/Sources/JavaStdlib/JavaLangReflect/generated/TypeVariable.swift similarity index 96% rename from Sources/JavaKitReflection/generated/TypeVariable.swift rename to Sources/JavaStdlib/JavaLangReflect/generated/TypeVariable.swift index c925cdcf..e6a7899c 100644 --- a/Sources/JavaKitReflection/generated/TypeVariable.swift +++ b/Sources/JavaStdlib/JavaLangReflect/generated/TypeVariable.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaInterface("java.lang.reflect.TypeVariable", extends: Type.self) public struct TypeVariable { diff --git a/Sources/JavaKitReflection/generated/WildcardType.swift b/Sources/JavaStdlib/JavaLangReflect/generated/WildcardType.swift similarity index 90% rename from Sources/JavaKitReflection/generated/WildcardType.swift rename to Sources/JavaStdlib/JavaLangReflect/generated/WildcardType.swift index e1551f50..2514495a 100644 --- a/Sources/JavaKitReflection/generated/WildcardType.swift +++ b/Sources/JavaStdlib/JavaLangReflect/generated/WildcardType.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaInterface("java.lang.reflect.WildcardType", extends: Type.self) public struct WildcardType { diff --git a/Sources/JavaKitReflection/swift-java.config b/Sources/JavaStdlib/JavaLangReflect/swift-java.config similarity index 100% rename from Sources/JavaKitReflection/swift-java.config rename to Sources/JavaStdlib/JavaLangReflect/swift-java.config diff --git a/Sources/JavaKitNetwork/generated/URI.swift b/Sources/JavaStdlib/JavaNet/generated/URI.swift similarity index 98% rename from Sources/JavaKitNetwork/generated/URI.swift rename to Sources/JavaStdlib/JavaNet/generated/URI.swift index 000e29ca..f1a6c078 100644 --- a/Sources/JavaKitNetwork/generated/URI.swift +++ b/Sources/JavaStdlib/JavaNet/generated/URI.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaClass("java.net.URI") open class URI: JavaObject { diff --git a/Sources/JavaKitNetwork/generated/URL.swift b/Sources/JavaStdlib/JavaNet/generated/URL.swift similarity index 97% rename from Sources/JavaKitNetwork/generated/URL.swift rename to Sources/JavaStdlib/JavaNet/generated/URL.swift index ed0dee38..9140a1d9 100644 --- a/Sources/JavaKitNetwork/generated/URL.swift +++ b/Sources/JavaStdlib/JavaNet/generated/URL.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaClass("java.net.URL") open class URL: JavaObject { diff --git a/Sources/JavaKitNetwork/generated/URLClassLoader.swift b/Sources/JavaStdlib/JavaNet/generated/URLClassLoader.swift similarity index 93% rename from Sources/JavaKitNetwork/generated/URLClassLoader.swift rename to Sources/JavaStdlib/JavaNet/generated/URLClassLoader.swift index eac9c14c..1750f197 100644 --- a/Sources/JavaKitNetwork/generated/URLClassLoader.swift +++ b/Sources/JavaStdlib/JavaNet/generated/URLClassLoader.swift @@ -1,7 +1,7 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaKitCollection -import JavaRuntime +import SwiftJava +import JavaUtil +import CJNI @JavaClass("java.net.URLClassLoader") open class URLClassLoader: JavaObject { diff --git a/Sources/JavaKitNetwork/generated/URLConnection.swift b/Sources/JavaStdlib/JavaNet/generated/URLConnection.swift similarity index 99% rename from Sources/JavaKitNetwork/generated/URLConnection.swift rename to Sources/JavaStdlib/JavaNet/generated/URLConnection.swift index 94fd6f52..6a93edd1 100644 --- a/Sources/JavaKitNetwork/generated/URLConnection.swift +++ b/Sources/JavaStdlib/JavaNet/generated/URLConnection.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaClass("java.net.URLConnection") public struct URLConnection { diff --git a/Sources/JavaKitNetwork/swift-java.config b/Sources/JavaStdlib/JavaNet/swift-java.config similarity index 100% rename from Sources/JavaKitNetwork/swift-java.config rename to Sources/JavaStdlib/JavaNet/swift-java.config diff --git a/Sources/JavaKitCollection/JavaEnumeration+Sequence.swift b/Sources/JavaStdlib/JavaUtil/JavaEnumeration+Sequence.swift similarity index 100% rename from Sources/JavaKitCollection/JavaEnumeration+Sequence.swift rename to Sources/JavaStdlib/JavaUtil/JavaEnumeration+Sequence.swift diff --git a/Sources/JavaKitCollection/JavaIterator+Iterator.swift b/Sources/JavaStdlib/JavaUtil/JavaIterator+Iterator.swift similarity index 97% rename from Sources/JavaKitCollection/JavaIterator+Iterator.swift rename to Sources/JavaStdlib/JavaUtil/JavaIterator+Iterator.swift index add2a48b..ad427527 100644 --- a/Sources/JavaKitCollection/JavaIterator+Iterator.swift +++ b/Sources/JavaStdlib/JavaUtil/JavaIterator+Iterator.swift @@ -11,7 +11,7 @@ // SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// -import JavaKit +import SwiftJava extension JavaIterator: IteratorProtocol { public typealias Element = E diff --git a/Sources/JavaKitCollection/List+Sequence.swift b/Sources/JavaStdlib/JavaUtil/List+Sequence.swift similarity index 100% rename from Sources/JavaKitCollection/List+Sequence.swift rename to Sources/JavaStdlib/JavaUtil/List+Sequence.swift diff --git a/Sources/JavaKitCollection/generated/ArrayDeque.swift b/Sources/JavaStdlib/JavaUtil/generated/ArrayDeque.swift similarity index 98% rename from Sources/JavaKitCollection/generated/ArrayDeque.swift rename to Sources/JavaStdlib/JavaUtil/generated/ArrayDeque.swift index 79a1e20b..f0d257af 100644 --- a/Sources/JavaKitCollection/generated/ArrayDeque.swift +++ b/Sources/JavaStdlib/JavaUtil/generated/ArrayDeque.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaClass("java.util.ArrayDeque") open class ArrayDeque: JavaObject { diff --git a/Sources/JavaKitCollection/generated/ArrayList.swift b/Sources/JavaStdlib/JavaUtil/generated/ArrayList.swift similarity index 98% rename from Sources/JavaKitCollection/generated/ArrayList.swift rename to Sources/JavaStdlib/JavaUtil/generated/ArrayList.swift index 6748640b..b39ada56 100644 --- a/Sources/JavaKitCollection/generated/ArrayList.swift +++ b/Sources/JavaStdlib/JavaUtil/generated/ArrayList.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaClass("java.util.ArrayList", implements: List.self, RandomAccess.self) open class ArrayList: JavaObject { diff --git a/Sources/JavaKitCollection/generated/BitSet.swift b/Sources/JavaStdlib/JavaUtil/generated/BitSet.swift similarity index 98% rename from Sources/JavaKitCollection/generated/BitSet.swift rename to Sources/JavaStdlib/JavaUtil/generated/BitSet.swift index d5211c28..2d89ba5a 100644 --- a/Sources/JavaKitCollection/generated/BitSet.swift +++ b/Sources/JavaStdlib/JavaUtil/generated/BitSet.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaClass("java.util.BitSet") open class BitSet: JavaObject { diff --git a/Sources/JavaKitCollection/generated/Enumeration.swift b/Sources/JavaStdlib/JavaUtil/generated/Enumeration.swift similarity index 90% rename from Sources/JavaKitCollection/generated/Enumeration.swift rename to Sources/JavaStdlib/JavaUtil/generated/Enumeration.swift index 492cc3b2..0229e16d 100644 --- a/Sources/JavaKitCollection/generated/Enumeration.swift +++ b/Sources/JavaStdlib/JavaUtil/generated/Enumeration.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaInterface("java.util.Enumeration") public struct Enumeration { diff --git a/Sources/JavaKitCollection/generated/HashMap.swift b/Sources/JavaStdlib/JavaUtil/generated/HashMap.swift similarity index 98% rename from Sources/JavaKitCollection/generated/HashMap.swift rename to Sources/JavaStdlib/JavaUtil/generated/HashMap.swift index 424dfbb9..6fd38bc4 100644 --- a/Sources/JavaKitCollection/generated/HashMap.swift +++ b/Sources/JavaStdlib/JavaUtil/generated/HashMap.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaClass("java.util.HashMap") open class HashMap: JavaObject { diff --git a/Sources/JavaKitCollection/generated/HashSet.swift b/Sources/JavaStdlib/JavaUtil/generated/HashSet.swift similarity index 97% rename from Sources/JavaKitCollection/generated/HashSet.swift rename to Sources/JavaStdlib/JavaUtil/generated/HashSet.swift index 97b15dff..f7c37d21 100644 --- a/Sources/JavaKitCollection/generated/HashSet.swift +++ b/Sources/JavaStdlib/JavaUtil/generated/HashSet.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaClass("java.util.HashSet", implements: JavaSet.self) open class HashSet: JavaObject { diff --git a/Sources/JavaKitCollection/generated/JavaCollection.swift b/Sources/JavaStdlib/JavaUtil/generated/JavaCollection.swift similarity index 97% rename from Sources/JavaKitCollection/generated/JavaCollection.swift rename to Sources/JavaStdlib/JavaUtil/generated/JavaCollection.swift index 26ca6827..4d1c8a81 100644 --- a/Sources/JavaKitCollection/generated/JavaCollection.swift +++ b/Sources/JavaStdlib/JavaUtil/generated/JavaCollection.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaInterface("java.util.Collection") public struct JavaCollection { diff --git a/Sources/JavaKitCollection/generated/JavaDictionary.swift b/Sources/JavaStdlib/JavaUtil/generated/JavaDictionary.swift similarity index 95% rename from Sources/JavaKitCollection/generated/JavaDictionary.swift rename to Sources/JavaStdlib/JavaUtil/generated/JavaDictionary.swift index 43ded915..85ee9beb 100644 --- a/Sources/JavaKitCollection/generated/JavaDictionary.swift +++ b/Sources/JavaStdlib/JavaUtil/generated/JavaDictionary.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaClass("java.util.Dictionary") open class JavaDictionary: JavaObject { diff --git a/Sources/JavaKitCollection/generated/JavaIterator.swift b/Sources/JavaStdlib/JavaUtil/generated/JavaIterator.swift similarity index 89% rename from Sources/JavaKitCollection/generated/JavaIterator.swift rename to Sources/JavaStdlib/JavaUtil/generated/JavaIterator.swift index 382c44e5..1038a5e1 100644 --- a/Sources/JavaKitCollection/generated/JavaIterator.swift +++ b/Sources/JavaStdlib/JavaUtil/generated/JavaIterator.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaInterface("java.util.Iterator") public struct JavaIterator { diff --git a/Sources/JavaKitCollection/generated/JavaSet.swift b/Sources/JavaStdlib/JavaUtil/generated/JavaSet.swift similarity index 99% rename from Sources/JavaKitCollection/generated/JavaSet.swift rename to Sources/JavaStdlib/JavaUtil/generated/JavaSet.swift index d924d2d1..7fec8e7a 100644 --- a/Sources/JavaKitCollection/generated/JavaSet.swift +++ b/Sources/JavaStdlib/JavaUtil/generated/JavaSet.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaInterface("java.util.Set", extends: JavaCollection.self) public struct JavaSet { diff --git a/Sources/JavaKitCollection/generated/LinkedList.swift b/Sources/JavaStdlib/JavaUtil/generated/LinkedList.swift similarity index 99% rename from Sources/JavaKitCollection/generated/LinkedList.swift rename to Sources/JavaStdlib/JavaUtil/generated/LinkedList.swift index 25abfbbf..9f27a3e1 100644 --- a/Sources/JavaKitCollection/generated/LinkedList.swift +++ b/Sources/JavaStdlib/JavaUtil/generated/LinkedList.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaClass("java.util.LinkedList") public struct LinkedList { diff --git a/Sources/JavaKitCollection/generated/List.swift b/Sources/JavaStdlib/JavaUtil/generated/List.swift similarity index 99% rename from Sources/JavaKitCollection/generated/List.swift rename to Sources/JavaStdlib/JavaUtil/generated/List.swift index b264f88e..1d745ec3 100644 --- a/Sources/JavaKitCollection/generated/List.swift +++ b/Sources/JavaStdlib/JavaUtil/generated/List.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaInterface("java.util.List") public struct List { diff --git a/Sources/JavaKitCollection/generated/ListIterator.swift b/Sources/JavaStdlib/JavaUtil/generated/ListIterator.swift similarity index 94% rename from Sources/JavaKitCollection/generated/ListIterator.swift rename to Sources/JavaStdlib/JavaUtil/generated/ListIterator.swift index 7b273160..a643efa7 100644 --- a/Sources/JavaKitCollection/generated/ListIterator.swift +++ b/Sources/JavaStdlib/JavaUtil/generated/ListIterator.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaInterface("java.util.ListIterator", extends: JavaIterator.self) public struct ListIterator { diff --git a/Sources/JavaKitCollection/generated/PriorityQueue.swift b/Sources/JavaStdlib/JavaUtil/generated/PriorityQueue.swift similarity index 97% rename from Sources/JavaKitCollection/generated/PriorityQueue.swift rename to Sources/JavaStdlib/JavaUtil/generated/PriorityQueue.swift index 14e50f31..13fc3629 100644 --- a/Sources/JavaKitCollection/generated/PriorityQueue.swift +++ b/Sources/JavaStdlib/JavaUtil/generated/PriorityQueue.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaClass("java.util.PriorityQueue") open class PriorityQueue: JavaObject { diff --git a/Sources/JavaKitCollection/generated/Queue.swift b/Sources/JavaStdlib/JavaUtil/generated/Queue.swift similarity index 97% rename from Sources/JavaKitCollection/generated/Queue.swift rename to Sources/JavaStdlib/JavaUtil/generated/Queue.swift index 44373fce..1d51d7c4 100644 --- a/Sources/JavaKitCollection/generated/Queue.swift +++ b/Sources/JavaStdlib/JavaUtil/generated/Queue.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaInterface("java.util.Queue", extends: JavaCollection.self) public struct Queue { diff --git a/Sources/JavaKitCollection/generated/RandomAccess.swift b/Sources/JavaStdlib/JavaUtil/generated/RandomAccess.swift similarity index 79% rename from Sources/JavaKitCollection/generated/RandomAccess.swift rename to Sources/JavaStdlib/JavaUtil/generated/RandomAccess.swift index 0084ceed..e0fcb390 100644 --- a/Sources/JavaKitCollection/generated/RandomAccess.swift +++ b/Sources/JavaStdlib/JavaUtil/generated/RandomAccess.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaInterface("java.util.RandomAccess") public struct RandomAccess { diff --git a/Sources/JavaKitCollection/generated/Stack.swift b/Sources/JavaStdlib/JavaUtil/generated/Stack.swift similarity index 93% rename from Sources/JavaKitCollection/generated/Stack.swift rename to Sources/JavaStdlib/JavaUtil/generated/Stack.swift index 867e9d44..636ed03b 100644 --- a/Sources/JavaKitCollection/generated/Stack.swift +++ b/Sources/JavaStdlib/JavaUtil/generated/Stack.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaClass("java.util.Stack") open class Stack: JavaObject { diff --git a/Sources/JavaKitCollection/generated/TreeMap.swift b/Sources/JavaStdlib/JavaUtil/generated/TreeMap.swift similarity index 98% rename from Sources/JavaKitCollection/generated/TreeMap.swift rename to Sources/JavaStdlib/JavaUtil/generated/TreeMap.swift index 7796d555..4bf41ed3 100644 --- a/Sources/JavaKitCollection/generated/TreeMap.swift +++ b/Sources/JavaStdlib/JavaUtil/generated/TreeMap.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaClass("java.util.TreeMap") open class TreeMap: JavaObject { diff --git a/Sources/JavaKitCollection/generated/TreeSet.swift b/Sources/JavaStdlib/JavaUtil/generated/TreeSet.swift similarity index 97% rename from Sources/JavaKitCollection/generated/TreeSet.swift rename to Sources/JavaStdlib/JavaUtil/generated/TreeSet.swift index 7e1807ab..cbfe8979 100644 --- a/Sources/JavaKitCollection/generated/TreeSet.swift +++ b/Sources/JavaStdlib/JavaUtil/generated/TreeSet.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaClass("java.util.TreeSet") open class TreeSet: JavaObject { diff --git a/Sources/JavaKitCollection/swift-java.config b/Sources/JavaStdlib/JavaUtil/swift-java.config similarity index 100% rename from Sources/JavaKitCollection/swift-java.config rename to Sources/JavaStdlib/JavaUtil/swift-java.config diff --git a/Sources/JavaKitFunction/generated/JavaBiConsumer.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaBiConsumer.swift similarity index 91% rename from Sources/JavaKitFunction/generated/JavaBiConsumer.swift rename to Sources/JavaStdlib/JavaUtilFunction/generated/JavaBiConsumer.swift index c5f5b7bf..a8f33127 100644 --- a/Sources/JavaKitFunction/generated/JavaBiConsumer.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaBiConsumer.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaInterface("java.util.function.BiConsumer") public struct JavaBiConsumer { diff --git a/Sources/JavaKitFunction/generated/JavaBiFunction.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaBiFunction.swift similarity index 92% rename from Sources/JavaKitFunction/generated/JavaBiFunction.swift rename to Sources/JavaStdlib/JavaUtilFunction/generated/JavaBiFunction.swift index edecbff5..d83e74a8 100644 --- a/Sources/JavaKitFunction/generated/JavaBiFunction.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaBiFunction.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaInterface("java.util.function.BiFunction") public struct JavaBiFunction { diff --git a/Sources/JavaKitFunction/generated/JavaBiPredicate.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaBiPredicate.swift similarity index 94% rename from Sources/JavaKitFunction/generated/JavaBiPredicate.swift rename to Sources/JavaStdlib/JavaUtilFunction/generated/JavaBiPredicate.swift index 5fbc145e..f1870aa4 100644 --- a/Sources/JavaKitFunction/generated/JavaBiPredicate.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaBiPredicate.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaInterface("java.util.function.BiPredicate") public struct JavaBiPredicate { diff --git a/Sources/JavaKitFunction/generated/JavaBinaryOperator.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaBinaryOperator.swift similarity index 93% rename from Sources/JavaKitFunction/generated/JavaBinaryOperator.swift rename to Sources/JavaStdlib/JavaUtilFunction/generated/JavaBinaryOperator.swift index 3d0b0cd5..a03e9add 100644 --- a/Sources/JavaKitFunction/generated/JavaBinaryOperator.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaBinaryOperator.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaInterface( "java.util.function.BinaryOperator", diff --git a/Sources/JavaKitFunction/generated/JavaBooleanSupplier.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaBooleanSupplier.swift similarity index 85% rename from Sources/JavaKitFunction/generated/JavaBooleanSupplier.swift rename to Sources/JavaStdlib/JavaUtilFunction/generated/JavaBooleanSupplier.swift index eef96025..d6ce66de 100644 --- a/Sources/JavaKitFunction/generated/JavaBooleanSupplier.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaBooleanSupplier.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaInterface("java.util.function.BooleanSupplier") public struct JavaBooleanSupplier { diff --git a/Sources/JavaKitFunction/generated/JavaConsumer.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaConsumer.swift similarity index 90% rename from Sources/JavaKitFunction/generated/JavaConsumer.swift rename to Sources/JavaStdlib/JavaUtilFunction/generated/JavaConsumer.swift index 91eac106..f8e64b2f 100644 --- a/Sources/JavaKitFunction/generated/JavaConsumer.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaConsumer.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaInterface("java.util.function.Consumer") public struct JavaConsumer { diff --git a/Sources/JavaKitFunction/generated/JavaDoubleBinaryOperator.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaDoubleBinaryOperator.swift similarity index 87% rename from Sources/JavaKitFunction/generated/JavaDoubleBinaryOperator.swift rename to Sources/JavaStdlib/JavaUtilFunction/generated/JavaDoubleBinaryOperator.swift index 0415ed90..ee82194d 100644 --- a/Sources/JavaKitFunction/generated/JavaDoubleBinaryOperator.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaDoubleBinaryOperator.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaInterface("java.util.function.DoubleBinaryOperator") public struct JavaDoubleBinaryOperator { diff --git a/Sources/JavaKitFunction/generated/JavaDoubleConsumer.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaDoubleConsumer.swift similarity index 89% rename from Sources/JavaKitFunction/generated/JavaDoubleConsumer.swift rename to Sources/JavaStdlib/JavaUtilFunction/generated/JavaDoubleConsumer.swift index 9c322584..a4a5a48f 100644 --- a/Sources/JavaKitFunction/generated/JavaDoubleConsumer.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaDoubleConsumer.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaInterface("java.util.function.DoubleConsumer") public struct JavaDoubleConsumer { diff --git a/Sources/JavaKitFunction/generated/JavaDoubleFunction.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaDoubleFunction.swift similarity index 86% rename from Sources/JavaKitFunction/generated/JavaDoubleFunction.swift rename to Sources/JavaStdlib/JavaUtilFunction/generated/JavaDoubleFunction.swift index 4ff4f3ef..96879af4 100644 --- a/Sources/JavaKitFunction/generated/JavaDoubleFunction.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaDoubleFunction.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaInterface("java.util.function.DoubleFunction") public struct JavaDoubleFunction { diff --git a/Sources/JavaKitFunction/generated/JavaDoublePredicate.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaDoublePredicate.swift similarity index 92% rename from Sources/JavaKitFunction/generated/JavaDoublePredicate.swift rename to Sources/JavaStdlib/JavaUtilFunction/generated/JavaDoublePredicate.swift index b2add42f..27ac5861 100644 --- a/Sources/JavaKitFunction/generated/JavaDoublePredicate.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaDoublePredicate.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaInterface("java.util.function.DoublePredicate") public struct JavaDoublePredicate { diff --git a/Sources/JavaKitFunction/generated/JavaDoubleSupplier.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaDoubleSupplier.swift similarity index 85% rename from Sources/JavaKitFunction/generated/JavaDoubleSupplier.swift rename to Sources/JavaStdlib/JavaUtilFunction/generated/JavaDoubleSupplier.swift index 184a4353..807668bc 100644 --- a/Sources/JavaKitFunction/generated/JavaDoubleSupplier.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaDoubleSupplier.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaInterface("java.util.function.DoubleSupplier") public struct JavaDoubleSupplier { diff --git a/Sources/JavaKitFunction/generated/JavaDoubleToIntFunction.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaDoubleToIntFunction.swift similarity index 86% rename from Sources/JavaKitFunction/generated/JavaDoubleToIntFunction.swift rename to Sources/JavaStdlib/JavaUtilFunction/generated/JavaDoubleToIntFunction.swift index ae4ab0b3..4de7ab7f 100644 --- a/Sources/JavaKitFunction/generated/JavaDoubleToIntFunction.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaDoubleToIntFunction.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaInterface("java.util.function.DoubleToIntFunction") public struct JavaDoubleToIntFunction { diff --git a/Sources/JavaKitFunction/generated/JavaDoubleToLongFunction.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaDoubleToLongFunction.swift similarity index 86% rename from Sources/JavaKitFunction/generated/JavaDoubleToLongFunction.swift rename to Sources/JavaStdlib/JavaUtilFunction/generated/JavaDoubleToLongFunction.swift index b0c9f9d6..492dbfa6 100644 --- a/Sources/JavaKitFunction/generated/JavaDoubleToLongFunction.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaDoubleToLongFunction.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaInterface("java.util.function.DoubleToLongFunction") public struct JavaDoubleToLongFunction { diff --git a/Sources/JavaKitFunction/generated/JavaDoubleUnaryOperator.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaDoubleUnaryOperator.swift similarity index 94% rename from Sources/JavaKitFunction/generated/JavaDoubleUnaryOperator.swift rename to Sources/JavaStdlib/JavaUtilFunction/generated/JavaDoubleUnaryOperator.swift index eb29139a..9db463ee 100644 --- a/Sources/JavaKitFunction/generated/JavaDoubleUnaryOperator.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaDoubleUnaryOperator.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaInterface("java.util.function.DoubleUnaryOperator") public struct JavaDoubleUnaryOperator { diff --git a/Sources/JavaKitFunction/generated/JavaFunction.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaFunction.swift similarity index 95% rename from Sources/JavaKitFunction/generated/JavaFunction.swift rename to Sources/JavaStdlib/JavaUtilFunction/generated/JavaFunction.swift index 744461a9..6e2361d7 100644 --- a/Sources/JavaKitFunction/generated/JavaFunction.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaFunction.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaInterface("java.util.function.Function") public struct JavaFunction { diff --git a/Sources/JavaKitFunction/generated/JavaIntBinaryOperator.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaIntBinaryOperator.swift similarity index 87% rename from Sources/JavaKitFunction/generated/JavaIntBinaryOperator.swift rename to Sources/JavaStdlib/JavaUtilFunction/generated/JavaIntBinaryOperator.swift index 458885fe..f7a56f18 100644 --- a/Sources/JavaKitFunction/generated/JavaIntBinaryOperator.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaIntBinaryOperator.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaInterface("java.util.function.IntBinaryOperator") public struct JavaIntBinaryOperator { diff --git a/Sources/JavaKitFunction/generated/JavaIntConsumer.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaIntConsumer.swift similarity index 88% rename from Sources/JavaKitFunction/generated/JavaIntConsumer.swift rename to Sources/JavaStdlib/JavaUtilFunction/generated/JavaIntConsumer.swift index 704a4513..62130b88 100644 --- a/Sources/JavaKitFunction/generated/JavaIntConsumer.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaIntConsumer.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaInterface("java.util.function.IntConsumer") public struct JavaIntConsumer { diff --git a/Sources/JavaKitFunction/generated/JavaIntFunction.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaIntFunction.swift similarity index 86% rename from Sources/JavaKitFunction/generated/JavaIntFunction.swift rename to Sources/JavaStdlib/JavaUtilFunction/generated/JavaIntFunction.swift index cd7e7219..c3fcdf1e 100644 --- a/Sources/JavaKitFunction/generated/JavaIntFunction.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaIntFunction.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaInterface("java.util.function.IntFunction") public struct JavaIntFunction { diff --git a/Sources/JavaKitFunction/generated/JavaIntPredicate.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaIntPredicate.swift similarity index 92% rename from Sources/JavaKitFunction/generated/JavaIntPredicate.swift rename to Sources/JavaStdlib/JavaUtilFunction/generated/JavaIntPredicate.swift index 9580ef87..2ca8fcc0 100644 --- a/Sources/JavaKitFunction/generated/JavaIntPredicate.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaIntPredicate.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaInterface("java.util.function.IntPredicate") public struct JavaIntPredicate { diff --git a/Sources/JavaKitFunction/generated/JavaIntSupplier.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaIntSupplier.swift similarity index 84% rename from Sources/JavaKitFunction/generated/JavaIntSupplier.swift rename to Sources/JavaStdlib/JavaUtilFunction/generated/JavaIntSupplier.swift index f0fae86a..05155e79 100644 --- a/Sources/JavaKitFunction/generated/JavaIntSupplier.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaIntSupplier.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaInterface("java.util.function.IntSupplier") public struct JavaIntSupplier { diff --git a/Sources/JavaKitFunction/generated/JavaIntToDoubleFunction.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaIntToDoubleFunction.swift similarity index 86% rename from Sources/JavaKitFunction/generated/JavaIntToDoubleFunction.swift rename to Sources/JavaStdlib/JavaUtilFunction/generated/JavaIntToDoubleFunction.swift index 0a52e5b7..f3efcc6d 100644 --- a/Sources/JavaKitFunction/generated/JavaIntToDoubleFunction.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaIntToDoubleFunction.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaInterface("java.util.function.IntToDoubleFunction") public struct JavaIntToDoubleFunction { diff --git a/Sources/JavaKitFunction/generated/JavaIntToLongFunction.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaIntToLongFunction.swift similarity index 86% rename from Sources/JavaKitFunction/generated/JavaIntToLongFunction.swift rename to Sources/JavaStdlib/JavaUtilFunction/generated/JavaIntToLongFunction.swift index 395dc876..1bbe989c 100644 --- a/Sources/JavaKitFunction/generated/JavaIntToLongFunction.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaIntToLongFunction.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaInterface("java.util.function.IntToLongFunction") public struct JavaIntToLongFunction { diff --git a/Sources/JavaKitFunction/generated/JavaIntUnaryOperator.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaIntUnaryOperator.swift similarity index 93% rename from Sources/JavaKitFunction/generated/JavaIntUnaryOperator.swift rename to Sources/JavaStdlib/JavaUtilFunction/generated/JavaIntUnaryOperator.swift index 221b3a97..04ed0b2b 100644 --- a/Sources/JavaKitFunction/generated/JavaIntUnaryOperator.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaIntUnaryOperator.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaInterface("java.util.function.IntUnaryOperator") public struct JavaIntUnaryOperator { diff --git a/Sources/JavaKitFunction/generated/JavaLongBinaryOperator.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaLongBinaryOperator.swift similarity index 87% rename from Sources/JavaKitFunction/generated/JavaLongBinaryOperator.swift rename to Sources/JavaStdlib/JavaUtilFunction/generated/JavaLongBinaryOperator.swift index 88035edc..1f3ca791 100644 --- a/Sources/JavaKitFunction/generated/JavaLongBinaryOperator.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaLongBinaryOperator.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaInterface("java.util.function.LongBinaryOperator") public struct JavaLongBinaryOperator { diff --git a/Sources/JavaKitFunction/generated/JavaLongConsumer.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaLongConsumer.swift similarity index 88% rename from Sources/JavaKitFunction/generated/JavaLongConsumer.swift rename to Sources/JavaStdlib/JavaUtilFunction/generated/JavaLongConsumer.swift index b0ef6013..82ae2a3b 100644 --- a/Sources/JavaKitFunction/generated/JavaLongConsumer.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaLongConsumer.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaInterface("java.util.function.LongConsumer") public struct JavaLongConsumer { diff --git a/Sources/JavaKitFunction/generated/JavaLongFunction.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaLongFunction.swift similarity index 86% rename from Sources/JavaKitFunction/generated/JavaLongFunction.swift rename to Sources/JavaStdlib/JavaUtilFunction/generated/JavaLongFunction.swift index 2d9a7559..eeed2bd8 100644 --- a/Sources/JavaKitFunction/generated/JavaLongFunction.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaLongFunction.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaInterface("java.util.function.LongFunction") public struct JavaLongFunction { diff --git a/Sources/JavaKitFunction/generated/JavaLongPredicate.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaLongPredicate.swift similarity index 92% rename from Sources/JavaKitFunction/generated/JavaLongPredicate.swift rename to Sources/JavaStdlib/JavaUtilFunction/generated/JavaLongPredicate.swift index 3ed020eb..77f1293e 100644 --- a/Sources/JavaKitFunction/generated/JavaLongPredicate.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaLongPredicate.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaInterface("java.util.function.LongPredicate") public struct JavaLongPredicate { diff --git a/Sources/JavaKitFunction/generated/JavaLongSupplier.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaLongSupplier.swift similarity index 84% rename from Sources/JavaKitFunction/generated/JavaLongSupplier.swift rename to Sources/JavaStdlib/JavaUtilFunction/generated/JavaLongSupplier.swift index 03ad6303..60e5421d 100644 --- a/Sources/JavaKitFunction/generated/JavaLongSupplier.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaLongSupplier.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaInterface("java.util.function.LongSupplier") public struct JavaLongSupplier { diff --git a/Sources/JavaKitFunction/generated/JavaLongToDoubleFunction.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaLongToDoubleFunction.swift similarity index 86% rename from Sources/JavaKitFunction/generated/JavaLongToDoubleFunction.swift rename to Sources/JavaStdlib/JavaUtilFunction/generated/JavaLongToDoubleFunction.swift index 99b56ba3..a115477c 100644 --- a/Sources/JavaKitFunction/generated/JavaLongToDoubleFunction.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaLongToDoubleFunction.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaInterface("java.util.function.LongToDoubleFunction") public struct JavaLongToDoubleFunction { diff --git a/Sources/JavaKitFunction/generated/JavaLongToIntFunction.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaLongToIntFunction.swift similarity index 86% rename from Sources/JavaKitFunction/generated/JavaLongToIntFunction.swift rename to Sources/JavaStdlib/JavaUtilFunction/generated/JavaLongToIntFunction.swift index 2c952a17..984dbda3 100644 --- a/Sources/JavaKitFunction/generated/JavaLongToIntFunction.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaLongToIntFunction.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaInterface("java.util.function.LongToIntFunction") public struct JavaLongToIntFunction { diff --git a/Sources/JavaKitFunction/generated/JavaLongUnaryOperator.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaLongUnaryOperator.swift similarity index 93% rename from Sources/JavaKitFunction/generated/JavaLongUnaryOperator.swift rename to Sources/JavaStdlib/JavaUtilFunction/generated/JavaLongUnaryOperator.swift index fe99e338..7e379b0a 100644 --- a/Sources/JavaKitFunction/generated/JavaLongUnaryOperator.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaLongUnaryOperator.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaInterface("java.util.function.LongUnaryOperator") public struct JavaLongUnaryOperator { diff --git a/Sources/JavaKitFunction/generated/JavaObjDoubleConsumer.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaObjDoubleConsumer.swift similarity index 87% rename from Sources/JavaKitFunction/generated/JavaObjDoubleConsumer.swift rename to Sources/JavaStdlib/JavaUtilFunction/generated/JavaObjDoubleConsumer.swift index cf1ac236..5c19ff03 100644 --- a/Sources/JavaKitFunction/generated/JavaObjDoubleConsumer.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaObjDoubleConsumer.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaInterface("java.util.function.ObjDoubleConsumer") public struct JavaObjDoubleConsumer { diff --git a/Sources/JavaKitFunction/generated/JavaObjIntConsumer.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaObjIntConsumer.swift similarity index 87% rename from Sources/JavaKitFunction/generated/JavaObjIntConsumer.swift rename to Sources/JavaStdlib/JavaUtilFunction/generated/JavaObjIntConsumer.swift index 6c1e3b1e..a511db83 100644 --- a/Sources/JavaKitFunction/generated/JavaObjIntConsumer.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaObjIntConsumer.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaInterface("java.util.function.ObjIntConsumer") public struct JavaObjIntConsumer { diff --git a/Sources/JavaKitFunction/generated/JavaObjLongConsumer.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaObjLongConsumer.swift similarity index 87% rename from Sources/JavaKitFunction/generated/JavaObjLongConsumer.swift rename to Sources/JavaStdlib/JavaUtilFunction/generated/JavaObjLongConsumer.swift index 5486e910..a2c32cfa 100644 --- a/Sources/JavaKitFunction/generated/JavaObjLongConsumer.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaObjLongConsumer.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaInterface("java.util.function.ObjLongConsumer") public struct JavaObjLongConsumer { diff --git a/Sources/JavaKitFunction/generated/JavaPredicate.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaPredicate.swift similarity index 96% rename from Sources/JavaKitFunction/generated/JavaPredicate.swift rename to Sources/JavaStdlib/JavaUtilFunction/generated/JavaPredicate.swift index 9c953e3f..a2de359a 100644 --- a/Sources/JavaKitFunction/generated/JavaPredicate.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaPredicate.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaInterface("java.util.function.Predicate") public struct JavaPredicate { diff --git a/Sources/JavaKitFunction/generated/JavaSupplier.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaSupplier.swift similarity index 85% rename from Sources/JavaKitFunction/generated/JavaSupplier.swift rename to Sources/JavaStdlib/JavaUtilFunction/generated/JavaSupplier.swift index b44740dd..a751ae79 100644 --- a/Sources/JavaKitFunction/generated/JavaSupplier.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaSupplier.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaInterface("java.util.function.Supplier") public struct JavaSupplier { diff --git a/Sources/JavaKitFunction/generated/JavaToDoubleBiFunction.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaToDoubleBiFunction.swift similarity index 89% rename from Sources/JavaKitFunction/generated/JavaToDoubleBiFunction.swift rename to Sources/JavaStdlib/JavaUtilFunction/generated/JavaToDoubleBiFunction.swift index 22ccf62c..739f1f17 100644 --- a/Sources/JavaKitFunction/generated/JavaToDoubleBiFunction.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaToDoubleBiFunction.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaInterface("java.util.function.ToDoubleBiFunction") public struct JavaToDoubleBiFunction { diff --git a/Sources/JavaKitFunction/generated/JavaToDoubleFunction.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaToDoubleFunction.swift similarity index 87% rename from Sources/JavaKitFunction/generated/JavaToDoubleFunction.swift rename to Sources/JavaStdlib/JavaUtilFunction/generated/JavaToDoubleFunction.swift index bf1c1d37..acdf7adb 100644 --- a/Sources/JavaKitFunction/generated/JavaToDoubleFunction.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaToDoubleFunction.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaInterface("java.util.function.ToDoubleFunction") public struct JavaToDoubleFunction { diff --git a/Sources/JavaKitFunction/generated/JavaToIntBiFunction.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaToIntBiFunction.swift similarity index 88% rename from Sources/JavaKitFunction/generated/JavaToIntBiFunction.swift rename to Sources/JavaStdlib/JavaUtilFunction/generated/JavaToIntBiFunction.swift index 6ebc0ff1..e1fdcc0a 100644 --- a/Sources/JavaKitFunction/generated/JavaToIntBiFunction.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaToIntBiFunction.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaInterface("java.util.function.ToIntBiFunction") public struct JavaToIntBiFunction { diff --git a/Sources/JavaKitFunction/generated/JavaToIntFunction.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaToIntFunction.swift similarity index 87% rename from Sources/JavaKitFunction/generated/JavaToIntFunction.swift rename to Sources/JavaStdlib/JavaUtilFunction/generated/JavaToIntFunction.swift index c960913d..4d963c57 100644 --- a/Sources/JavaKitFunction/generated/JavaToIntFunction.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaToIntFunction.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaInterface("java.util.function.ToIntFunction") public struct JavaToIntFunction { diff --git a/Sources/JavaKitFunction/generated/JavaToLongBiFunction.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaToLongBiFunction.swift similarity index 88% rename from Sources/JavaKitFunction/generated/JavaToLongBiFunction.swift rename to Sources/JavaStdlib/JavaUtilFunction/generated/JavaToLongBiFunction.swift index 93d0fc47..fb42c3e4 100644 --- a/Sources/JavaKitFunction/generated/JavaToLongBiFunction.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaToLongBiFunction.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaInterface("java.util.function.ToLongBiFunction") public struct JavaToLongBiFunction { diff --git a/Sources/JavaKitFunction/generated/JavaToLongFunction.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaToLongFunction.swift similarity index 87% rename from Sources/JavaKitFunction/generated/JavaToLongFunction.swift rename to Sources/JavaStdlib/JavaUtilFunction/generated/JavaToLongFunction.swift index f4fd5767..e34b5bd0 100644 --- a/Sources/JavaKitFunction/generated/JavaToLongFunction.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaToLongFunction.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaInterface("java.util.function.ToLongFunction") public struct JavaToLongFunction { diff --git a/Sources/JavaKitFunction/generated/JavaUnaryOperator.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaUnaryOperator.swift similarity index 95% rename from Sources/JavaKitFunction/generated/JavaUnaryOperator.swift rename to Sources/JavaStdlib/JavaUtilFunction/generated/JavaUnaryOperator.swift index 232283ba..a31be86e 100644 --- a/Sources/JavaKitFunction/generated/JavaUnaryOperator.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaUnaryOperator.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaInterface( "java.util.function.UnaryOperator", extends: JavaFunction.self) diff --git a/Sources/JavaKitFunction/swift-java.config b/Sources/JavaStdlib/JavaUtilFunction/swift-java.config similarity index 100% rename from Sources/JavaKitFunction/swift-java.config rename to Sources/JavaStdlib/JavaUtilFunction/swift-java.config diff --git a/Sources/JavaKitJar/generated/Attributes.swift b/Sources/JavaStdlib/JavaUtilJar/generated/Attributes.swift similarity index 98% rename from Sources/JavaKitJar/generated/Attributes.swift rename to Sources/JavaStdlib/JavaUtilJar/generated/Attributes.swift index f173c98d..710ce640 100644 --- a/Sources/JavaKitJar/generated/Attributes.swift +++ b/Sources/JavaStdlib/JavaUtilJar/generated/Attributes.swift @@ -1,7 +1,7 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaKitCollection -import JavaRuntime +import SwiftJava +import JavaUtil +import CJNI @JavaClass("java.util.jar.Attributes") open class Attributes: JavaObject { diff --git a/Sources/JavaKitJar/generated/JarEntry.swift b/Sources/JavaStdlib/JavaUtilJar/generated/JarEntry.swift similarity index 98% rename from Sources/JavaKitJar/generated/JarEntry.swift rename to Sources/JavaStdlib/JavaUtilJar/generated/JarEntry.swift index 3a90d6a8..7140cb97 100644 --- a/Sources/JavaKitJar/generated/JarEntry.swift +++ b/Sources/JavaStdlib/JavaUtilJar/generated/JarEntry.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaClass("java.util.jar.JarEntry") open class JarEntry: ZipEntry { diff --git a/Sources/JavaKitJar/generated/JarFile.swift b/Sources/JavaStdlib/JavaUtilJar/generated/JarFile.swift similarity index 98% rename from Sources/JavaKitJar/generated/JarFile.swift rename to Sources/JavaStdlib/JavaUtilJar/generated/JarFile.swift index d5ea9969..db84e626 100644 --- a/Sources/JavaKitJar/generated/JarFile.swift +++ b/Sources/JavaStdlib/JavaUtilJar/generated/JarFile.swift @@ -1,7 +1,7 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaKitCollection -import JavaRuntime +import SwiftJava +import JavaUtil +import CJNI @JavaClass("java.util.jar.JarFile") open class JarFile: JavaObject { diff --git a/Sources/JavaKitJar/generated/JarInputStream.swift b/Sources/JavaStdlib/JavaUtilJar/generated/JarInputStream.swift similarity index 98% rename from Sources/JavaKitJar/generated/JarInputStream.swift rename to Sources/JavaStdlib/JavaUtilJar/generated/JarInputStream.swift index f6d121d9..7d2ce423 100644 --- a/Sources/JavaKitJar/generated/JarInputStream.swift +++ b/Sources/JavaStdlib/JavaUtilJar/generated/JarInputStream.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaClass("java.util.jar.JarInputStream") open class JarInputStream: JavaObject { diff --git a/Sources/JavaKitJar/generated/JarOutputStream.swift b/Sources/JavaStdlib/JavaUtilJar/generated/JarOutputStream.swift similarity index 98% rename from Sources/JavaKitJar/generated/JarOutputStream.swift rename to Sources/JavaStdlib/JavaUtilJar/generated/JarOutputStream.swift index e13dc973..79a7c14e 100644 --- a/Sources/JavaKitJar/generated/JarOutputStream.swift +++ b/Sources/JavaStdlib/JavaUtilJar/generated/JarOutputStream.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaClass("java.util.jar.JarOutputStream") open class JarOutputStream: JavaObject { diff --git a/Sources/JavaKitJar/generated/Manifest.swift b/Sources/JavaStdlib/JavaUtilJar/generated/Manifest.swift similarity index 95% rename from Sources/JavaKitJar/generated/Manifest.swift rename to Sources/JavaStdlib/JavaUtilJar/generated/Manifest.swift index 101af57c..b43b9e85 100644 --- a/Sources/JavaKitJar/generated/Manifest.swift +++ b/Sources/JavaStdlib/JavaUtilJar/generated/Manifest.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaClass("java.util.jar.Manifest") open class Manifest: JavaObject { diff --git a/Sources/JavaKitJar/generated/ZipEntry.swift b/Sources/JavaStdlib/JavaUtilJar/generated/ZipEntry.swift similarity index 99% rename from Sources/JavaKitJar/generated/ZipEntry.swift rename to Sources/JavaStdlib/JavaUtilJar/generated/ZipEntry.swift index 6a0fbd20..e276ae2a 100644 --- a/Sources/JavaKitJar/generated/ZipEntry.swift +++ b/Sources/JavaStdlib/JavaUtilJar/generated/ZipEntry.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaKit -import JavaRuntime +import SwiftJava +import CJNI @JavaClass("java.util.zip.ZipEntry") open class ZipEntry: JavaObject { diff --git a/Sources/JavaKitJar/swift-java.config b/Sources/JavaStdlib/JavaUtilJar/swift-java.config similarity index 100% rename from Sources/JavaKitJar/swift-java.config rename to Sources/JavaStdlib/JavaUtilJar/swift-java.config diff --git a/Sources/JavaStdlib/README_PACKAGE_CONVENTION.md b/Sources/JavaStdlib/README_PACKAGE_CONVENTION.md new file mode 100644 index 00000000..ab65fa17 --- /dev/null +++ b/Sources/JavaStdlib/README_PACKAGE_CONVENTION.md @@ -0,0 +1,13 @@ +# Extracted Java Modules + +This directory contains Swift bindings for common Java standard library packages. +These pre-built bindings to solve a circular dependency problem - SwiftJava tools need these types to process and generate other bindings. + +You can also use these bindings directly in your SwiftJava programs to call Java classes without having to generate wrappers each time. + +The naming follows this pattern: Java package names become Swift target names. Example: `java.lang.util` becomes `JavaLangUtil`. + +Since Swift doesn't have namespaces like Java, all types appear at the top level in Swift. To avoid naming conflicts, +some types may be prefixed with 'J' (e.g. `JList` to avoid confusion with Swift native types). + +To see which Java types are included and any naming changes, check the `swift-java.config` file in each module. \ No newline at end of file diff --git a/Sources/JavaKit/AnyJavaObject.swift b/Sources/SwiftJava/AnyJavaObject.swift similarity index 99% rename from Sources/JavaKit/AnyJavaObject.swift rename to Sources/SwiftJava/AnyJavaObject.swift index 5e0a88d0..02b9d70b 100644 --- a/Sources/JavaKit/AnyJavaObject.swift +++ b/Sources/SwiftJava/AnyJavaObject.swift @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -import JavaRuntime +import CJNI /// Protocol that describes Swift types that are bridged to a Java class type. /// diff --git a/Sources/JavaKit/BridgedValues/JavaValue+Array.swift b/Sources/SwiftJava/BridgedValues/JavaValue+Array.swift similarity index 100% rename from Sources/JavaKit/BridgedValues/JavaValue+Array.swift rename to Sources/SwiftJava/BridgedValues/JavaValue+Array.swift diff --git a/Sources/JavaKit/BridgedValues/JavaValue+Bool.swift b/Sources/SwiftJava/BridgedValues/JavaValue+Bool.swift similarity index 100% rename from Sources/JavaKit/BridgedValues/JavaValue+Bool.swift rename to Sources/SwiftJava/BridgedValues/JavaValue+Bool.swift diff --git a/Sources/JavaKit/BridgedValues/JavaValue+FloatingPoint.swift b/Sources/SwiftJava/BridgedValues/JavaValue+FloatingPoint.swift similarity index 100% rename from Sources/JavaKit/BridgedValues/JavaValue+FloatingPoint.swift rename to Sources/SwiftJava/BridgedValues/JavaValue+FloatingPoint.swift diff --git a/Sources/JavaKit/BridgedValues/JavaValue+Integers.swift b/Sources/SwiftJava/BridgedValues/JavaValue+Integers.swift similarity index 100% rename from Sources/JavaKit/BridgedValues/JavaValue+Integers.swift rename to Sources/SwiftJava/BridgedValues/JavaValue+Integers.swift diff --git a/Sources/JavaKit/BridgedValues/JavaValue+String.swift b/Sources/SwiftJava/BridgedValues/JavaValue+String.swift similarity index 100% rename from Sources/JavaKit/BridgedValues/JavaValue+String.swift rename to Sources/SwiftJava/BridgedValues/JavaValue+String.swift diff --git a/Sources/JavaKit/Documentation.docc/JavaKit.md b/Sources/SwiftJava/Documentation.docc/JavaKit.md similarity index 99% rename from Sources/JavaKit/Documentation.docc/JavaKit.md rename to Sources/SwiftJava/Documentation.docc/JavaKit.md index fe0f50ba..a050e88b 100644 --- a/Sources/JavaKit/Documentation.docc/JavaKit.md +++ b/Sources/SwiftJava/Documentation.docc/JavaKit.md @@ -200,7 +200,7 @@ let primes = sieveClass.findPrimes(100) // returns a List? Putting it all together, we can define a main program in `Sources/JavaSieve/main.swift` that looks like this: ```swift -import JavaKit +import SwiftJNI let jvm = try JavaVirtualMachine.shared(classpath: ["QuadraticSieve-1.0.jar"]) do { diff --git a/Sources/JavaKit/Exceptions/Exception+Error.swift b/Sources/SwiftJava/Exceptions/Exception+Error.swift similarity index 100% rename from Sources/JavaKit/Exceptions/Exception+Error.swift rename to Sources/SwiftJava/Exceptions/Exception+Error.swift diff --git a/Sources/JavaKit/Exceptions/ExceptionHandling.swift b/Sources/SwiftJava/Exceptions/ExceptionHandling.swift similarity index 100% rename from Sources/JavaKit/Exceptions/ExceptionHandling.swift rename to Sources/SwiftJava/Exceptions/ExceptionHandling.swift diff --git a/Sources/JavaKit/Exceptions/Throwable+Error.swift b/Sources/SwiftJava/Exceptions/Throwable+Error.swift similarity index 100% rename from Sources/JavaKit/Exceptions/Throwable+Error.swift rename to Sources/SwiftJava/Exceptions/Throwable+Error.swift diff --git a/Sources/SwiftJava/Helpers/_JNIMethodIDCache.swift b/Sources/SwiftJava/Helpers/_JNIMethodIDCache.swift new file mode 100644 index 00000000..a67d225f --- /dev/null +++ b/Sources/SwiftJava/Helpers/_JNIMethodIDCache.swift @@ -0,0 +1,59 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +/// A cache used to hold references for JNI method and classes. +/// +/// This type is used internally in by the outputted JExtract wrappers +/// to improve performance of any JNI lookups. +public final class _JNIMethodIDCache: Sendable { + public struct Method: Hashable { + public let name: String + public let signature: String + + public init(name: String, signature: String) { + self.name = name + self.signature = signature + } + } + + nonisolated(unsafe) let _class: jclass? + nonisolated(unsafe) let methods: [Method: jmethodID] + + public var javaClass: jclass { + self._class! + } + + public init(environment: UnsafeMutablePointer!, className: String, methods: [Method]) { + guard let clazz = environment.interface.FindClass(environment, className) else { + fatalError("Class \(className) could not be found!") + } + self._class = environment.interface.NewGlobalRef(environment, clazz)! + self.methods = methods.reduce(into: [:]) { (result, method) in + if let methodID = environment.interface.GetMethodID(environment, clazz, method.name, method.signature) { + result[method] = methodID + } else { + fatalError("Method \(method.signature) with signature \(method.signature) not found in class \(className)") + } + } + } + + + public subscript(_ method: Method) -> jmethodID? { + methods[method] + } + + public func cleanup(environment: UnsafeMutablePointer!) { + environment.interface.DeleteGlobalRef(environment, self._class) + } +} diff --git a/Sources/JavaKit/JavaClass+Initialization.swift b/Sources/SwiftJava/JavaClass+Initialization.swift similarity index 98% rename from Sources/JavaKit/JavaClass+Initialization.swift rename to Sources/SwiftJava/JavaClass+Initialization.swift index d443120f..8101c37a 100644 --- a/Sources/JavaKit/JavaClass+Initialization.swift +++ b/Sources/SwiftJava/JavaClass+Initialization.swift @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -import JavaRuntime +import CJNI extension JavaClass { public typealias ObjectType = T diff --git a/Sources/JavaKit/JavaEnvironment.swift b/Sources/SwiftJava/JavaEnvironment.swift similarity index 97% rename from Sources/JavaKit/JavaEnvironment.swift rename to Sources/SwiftJava/JavaEnvironment.swift index 422262da..fd6a626b 100644 --- a/Sources/JavaKit/JavaEnvironment.swift +++ b/Sources/SwiftJava/JavaEnvironment.swift @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -import JavaRuntime +import CJNI #if canImport(Android) typealias JNINativeInterface_ = JNINativeInterface diff --git a/Sources/JavaKit/JavaKitVM/JavaVirtualMachine.swift b/Sources/SwiftJava/JavaKitVM/JavaVirtualMachine.swift similarity index 100% rename from Sources/JavaKit/JavaKitVM/JavaVirtualMachine.swift rename to Sources/SwiftJava/JavaKitVM/JavaVirtualMachine.swift diff --git a/Sources/JavaKit/JavaKitVM/LockedState.swift b/Sources/SwiftJava/JavaKitVM/LockedState.swift similarity index 100% rename from Sources/JavaKit/JavaKitVM/LockedState.swift rename to Sources/SwiftJava/JavaKitVM/LockedState.swift diff --git a/Sources/JavaKit/JavaKitVM/ThreadLocalStorage.swift b/Sources/SwiftJava/JavaKitVM/ThreadLocalStorage.swift similarity index 100% rename from Sources/JavaKit/JavaKitVM/ThreadLocalStorage.swift rename to Sources/SwiftJava/JavaKitVM/ThreadLocalStorage.swift diff --git a/Sources/JavaKit/JavaObject+Inheritance.swift b/Sources/SwiftJava/JavaObject+Inheritance.swift similarity index 98% rename from Sources/JavaKit/JavaObject+Inheritance.swift rename to Sources/SwiftJava/JavaObject+Inheritance.swift index 43d86c2a..aa80fa54 100644 --- a/Sources/JavaKit/JavaObject+Inheritance.swift +++ b/Sources/SwiftJava/JavaObject+Inheritance.swift @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -import JavaRuntime +import CJNI extension AnyJavaObject { /// Look up the other class type diff --git a/Sources/JavaKit/JavaObject+MethodCalls.swift b/Sources/SwiftJava/JavaObject+MethodCalls.swift similarity index 99% rename from Sources/JavaKit/JavaObject+MethodCalls.swift rename to Sources/SwiftJava/JavaObject+MethodCalls.swift index 9f02a58d..1a62d0f4 100644 --- a/Sources/JavaKit/JavaObject+MethodCalls.swift +++ b/Sources/SwiftJava/JavaObject+MethodCalls.swift @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -import JavaRuntime +import CJNI import JavaTypes /// Produce the mangling for a method with the given argument and result types. diff --git a/Sources/JavaKit/JavaObjectHolder.swift b/Sources/SwiftJava/JavaObjectHolder.swift similarity index 98% rename from Sources/JavaKit/JavaObjectHolder.swift rename to Sources/SwiftJava/JavaObjectHolder.swift index 173991c9..50f60a82 100644 --- a/Sources/JavaKit/JavaObjectHolder.swift +++ b/Sources/SwiftJava/JavaObjectHolder.swift @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -import JavaRuntime +import CJNI /// Stores a reference to a Java object, managing it as a global reference so /// that the Java virtual machine will not move or deallocate the object diff --git a/Sources/JavaKit/JavaRuntime+Reexport.swift b/Sources/SwiftJava/JavaRuntime+Reexport.swift similarity index 94% rename from Sources/JavaKit/JavaRuntime+Reexport.swift rename to Sources/SwiftJava/JavaRuntime+Reexport.swift index e65d4e18..f1a19e1c 100644 --- a/Sources/JavaKit/JavaRuntime+Reexport.swift +++ b/Sources/SwiftJava/JavaRuntime+Reexport.swift @@ -12,4 +12,4 @@ // //===----------------------------------------------------------------------===// -@_exported import JavaRuntime +@_exported import CJNI diff --git a/Sources/JavaKit/JavaValue.swift b/Sources/SwiftJava/JavaValue.swift similarity index 99% rename from Sources/JavaKit/JavaValue.swift rename to Sources/SwiftJava/JavaValue.swift index 0f208144..a740eb50 100644 --- a/Sources/JavaKit/JavaValue.swift +++ b/Sources/SwiftJava/JavaValue.swift @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -import JavaRuntime +import CJNI import JavaTypes /// Describes a type that can be bridged with Java. diff --git a/Sources/JavaKit/Macros.swift b/Sources/SwiftJava/Macros.swift similarity index 90% rename from Sources/JavaKit/Macros.swift rename to Sources/SwiftJava/Macros.swift index 029344d8..8e1bb86c 100644 --- a/Sources/JavaKit/Macros.swift +++ b/Sources/SwiftJava/Macros.swift @@ -43,7 +43,7 @@ public macro JavaClass( _ fullClassName: String, extends: (any AnyJavaObject.Type)? = nil, implements: (any AnyJavaObject.Type)?... -) = #externalMacro(module: "JavaKitMacros", type: "JavaClassMacro") +) = #externalMacro(module: "SwiftJavaMacros", type: "JavaClassMacro") /// Attached macro that declares that a particular `struct` type is a wrapper around a Java interface. /// @@ -74,7 +74,7 @@ public macro JavaClass( ) @attached(extension, conformances: AnyJavaObject) public macro JavaInterface(_ fullClassName: String, extends: (any AnyJavaObject.Type)?...) = - #externalMacro(module: "JavaKitMacros", type: "JavaClassMacro") + #externalMacro(module: "SwiftJavaMacros", type: "JavaClassMacro") /// Attached macro that turns a Swift property into one that accesses a Java field on the underlying Java object. /// @@ -88,7 +88,7 @@ public macro JavaInterface(_ fullClassName: String, extends: (any AnyJavaObject. /// } /// ``` @attached(accessor) -public macro JavaField(_ javaFieldName: String? = nil, isFinal: Bool = false) = #externalMacro(module: "JavaKitMacros", type: "JavaFieldMacro") +public macro JavaField(_ javaFieldName: String? = nil, isFinal: Bool = false) = #externalMacro(module: "SwiftJavaMacros", type: "JavaFieldMacro") /// Attached macro that turns a Swift property into one that accesses a Java static field on the underlying Java object. @@ -102,7 +102,7 @@ public macro JavaField(_ javaFieldName: String? = nil, isFinal: Bool = false) = /// } /// ``` @attached(accessor) -public macro JavaStaticField(_ javaFieldName: String? = nil, isFinal: Bool = false) = #externalMacro(module: "JavaKitMacros", type: "JavaFieldMacro") +public macro JavaStaticField(_ javaFieldName: String? = nil, isFinal: Bool = false) = #externalMacro(module: "SwiftJavaMacros", type: "JavaFieldMacro") /// Attached macro that turns a Swift method into one that wraps a Java method on the underlying Java object. /// @@ -124,7 +124,7 @@ public macro JavaStaticField(_ javaFieldName: String? = nil, isFinal: Bool = fal /// /// corresponds to the Java constructor `HelloSwift(String name)`. @attached(body) -public macro JavaMethod() = #externalMacro(module: "JavaKitMacros", type: "JavaMethodMacro") +public macro JavaMethod() = #externalMacro(module: "SwiftJavaMacros", type: "JavaMethodMacro") /// Attached macro that turns a Swift method on JavaClass into one that wraps /// a Java static method on the underlying Java class object. @@ -136,7 +136,7 @@ public macro JavaMethod() = #externalMacro(module: "JavaKitMacros", type: "JavaM /// func sayHelloBack(_ i: Int32) -> Double /// ``` @attached(body) -public macro JavaStaticMethod() = #externalMacro(module: "JavaKitMacros", type: "JavaMethodMacro") +public macro JavaStaticMethod() = #externalMacro(module: "SwiftJavaMacros", type: "JavaMethodMacro") /// Macro that marks extensions to specify that all of the @JavaMethod /// methods are implementations of Java methods spelled as `native`. @@ -161,4 +161,4 @@ public macro JavaStaticMethod() = #externalMacro(module: "JavaKitMacros", type: /// } /// ``` @attached(peer) -public macro JavaImplementation(_ fullClassName: String) = #externalMacro(module: "JavaKitMacros", type: "JavaImplementationMacro") +public macro JavaImplementation(_ fullClassName: String) = #externalMacro(module: "SwiftJavaMacros", type: "JavaImplementationMacro") diff --git a/Sources/JavaKit/Optional+JavaObject.swift b/Sources/SwiftJava/Optional+JavaObject.swift similarity index 99% rename from Sources/JavaKit/Optional+JavaObject.swift rename to Sources/SwiftJava/Optional+JavaObject.swift index 7aff4294..f34ef2b3 100644 --- a/Sources/JavaKit/Optional+JavaObject.swift +++ b/Sources/SwiftJava/Optional+JavaObject.swift @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -import JavaRuntime +import CJNI import JavaTypes extension Optional: JavaValue where Wrapped: AnyJavaObject { diff --git a/Sources/JavaKit/Optional+JavaOptional.swift b/Sources/SwiftJava/Optional+JavaOptional.swift similarity index 100% rename from Sources/JavaKit/Optional+JavaOptional.swift rename to Sources/SwiftJava/Optional+JavaOptional.swift diff --git a/Sources/JavaKit/generated/Appendable.swift b/Sources/SwiftJava/generated/Appendable.swift similarity index 95% rename from Sources/JavaKit/generated/Appendable.swift rename to Sources/SwiftJava/generated/Appendable.swift index 5c6663f2..7ff4f97e 100644 --- a/Sources/JavaKit/generated/Appendable.swift +++ b/Sources/SwiftJava/generated/Appendable.swift @@ -1,5 +1,5 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaRuntime +import CJNI @JavaInterface("java.lang.Appendable") public struct Appendable { diff --git a/Sources/JavaKit/generated/CharSequence.swift b/Sources/SwiftJava/generated/CharSequence.swift similarity index 96% rename from Sources/JavaKit/generated/CharSequence.swift rename to Sources/SwiftJava/generated/CharSequence.swift index cab17273..c6e3d5be 100644 --- a/Sources/JavaKit/generated/CharSequence.swift +++ b/Sources/SwiftJava/generated/CharSequence.swift @@ -1,5 +1,5 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaRuntime +import CJNI @JavaInterface("java.lang.CharSequence") public struct CharSequence { diff --git a/Sources/JavaKit/generated/Exception.swift b/Sources/SwiftJava/generated/Exception.swift similarity index 96% rename from Sources/JavaKit/generated/Exception.swift rename to Sources/SwiftJava/generated/Exception.swift index 6fc9de8c..8361f1b0 100644 --- a/Sources/JavaKit/generated/Exception.swift +++ b/Sources/SwiftJava/generated/Exception.swift @@ -1,5 +1,5 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaRuntime +import CJNI @JavaClass("java.lang.Exception") open class Exception: Throwable { diff --git a/Sources/JavaKit/generated/JavaArray.swift b/Sources/SwiftJava/generated/JavaArray.swift similarity index 99% rename from Sources/JavaKit/generated/JavaArray.swift rename to Sources/SwiftJava/generated/JavaArray.swift index 147f24df..65d3f88f 100644 --- a/Sources/JavaKit/generated/JavaArray.swift +++ b/Sources/SwiftJava/generated/JavaArray.swift @@ -1,5 +1,5 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaRuntime +import CJNI @JavaClass("java.lang.reflect.Array") open class JavaArray: JavaObject { diff --git a/Sources/JavaKit/generated/JavaBoolean.swift b/Sources/SwiftJava/generated/JavaBoolean.swift similarity index 98% rename from Sources/JavaKit/generated/JavaBoolean.swift rename to Sources/SwiftJava/generated/JavaBoolean.swift index 0ab51f6d..995afc57 100644 --- a/Sources/JavaKit/generated/JavaBoolean.swift +++ b/Sources/SwiftJava/generated/JavaBoolean.swift @@ -1,5 +1,5 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaRuntime +import CJNI @JavaClass("java.lang.Boolean") open class JavaBoolean: JavaObject { diff --git a/Sources/JavaKit/generated/JavaByte.swift b/Sources/SwiftJava/generated/JavaByte.swift similarity index 99% rename from Sources/JavaKit/generated/JavaByte.swift rename to Sources/SwiftJava/generated/JavaByte.swift index e75c5996..a9ed639b 100644 --- a/Sources/JavaKit/generated/JavaByte.swift +++ b/Sources/SwiftJava/generated/JavaByte.swift @@ -1,5 +1,5 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaRuntime +import CJNI @JavaClass("java.lang.Byte") open class JavaByte: JavaNumber { diff --git a/Sources/JavaKit/generated/JavaCharacter.swift b/Sources/SwiftJava/generated/JavaCharacter.swift similarity index 99% rename from Sources/JavaKit/generated/JavaCharacter.swift rename to Sources/SwiftJava/generated/JavaCharacter.swift index eead7dfd..308a7fce 100644 --- a/Sources/JavaKit/generated/JavaCharacter.swift +++ b/Sources/SwiftJava/generated/JavaCharacter.swift @@ -1,5 +1,5 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaRuntime +import CJNI @JavaClass("java.lang.Character") open class JavaCharacter: JavaObject { diff --git a/Sources/JavaKit/generated/JavaClass.swift b/Sources/SwiftJava/generated/JavaClass.swift similarity index 99% rename from Sources/JavaKit/generated/JavaClass.swift rename to Sources/SwiftJava/generated/JavaClass.swift index 03d7f5e6..1144482f 100644 --- a/Sources/JavaKit/generated/JavaClass.swift +++ b/Sources/SwiftJava/generated/JavaClass.swift @@ -1,5 +1,5 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaRuntime +import CJNI @JavaClass("java.lang.Class") open class JavaClass: JavaObject { diff --git a/Sources/JavaKit/generated/JavaClassLoader.swift b/Sources/SwiftJava/generated/JavaClassLoader.swift similarity index 99% rename from Sources/JavaKit/generated/JavaClassLoader.swift rename to Sources/SwiftJava/generated/JavaClassLoader.swift index 6c877cc3..b6fabea4 100644 --- a/Sources/JavaKit/generated/JavaClassLoader.swift +++ b/Sources/SwiftJava/generated/JavaClassLoader.swift @@ -1,5 +1,5 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaRuntime +import CJNI @JavaClass("java.lang.ClassLoader") open class JavaClassLoader: JavaObject { diff --git a/Sources/JavaKit/generated/JavaDouble.swift b/Sources/SwiftJava/generated/JavaDouble.swift similarity index 99% rename from Sources/JavaKit/generated/JavaDouble.swift rename to Sources/SwiftJava/generated/JavaDouble.swift index efa77a95..9d979fb3 100644 --- a/Sources/JavaKit/generated/JavaDouble.swift +++ b/Sources/SwiftJava/generated/JavaDouble.swift @@ -1,5 +1,5 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaRuntime +import CJNI @JavaClass("java.lang.Double") open class JavaDouble: JavaNumber { diff --git a/Sources/JavaKit/generated/JavaError.swift b/Sources/SwiftJava/generated/JavaError.swift similarity index 96% rename from Sources/JavaKit/generated/JavaError.swift rename to Sources/SwiftJava/generated/JavaError.swift index 97c2e555..da3c4218 100644 --- a/Sources/JavaKit/generated/JavaError.swift +++ b/Sources/SwiftJava/generated/JavaError.swift @@ -1,5 +1,5 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaRuntime +import CJNI @JavaClass("java.lang.Error") open class JavaError: Throwable { diff --git a/Sources/JavaKit/generated/JavaFloat.swift b/Sources/SwiftJava/generated/JavaFloat.swift similarity index 99% rename from Sources/JavaKit/generated/JavaFloat.swift rename to Sources/SwiftJava/generated/JavaFloat.swift index 0c38d1ae..9b11957e 100644 --- a/Sources/JavaKit/generated/JavaFloat.swift +++ b/Sources/SwiftJava/generated/JavaFloat.swift @@ -1,5 +1,5 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaRuntime +import CJNI @JavaClass("java.lang.Float") open class JavaFloat: JavaNumber { diff --git a/Sources/JavaKit/generated/JavaInteger.swift b/Sources/SwiftJava/generated/JavaInteger.swift similarity index 99% rename from Sources/JavaKit/generated/JavaInteger.swift rename to Sources/SwiftJava/generated/JavaInteger.swift index 646aac9e..286bc525 100644 --- a/Sources/JavaKit/generated/JavaInteger.swift +++ b/Sources/SwiftJava/generated/JavaInteger.swift @@ -1,5 +1,5 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaRuntime +import CJNI @JavaClass("java.lang.Integer") open class JavaInteger: JavaNumber { diff --git a/Sources/JavaKit/generated/JavaLong.swift b/Sources/SwiftJava/generated/JavaLong.swift similarity index 99% rename from Sources/JavaKit/generated/JavaLong.swift rename to Sources/SwiftJava/generated/JavaLong.swift index 7ff70efa..9e4a183e 100644 --- a/Sources/JavaKit/generated/JavaLong.swift +++ b/Sources/SwiftJava/generated/JavaLong.swift @@ -1,5 +1,5 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaRuntime +import CJNI @JavaClass("java.lang.Long") open class JavaLong: JavaNumber { diff --git a/Sources/JavaKit/generated/JavaNumber.swift b/Sources/SwiftJava/generated/JavaNumber.swift similarity index 96% rename from Sources/JavaKit/generated/JavaNumber.swift rename to Sources/SwiftJava/generated/JavaNumber.swift index 414cd89b..81d0bacd 100644 --- a/Sources/JavaKit/generated/JavaNumber.swift +++ b/Sources/SwiftJava/generated/JavaNumber.swift @@ -1,5 +1,5 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaRuntime +import CJNI @JavaClass("java.lang.Number") open class JavaNumber: JavaObject { diff --git a/Sources/JavaKit/generated/JavaObject.swift b/Sources/SwiftJava/generated/JavaObject.swift similarity index 97% rename from Sources/JavaKit/generated/JavaObject.swift rename to Sources/SwiftJava/generated/JavaObject.swift index 07a6eaff..37e48b2d 100644 --- a/Sources/JavaKit/generated/JavaObject.swift +++ b/Sources/SwiftJava/generated/JavaObject.swift @@ -1,5 +1,5 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaRuntime +import CJNI @JavaClass("java.lang.Object") open class JavaObject { diff --git a/Sources/JavaKit/generated/JavaOptional.swift b/Sources/SwiftJava/generated/JavaOptional.swift similarity index 98% rename from Sources/JavaKit/generated/JavaOptional.swift rename to Sources/SwiftJava/generated/JavaOptional.swift index bd77cfed..7615c738 100644 --- a/Sources/JavaKit/generated/JavaOptional.swift +++ b/Sources/SwiftJava/generated/JavaOptional.swift @@ -1,5 +1,5 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaRuntime +import CJNI @JavaClass("java.util.Optional") open class JavaOptional: JavaObject { diff --git a/Sources/JavaKit/generated/JavaOptionalDouble.swift b/Sources/SwiftJava/generated/JavaOptionalDouble.swift similarity index 98% rename from Sources/JavaKit/generated/JavaOptionalDouble.swift rename to Sources/SwiftJava/generated/JavaOptionalDouble.swift index 5926282a..8f1514be 100644 --- a/Sources/JavaKit/generated/JavaOptionalDouble.swift +++ b/Sources/SwiftJava/generated/JavaOptionalDouble.swift @@ -1,5 +1,5 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaRuntime +import CJNI @JavaClass("java.util.OptionalDouble") open class JavaOptionalDouble: JavaObject { diff --git a/Sources/JavaKit/generated/JavaOptionalInt.swift b/Sources/SwiftJava/generated/JavaOptionalInt.swift similarity index 97% rename from Sources/JavaKit/generated/JavaOptionalInt.swift rename to Sources/SwiftJava/generated/JavaOptionalInt.swift index 1237a085..9543d090 100644 --- a/Sources/JavaKit/generated/JavaOptionalInt.swift +++ b/Sources/SwiftJava/generated/JavaOptionalInt.swift @@ -1,5 +1,5 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaRuntime +import CJNI @JavaClass("java.util.OptionalInt") open class JavaOptionalInt: JavaObject { diff --git a/Sources/JavaKit/generated/JavaOptionalLong.swift b/Sources/SwiftJava/generated/JavaOptionalLong.swift similarity index 97% rename from Sources/JavaKit/generated/JavaOptionalLong.swift rename to Sources/SwiftJava/generated/JavaOptionalLong.swift index 79a9e06f..ac9b4409 100644 --- a/Sources/JavaKit/generated/JavaOptionalLong.swift +++ b/Sources/SwiftJava/generated/JavaOptionalLong.swift @@ -1,5 +1,5 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaRuntime +import CJNI @JavaClass("java.util.OptionalLong") open class JavaOptionalLong: JavaObject { diff --git a/Sources/JavaKit/generated/JavaShort.swift b/Sources/SwiftJava/generated/JavaShort.swift similarity index 99% rename from Sources/JavaKit/generated/JavaShort.swift rename to Sources/SwiftJava/generated/JavaShort.swift index f425ae18..12ca1dd2 100644 --- a/Sources/JavaKit/generated/JavaShort.swift +++ b/Sources/SwiftJava/generated/JavaShort.swift @@ -1,5 +1,5 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaRuntime +import CJNI @JavaClass("java.lang.Short") open class JavaShort: JavaNumber { diff --git a/Sources/JavaKit/generated/JavaString.swift b/Sources/SwiftJava/generated/JavaString.swift similarity index 99% rename from Sources/JavaKit/generated/JavaString.swift rename to Sources/SwiftJava/generated/JavaString.swift index c5f627f2..393c1acf 100644 --- a/Sources/JavaKit/generated/JavaString.swift +++ b/Sources/SwiftJava/generated/JavaString.swift @@ -1,5 +1,5 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaRuntime +import CJNI @JavaClass("java.lang.String", implements: CharSequence.self) open class JavaString: JavaObject { diff --git a/Sources/JavaKit/generated/JavaVoid.swift b/Sources/SwiftJava/generated/JavaVoid.swift similarity index 92% rename from Sources/JavaKit/generated/JavaVoid.swift rename to Sources/SwiftJava/generated/JavaVoid.swift index 76a7334a..b2976196 100644 --- a/Sources/JavaKit/generated/JavaVoid.swift +++ b/Sources/SwiftJava/generated/JavaVoid.swift @@ -1,5 +1,5 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaRuntime +import CJNI @JavaClass("java.lang.Void") open class JavaVoid: JavaObject { diff --git a/Sources/JavaKit/generated/RuntimeException.swift b/Sources/SwiftJava/generated/RuntimeException.swift similarity index 96% rename from Sources/JavaKit/generated/RuntimeException.swift rename to Sources/SwiftJava/generated/RuntimeException.swift index c3e32506..aacd2362 100644 --- a/Sources/JavaKit/generated/RuntimeException.swift +++ b/Sources/SwiftJava/generated/RuntimeException.swift @@ -1,5 +1,5 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaRuntime +import CJNI @JavaClass("java.lang.RuntimeException") open class RuntimeException: Exception { diff --git a/Sources/JavaKit/generated/Throwable.swift b/Sources/SwiftJava/generated/Throwable.swift similarity index 98% rename from Sources/JavaKit/generated/Throwable.swift rename to Sources/SwiftJava/generated/Throwable.swift index 574fedf5..823486d8 100644 --- a/Sources/JavaKit/generated/Throwable.swift +++ b/Sources/SwiftJava/generated/Throwable.swift @@ -1,5 +1,5 @@ // Auto-generated by Java-to-Swift wrapper generator. -import JavaRuntime +import CJNI @JavaClass("java.lang.Throwable") open class Throwable: JavaObject { diff --git a/Sources/JavaKit/swift-java.config b/Sources/SwiftJava/swift-java.config similarity index 100% rename from Sources/JavaKit/swift-java.config rename to Sources/SwiftJava/swift-java.config diff --git a/Sources/JavaKitConfigurationShared/Configuration.swift b/Sources/SwiftJavaConfigurationShared/Configuration.swift similarity index 100% rename from Sources/JavaKitConfigurationShared/Configuration.swift rename to Sources/SwiftJavaConfigurationShared/Configuration.swift diff --git a/Sources/JavaKitConfigurationShared/GenerationMode.swift b/Sources/SwiftJavaConfigurationShared/GenerationMode.swift similarity index 100% rename from Sources/JavaKitConfigurationShared/GenerationMode.swift rename to Sources/SwiftJavaConfigurationShared/GenerationMode.swift diff --git a/Sources/JavaKitConfigurationShared/GradleDependencyParsing.swift b/Sources/SwiftJavaConfigurationShared/GradleDependencyParsing.swift similarity index 100% rename from Sources/JavaKitConfigurationShared/GradleDependencyParsing.swift rename to Sources/SwiftJavaConfigurationShared/GradleDependencyParsing.swift diff --git a/Sources/SwiftJavaDocumentation/Documentation.docc/SwiftJavaCommandLineTool.md b/Sources/SwiftJavaDocumentation/Documentation.docc/SwiftJavaCommandLineTool.md index e8a3dfed..32a82eb4 100644 --- a/Sources/SwiftJavaDocumentation/Documentation.docc/SwiftJavaCommandLineTool.md +++ b/Sources/SwiftJavaDocumentation/Documentation.docc/SwiftJavaCommandLineTool.md @@ -72,7 +72,7 @@ OPTIONS: For example, the `JavaKitJar` library is generated with this command line: ```swift -swift-java wrap-java --swift-module JavaKitJar --depends-on JavaKit=Sources/JavaKit/swift-java.config -o Sources/JavaKitJar/generated Sources/JavaKitJar/swift-java.config +swift-java wrap-java --swift-module JavaKitJar --depends-on SwiftJNI=Sources/SwiftJNI/swift-java.config -o Sources/JavaKitJar/generated Sources/JavaKitJar/swift-java.config ``` The `--swift-module JavaKitJar` parameter describes the name of the Swift module in which the code will be generated. @@ -149,7 +149,7 @@ with an associated target that depends on `JavaKit`: Now, in the `HelloSwift` Swift library, define a `struct` that provides the `main` method for the Java class we already defined: ```swift -import JavaKit +import SwiftJNI @JavaImplementation("org.swift.javakit.HelloSwiftMain") struct HelloSwiftMain { @@ -178,9 +178,9 @@ The easiest way to build a command-line program in Swift is with the [Swift argu ```swift import ArgumentParser -import JavaKit +import SwiftJNI -@JavaClass("org.swift.javakit.HelloSwiftMain") +@JavaClass("org.swift.jni.HelloSwiftMain") struct HelloSwiftMain: ParsableCommand { @Option(name: .shortAndLong, help: "Enable verbose output") var verbose: Bool = false diff --git a/Sources/JavaKitMacros/GenerationMode.swift b/Sources/SwiftJavaMacros/GenerationMode.swift similarity index 100% rename from Sources/JavaKitMacros/GenerationMode.swift rename to Sources/SwiftJavaMacros/GenerationMode.swift diff --git a/Sources/JavaKitMacros/ImplementsJavaMacro.swift b/Sources/SwiftJavaMacros/ImplementsJavaMacro.swift similarity index 100% rename from Sources/JavaKitMacros/ImplementsJavaMacro.swift rename to Sources/SwiftJavaMacros/ImplementsJavaMacro.swift diff --git a/Sources/JavaKitMacros/JavaClassMacro.swift b/Sources/SwiftJavaMacros/JavaClassMacro.swift similarity index 100% rename from Sources/JavaKitMacros/JavaClassMacro.swift rename to Sources/SwiftJavaMacros/JavaClassMacro.swift diff --git a/Sources/JavaKitMacros/JavaFieldMacro.swift b/Sources/SwiftJavaMacros/JavaFieldMacro.swift similarity index 100% rename from Sources/JavaKitMacros/JavaFieldMacro.swift rename to Sources/SwiftJavaMacros/JavaFieldMacro.swift diff --git a/Sources/JavaKitMacros/JavaMethodMacro.swift b/Sources/SwiftJavaMacros/JavaMethodMacro.swift similarity index 100% rename from Sources/JavaKitMacros/JavaMethodMacro.swift rename to Sources/SwiftJavaMacros/JavaMethodMacro.swift diff --git a/Sources/JavaKitMacros/MacroErrors.swift b/Sources/SwiftJavaMacros/MacroErrors.swift similarity index 100% rename from Sources/JavaKitMacros/MacroErrors.swift rename to Sources/SwiftJavaMacros/MacroErrors.swift diff --git a/Sources/JavaKitMacros/JavaKitMacrosPlugin.swift b/Sources/SwiftJavaMacros/SwiftJNIMacrosPlugin.swift similarity index 93% rename from Sources/JavaKitMacros/JavaKitMacrosPlugin.swift rename to Sources/SwiftJavaMacros/SwiftJNIMacrosPlugin.swift index 255e61f5..637b2ea4 100644 --- a/Sources/JavaKitMacros/JavaKitMacrosPlugin.swift +++ b/Sources/SwiftJavaMacros/SwiftJNIMacrosPlugin.swift @@ -16,7 +16,7 @@ import SwiftCompilerPlugin import SwiftSyntaxMacros @main -struct JavaKitMacrosPlugin: CompilerPlugin { +struct SwiftJavaMacrosPlugin: CompilerPlugin { var providingMacros: [Macro.Type] = [ JavaImplementationMacro.self, JavaClassMacro.self, diff --git a/Sources/JavaKitMacros/SwiftSyntaxUtils.swift b/Sources/SwiftJavaMacros/SwiftSyntaxUtils.swift similarity index 100% rename from Sources/JavaKitMacros/SwiftSyntaxUtils.swift rename to Sources/SwiftJavaMacros/SwiftSyntaxUtils.swift diff --git a/Sources/JavaKitShared/TerminalColors.swift b/Sources/SwiftJavaShared/TerminalColors.swift similarity index 100% rename from Sources/JavaKitShared/TerminalColors.swift rename to Sources/SwiftJavaShared/TerminalColors.swift diff --git a/Sources/SwiftJavaTool/Commands/ConfigureCommand.swift b/Sources/SwiftJavaTool/Commands/ConfigureCommand.swift index 2355ea81..8bafd257 100644 --- a/Sources/SwiftJavaTool/Commands/ConfigureCommand.swift +++ b/Sources/SwiftJavaTool/Commands/ConfigureCommand.swift @@ -14,16 +14,16 @@ import ArgumentParser import Foundation -import SwiftJavaLib +import SwiftJavaToolLib import JExtractSwiftLib -import JavaKit -import JavaKitJar -import JavaKitNetwork -import JavaKitReflection +import SwiftJava +import JavaUtilJar +import JavaNet +import JavaLangReflect import SwiftSyntax import SwiftSyntaxBuilder -import JavaKitConfigurationShared -import JavaKitShared +import SwiftJavaConfigurationShared +import SwiftJavaShared extension SwiftJava { struct ConfigureCommand: SwiftJavaBaseAsyncParsableCommand, HasCommonOptions, HasCommonJVMOptions { diff --git a/Sources/SwiftJavaTool/Commands/JExtractCommand.swift b/Sources/SwiftJavaTool/Commands/JExtractCommand.swift index b32f34a0..29db6081 100644 --- a/Sources/SwiftJavaTool/Commands/JExtractCommand.swift +++ b/Sources/SwiftJavaTool/Commands/JExtractCommand.swift @@ -14,12 +14,12 @@ import Foundation import ArgumentParser -import SwiftJavaLib -import JavaKit -import JavaKitJar -import SwiftJavaLib +import SwiftJavaToolLib +import SwiftJava +import JavaUtilJar +import SwiftJavaToolLib import JExtractSwiftLib -import JavaKitConfigurationShared +import SwiftJavaConfigurationShared /// Extract Java bindings from Swift sources or interface files. /// @@ -73,7 +73,7 @@ extension SwiftJava { @Option( help: """ A swift-java configuration file for a given Swift module name on which this module depends, - e.g., Sources/JavaKitJar/swift-java.config. There should be one of these options + e.g., Sources/JavaJar/swift-java.config. There should be one of these options for each Swift module that this module depends on (transitively) that contains wrapped Java sources. """ ) diff --git a/Sources/SwiftJavaTool/Commands/ResolveCommand.swift b/Sources/SwiftJavaTool/Commands/ResolveCommand.swift index c492e788..58c64690 100644 --- a/Sources/SwiftJavaTool/Commands/ResolveCommand.swift +++ b/Sources/SwiftJavaTool/Commands/ResolveCommand.swift @@ -14,13 +14,13 @@ import ArgumentParser import Foundation -import SwiftJavaLib -import JavaKit +import SwiftJavaToolLib +import SwiftJava import Foundation -import JavaKitJar -import SwiftJavaLib -import JavaKitConfigurationShared -import JavaKitShared +import JavaUtilJar +import SwiftJavaToolLib +import SwiftJavaConfigurationShared +import SwiftJavaShared import _Subprocess #if canImport(System) import System @@ -28,7 +28,7 @@ import System @preconcurrency import SystemPackage #endif -typealias Configuration = JavaKitConfigurationShared.Configuration +typealias Configuration = SwiftJavaConfigurationShared.Configuration extension SwiftJava { struct ResolveCommand: SwiftJavaBaseAsyncParsableCommand, HasCommonOptions, HasCommonJVMOptions { diff --git a/Sources/SwiftJavaTool/Commands/WrapJavaCommand.swift b/Sources/SwiftJavaTool/Commands/WrapJavaCommand.swift index 3e4a62af..69ad3ebe 100644 --- a/Sources/SwiftJavaTool/Commands/WrapJavaCommand.swift +++ b/Sources/SwiftJavaTool/Commands/WrapJavaCommand.swift @@ -14,11 +14,11 @@ import Foundation import ArgumentParser -import SwiftJavaLib -import JavaKit -import JavaKitJar -import SwiftJavaLib -import JavaKitConfigurationShared +import SwiftJavaToolLib +import SwiftJava +import JavaUtilJar +import SwiftJavaToolLib +import SwiftJavaConfigurationShared extension SwiftJava { diff --git a/Sources/SwiftJavaTool/CommonOptions.swift b/Sources/SwiftJavaTool/CommonOptions.swift index e3ddfa44..c88ecbc8 100644 --- a/Sources/SwiftJavaTool/CommonOptions.swift +++ b/Sources/SwiftJavaTool/CommonOptions.swift @@ -14,14 +14,14 @@ import ArgumentParser import Foundation -import SwiftJavaLib +import SwiftJavaToolLib import JExtractSwiftLib -import JavaKit -import JavaKitJar -import JavaKitNetwork +import SwiftJava +import JavaUtilJar +import JavaNet import SwiftSyntax -import JavaKitConfigurationShared -import JavaKitShared +import SwiftJavaConfigurationShared +import SwiftJavaShared // - MARK: Common Options diff --git a/Sources/SwiftJavaTool/Java/JavaClassLoader.swift b/Sources/SwiftJavaTool/Java/JavaClassLoader.swift index 41492d53..bd1ec3f2 100644 --- a/Sources/SwiftJavaTool/Java/JavaClassLoader.swift +++ b/Sources/SwiftJavaTool/Java/JavaClassLoader.swift @@ -12,10 +12,10 @@ // //===----------------------------------------------------------------------===// -import SwiftJavaLib -import JavaKitShared -import JavaRuntime -import JavaKit +import SwiftJavaToolLib +import SwiftJavaShared +import CJNI +import SwiftJava @JavaClass("java.lang.ClassLoader") public struct ClassLoader { diff --git a/Sources/SwiftJavaTool/String+Extensions.swift b/Sources/SwiftJavaTool/String+Extensions.swift index f2bb9e72..304e217d 100644 --- a/Sources/SwiftJavaTool/String+Extensions.swift +++ b/Sources/SwiftJavaTool/String+Extensions.swift @@ -14,11 +14,11 @@ import Foundation import ArgumentParser -import SwiftJavaLib -import JavaKit -import JavaKitJar -import SwiftJavaLib -import JavaKitConfigurationShared +import SwiftJavaToolLib +import SwiftJava +import JavaUtilJar +import SwiftJavaToolLib +import SwiftJavaConfigurationShared extension String { /// For a String that's of the form java.util.Vector, return the "Vector" diff --git a/Sources/SwiftJavaTool/SwiftJava.swift b/Sources/SwiftJavaTool/SwiftJava.swift index 01917d4b..ac5182a0 100644 --- a/Sources/SwiftJavaTool/SwiftJava.swift +++ b/Sources/SwiftJavaTool/SwiftJava.swift @@ -14,16 +14,16 @@ import ArgumentParser import Foundation -import SwiftJavaLib +import SwiftJavaToolLib import JExtractSwiftLib -import JavaKit -import JavaKitJar -import JavaKitNetwork -import JavaKitReflection +import SwiftJava +import JavaUtilJar +import JavaNet +import JavaLangReflect import SwiftSyntax import SwiftSyntaxBuilder -import JavaKitConfigurationShared -import JavaKitShared +import SwiftJavaConfigurationShared +import SwiftJavaShared /// Command-line utility to drive the export of Java classes into Swift types. @main diff --git a/Sources/SwiftJavaTool/SwiftJavaBaseAsyncParsableCommand.swift b/Sources/SwiftJavaTool/SwiftJavaBaseAsyncParsableCommand.swift index 20b177af..25b162e1 100644 --- a/Sources/SwiftJavaTool/SwiftJavaBaseAsyncParsableCommand.swift +++ b/Sources/SwiftJavaTool/SwiftJavaBaseAsyncParsableCommand.swift @@ -14,16 +14,16 @@ import ArgumentParser import Foundation -import SwiftJavaLib +import SwiftJavaToolLib import JExtractSwiftLib -import JavaKit -import JavaKitJar -import JavaKitNetwork -import JavaKitReflection +import SwiftJava +import JavaUtilJar +import JavaNet +import JavaLangReflect import SwiftSyntax import SwiftSyntaxBuilder -import JavaKitConfigurationShared -import JavaKitShared +import SwiftJavaConfigurationShared +import SwiftJavaShared protocol SwiftJavaBaseAsyncParsableCommand: AsyncParsableCommand { var logLevel: Logger.Level { get set } diff --git a/Sources/SwiftJavaLib/JavaClassTranslator.swift b/Sources/SwiftJavaToolLib/JavaClassTranslator.swift similarity index 99% rename from Sources/SwiftJavaLib/JavaClassTranslator.swift rename to Sources/SwiftJavaToolLib/JavaClassTranslator.swift index ea6ca481..a7c4d76f 100644 --- a/Sources/SwiftJavaLib/JavaClassTranslator.swift +++ b/Sources/SwiftJavaToolLib/JavaClassTranslator.swift @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -import JavaKit -import JavaKitReflection +import SwiftJava +import JavaLangReflect import SwiftSyntax /// Utility type that translates a single Java class into its corresponding diff --git a/Sources/SwiftJavaLib/JavaTranslator+Configuration.swift b/Sources/SwiftJavaToolLib/JavaTranslator+Configuration.swift similarity index 97% rename from Sources/SwiftJavaLib/JavaTranslator+Configuration.swift rename to Sources/SwiftJavaToolLib/JavaTranslator+Configuration.swift index 0f764633..4fc9feb0 100644 --- a/Sources/SwiftJavaLib/JavaTranslator+Configuration.swift +++ b/Sources/SwiftJavaToolLib/JavaTranslator+Configuration.swift @@ -13,7 +13,7 @@ //===----------------------------------------------------------------------===// import Foundation -import JavaKitConfigurationShared +import SwiftJavaConfigurationShared extension JavaTranslator { // /// Read a configuration file from the given URL. diff --git a/Sources/SwiftJavaLib/JavaTranslator+Validation.swift b/Sources/SwiftJavaToolLib/JavaTranslator+Validation.swift similarity index 100% rename from Sources/SwiftJavaLib/JavaTranslator+Validation.swift rename to Sources/SwiftJavaToolLib/JavaTranslator+Validation.swift diff --git a/Sources/SwiftJavaLib/JavaTranslator.swift b/Sources/SwiftJavaToolLib/JavaTranslator.swift similarity index 98% rename from Sources/SwiftJavaLib/JavaTranslator.swift rename to Sources/SwiftJavaToolLib/JavaTranslator.swift index 225d3868..2f6f280c 100644 --- a/Sources/SwiftJavaLib/JavaTranslator.swift +++ b/Sources/SwiftJavaToolLib/JavaTranslator.swift @@ -12,12 +12,12 @@ // //===----------------------------------------------------------------------===// -import JavaKit -import JavaKitReflection +import SwiftJava +import JavaLangReflect import JavaTypes import SwiftBasicFormat import SwiftSyntax -import JavaKitConfigurationShared +import SwiftJavaConfigurationShared import SwiftSyntaxBuilder /// Utility that translates Java classes into Swift source code to access @@ -45,7 +45,7 @@ package class JavaTranslator { /// an AnyJavaObject-conforming type) whereas the entry here should map to /// a value type. package let translatedToValueTypes: [String: (swiftType: String, swiftModule: String) ] = [ - "java.lang.String": ("String", "JavaKit"), + "java.lang.String": ("String", "SwiftJava"), ] /// The set of Swift modules that need to be imported to make the generated @@ -93,8 +93,8 @@ extension JavaTranslator { /// Default set of modules that will always be imported. private static let defaultImportedSwiftModules: Set = [ - "JavaKit", - "JavaRuntime", + "SwiftJava", + "CJNI", ] } diff --git a/Sources/SwiftJavaLib/MethodVariance.swift b/Sources/SwiftJavaToolLib/MethodVariance.swift similarity index 98% rename from Sources/SwiftJavaLib/MethodVariance.swift rename to Sources/SwiftJavaToolLib/MethodVariance.swift index 09bd6444..c130a75c 100644 --- a/Sources/SwiftJavaLib/MethodVariance.swift +++ b/Sources/SwiftJavaToolLib/MethodVariance.swift @@ -11,8 +11,8 @@ // SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// -import JavaKit -import JavaKitReflection +import SwiftJava +import JavaLangReflect /// Captures the relationship between two methods by comparing their parameter /// and result types. diff --git a/Sources/SwiftJavaLib/OptionalKind.swift b/Sources/SwiftJavaToolLib/OptionalKind.swift similarity index 100% rename from Sources/SwiftJavaLib/OptionalKind.swift rename to Sources/SwiftJavaToolLib/OptionalKind.swift diff --git a/Sources/SwiftJavaLib/StringExtras.swift b/Sources/SwiftJavaToolLib/StringExtras.swift similarity index 100% rename from Sources/SwiftJavaLib/StringExtras.swift rename to Sources/SwiftJavaToolLib/StringExtras.swift diff --git a/Sources/SwiftJavaLib/TranslationError.swift b/Sources/SwiftJavaToolLib/TranslationError.swift similarity index 97% rename from Sources/SwiftJavaLib/TranslationError.swift rename to Sources/SwiftJavaToolLib/TranslationError.swift index d44fd2d7..1e01134b 100644 --- a/Sources/SwiftJavaLib/TranslationError.swift +++ b/Sources/SwiftJavaToolLib/TranslationError.swift @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -import JavaKitReflection +import JavaLangReflect /// Errors that can occur when translating Java types into Swift. enum TranslationError: Error { diff --git a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMSwiftInstanceCleanup.java b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMSwiftInstanceCleanup.java index c3a9beb6..7b7bb1ec 100644 --- a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMSwiftInstanceCleanup.java +++ b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMSwiftInstanceCleanup.java @@ -16,6 +16,8 @@ import org.swift.swiftkit.core.SwiftInstanceCleanup; +import static org.swift.swiftkit.ffm.SwiftJavaLogGroup.LIFECYCLE; + import java.lang.foreign.MemorySegment; public class FFMSwiftInstanceCleanup implements SwiftInstanceCleanup { @@ -35,7 +37,7 @@ public void run() { // Allow null pointers just for AutoArena tests. if (type != null && memoryAddress != null) { - System.out.println("[debug] Destroy swift value [" + type.getSwiftName() + "]: " + memoryAddress); + SwiftRuntime.log(LIFECYCLE, "Destroy swift value [" + type.getSwiftName() + "]: " + memoryAddress); SwiftValueWitnessTable.destroy(type, memoryAddress); } } diff --git a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/SwiftRuntime.java b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/SwiftRuntime.java index eca6be82..e03b9bfe 100644 --- a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/SwiftRuntime.java +++ b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/SwiftRuntime.java @@ -17,6 +17,7 @@ import org.swift.swiftkit.core.SwiftInstance; import org.swift.swiftkit.core.CallTraces; import org.swift.swiftkit.core.util.PlatformUtils; +import org.swift.swiftkit.ffm.SwiftRuntime.swiftjava; import java.lang.foreign.*; import java.lang.invoke.MethodHandle; @@ -460,4 +461,30 @@ private static class swift_getTypeName { public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } + public static void log(SwiftJavaLogGroup group, String message) { + if (group.isEnabled()) { + System.err.println(message); + } + } + + public static void log(SwiftJavaLogGroup group, String format, String ...args) { + if (group.isEnabled()) { + System.err.println(String.format(format, (Object[]) args)); + } + } + } + +enum SwiftJavaLogGroup { + LIFECYCLE; + + static boolean LOG_LIFECYCLE = + Boolean.getBoolean("swift-java.log.lifecycle"); + + boolean isEnabled() { + switch (this) { + case LIFECYCLE: return LOG_LIFECYCLE; + } + throw new IllegalArgumentException("Not handled log group: " + this); + } +} \ No newline at end of file diff --git a/Tests/JExtractSwiftTests/Asserts/LoweringAssertions.swift b/Tests/JExtractSwiftTests/Asserts/LoweringAssertions.swift index 0b8ca1d3..06d1d555 100644 --- a/Tests/JExtractSwiftTests/Asserts/LoweringAssertions.swift +++ b/Tests/JExtractSwiftTests/Asserts/LoweringAssertions.swift @@ -13,7 +13,7 @@ //===----------------------------------------------------------------------===// @_spi(Testing) import JExtractSwiftLib -import JavaKitConfigurationShared +import SwiftJavaConfigurationShared import SwiftSyntax import Testing diff --git a/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift b/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift index 1f768fb2..66563fee 100644 --- a/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift +++ b/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift @@ -14,7 +14,7 @@ import JExtractSwiftLib import Testing -import JavaKitConfigurationShared +import SwiftJavaConfigurationShared import struct Foundation.CharacterSet enum RenderKind { diff --git a/Tests/JExtractSwiftTests/FuncCallbackImportTests.swift b/Tests/JExtractSwiftTests/FuncCallbackImportTests.swift index a87294b0..82747ec9 100644 --- a/Tests/JExtractSwiftTests/FuncCallbackImportTests.swift +++ b/Tests/JExtractSwiftTests/FuncCallbackImportTests.swift @@ -13,7 +13,7 @@ //===----------------------------------------------------------------------===// import JExtractSwiftLib -import JavaKitConfigurationShared +import SwiftJavaConfigurationShared import Testing final class FuncCallbackImportTests { diff --git a/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift b/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift index a8d83a2a..ff19f4a2 100644 --- a/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift +++ b/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift @@ -13,7 +13,7 @@ //===----------------------------------------------------------------------===// import JExtractSwiftLib -import JavaKitConfigurationShared +import SwiftJavaConfigurationShared import Testing @Suite diff --git a/Tests/JExtractSwiftTests/InternalExtractTests.swift b/Tests/JExtractSwiftTests/InternalExtractTests.swift index 78e71236..54829bd7 100644 --- a/Tests/JExtractSwiftTests/InternalExtractTests.swift +++ b/Tests/JExtractSwiftTests/InternalExtractTests.swift @@ -13,7 +13,7 @@ //===----------------------------------------------------------------------===// import JExtractSwiftLib -import JavaKitConfigurationShared +import SwiftJavaConfigurationShared import Testing final class InternalExtractTests { diff --git a/Tests/JExtractSwiftTests/JNI/JNIUnsignedNumberTests.swift b/Tests/JExtractSwiftTests/JNI/JNIUnsignedNumberTests.swift index bfae447a..61a94062 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIUnsignedNumberTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIUnsignedNumberTests.swift @@ -13,7 +13,7 @@ //===----------------------------------------------------------------------===// import JExtractSwiftLib -import JavaKitConfigurationShared +import SwiftJavaConfigurationShared import Testing final class JNIUnsignedNumberTests { diff --git a/Tests/JExtractSwiftTests/MemoryManagementModeTests.swift b/Tests/JExtractSwiftTests/MemoryManagementModeTests.swift index 3ce839b9..6017c987 100644 --- a/Tests/JExtractSwiftTests/MemoryManagementModeTests.swift +++ b/Tests/JExtractSwiftTests/MemoryManagementModeTests.swift @@ -13,7 +13,7 @@ //===----------------------------------------------------------------------===// import JExtractSwiftLib -import JavaKitConfigurationShared +import SwiftJavaConfigurationShared import Testing @Suite diff --git a/Tests/JExtractSwiftTests/MethodImportTests.swift b/Tests/JExtractSwiftTests/MethodImportTests.swift index 3aa7d394..938b5e7f 100644 --- a/Tests/JExtractSwiftTests/MethodImportTests.swift +++ b/Tests/JExtractSwiftTests/MethodImportTests.swift @@ -13,7 +13,7 @@ //===----------------------------------------------------------------------===// import JExtractSwiftLib -import JavaKitConfigurationShared +import SwiftJavaConfigurationShared import Testing final class MethodImportTests { diff --git a/Tests/JExtractSwiftTests/UnsignedNumberTests.swift b/Tests/JExtractSwiftTests/UnsignedNumberTests.swift index 11b91e53..8109714c 100644 --- a/Tests/JExtractSwiftTests/UnsignedNumberTests.swift +++ b/Tests/JExtractSwiftTests/UnsignedNumberTests.swift @@ -13,7 +13,7 @@ //===----------------------------------------------------------------------===// import JExtractSwiftLib -import JavaKitConfigurationShared +import SwiftJavaConfigurationShared import Testing final class UnsignedNumberTests { diff --git a/Tests/JavaKitConfigurationSharedTests/GradleDependencyParsingTests.swift b/Tests/SwiftJavaConfigurationSharedTests/GradleDependencyParsingTests.swift similarity index 97% rename from Tests/JavaKitConfigurationSharedTests/GradleDependencyParsingTests.swift rename to Tests/SwiftJavaConfigurationSharedTests/GradleDependencyParsingTests.swift index dbd05f66..cb085fe2 100644 --- a/Tests/JavaKitConfigurationSharedTests/GradleDependencyParsingTests.swift +++ b/Tests/SwiftJavaConfigurationSharedTests/GradleDependencyParsingTests.swift @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -import JavaKitConfigurationShared +import SwiftJavaConfigurationShared import Testing @Suite diff --git a/Tests/JavaKitMacroTests/JavaClassMacroTests.swift b/Tests/SwiftJavaMacrosTests/JavaClassMacroTests.swift similarity index 99% rename from Tests/JavaKitMacroTests/JavaClassMacroTests.swift rename to Tests/SwiftJavaMacrosTests/JavaClassMacroTests.swift index 1dc08ba8..7eead3d2 100644 --- a/Tests/JavaKitMacroTests/JavaClassMacroTests.swift +++ b/Tests/SwiftJavaMacrosTests/JavaClassMacroTests.swift @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -import JavaKitMacros +import SwiftJavaMacros import SwiftSyntax import SwiftSyntaxBuilder import SwiftSyntaxMacros diff --git a/Tests/JavaKitTests/BasicRuntimeTests.swift b/Tests/SwiftJavaTests/BasicRuntimeTests.swift similarity index 98% rename from Tests/JavaKitTests/BasicRuntimeTests.swift rename to Tests/SwiftJavaTests/BasicRuntimeTests.swift index d42fa4b1..b6c18bee 100644 --- a/Tests/JavaKitTests/BasicRuntimeTests.swift +++ b/Tests/SwiftJavaTests/BasicRuntimeTests.swift @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -import JavaKit -import JavaKitNetwork +import SwiftJava +import JavaNet import XCTest // NOTE: Workaround for https://github.com/swiftlang/swift-java/issues/43 /// Handy reference to the JVM abstraction. diff --git a/Tests/SwiftJavaTests/Java2SwiftTests.swift b/Tests/SwiftJavaToolLibTests/Java2SwiftTests.swift similarity index 89% rename from Tests/SwiftJavaTests/Java2SwiftTests.swift rename to Tests/SwiftJavaToolLibTests/Java2SwiftTests.swift index e2b68a34..f251766a 100644 --- a/Tests/SwiftJavaTests/Java2SwiftTests.swift +++ b/Tests/SwiftJavaToolLibTests/Java2SwiftTests.swift @@ -13,8 +13,8 @@ //===----------------------------------------------------------------------===// @_spi(Testing) -import JavaKit -import SwiftJavaLib +import SwiftJava +import SwiftJavaToolLib import XCTest // NOTE: Workaround for https://github.com/swiftlang/swift-java/issues/43 /// Handy reference to the JVM abstraction. @@ -42,7 +42,7 @@ class Java2SwiftTests: XCTestCase { JavaObject.self, swiftTypeName: "MyJavaObject", expectedChunks: [ - "import JavaKit", + "import SwiftJava", """ @JavaClass("java.lang.Object") public struct MyJavaObject { @@ -67,7 +67,7 @@ class Java2SwiftTests: XCTestCase { "java.lang.Object": ("JavaObject", nil), ], expectedChunks: [ - "import JavaKit", + "import SwiftJava", """ @JavaClass("java.lang.Class", extends: JavaObject.self) public struct MyJavaClass { @@ -85,7 +85,7 @@ class Java2SwiftTests: XCTestCase { JavaMonth.self, swiftTypeName: "Month", expectedChunks: [ - "import JavaKit", + "import SwiftJava", "enum MonthCases: Equatable", "case APRIL", "public var enumValue: MonthCases!", @@ -164,7 +164,7 @@ class Java2SwiftTests: XCTestCase { "java.lang.ProcessBuilder$Redirect": [JavaClass().as(JavaClass.self)!], ], expectedChunks: [ - "import JavaKit", + "import SwiftJava", """ @JavaMethod public func redirectInput() -> ProcessBuilder.Redirect! @@ -204,7 +204,7 @@ class Java2SwiftTests: XCTestCase { "java.lang.ProcessBuilder$Redirect": [JavaClass().as(JavaClass.self)!], ], expectedChunks: [ - "import JavaKit", + "import SwiftJava", """ @JavaMethod public func redirectInput() -> ProcessBuilder.PBRedirect! @@ -248,13 +248,13 @@ class Java2SwiftTests: XCTestCase { MyObjects.self, swiftTypeName: "MyJavaObjects", translatedClasses: [ - "java.lang.Object" : ("JavaObject", "JavaKit"), - "java.util.function.Supplier" : ("MySupplier", "JavaKitFunction"), - "java.lang.String" : ("JavaString", "JavaKit"), + "java.lang.Object" : ("JavaObject", "SwiftJava"), + "java.util.function.Supplier" : ("MySupplier", "JavaUtilFunction"), + "java.lang.String" : ("JavaString", "SwiftJava"), ], expectedChunks: [ """ - import JavaKitFunction + import JavaUtilFunction """, """ @JavaClass("java.util.Objects", extends: JavaObject.self) @@ -274,7 +274,7 @@ class Java2SwiftTests: XCTestCase { swiftTypeName: "JavaObject", asClass: true, expectedChunks: [ - "import JavaKit", + "import SwiftJava", """ @JavaClass("java.lang.Object") open class JavaObject { @@ -305,10 +305,10 @@ class Java2SwiftTests: XCTestCase { swiftTypeName: "JavaString", asClass: true, translatedClasses: [ - "java.lang.Object" : ("JavaObject", "JavaKit"), + "java.lang.Object" : ("JavaObject", "SwiftJava"), ], expectedChunks: [ - "import JavaKit", + "import SwiftJava", """ @JavaClass("java.lang.String") open class JavaString: JavaObject { @@ -343,7 +343,7 @@ class Java2SwiftTests: XCTestCase { swiftTypeName: "Month", asClass: true, expectedChunks: [ - "import JavaKit", + "import SwiftJava", "enum MonthCases: Equatable", "case APRIL", "public var enumValue: MonthCases!", @@ -380,12 +380,12 @@ class Java2SwiftTests: XCTestCase { swiftTypeName: "URLClassLoader", asClass: true, translatedClasses: [ - "java.lang.Object" : ("JavaObject", "JavaKit"), - "java.lang.ClassLoader" : ("ClassLoader", "JavaKit"), - "java.net.URL" : ("URL", "JavaKitNetwork"), + "java.lang.Object" : ("JavaObject", "SwiftJava"), + "java.lang.ClassLoader" : ("ClassLoader", "SwiftJava"), + "java.net.URL" : ("URL", "JavaNet"), ], expectedChunks: [ - "import JavaKit", + "import SwiftJava", """ @JavaClass("java.net.URLClassLoader") open class URLClassLoader: ClassLoader { @@ -411,11 +411,11 @@ class Java2SwiftTests: XCTestCase { swiftTypeName: "URLClassLoader", asClass: true, translatedClasses: [ - "java.lang.Object" : ("JavaObject", "JavaKit"), - "java.net.URL" : ("URL", "JavaKitNetwork"), + "java.lang.Object" : ("JavaObject", "SwiftJava"), + "java.net.URL" : ("URL", "JavaNet"), ], expectedChunks: [ - "import JavaKit", + "import SwiftJava", """ @JavaClass("java.net.URLClassLoader") open class URLClassLoader: JavaObject { @@ -440,12 +440,12 @@ class Java2SwiftTests: XCTestCase { swiftTypeName: "JavaByte", asClass: true, translatedClasses: [ - "java.lang.Object" : ("JavaObject", "JavaKit"), - "java.lang.Number" : ("JavaNumber", "JavaKit"), - "java.lang.Byte" : ("JavaByte", "JavaKit"), + "java.lang.Object" : ("JavaObject", "SwiftJava"), + "java.lang.Number" : ("JavaNumber", "SwiftJava"), + "java.lang.Byte" : ("JavaByte", "SwiftJava"), ], expectedChunks: [ - "import JavaKit", + "import SwiftJava", """ @JavaClass("java.lang.Byte") open class JavaByte: JavaNumber { @@ -464,11 +464,11 @@ class Java2SwiftTests: XCTestCase { swiftTypeName: "MyJavaIntFunction", asClass: true, translatedClasses: [ - "java.lang.Object" : ("JavaObject", "JavaKit"), + "java.lang.Object" : ("JavaObject", "SwiftJava"), "java.util.function.IntFunction": ("MyJavaIntFunction", nil), ], expectedChunks: [ - "import JavaKit", + "import SwiftJava", """ @JavaInterface("java.util.function.IntFunction") public struct MyJavaIntFunction { @@ -487,14 +487,14 @@ class Java2SwiftTests: XCTestCase { swiftTypeName: "Method", asClass: true, translatedClasses: [ - "java.lang.Object" : ("JavaObject", "JavaKit"), - "java.lang.Class" : ("JavaClass", "JavaKit"), - "java.lang.reflect.Executable": ("Executable", "JavaKitReflection"), - "java.lang.reflect.Method": ("Method", "JavaKitReflection"), - "java.lang.reflect.TypeVariable" : ("TypeVariable", "JavaKitReflection"), + "java.lang.Object" : ("JavaObject", "SwiftJava"), + "java.lang.Class" : ("JavaClass", "SwiftJava"), + "java.lang.reflect.Executable": ("Executable", "JavaLangReflect"), + "java.lang.reflect.Method": ("Method", "JavaLangReflect"), + "java.lang.reflect.TypeVariable" : ("TypeVariable", "JavaLangReflect"), ], expectedChunks: [ - "import JavaKitReflection", + "import JavaLangReflect", """ @JavaClass("java.lang.reflect.Method") open class Method: Executable { @@ -521,14 +521,14 @@ class Java2SwiftTests: XCTestCase { swiftTypeName: "Constructor", asClass: true, translatedClasses: [ - "java.lang.Object" : ("JavaObject", "JavaKit"), - "java.lang.Class" : ("JavaClass", "JavaKit"), - "java.lang.reflect.Executable": ("Executable", "JavaKitReflection"), - "java.lang.reflect.Method": ("Method", "JavaKitReflection"), - "java.lang.reflect.TypeVariable" : ("TypeVariable", "JavaKitReflection"), + "java.lang.Object" : ("JavaObject", "SwiftJava"), + "java.lang.Class" : ("JavaClass", "SwiftJava"), + "java.lang.reflect.Executable": ("Executable", "JavaLangReflect"), + "java.lang.reflect.Method": ("Method", "JavaLangReflect"), + "java.lang.reflect.TypeVariable" : ("TypeVariable", "JavaLangReflect"), ], expectedChunks: [ - "import JavaKitReflection", + "import JavaLangReflect", """ @JavaClass("java.lang.reflect.Constructor") open class Constructor: Executable { @@ -555,13 +555,13 @@ class Java2SwiftTests: XCTestCase { swiftTypeName: "NIOByteBuffer", asClass: true, translatedClasses: [ - "java.lang.Object" : ("JavaObject", "JavaKit"), - "java.lang.Class" : ("JavaClass", "JavaKit"), - "java.nio.Buffer": ("NIOBuffer", "JavaKitNIO"), - "java.nio.ByteBuffer": ("NIOByteBuffer", "JavaKitNIO"), + "java.lang.Object" : ("JavaObject", "SwiftJava"), + "java.lang.Class" : ("JavaClass", "SwiftJava"), + "java.nio.Buffer": ("NIOBuffer", "JavaNio"), + "java.nio.ByteBuffer": ("NIOByteBuffer", "JavaNio"), ], expectedChunks: [ - "import JavaKitNIO", + "import JavaNio", """ @JavaClass("java.nio.ByteBuffer") open class NIOByteBuffer: NIOBuffer { diff --git a/Tests/SwiftJavaTests/JavaTranslatorValidationTests.swift b/Tests/SwiftJavaToolLibTests/JavaTranslatorValidationTests.swift similarity index 98% rename from Tests/SwiftJavaTests/JavaTranslatorValidationTests.swift rename to Tests/SwiftJavaToolLibTests/JavaTranslatorValidationTests.swift index a203486a..220f1c61 100644 --- a/Tests/SwiftJavaTests/JavaTranslatorValidationTests.swift +++ b/Tests/SwiftJavaToolLibTests/JavaTranslatorValidationTests.swift @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -import SwiftJavaLib +import SwiftJavaToolLib import XCTest final class JavaTranslatorValidationTests: XCTestCase { From 2268bb66cd7da3f2e5efbb52c8ca12d594692828 Mon Sep 17 00:00:00 2001 From: David Ko Date: Wed, 27 Aug 2025 09:12:26 -0400 Subject: [PATCH 352/426] Align Renaming Changes (#375) --- README.md | 12 +++--- .../{JavaKit.md => SwiftJava.md} | 38 +++++++++---------- .../Commands/ConfigureCommand.swift | 11 ++---- 3 files changed, 28 insertions(+), 33 deletions(-) rename Sources/SwiftJava/Documentation.docc/{JavaKit.md => SwiftJava.md} (90%) diff --git a/README.md b/README.md index 9f676905..c15db541 100644 --- a/README.md +++ b/README.md @@ -138,7 +138,7 @@ cd Samples/JavaKitSampleApp To run a simple example app showcasing the jextract (Java calling Swift) approach you can: ```bash -./gradlew Samples:SwiftKitSampleApp:run +./gradlew Samples:SwiftJavaExtractFFMSampleApp:run ``` This will also generate the necessary sources (by invoking jextract, extracting the `Sources/ExampleSwiftLibrary`) @@ -152,7 +152,7 @@ Please refer to the [Samples](Samples) directory for more sample apps which show You can run Swift [ordo-one/package-benchmark](https://github.com/ordo-one/package-benchmark) and OpenJDK [JMH](https://github.com/openjdk/jmh) benchmarks in this project. -Swift benchmarks are located under `Benchmarks/` and JMH benchmarks are currently part of the SwiftKit sample project: `Samples/SwiftKitSampleApp/src/jmh` because they depend on generated sources from the sample. +Swift benchmarks are located under `Benchmarks/` and JMH benchmarks are currently part of the SwiftKit sample project: `Samples/SwiftJavaExtractFFMSampleApp/src/jmh` because they depend on generated sources from the sample. ### Swift benchmarks @@ -168,8 +168,8 @@ swift package benchmark In order to run JMH benchmarks you can: ```bash -cd Samples/SwiftKitSampleApp -gradle jmh +cd Samples/SwiftJavaExtractFFMSampleApp +./gradlew jmh ``` Please read documentation of both performance testing tools and understand that results must be interpreted and not just taken at face value. Benchmarking is tricky and environment sensitive task, so please be careful when constructing and reading benchmarks and their results. If in doubt, please reach out on the forums. @@ -183,8 +183,8 @@ To view the rendered docc documentation you can use the docc preview command: ```bash xcrun docc preview Sources/SwiftJavaDocumentation/Documentation.docc -# OR JavaKit to view JavaKit documentation: -# xcrun docc preview Sources/SwiftJNI/Documentation.docc +# OR SwiftJava to view SwiftJava documentation: +# xcrun docc preview Sources/SwiftJava/Documentation.docc # ======================================== # Starting Local Preview Server diff --git a/Sources/SwiftJava/Documentation.docc/JavaKit.md b/Sources/SwiftJava/Documentation.docc/SwiftJava.md similarity index 90% rename from Sources/SwiftJava/Documentation.docc/JavaKit.md rename to Sources/SwiftJava/Documentation.docc/SwiftJava.md index a050e88b..d4b5dacd 100644 --- a/Sources/SwiftJava/Documentation.docc/JavaKit.md +++ b/Sources/SwiftJava/Documentation.docc/SwiftJava.md @@ -1,8 +1,8 @@ -# JavaKit +# SwiftJava Library and tools to make it easy to use Java libraries from Swift using the Java Native Interface (JNI). -## JavaKit: Using Java libraries from Swift +## SwiftJava: Using Java libraries from Swift Existing Java libraries can be wrapped for use in Swift with the `swift-java` tool. In a Swift program, the most direct way to access a Java API is to use the SwiftPM plugin to provide Swift wrappers for the Java classes. To do so, add a configuration file `swift-java.config` into the source directory for the Swift target. This is a JSON file that specifies Java classes and the Swift type name that should be generated to wrap them. For example, the following file maps `java.math.BigInteger` to a Swift type named `BigInteger`: @@ -77,7 +77,7 @@ Swift ensures that the Java garbage collector will keep the object alive until ` ### Creating a Java Virtual Machine instance from Swift -When JavaKit requires a running Java Virtual Machine to use an operation (for example, to create an instance of `BigInteger`), it will query to determine if one is running and, if not, create one. To exercise more control over the creation and configuration of the Java virtual machine, use the `JavaVirtualMachine` class, which provides creation and query operations. One can create a shared instance by calling `JavaVirtualMachine.shared()`, optionally passing along extra options to the JVM (such as the class path): +When SwiftJava requires a running Java Virtual Machine to use an operation (for example, to create an instance of `BigInteger`), it will query to determine if one is running and, if not, create one. To exercise more control over the creation and configuration of the Java virtual machine, use the `JavaVirtualMachine` class, which provides creation and query operations. One can create a shared instance by calling `JavaVirtualMachine.shared()`, optionally passing along extra options to the JVM (such as the class path): ```swift let javaVirtualMachine = try JavaVirtualMachine.shared() @@ -100,7 +100,7 @@ let bigInt = BigInteger(veryBigNumber, environment: jniEnvironment) Java libraries are often distributed as Jar files. The `swift-java` tool can inspect a Jar file to create a `swift-java.config` file that will wrap all of the public classes for use in Swift. Following the example in `swift-java/Samples/JavaSieve`, we will wrap a small [Java library for computing prime numbers](https://github.com/gazman-sdk/quadratic-sieve-Java) for use in Swift. Assuming we have a Jar file `QuadraticSieve-1.0.jar` in the package directory, run the following command: ```swift -swift-java generate --module-name JavaSieve --jar QuadraticSieve-1.0.jar +swift-java configure --swift-module JavaSieve --jar QuadraticSieve-1.0.jar ``` The resulting configuration file will look something like this: @@ -138,7 +138,7 @@ The resulting configuration file will look something like this: } ``` -As with the previous `JavaProbablyPrime` sample, the `JavaSieve` target in `Package.swift` should depend on the `swift-java` package modules (`JavaKit`) and apply the `swift-java` plugin. This makes all of the Java classes found in the Jar file available to Swift within the `JavaSieve` target. +As with the previous `JavaProbablyPrime` sample, the `JavaSieve` target in `Package.swift` should depend on the `swift-java` package modules (`SwiftJava`) and apply the `swift-java` plugin. This makes all of the Java classes found in the Jar file available to Swift within the `JavaSieve` target. If you inspect the build output, there are a number of warnings that look like this: @@ -152,7 +152,7 @@ These warnings mean that some of the APIs in the Java library aren't available i .target( name: "JavaMath", dependencies: [ - .product(name: "JavaKit", package: "swift-java"), + .product(name: "SwiftJava", package: "swift-java"), ], plugins: [ .plugin(name: "SwiftJavaPlugin", package: "swift-java"), @@ -237,10 +237,10 @@ if let url = myObject.as(URL.self) { ### Implementing Java `native` methods in Swift -JavaKit supports implementing Java `native` methods in Swift using JNI with the `@JavaImplementation` macro. In Java, the method must be declared as `native`, e.g., +SwiftJava supports implementing Java `native` methods in Swift using JNI with the `@JavaImplementation` macro. In Java, the method must be declared as `native`, e.g., ```java -package org.swift.javakit.example; +package org.swift.swiftjava.example; public class HelloSwift { static { @@ -256,15 +256,15 @@ On the Swift side, the Java class needs to be exposed to Swift through `swift-ja ```swift { "classes" : { - "org.swift.javakit.example.HelloSwift" : "Hello", + "org.swift.swiftjava.example.HelloSwift" : "Hello", } } ``` -Implementations of `native` methods are written in an extension of the Swift type that has been marked with `@JavaImplementation`. The methods themselves must be marked with `@JavaMethod`, indicating that they are available to Java as well. To help ensure that the Swift code implements all of the `native` methods with the right signatures, JavaKit produces a protocol with the Swift type name suffixed by `NativeMethods`. Declare conformance to that protocol and implement its requirements, for example: +Implementations of `native` methods are written in an extension of the Swift type that has been marked with `@JavaImplementation`. The methods themselves must be marked with `@JavaMethod`, indicating that they are available to Java as well. To help ensure that the Swift code implements all of the `native` methods with the right signatures, SwiftJava produces a protocol with the Swift type name suffixed by `NativeMethods`. Declare conformance to that protocol and implement its requirements, for example: ```swift -@JavaImplementation("org.swift.javakit.HelloSwift") +@JavaImplementation("org.swift.swiftjava.HelloSwift") extension Hello: HelloNativeMethods { @JavaMethod func reportStatistics(_ meaning: String, _ numbers: [Double]) -> String { @@ -278,7 +278,7 @@ Java native methods that throw any checked exception should be marked as `throws The Swift implementations of Java `native` constructors and static methods require an additional Swift parameter `environment: JNIEnvironment? = nil`, which will receive the JNI environment in which the function is being executed. In case of nil, the `JavaVirtualMachine.shared().environment()` value will be used. -## JavaKit: Using Java libraries from Swift +## SwiftJava: Using Java libraries from Swift This section describes how Java libraries and mapped into Swift and their use from Swift. @@ -353,7 +353,7 @@ for entry in jarFile.entries()! { `JavaMethod` is a [function body macro](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0415-function-body-macros.md) that translates the argument and result types to/from Java and performs a call to the named method via JNI. -A Java method or constructor that throws a checked exception should be marked as `throws` in Swift. Swift's projection of Java throwable types (as `JavaKit.Throwable`) conforms to the Swift `Error` protocol, so Java exceptions will be rethrown as Swift errors. +A Java method or constructor that throws a checked exception should be marked as `throws` in Swift. Swift's projection of Java throwable types (as `SwiftJava.Throwable`) conforms to the Swift `Error` protocol, so Java exceptions will be rethrown as Swift errors. ### Java <-> Swift Type mapping @@ -380,14 +380,14 @@ For Swift projections of Java classes, the Swift type itself conforms to the `An Because Java has implicitly nullability of references, `AnyJavaObject` types do not directly conform to `JavaValue`: rather, optionals of `AnyJavaObject`-conforming type conform to `JavaValue`. This requires Swift code to deal with the optionality at interface boundaries rather than invite implicit NULL pointer dereferences. -A number of JavaKit modules provide Swift projections of Java classes and interfaces. Here are a few: +A number of SwiftJava modules provide Swift projections of Java classes and interfaces. Here are a few: | Java class | Swift class | Swift module | | --------------------- | -------------- | ---------------- | -| `java.lang.Object` | `JavaObject` | `JavaKit` | -| `java.lang.Class` | `JavaClass` | `JavaKit` | -| `java.lang.Throwable` | `Throwable` | `JavaKit` | -| `java.net.URL` | `URL` | `JavaKitNetwork` | +| `java.lang.Object` | `JavaObject` | `SwiftJava` | +| `java.lang.Class` | `JavaClass` | `SwiftJava` | +| `java.lang.Throwable` | `Throwable` | `SwiftJava` | +| `java.net.URL` | `URL` | `JavaNet` | The `swift-java` tool can translate any other Java classes into Swift projections. The easiest way to use `swift-java` is with the SwiftPM plugin described above. More information about using this tool directly are provided later in this document @@ -406,7 +406,7 @@ When building Java sources using the JavaCompilerPlugin this option is passed by ### Class objects and static methods -Every `AnyJavaObject` has a property `javaClass` that provides an instance of `JavaClass` specialized to the type. For example, `url.javaClass` will produce an instance of `JavaClass`. The `JavaClass` instance is a wrapper around a Java class object (`java.lang.Class`) that has two roles in Swift. First, it provides access to all of the APIs on the Java class object. The `JavaKitReflection` library, for example, exposes these APIs and the types they depend on (`Method`, +Every `AnyJavaObject` has a property `javaClass` that provides an instance of `JavaClass` specialized to the type. For example, `url.javaClass` will produce an instance of `JavaClass`. The `JavaClass` instance is a wrapper around a Java class object (`java.lang.Class`) that has two roles in Swift. First, it provides access to all of the APIs on the Java class object. The `JavaLangReflect` library, for example, exposes these APIs and the types they depend on (`Method`, `Constructor`, etc.) for dynamic reflection. Second, the `JavaClass` provides access to the `static` methods on the Java class. For example, [`java.net.URLConnection`](https://docs.oracle.com/javase/8/docs/api/java/net/URLConnection.html) has static methods to access default settings, such as the default for the `allowUserInteraction` field. These are exposed as instance methods on `JavaClass`, e.g., ```swift diff --git a/Sources/SwiftJavaTool/Commands/ConfigureCommand.swift b/Sources/SwiftJavaTool/Commands/ConfigureCommand.swift index 8bafd257..3bce6c18 100644 --- a/Sources/SwiftJavaTool/Commands/ConfigureCommand.swift +++ b/Sources/SwiftJavaTool/Commands/ConfigureCommand.swift @@ -35,9 +35,7 @@ extension SwiftJava { @OptionGroup var commonJVMOptions: SwiftJava.CommonJVMOptions // TODO: This should be a "make wrappers" option that just detects when we give it a jar - @Flag( - help: "Specifies that the input is a *.jar file whose public classes will be loaded. The output of swift-java will be a configuration file (swift-java.config) that can be used as input to a subsequent swift-java invocation to generate wrappers for those public classes." - ) + @Flag(help: "Specifies that the input is a *.jar file whose public classes will be loaded. The output of swift-java will be a configuration file (swift-java.config) that can be used as input to a subsequent swift-java invocation to generate wrappers for those public classes.") var jar: Bool = false @Option( @@ -57,9 +55,7 @@ extension SwiftJava { swiftModule } - @Argument( - help: "The input file, which is either a swift-java configuration file or (if '-jar' was specified) a Jar file." - ) + @Argument(help: "The input file, which is either a swift-java configuration file or (if '-jar' was specified) a Jar file.") var input: String? } } @@ -199,10 +195,9 @@ extension SwiftJava.ConfigureCommand { javaCanonicalName.defaultSwiftNameForJavaClass } } - } package func fileOrDirectoryExists(at path: String) -> Bool { var isDirectory: ObjCBool = false return FileManager.default.fileExists(atPath: path, isDirectory: &isDirectory) -} \ No newline at end of file +} From 3c36c767c6268d5b9d051e63ab669b5c91f1bb0d Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Thu, 28 Aug 2025 16:45:32 +0900 Subject: [PATCH 353/426] rename CJNI module to avoid conflicts; call it CSwiftJavaJNI (#377) --- Benchmarks/Package.swift | 2 +- Package.swift | 8 ++++---- Samples/JavaDependencySampleApp/Package.swift | 2 +- Samples/SwiftJavaExtractFFMSampleApp/Package.swift | 2 +- .../Sources/MySwiftLibrary/jni/JNIImplementations.swift | 2 +- Samples/SwiftJavaExtractJNISampleApp/Package.swift | 2 +- Sources/CJNI/include/module.modulemap | 4 ---- Sources/{CJNI => CSwiftJavaJNI}/dummy.c | 0 .../CJNI.h => CSwiftJavaJNI/include/CSwiftJavaJNI.h} | 6 +++--- Sources/CSwiftJavaJNI/include/module.modulemap | 4 ++++ .../JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift | 2 +- .../JavaKitDependencyResolver/DependencyResolver.swift | 2 +- .../JavaStdlib/JavaIO/generated/BufferedInputStream.swift | 2 +- Sources/JavaStdlib/JavaIO/generated/Charset.swift | 2 +- Sources/JavaStdlib/JavaIO/generated/Closeable.swift | 2 +- Sources/JavaStdlib/JavaIO/generated/File.swift | 2 +- Sources/JavaStdlib/JavaIO/generated/FileDescriptor.swift | 2 +- Sources/JavaStdlib/JavaIO/generated/FileReader.swift | 2 +- Sources/JavaStdlib/JavaIO/generated/Flushable.swift | 2 +- Sources/JavaStdlib/JavaIO/generated/InputStream.swift | 2 +- .../JavaStdlib/JavaIO/generated/InputStreamReader.swift | 2 +- Sources/JavaStdlib/JavaIO/generated/OutputStream.swift | 2 +- Sources/JavaStdlib/JavaIO/generated/Path.swift | 2 +- Sources/JavaStdlib/JavaIO/generated/Readable.swift | 2 +- Sources/JavaStdlib/JavaIO/generated/Reader.swift | 2 +- Sources/JavaStdlib/JavaIO/generated/StringReader.swift | 2 +- Sources/JavaStdlib/JavaIO/generated/WatchService.swift | 2 +- Sources/JavaStdlib/JavaIO/generated/Writer.swift | 2 +- .../JavaLangReflect/generated/AccessibleObject.swift | 2 +- .../JavaLangReflect/generated/AnnotatedType.swift | 2 +- .../JavaStdlib/JavaLangReflect/generated/Annotation.swift | 2 +- .../JavaLangReflect/generated/Constructor.swift | 2 +- .../JavaStdlib/JavaLangReflect/generated/Executable.swift | 2 +- Sources/JavaStdlib/JavaLangReflect/generated/Field.swift | 2 +- .../JavaLangReflect/generated/GenericArrayType.swift | 2 +- .../JavaLangReflect/generated/GenericDeclaration.swift | 2 +- Sources/JavaStdlib/JavaLangReflect/generated/Method.swift | 2 +- .../JavaStdlib/JavaLangReflect/generated/Parameter.swift | 2 +- .../JavaLangReflect/generated/ParameterizedType.swift | 2 +- Sources/JavaStdlib/JavaLangReflect/generated/Type.swift | 2 +- .../JavaLangReflect/generated/TypeVariable.swift | 2 +- .../JavaLangReflect/generated/WildcardType.swift | 2 +- Sources/JavaStdlib/JavaNet/generated/URI.swift | 2 +- Sources/JavaStdlib/JavaNet/generated/URL.swift | 2 +- Sources/JavaStdlib/JavaNet/generated/URLClassLoader.swift | 2 +- Sources/JavaStdlib/JavaNet/generated/URLConnection.swift | 2 +- Sources/JavaStdlib/JavaUtil/generated/ArrayDeque.swift | 2 +- Sources/JavaStdlib/JavaUtil/generated/ArrayList.swift | 2 +- Sources/JavaStdlib/JavaUtil/generated/BitSet.swift | 2 +- Sources/JavaStdlib/JavaUtil/generated/Enumeration.swift | 2 +- Sources/JavaStdlib/JavaUtil/generated/HashMap.swift | 2 +- Sources/JavaStdlib/JavaUtil/generated/HashSet.swift | 2 +- .../JavaStdlib/JavaUtil/generated/JavaCollection.swift | 2 +- .../JavaStdlib/JavaUtil/generated/JavaDictionary.swift | 2 +- Sources/JavaStdlib/JavaUtil/generated/JavaIterator.swift | 2 +- Sources/JavaStdlib/JavaUtil/generated/JavaSet.swift | 2 +- Sources/JavaStdlib/JavaUtil/generated/LinkedList.swift | 2 +- Sources/JavaStdlib/JavaUtil/generated/List.swift | 2 +- Sources/JavaStdlib/JavaUtil/generated/ListIterator.swift | 2 +- Sources/JavaStdlib/JavaUtil/generated/PriorityQueue.swift | 2 +- Sources/JavaStdlib/JavaUtil/generated/Queue.swift | 2 +- Sources/JavaStdlib/JavaUtil/generated/RandomAccess.swift | 2 +- Sources/JavaStdlib/JavaUtil/generated/Stack.swift | 2 +- Sources/JavaStdlib/JavaUtil/generated/TreeMap.swift | 2 +- Sources/JavaStdlib/JavaUtil/generated/TreeSet.swift | 2 +- .../JavaUtilFunction/generated/JavaBiConsumer.swift | 2 +- .../JavaUtilFunction/generated/JavaBiFunction.swift | 2 +- .../JavaUtilFunction/generated/JavaBiPredicate.swift | 2 +- .../JavaUtilFunction/generated/JavaBinaryOperator.swift | 2 +- .../JavaUtilFunction/generated/JavaBooleanSupplier.swift | 2 +- .../JavaUtilFunction/generated/JavaConsumer.swift | 2 +- .../generated/JavaDoubleBinaryOperator.swift | 2 +- .../JavaUtilFunction/generated/JavaDoubleConsumer.swift | 2 +- .../JavaUtilFunction/generated/JavaDoubleFunction.swift | 2 +- .../JavaUtilFunction/generated/JavaDoublePredicate.swift | 2 +- .../JavaUtilFunction/generated/JavaDoubleSupplier.swift | 2 +- .../generated/JavaDoubleToIntFunction.swift | 2 +- .../generated/JavaDoubleToLongFunction.swift | 2 +- .../generated/JavaDoubleUnaryOperator.swift | 2 +- .../JavaUtilFunction/generated/JavaFunction.swift | 2 +- .../generated/JavaIntBinaryOperator.swift | 2 +- .../JavaUtilFunction/generated/JavaIntConsumer.swift | 2 +- .../JavaUtilFunction/generated/JavaIntFunction.swift | 2 +- .../JavaUtilFunction/generated/JavaIntPredicate.swift | 2 +- .../JavaUtilFunction/generated/JavaIntSupplier.swift | 2 +- .../generated/JavaIntToDoubleFunction.swift | 2 +- .../generated/JavaIntToLongFunction.swift | 2 +- .../JavaUtilFunction/generated/JavaIntUnaryOperator.swift | 2 +- .../generated/JavaLongBinaryOperator.swift | 2 +- .../JavaUtilFunction/generated/JavaLongConsumer.swift | 2 +- .../JavaUtilFunction/generated/JavaLongFunction.swift | 2 +- .../JavaUtilFunction/generated/JavaLongPredicate.swift | 2 +- .../JavaUtilFunction/generated/JavaLongSupplier.swift | 2 +- .../generated/JavaLongToDoubleFunction.swift | 2 +- .../generated/JavaLongToIntFunction.swift | 2 +- .../generated/JavaLongUnaryOperator.swift | 2 +- .../generated/JavaObjDoubleConsumer.swift | 2 +- .../JavaUtilFunction/generated/JavaObjIntConsumer.swift | 2 +- .../JavaUtilFunction/generated/JavaObjLongConsumer.swift | 2 +- .../JavaUtilFunction/generated/JavaPredicate.swift | 2 +- .../JavaUtilFunction/generated/JavaSupplier.swift | 2 +- .../generated/JavaToDoubleBiFunction.swift | 2 +- .../JavaUtilFunction/generated/JavaToDoubleFunction.swift | 2 +- .../JavaUtilFunction/generated/JavaToIntBiFunction.swift | 2 +- .../JavaUtilFunction/generated/JavaToIntFunction.swift | 2 +- .../JavaUtilFunction/generated/JavaToLongBiFunction.swift | 2 +- .../JavaUtilFunction/generated/JavaToLongFunction.swift | 2 +- .../JavaUtilFunction/generated/JavaUnaryOperator.swift | 2 +- Sources/JavaStdlib/JavaUtilJar/generated/Attributes.swift | 2 +- Sources/JavaStdlib/JavaUtilJar/generated/JarEntry.swift | 2 +- Sources/JavaStdlib/JavaUtilJar/generated/JarFile.swift | 2 +- .../JavaStdlib/JavaUtilJar/generated/JarInputStream.swift | 2 +- .../JavaUtilJar/generated/JarOutputStream.swift | 2 +- Sources/JavaStdlib/JavaUtilJar/generated/Manifest.swift | 2 +- Sources/JavaStdlib/JavaUtilJar/generated/ZipEntry.swift | 2 +- Sources/SwiftJava/AnyJavaObject.swift | 2 +- Sources/SwiftJava/JavaClass+Initialization.swift | 2 +- Sources/SwiftJava/JavaEnvironment.swift | 2 +- Sources/SwiftJava/JavaObject+Inheritance.swift | 2 +- Sources/SwiftJava/JavaObject+MethodCalls.swift | 2 +- Sources/SwiftJava/JavaObjectHolder.swift | 2 +- Sources/SwiftJava/JavaRuntime+Reexport.swift | 2 +- Sources/SwiftJava/JavaValue.swift | 2 +- Sources/SwiftJava/Optional+JavaObject.swift | 2 +- Sources/SwiftJava/generated/Appendable.swift | 2 +- Sources/SwiftJava/generated/CharSequence.swift | 2 +- Sources/SwiftJava/generated/Exception.swift | 2 +- Sources/SwiftJava/generated/JavaArray.swift | 2 +- Sources/SwiftJava/generated/JavaBoolean.swift | 2 +- Sources/SwiftJava/generated/JavaByte.swift | 2 +- Sources/SwiftJava/generated/JavaCharacter.swift | 2 +- Sources/SwiftJava/generated/JavaClass.swift | 2 +- Sources/SwiftJava/generated/JavaClassLoader.swift | 2 +- Sources/SwiftJava/generated/JavaDouble.swift | 2 +- Sources/SwiftJava/generated/JavaError.swift | 2 +- Sources/SwiftJava/generated/JavaFloat.swift | 2 +- Sources/SwiftJava/generated/JavaInteger.swift | 2 +- Sources/SwiftJava/generated/JavaLong.swift | 2 +- Sources/SwiftJava/generated/JavaNumber.swift | 2 +- Sources/SwiftJava/generated/JavaObject.swift | 2 +- Sources/SwiftJava/generated/JavaOptional.swift | 2 +- Sources/SwiftJava/generated/JavaOptionalDouble.swift | 2 +- Sources/SwiftJava/generated/JavaOptionalInt.swift | 2 +- Sources/SwiftJava/generated/JavaOptionalLong.swift | 2 +- Sources/SwiftJava/generated/JavaShort.swift | 2 +- Sources/SwiftJava/generated/JavaString.swift | 2 +- Sources/SwiftJava/generated/JavaVoid.swift | 2 +- Sources/SwiftJava/generated/RuntimeException.swift | 2 +- Sources/SwiftJava/generated/Throwable.swift | 2 +- Sources/SwiftJavaTool/Java/JavaClassLoader.swift | 2 +- Sources/SwiftJavaToolLib/JavaTranslator.swift | 2 +- 151 files changed, 157 insertions(+), 157 deletions(-) delete mode 100644 Sources/CJNI/include/module.modulemap rename Sources/{CJNI => CSwiftJavaJNI}/dummy.c (100%) rename Sources/{CJNI/include/CJNI.h => CSwiftJavaJNI/include/CSwiftJavaJNI.h} (86%) create mode 100644 Sources/CSwiftJavaJNI/include/module.modulemap diff --git a/Benchmarks/Package.swift b/Benchmarks/Package.swift index 955378fc..127e4d48 100644 --- a/Benchmarks/Package.swift +++ b/Benchmarks/Package.swift @@ -51,7 +51,7 @@ let package = Package( .executableTarget( name: "JavaApiCallBenchmarks", dependencies: [ - .product(name: "CJNI", package: "swift-java"), + .product(name: "CSwiftJavaJNI", package: "swift-java"), .product(name: "SwiftJava", package: "swift-java"), .product(name: "JavaNet", package: "swift-java"), .product(name: "Benchmark", package: "package-benchmark"), diff --git a/Package.swift b/Package.swift index a30b9510..1c0e9481 100644 --- a/Package.swift +++ b/Package.swift @@ -101,8 +101,8 @@ let package = Package( ), .library( - name: "CJNI", - targets: ["CJNI"] + name: "CSwiftJavaJNI", + targets: ["CSwiftJavaJNI"] ), .library( @@ -237,7 +237,7 @@ let package = Package( .target( name: "SwiftJava", dependencies: [ - "CJNI", + "CSwiftJavaJNI", "SwiftJavaMacros", "JavaTypes", "SwiftJavaConfigurationShared", // for Configuration reading at runtime @@ -359,7 +359,7 @@ let package = Package( ), .target( - name: "CJNI", + name: "CSwiftJavaJNI", swiftSettings: [ .swiftLanguageMode(.v5), .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) diff --git a/Samples/JavaDependencySampleApp/Package.swift b/Samples/JavaDependencySampleApp/Package.swift index c5ae97c7..573a60cc 100644 --- a/Samples/JavaDependencySampleApp/Package.swift +++ b/Samples/JavaDependencySampleApp/Package.swift @@ -65,7 +65,7 @@ let package = Package( name: "JavaDependencySample", dependencies: [ .product(name: "SwiftJava", package: "swift-java"), - .product(name: "CJNI", package: "swift-java"), + .product(name: "CSwiftJavaJNI", package: "swift-java"), .product(name: "JavaUtilFunction", package: "swift-java"), "JavaCommonsCSV" ], diff --git a/Samples/SwiftJavaExtractFFMSampleApp/Package.swift b/Samples/SwiftJavaExtractFFMSampleApp/Package.swift index 30630a01..b9765c24 100644 --- a/Samples/SwiftJavaExtractFFMSampleApp/Package.swift +++ b/Samples/SwiftJavaExtractFFMSampleApp/Package.swift @@ -64,7 +64,7 @@ let package = Package( name: "MySwiftLibrary", dependencies: [ .product(name: "SwiftJava", package: "swift-java"), - .product(name: "CJNI", package: "swift-java"), + .product(name: "CSwiftJavaJNI", package: "swift-java"), .product(name: "SwiftKitSwift", package: "swift-java"), ], exclude: [ diff --git a/Samples/SwiftJavaExtractFFMSampleApp/Sources/MySwiftLibrary/jni/JNIImplementations.swift b/Samples/SwiftJavaExtractFFMSampleApp/Sources/MySwiftLibrary/jni/JNIImplementations.swift index 481265d5..50561d32 100644 --- a/Samples/SwiftJavaExtractFFMSampleApp/Sources/MySwiftLibrary/jni/JNIImplementations.swift +++ b/Samples/SwiftJavaExtractFFMSampleApp/Sources/MySwiftLibrary/jni/JNIImplementations.swift @@ -13,7 +13,7 @@ //===----------------------------------------------------------------------===// import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaClass("com.example.swift.HelloJava2Swift") open class HelloJava2Swift: JavaObject { diff --git a/Samples/SwiftJavaExtractJNISampleApp/Package.swift b/Samples/SwiftJavaExtractJNISampleApp/Package.swift index 0d2d2fa8..c7d5d717 100644 --- a/Samples/SwiftJavaExtractJNISampleApp/Package.swift +++ b/Samples/SwiftJavaExtractJNISampleApp/Package.swift @@ -61,7 +61,7 @@ let package = Package( name: "MySwiftLibrary", dependencies: [ .product(name: "SwiftJava", package: "swift-java"), - .product(name: "CJNI", package: "swift-java"), + .product(name: "CSwiftJavaJNI", package: "swift-java"), .product(name: "SwiftKitSwift", package: "swift-java"), ], exclude: [ diff --git a/Sources/CJNI/include/module.modulemap b/Sources/CJNI/include/module.modulemap deleted file mode 100644 index c71f30c2..00000000 --- a/Sources/CJNI/include/module.modulemap +++ /dev/null @@ -1,4 +0,0 @@ -module CJNI { - umbrella header "CJNI.h" - export * -} diff --git a/Sources/CJNI/dummy.c b/Sources/CSwiftJavaJNI/dummy.c similarity index 100% rename from Sources/CJNI/dummy.c rename to Sources/CSwiftJavaJNI/dummy.c diff --git a/Sources/CJNI/include/CJNI.h b/Sources/CSwiftJavaJNI/include/CSwiftJavaJNI.h similarity index 86% rename from Sources/CJNI/include/CJNI.h rename to Sources/CSwiftJavaJNI/include/CSwiftJavaJNI.h index bef6e7ff..fb5f71af 100644 --- a/Sources/CJNI/include/CJNI.h +++ b/Sources/CSwiftJavaJNI/include/CSwiftJavaJNI.h @@ -12,9 +12,9 @@ // //===----------------------------------------------------------------------===// -#ifndef Swift_CJNI_h -#define Swift_CJNI_h +#ifndef CSwiftJavaJNI_h +#define CSwiftJavaJNI_h #include -#endif /* Swift_CJNI_h */ +#endif /* CSwiftJavaJNI_h */ diff --git a/Sources/CSwiftJavaJNI/include/module.modulemap b/Sources/CSwiftJavaJNI/include/module.modulemap new file mode 100644 index 00000000..2be3eda9 --- /dev/null +++ b/Sources/CSwiftJavaJNI/include/module.modulemap @@ -0,0 +1,4 @@ +module CSwiftJavaJNI { + umbrella header "CSwiftJavaJNI.h" + export * +} diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift index 53679783..329b7dfd 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift @@ -409,7 +409,7 @@ extension JNISwift2JavaGenerator { // Generated by swift-java import SwiftJava - import CJNI + import CSwiftJavaJNI """ ) diff --git a/Sources/JavaKitDependencyResolver/DependencyResolver.swift b/Sources/JavaKitDependencyResolver/DependencyResolver.swift index 1ecc8dc5..2d339b15 100644 --- a/Sources/JavaKitDependencyResolver/DependencyResolver.swift +++ b/Sources/JavaKitDependencyResolver/DependencyResolver.swift @@ -13,7 +13,7 @@ //===----------------------------------------------------------------------===// import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaInterface("org.swift.jni.dependencies.DependencyResolver") public struct DependencyResolver { diff --git a/Sources/JavaStdlib/JavaIO/generated/BufferedInputStream.swift b/Sources/JavaStdlib/JavaIO/generated/BufferedInputStream.swift index b4a13494..2a211eb9 100644 --- a/Sources/JavaStdlib/JavaIO/generated/BufferedInputStream.swift +++ b/Sources/JavaStdlib/JavaIO/generated/BufferedInputStream.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaClass("java.io.BufferedInputStream") open class BufferedInputStream: InputStream { diff --git a/Sources/JavaStdlib/JavaIO/generated/Charset.swift b/Sources/JavaStdlib/JavaIO/generated/Charset.swift index f3b9126c..03e85a8c 100644 --- a/Sources/JavaStdlib/JavaIO/generated/Charset.swift +++ b/Sources/JavaStdlib/JavaIO/generated/Charset.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaClass("java.nio.charset.Charset") open class Charset: JavaObject { diff --git a/Sources/JavaStdlib/JavaIO/generated/Closeable.swift b/Sources/JavaStdlib/JavaIO/generated/Closeable.swift index 9e68c58b..1df52641 100644 --- a/Sources/JavaStdlib/JavaIO/generated/Closeable.swift +++ b/Sources/JavaStdlib/JavaIO/generated/Closeable.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaInterface("java.io.Closeable") public struct Closeable { diff --git a/Sources/JavaStdlib/JavaIO/generated/File.swift b/Sources/JavaStdlib/JavaIO/generated/File.swift index 11831b5e..68b04efb 100644 --- a/Sources/JavaStdlib/JavaIO/generated/File.swift +++ b/Sources/JavaStdlib/JavaIO/generated/File.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaClass("java.io.File") open class File: JavaObject { diff --git a/Sources/JavaStdlib/JavaIO/generated/FileDescriptor.swift b/Sources/JavaStdlib/JavaIO/generated/FileDescriptor.swift index 36f1686c..4c95b2b3 100644 --- a/Sources/JavaStdlib/JavaIO/generated/FileDescriptor.swift +++ b/Sources/JavaStdlib/JavaIO/generated/FileDescriptor.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaClass("java.io.FileDescriptor") open class FileDescriptor: JavaObject { diff --git a/Sources/JavaStdlib/JavaIO/generated/FileReader.swift b/Sources/JavaStdlib/JavaIO/generated/FileReader.swift index ed0898c7..b793a3f6 100644 --- a/Sources/JavaStdlib/JavaIO/generated/FileReader.swift +++ b/Sources/JavaStdlib/JavaIO/generated/FileReader.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaClass("java.io.FileReader") open class FileReader: InputStreamReader { diff --git a/Sources/JavaStdlib/JavaIO/generated/Flushable.swift b/Sources/JavaStdlib/JavaIO/generated/Flushable.swift index 59854369..95cfc448 100644 --- a/Sources/JavaStdlib/JavaIO/generated/Flushable.swift +++ b/Sources/JavaStdlib/JavaIO/generated/Flushable.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaInterface("java.io.Flushable") public struct Flushable { diff --git a/Sources/JavaStdlib/JavaIO/generated/InputStream.swift b/Sources/JavaStdlib/JavaIO/generated/InputStream.swift index d521f265..b42a8fd8 100644 --- a/Sources/JavaStdlib/JavaIO/generated/InputStream.swift +++ b/Sources/JavaStdlib/JavaIO/generated/InputStream.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaClass("java.io.InputStream", implements: Closeable.self) open class InputStream: JavaObject { diff --git a/Sources/JavaStdlib/JavaIO/generated/InputStreamReader.swift b/Sources/JavaStdlib/JavaIO/generated/InputStreamReader.swift index faa04eda..7e55d633 100644 --- a/Sources/JavaStdlib/JavaIO/generated/InputStreamReader.swift +++ b/Sources/JavaStdlib/JavaIO/generated/InputStreamReader.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaClass("java.io.InputStreamReader") open class InputStreamReader: Reader { diff --git a/Sources/JavaStdlib/JavaIO/generated/OutputStream.swift b/Sources/JavaStdlib/JavaIO/generated/OutputStream.swift index 1d3ec356..d499508c 100644 --- a/Sources/JavaStdlib/JavaIO/generated/OutputStream.swift +++ b/Sources/JavaStdlib/JavaIO/generated/OutputStream.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaClass("java.io.OutputStream", implements: Closeable.self, Flushable.self) open class OutputStream: JavaObject { diff --git a/Sources/JavaStdlib/JavaIO/generated/Path.swift b/Sources/JavaStdlib/JavaIO/generated/Path.swift index 87956f10..235d9cef 100644 --- a/Sources/JavaStdlib/JavaIO/generated/Path.swift +++ b/Sources/JavaStdlib/JavaIO/generated/Path.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaInterface("java.nio.file.Path") public struct Path { diff --git a/Sources/JavaStdlib/JavaIO/generated/Readable.swift b/Sources/JavaStdlib/JavaIO/generated/Readable.swift index 25f48221..8961e18a 100644 --- a/Sources/JavaStdlib/JavaIO/generated/Readable.swift +++ b/Sources/JavaStdlib/JavaIO/generated/Readable.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaInterface("java.lang.Readable") public struct Readable { diff --git a/Sources/JavaStdlib/JavaIO/generated/Reader.swift b/Sources/JavaStdlib/JavaIO/generated/Reader.swift index e133f741..5d8f77bf 100644 --- a/Sources/JavaStdlib/JavaIO/generated/Reader.swift +++ b/Sources/JavaStdlib/JavaIO/generated/Reader.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaClass("java.io.Reader", implements: Readable.self, Closeable.self) open class Reader: JavaObject { diff --git a/Sources/JavaStdlib/JavaIO/generated/StringReader.swift b/Sources/JavaStdlib/JavaIO/generated/StringReader.swift index aa3efd38..ae4464ed 100644 --- a/Sources/JavaStdlib/JavaIO/generated/StringReader.swift +++ b/Sources/JavaStdlib/JavaIO/generated/StringReader.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaClass("java.io.StringReader") open class StringReader: Reader { diff --git a/Sources/JavaStdlib/JavaIO/generated/WatchService.swift b/Sources/JavaStdlib/JavaIO/generated/WatchService.swift index 0b44c4fe..e2c570a3 100644 --- a/Sources/JavaStdlib/JavaIO/generated/WatchService.swift +++ b/Sources/JavaStdlib/JavaIO/generated/WatchService.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaInterface("java.nio.file.WatchService", extends: Closeable.self) public struct WatchService { diff --git a/Sources/JavaStdlib/JavaIO/generated/Writer.swift b/Sources/JavaStdlib/JavaIO/generated/Writer.swift index 7712a1c0..fe20d27d 100644 --- a/Sources/JavaStdlib/JavaIO/generated/Writer.swift +++ b/Sources/JavaStdlib/JavaIO/generated/Writer.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaClass("java.io.Writer", implements: Appendable.self, Closeable.self, Flushable.self) open class Writer: JavaObject { diff --git a/Sources/JavaStdlib/JavaLangReflect/generated/AccessibleObject.swift b/Sources/JavaStdlib/JavaLangReflect/generated/AccessibleObject.swift index c118f78b..c6b0f4fc 100644 --- a/Sources/JavaStdlib/JavaLangReflect/generated/AccessibleObject.swift +++ b/Sources/JavaStdlib/JavaLangReflect/generated/AccessibleObject.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaClass("java.lang.reflect.AccessibleObject") open class AccessibleObject: JavaObject { diff --git a/Sources/JavaStdlib/JavaLangReflect/generated/AnnotatedType.swift b/Sources/JavaStdlib/JavaLangReflect/generated/AnnotatedType.swift index cc5b418c..87480ef4 100644 --- a/Sources/JavaStdlib/JavaLangReflect/generated/AnnotatedType.swift +++ b/Sources/JavaStdlib/JavaLangReflect/generated/AnnotatedType.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaInterface("java.lang.reflect.AnnotatedType") public struct AnnotatedType { diff --git a/Sources/JavaStdlib/JavaLangReflect/generated/Annotation.swift b/Sources/JavaStdlib/JavaLangReflect/generated/Annotation.swift index 66ab49cc..1449bf32 100644 --- a/Sources/JavaStdlib/JavaLangReflect/generated/Annotation.swift +++ b/Sources/JavaStdlib/JavaLangReflect/generated/Annotation.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaInterface("java.lang.annotation.Annotation") public struct Annotation { diff --git a/Sources/JavaStdlib/JavaLangReflect/generated/Constructor.swift b/Sources/JavaStdlib/JavaLangReflect/generated/Constructor.swift index 76f49f11..202cba9b 100644 --- a/Sources/JavaStdlib/JavaLangReflect/generated/Constructor.swift +++ b/Sources/JavaStdlib/JavaLangReflect/generated/Constructor.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaClass("java.lang.reflect.Constructor") open class Constructor: Executable { diff --git a/Sources/JavaStdlib/JavaLangReflect/generated/Executable.swift b/Sources/JavaStdlib/JavaLangReflect/generated/Executable.swift index 31799784..3a6df8ea 100644 --- a/Sources/JavaStdlib/JavaLangReflect/generated/Executable.swift +++ b/Sources/JavaStdlib/JavaLangReflect/generated/Executable.swift @@ -1,7 +1,7 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava import JavaUtil -import CJNI +import CSwiftJavaJNI @JavaClass("java.lang.reflect.Executable", implements: GenericDeclaration.self) open class Executable: AccessibleObject { diff --git a/Sources/JavaStdlib/JavaLangReflect/generated/Field.swift b/Sources/JavaStdlib/JavaLangReflect/generated/Field.swift index 2c4a49e9..ba4f4538 100644 --- a/Sources/JavaStdlib/JavaLangReflect/generated/Field.swift +++ b/Sources/JavaStdlib/JavaLangReflect/generated/Field.swift @@ -1,7 +1,7 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava import JavaUtil -import CJNI +import CSwiftJavaJNI @JavaClass("java.lang.reflect.Field") open class Field: AccessibleObject { diff --git a/Sources/JavaStdlib/JavaLangReflect/generated/GenericArrayType.swift b/Sources/JavaStdlib/JavaLangReflect/generated/GenericArrayType.swift index 75ad2c75..42375e08 100644 --- a/Sources/JavaStdlib/JavaLangReflect/generated/GenericArrayType.swift +++ b/Sources/JavaStdlib/JavaLangReflect/generated/GenericArrayType.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaInterface("java.lang.reflect.GenericArrayType", extends: Type.self) public struct GenericArrayType { diff --git a/Sources/JavaStdlib/JavaLangReflect/generated/GenericDeclaration.swift b/Sources/JavaStdlib/JavaLangReflect/generated/GenericDeclaration.swift index bec84aa5..839fa7db 100644 --- a/Sources/JavaStdlib/JavaLangReflect/generated/GenericDeclaration.swift +++ b/Sources/JavaStdlib/JavaLangReflect/generated/GenericDeclaration.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaInterface("java.lang.reflect.GenericDeclaration") public struct GenericDeclaration { diff --git a/Sources/JavaStdlib/JavaLangReflect/generated/Method.swift b/Sources/JavaStdlib/JavaLangReflect/generated/Method.swift index 4489cf24..94371cd4 100644 --- a/Sources/JavaStdlib/JavaLangReflect/generated/Method.swift +++ b/Sources/JavaStdlib/JavaLangReflect/generated/Method.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaClass("java.lang.reflect.Method") open class Method: Executable { diff --git a/Sources/JavaStdlib/JavaLangReflect/generated/Parameter.swift b/Sources/JavaStdlib/JavaLangReflect/generated/Parameter.swift index 6dea46fd..35ea7098 100644 --- a/Sources/JavaStdlib/JavaLangReflect/generated/Parameter.swift +++ b/Sources/JavaStdlib/JavaLangReflect/generated/Parameter.swift @@ -1,7 +1,7 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava import JavaUtil -import CJNI +import CSwiftJavaJNI @JavaClass("java.lang.reflect.Parameter") open class Parameter: JavaObject { diff --git a/Sources/JavaStdlib/JavaLangReflect/generated/ParameterizedType.swift b/Sources/JavaStdlib/JavaLangReflect/generated/ParameterizedType.swift index a427a2a5..5e29ee05 100644 --- a/Sources/JavaStdlib/JavaLangReflect/generated/ParameterizedType.swift +++ b/Sources/JavaStdlib/JavaLangReflect/generated/ParameterizedType.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaInterface("java.lang.reflect.ParameterizedType", extends: Type.self) public struct ParameterizedType { diff --git a/Sources/JavaStdlib/JavaLangReflect/generated/Type.swift b/Sources/JavaStdlib/JavaLangReflect/generated/Type.swift index 05e8687e..ff52b41a 100644 --- a/Sources/JavaStdlib/JavaLangReflect/generated/Type.swift +++ b/Sources/JavaStdlib/JavaLangReflect/generated/Type.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaInterface("java.lang.reflect.Type") public struct Type { diff --git a/Sources/JavaStdlib/JavaLangReflect/generated/TypeVariable.swift b/Sources/JavaStdlib/JavaLangReflect/generated/TypeVariable.swift index e6a7899c..736fcfde 100644 --- a/Sources/JavaStdlib/JavaLangReflect/generated/TypeVariable.swift +++ b/Sources/JavaStdlib/JavaLangReflect/generated/TypeVariable.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaInterface("java.lang.reflect.TypeVariable", extends: Type.self) public struct TypeVariable { diff --git a/Sources/JavaStdlib/JavaLangReflect/generated/WildcardType.swift b/Sources/JavaStdlib/JavaLangReflect/generated/WildcardType.swift index 2514495a..a09b1b3b 100644 --- a/Sources/JavaStdlib/JavaLangReflect/generated/WildcardType.swift +++ b/Sources/JavaStdlib/JavaLangReflect/generated/WildcardType.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaInterface("java.lang.reflect.WildcardType", extends: Type.self) public struct WildcardType { diff --git a/Sources/JavaStdlib/JavaNet/generated/URI.swift b/Sources/JavaStdlib/JavaNet/generated/URI.swift index f1a6c078..d6242406 100644 --- a/Sources/JavaStdlib/JavaNet/generated/URI.swift +++ b/Sources/JavaStdlib/JavaNet/generated/URI.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaClass("java.net.URI") open class URI: JavaObject { diff --git a/Sources/JavaStdlib/JavaNet/generated/URL.swift b/Sources/JavaStdlib/JavaNet/generated/URL.swift index 9140a1d9..95ac8fb4 100644 --- a/Sources/JavaStdlib/JavaNet/generated/URL.swift +++ b/Sources/JavaStdlib/JavaNet/generated/URL.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaClass("java.net.URL") open class URL: JavaObject { diff --git a/Sources/JavaStdlib/JavaNet/generated/URLClassLoader.swift b/Sources/JavaStdlib/JavaNet/generated/URLClassLoader.swift index 1750f197..d16e2eac 100644 --- a/Sources/JavaStdlib/JavaNet/generated/URLClassLoader.swift +++ b/Sources/JavaStdlib/JavaNet/generated/URLClassLoader.swift @@ -1,7 +1,7 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava import JavaUtil -import CJNI +import CSwiftJavaJNI @JavaClass("java.net.URLClassLoader") open class URLClassLoader: JavaObject { diff --git a/Sources/JavaStdlib/JavaNet/generated/URLConnection.swift b/Sources/JavaStdlib/JavaNet/generated/URLConnection.swift index 6a93edd1..332e7425 100644 --- a/Sources/JavaStdlib/JavaNet/generated/URLConnection.swift +++ b/Sources/JavaStdlib/JavaNet/generated/URLConnection.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaClass("java.net.URLConnection") public struct URLConnection { diff --git a/Sources/JavaStdlib/JavaUtil/generated/ArrayDeque.swift b/Sources/JavaStdlib/JavaUtil/generated/ArrayDeque.swift index f0d257af..b8a1fb18 100644 --- a/Sources/JavaStdlib/JavaUtil/generated/ArrayDeque.swift +++ b/Sources/JavaStdlib/JavaUtil/generated/ArrayDeque.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaClass("java.util.ArrayDeque") open class ArrayDeque: JavaObject { diff --git a/Sources/JavaStdlib/JavaUtil/generated/ArrayList.swift b/Sources/JavaStdlib/JavaUtil/generated/ArrayList.swift index b39ada56..9ead8f4c 100644 --- a/Sources/JavaStdlib/JavaUtil/generated/ArrayList.swift +++ b/Sources/JavaStdlib/JavaUtil/generated/ArrayList.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaClass("java.util.ArrayList", implements: List.self, RandomAccess.self) open class ArrayList: JavaObject { diff --git a/Sources/JavaStdlib/JavaUtil/generated/BitSet.swift b/Sources/JavaStdlib/JavaUtil/generated/BitSet.swift index 2d89ba5a..7356b4b8 100644 --- a/Sources/JavaStdlib/JavaUtil/generated/BitSet.swift +++ b/Sources/JavaStdlib/JavaUtil/generated/BitSet.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaClass("java.util.BitSet") open class BitSet: JavaObject { diff --git a/Sources/JavaStdlib/JavaUtil/generated/Enumeration.swift b/Sources/JavaStdlib/JavaUtil/generated/Enumeration.swift index 0229e16d..9c039b16 100644 --- a/Sources/JavaStdlib/JavaUtil/generated/Enumeration.swift +++ b/Sources/JavaStdlib/JavaUtil/generated/Enumeration.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaInterface("java.util.Enumeration") public struct Enumeration { diff --git a/Sources/JavaStdlib/JavaUtil/generated/HashMap.swift b/Sources/JavaStdlib/JavaUtil/generated/HashMap.swift index 6fd38bc4..a217d48f 100644 --- a/Sources/JavaStdlib/JavaUtil/generated/HashMap.swift +++ b/Sources/JavaStdlib/JavaUtil/generated/HashMap.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaClass("java.util.HashMap") open class HashMap: JavaObject { diff --git a/Sources/JavaStdlib/JavaUtil/generated/HashSet.swift b/Sources/JavaStdlib/JavaUtil/generated/HashSet.swift index f7c37d21..3b089c86 100644 --- a/Sources/JavaStdlib/JavaUtil/generated/HashSet.swift +++ b/Sources/JavaStdlib/JavaUtil/generated/HashSet.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaClass("java.util.HashSet", implements: JavaSet.self) open class HashSet: JavaObject { diff --git a/Sources/JavaStdlib/JavaUtil/generated/JavaCollection.swift b/Sources/JavaStdlib/JavaUtil/generated/JavaCollection.swift index 4d1c8a81..3a8db21b 100644 --- a/Sources/JavaStdlib/JavaUtil/generated/JavaCollection.swift +++ b/Sources/JavaStdlib/JavaUtil/generated/JavaCollection.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaInterface("java.util.Collection") public struct JavaCollection { diff --git a/Sources/JavaStdlib/JavaUtil/generated/JavaDictionary.swift b/Sources/JavaStdlib/JavaUtil/generated/JavaDictionary.swift index 85ee9beb..0a6508f5 100644 --- a/Sources/JavaStdlib/JavaUtil/generated/JavaDictionary.swift +++ b/Sources/JavaStdlib/JavaUtil/generated/JavaDictionary.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaClass("java.util.Dictionary") open class JavaDictionary: JavaObject { diff --git a/Sources/JavaStdlib/JavaUtil/generated/JavaIterator.swift b/Sources/JavaStdlib/JavaUtil/generated/JavaIterator.swift index 1038a5e1..06f09d7f 100644 --- a/Sources/JavaStdlib/JavaUtil/generated/JavaIterator.swift +++ b/Sources/JavaStdlib/JavaUtil/generated/JavaIterator.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaInterface("java.util.Iterator") public struct JavaIterator { diff --git a/Sources/JavaStdlib/JavaUtil/generated/JavaSet.swift b/Sources/JavaStdlib/JavaUtil/generated/JavaSet.swift index 7fec8e7a..12ff0056 100644 --- a/Sources/JavaStdlib/JavaUtil/generated/JavaSet.swift +++ b/Sources/JavaStdlib/JavaUtil/generated/JavaSet.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaInterface("java.util.Set", extends: JavaCollection.self) public struct JavaSet { diff --git a/Sources/JavaStdlib/JavaUtil/generated/LinkedList.swift b/Sources/JavaStdlib/JavaUtil/generated/LinkedList.swift index 9f27a3e1..2464980f 100644 --- a/Sources/JavaStdlib/JavaUtil/generated/LinkedList.swift +++ b/Sources/JavaStdlib/JavaUtil/generated/LinkedList.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaClass("java.util.LinkedList") public struct LinkedList { diff --git a/Sources/JavaStdlib/JavaUtil/generated/List.swift b/Sources/JavaStdlib/JavaUtil/generated/List.swift index 1d745ec3..2ebc1942 100644 --- a/Sources/JavaStdlib/JavaUtil/generated/List.swift +++ b/Sources/JavaStdlib/JavaUtil/generated/List.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaInterface("java.util.List") public struct List { diff --git a/Sources/JavaStdlib/JavaUtil/generated/ListIterator.swift b/Sources/JavaStdlib/JavaUtil/generated/ListIterator.swift index a643efa7..121330b1 100644 --- a/Sources/JavaStdlib/JavaUtil/generated/ListIterator.swift +++ b/Sources/JavaStdlib/JavaUtil/generated/ListIterator.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaInterface("java.util.ListIterator", extends: JavaIterator.self) public struct ListIterator { diff --git a/Sources/JavaStdlib/JavaUtil/generated/PriorityQueue.swift b/Sources/JavaStdlib/JavaUtil/generated/PriorityQueue.swift index 13fc3629..d9d9a85a 100644 --- a/Sources/JavaStdlib/JavaUtil/generated/PriorityQueue.swift +++ b/Sources/JavaStdlib/JavaUtil/generated/PriorityQueue.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaClass("java.util.PriorityQueue") open class PriorityQueue: JavaObject { diff --git a/Sources/JavaStdlib/JavaUtil/generated/Queue.swift b/Sources/JavaStdlib/JavaUtil/generated/Queue.swift index 1d51d7c4..b007e90a 100644 --- a/Sources/JavaStdlib/JavaUtil/generated/Queue.swift +++ b/Sources/JavaStdlib/JavaUtil/generated/Queue.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaInterface("java.util.Queue", extends: JavaCollection.self) public struct Queue { diff --git a/Sources/JavaStdlib/JavaUtil/generated/RandomAccess.swift b/Sources/JavaStdlib/JavaUtil/generated/RandomAccess.swift index e0fcb390..91b3fa31 100644 --- a/Sources/JavaStdlib/JavaUtil/generated/RandomAccess.swift +++ b/Sources/JavaStdlib/JavaUtil/generated/RandomAccess.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaInterface("java.util.RandomAccess") public struct RandomAccess { diff --git a/Sources/JavaStdlib/JavaUtil/generated/Stack.swift b/Sources/JavaStdlib/JavaUtil/generated/Stack.swift index 636ed03b..be4330eb 100644 --- a/Sources/JavaStdlib/JavaUtil/generated/Stack.swift +++ b/Sources/JavaStdlib/JavaUtil/generated/Stack.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaClass("java.util.Stack") open class Stack: JavaObject { diff --git a/Sources/JavaStdlib/JavaUtil/generated/TreeMap.swift b/Sources/JavaStdlib/JavaUtil/generated/TreeMap.swift index 4bf41ed3..c6dd3bb0 100644 --- a/Sources/JavaStdlib/JavaUtil/generated/TreeMap.swift +++ b/Sources/JavaStdlib/JavaUtil/generated/TreeMap.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaClass("java.util.TreeMap") open class TreeMap: JavaObject { diff --git a/Sources/JavaStdlib/JavaUtil/generated/TreeSet.swift b/Sources/JavaStdlib/JavaUtil/generated/TreeSet.swift index cbfe8979..3ec9b1ea 100644 --- a/Sources/JavaStdlib/JavaUtil/generated/TreeSet.swift +++ b/Sources/JavaStdlib/JavaUtil/generated/TreeSet.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaClass("java.util.TreeSet") open class TreeSet: JavaObject { diff --git a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaBiConsumer.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaBiConsumer.swift index a8f33127..a01a0933 100644 --- a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaBiConsumer.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaBiConsumer.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaInterface("java.util.function.BiConsumer") public struct JavaBiConsumer { diff --git a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaBiFunction.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaBiFunction.swift index d83e74a8..ad54c58b 100644 --- a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaBiFunction.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaBiFunction.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaInterface("java.util.function.BiFunction") public struct JavaBiFunction { diff --git a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaBiPredicate.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaBiPredicate.swift index f1870aa4..ee8aa0f5 100644 --- a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaBiPredicate.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaBiPredicate.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaInterface("java.util.function.BiPredicate") public struct JavaBiPredicate { diff --git a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaBinaryOperator.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaBinaryOperator.swift index a03e9add..1c7f5456 100644 --- a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaBinaryOperator.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaBinaryOperator.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaInterface( "java.util.function.BinaryOperator", diff --git a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaBooleanSupplier.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaBooleanSupplier.swift index d6ce66de..e6e4a3ce 100644 --- a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaBooleanSupplier.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaBooleanSupplier.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaInterface("java.util.function.BooleanSupplier") public struct JavaBooleanSupplier { diff --git a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaConsumer.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaConsumer.swift index f8e64b2f..7da9bea8 100644 --- a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaConsumer.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaConsumer.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaInterface("java.util.function.Consumer") public struct JavaConsumer { diff --git a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaDoubleBinaryOperator.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaDoubleBinaryOperator.swift index ee82194d..f6c1c671 100644 --- a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaDoubleBinaryOperator.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaDoubleBinaryOperator.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaInterface("java.util.function.DoubleBinaryOperator") public struct JavaDoubleBinaryOperator { diff --git a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaDoubleConsumer.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaDoubleConsumer.swift index a4a5a48f..baf53c4a 100644 --- a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaDoubleConsumer.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaDoubleConsumer.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaInterface("java.util.function.DoubleConsumer") public struct JavaDoubleConsumer { diff --git a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaDoubleFunction.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaDoubleFunction.swift index 96879af4..6f5d6752 100644 --- a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaDoubleFunction.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaDoubleFunction.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaInterface("java.util.function.DoubleFunction") public struct JavaDoubleFunction { diff --git a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaDoublePredicate.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaDoublePredicate.swift index 27ac5861..c594518d 100644 --- a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaDoublePredicate.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaDoublePredicate.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaInterface("java.util.function.DoublePredicate") public struct JavaDoublePredicate { diff --git a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaDoubleSupplier.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaDoubleSupplier.swift index 807668bc..839ae7e7 100644 --- a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaDoubleSupplier.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaDoubleSupplier.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaInterface("java.util.function.DoubleSupplier") public struct JavaDoubleSupplier { diff --git a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaDoubleToIntFunction.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaDoubleToIntFunction.swift index 4de7ab7f..438249eb 100644 --- a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaDoubleToIntFunction.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaDoubleToIntFunction.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaInterface("java.util.function.DoubleToIntFunction") public struct JavaDoubleToIntFunction { diff --git a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaDoubleToLongFunction.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaDoubleToLongFunction.swift index 492dbfa6..76b916db 100644 --- a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaDoubleToLongFunction.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaDoubleToLongFunction.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaInterface("java.util.function.DoubleToLongFunction") public struct JavaDoubleToLongFunction { diff --git a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaDoubleUnaryOperator.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaDoubleUnaryOperator.swift index 9db463ee..cf1ff7e5 100644 --- a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaDoubleUnaryOperator.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaDoubleUnaryOperator.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaInterface("java.util.function.DoubleUnaryOperator") public struct JavaDoubleUnaryOperator { diff --git a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaFunction.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaFunction.swift index 6e2361d7..7a8165d8 100644 --- a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaFunction.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaFunction.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaInterface("java.util.function.Function") public struct JavaFunction { diff --git a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaIntBinaryOperator.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaIntBinaryOperator.swift index f7a56f18..3df580c7 100644 --- a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaIntBinaryOperator.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaIntBinaryOperator.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaInterface("java.util.function.IntBinaryOperator") public struct JavaIntBinaryOperator { diff --git a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaIntConsumer.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaIntConsumer.swift index 62130b88..a8ac7c0b 100644 --- a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaIntConsumer.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaIntConsumer.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaInterface("java.util.function.IntConsumer") public struct JavaIntConsumer { diff --git a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaIntFunction.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaIntFunction.swift index c3fcdf1e..6ebb7292 100644 --- a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaIntFunction.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaIntFunction.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaInterface("java.util.function.IntFunction") public struct JavaIntFunction { diff --git a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaIntPredicate.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaIntPredicate.swift index 2ca8fcc0..66c5e133 100644 --- a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaIntPredicate.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaIntPredicate.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaInterface("java.util.function.IntPredicate") public struct JavaIntPredicate { diff --git a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaIntSupplier.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaIntSupplier.swift index 05155e79..0976fd53 100644 --- a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaIntSupplier.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaIntSupplier.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaInterface("java.util.function.IntSupplier") public struct JavaIntSupplier { diff --git a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaIntToDoubleFunction.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaIntToDoubleFunction.swift index f3efcc6d..9891e815 100644 --- a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaIntToDoubleFunction.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaIntToDoubleFunction.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaInterface("java.util.function.IntToDoubleFunction") public struct JavaIntToDoubleFunction { diff --git a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaIntToLongFunction.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaIntToLongFunction.swift index 1bbe989c..17a7b7fa 100644 --- a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaIntToLongFunction.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaIntToLongFunction.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaInterface("java.util.function.IntToLongFunction") public struct JavaIntToLongFunction { diff --git a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaIntUnaryOperator.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaIntUnaryOperator.swift index 04ed0b2b..89528a2b 100644 --- a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaIntUnaryOperator.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaIntUnaryOperator.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaInterface("java.util.function.IntUnaryOperator") public struct JavaIntUnaryOperator { diff --git a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaLongBinaryOperator.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaLongBinaryOperator.swift index 1f3ca791..1cd53b93 100644 --- a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaLongBinaryOperator.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaLongBinaryOperator.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaInterface("java.util.function.LongBinaryOperator") public struct JavaLongBinaryOperator { diff --git a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaLongConsumer.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaLongConsumer.swift index 82ae2a3b..4c84754a 100644 --- a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaLongConsumer.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaLongConsumer.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaInterface("java.util.function.LongConsumer") public struct JavaLongConsumer { diff --git a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaLongFunction.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaLongFunction.swift index eeed2bd8..9ce4cef1 100644 --- a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaLongFunction.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaLongFunction.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaInterface("java.util.function.LongFunction") public struct JavaLongFunction { diff --git a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaLongPredicate.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaLongPredicate.swift index 77f1293e..8f8f91fc 100644 --- a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaLongPredicate.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaLongPredicate.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaInterface("java.util.function.LongPredicate") public struct JavaLongPredicate { diff --git a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaLongSupplier.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaLongSupplier.swift index 60e5421d..e0a203a1 100644 --- a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaLongSupplier.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaLongSupplier.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaInterface("java.util.function.LongSupplier") public struct JavaLongSupplier { diff --git a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaLongToDoubleFunction.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaLongToDoubleFunction.swift index a115477c..7167d8fc 100644 --- a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaLongToDoubleFunction.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaLongToDoubleFunction.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaInterface("java.util.function.LongToDoubleFunction") public struct JavaLongToDoubleFunction { diff --git a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaLongToIntFunction.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaLongToIntFunction.swift index 984dbda3..00671304 100644 --- a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaLongToIntFunction.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaLongToIntFunction.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaInterface("java.util.function.LongToIntFunction") public struct JavaLongToIntFunction { diff --git a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaLongUnaryOperator.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaLongUnaryOperator.swift index 7e379b0a..8cf8944b 100644 --- a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaLongUnaryOperator.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaLongUnaryOperator.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaInterface("java.util.function.LongUnaryOperator") public struct JavaLongUnaryOperator { diff --git a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaObjDoubleConsumer.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaObjDoubleConsumer.swift index 5c19ff03..aa7d5a48 100644 --- a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaObjDoubleConsumer.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaObjDoubleConsumer.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaInterface("java.util.function.ObjDoubleConsumer") public struct JavaObjDoubleConsumer { diff --git a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaObjIntConsumer.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaObjIntConsumer.swift index a511db83..c53c3631 100644 --- a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaObjIntConsumer.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaObjIntConsumer.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaInterface("java.util.function.ObjIntConsumer") public struct JavaObjIntConsumer { diff --git a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaObjLongConsumer.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaObjLongConsumer.swift index a2c32cfa..ff4f7798 100644 --- a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaObjLongConsumer.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaObjLongConsumer.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaInterface("java.util.function.ObjLongConsumer") public struct JavaObjLongConsumer { diff --git a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaPredicate.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaPredicate.swift index a2de359a..b888e178 100644 --- a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaPredicate.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaPredicate.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaInterface("java.util.function.Predicate") public struct JavaPredicate { diff --git a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaSupplier.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaSupplier.swift index a751ae79..4d4c73cd 100644 --- a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaSupplier.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaSupplier.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaInterface("java.util.function.Supplier") public struct JavaSupplier { diff --git a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaToDoubleBiFunction.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaToDoubleBiFunction.swift index 739f1f17..35f77b78 100644 --- a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaToDoubleBiFunction.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaToDoubleBiFunction.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaInterface("java.util.function.ToDoubleBiFunction") public struct JavaToDoubleBiFunction { diff --git a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaToDoubleFunction.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaToDoubleFunction.swift index acdf7adb..56ee180d 100644 --- a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaToDoubleFunction.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaToDoubleFunction.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaInterface("java.util.function.ToDoubleFunction") public struct JavaToDoubleFunction { diff --git a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaToIntBiFunction.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaToIntBiFunction.swift index e1fdcc0a..dc17fa2b 100644 --- a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaToIntBiFunction.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaToIntBiFunction.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaInterface("java.util.function.ToIntBiFunction") public struct JavaToIntBiFunction { diff --git a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaToIntFunction.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaToIntFunction.swift index 4d963c57..3663f499 100644 --- a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaToIntFunction.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaToIntFunction.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaInterface("java.util.function.ToIntFunction") public struct JavaToIntFunction { diff --git a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaToLongBiFunction.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaToLongBiFunction.swift index fb42c3e4..1d5fc739 100644 --- a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaToLongBiFunction.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaToLongBiFunction.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaInterface("java.util.function.ToLongBiFunction") public struct JavaToLongBiFunction { diff --git a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaToLongFunction.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaToLongFunction.swift index e34b5bd0..66805be7 100644 --- a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaToLongFunction.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaToLongFunction.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaInterface("java.util.function.ToLongFunction") public struct JavaToLongFunction { diff --git a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaUnaryOperator.swift b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaUnaryOperator.swift index a31be86e..11dc00ee 100644 --- a/Sources/JavaStdlib/JavaUtilFunction/generated/JavaUnaryOperator.swift +++ b/Sources/JavaStdlib/JavaUtilFunction/generated/JavaUnaryOperator.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaInterface( "java.util.function.UnaryOperator", extends: JavaFunction.self) diff --git a/Sources/JavaStdlib/JavaUtilJar/generated/Attributes.swift b/Sources/JavaStdlib/JavaUtilJar/generated/Attributes.swift index 710ce640..4897ebe3 100644 --- a/Sources/JavaStdlib/JavaUtilJar/generated/Attributes.swift +++ b/Sources/JavaStdlib/JavaUtilJar/generated/Attributes.swift @@ -1,7 +1,7 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava import JavaUtil -import CJNI +import CSwiftJavaJNI @JavaClass("java.util.jar.Attributes") open class Attributes: JavaObject { diff --git a/Sources/JavaStdlib/JavaUtilJar/generated/JarEntry.swift b/Sources/JavaStdlib/JavaUtilJar/generated/JarEntry.swift index 7140cb97..adfb6d17 100644 --- a/Sources/JavaStdlib/JavaUtilJar/generated/JarEntry.swift +++ b/Sources/JavaStdlib/JavaUtilJar/generated/JarEntry.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaClass("java.util.jar.JarEntry") open class JarEntry: ZipEntry { diff --git a/Sources/JavaStdlib/JavaUtilJar/generated/JarFile.swift b/Sources/JavaStdlib/JavaUtilJar/generated/JarFile.swift index db84e626..e630afd2 100644 --- a/Sources/JavaStdlib/JavaUtilJar/generated/JarFile.swift +++ b/Sources/JavaStdlib/JavaUtilJar/generated/JarFile.swift @@ -1,7 +1,7 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava import JavaUtil -import CJNI +import CSwiftJavaJNI @JavaClass("java.util.jar.JarFile") open class JarFile: JavaObject { diff --git a/Sources/JavaStdlib/JavaUtilJar/generated/JarInputStream.swift b/Sources/JavaStdlib/JavaUtilJar/generated/JarInputStream.swift index 7d2ce423..60f007fe 100644 --- a/Sources/JavaStdlib/JavaUtilJar/generated/JarInputStream.swift +++ b/Sources/JavaStdlib/JavaUtilJar/generated/JarInputStream.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaClass("java.util.jar.JarInputStream") open class JarInputStream: JavaObject { diff --git a/Sources/JavaStdlib/JavaUtilJar/generated/JarOutputStream.swift b/Sources/JavaStdlib/JavaUtilJar/generated/JarOutputStream.swift index 79a7c14e..bd27471f 100644 --- a/Sources/JavaStdlib/JavaUtilJar/generated/JarOutputStream.swift +++ b/Sources/JavaStdlib/JavaUtilJar/generated/JarOutputStream.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaClass("java.util.jar.JarOutputStream") open class JarOutputStream: JavaObject { diff --git a/Sources/JavaStdlib/JavaUtilJar/generated/Manifest.swift b/Sources/JavaStdlib/JavaUtilJar/generated/Manifest.swift index b43b9e85..2033f41a 100644 --- a/Sources/JavaStdlib/JavaUtilJar/generated/Manifest.swift +++ b/Sources/JavaStdlib/JavaUtilJar/generated/Manifest.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaClass("java.util.jar.Manifest") open class Manifest: JavaObject { diff --git a/Sources/JavaStdlib/JavaUtilJar/generated/ZipEntry.swift b/Sources/JavaStdlib/JavaUtilJar/generated/ZipEntry.swift index e276ae2a..3066d54c 100644 --- a/Sources/JavaStdlib/JavaUtilJar/generated/ZipEntry.swift +++ b/Sources/JavaStdlib/JavaUtilJar/generated/ZipEntry.swift @@ -1,6 +1,6 @@ // Auto-generated by Java-to-Swift wrapper generator. import SwiftJava -import CJNI +import CSwiftJavaJNI @JavaClass("java.util.zip.ZipEntry") open class ZipEntry: JavaObject { diff --git a/Sources/SwiftJava/AnyJavaObject.swift b/Sources/SwiftJava/AnyJavaObject.swift index 02b9d70b..e514d3e6 100644 --- a/Sources/SwiftJava/AnyJavaObject.swift +++ b/Sources/SwiftJava/AnyJavaObject.swift @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -import CJNI +import CSwiftJavaJNI /// Protocol that describes Swift types that are bridged to a Java class type. /// diff --git a/Sources/SwiftJava/JavaClass+Initialization.swift b/Sources/SwiftJava/JavaClass+Initialization.swift index 8101c37a..89bfa62b 100644 --- a/Sources/SwiftJava/JavaClass+Initialization.swift +++ b/Sources/SwiftJava/JavaClass+Initialization.swift @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -import CJNI +import CSwiftJavaJNI extension JavaClass { public typealias ObjectType = T diff --git a/Sources/SwiftJava/JavaEnvironment.swift b/Sources/SwiftJava/JavaEnvironment.swift index fd6a626b..a533a932 100644 --- a/Sources/SwiftJava/JavaEnvironment.swift +++ b/Sources/SwiftJava/JavaEnvironment.swift @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -import CJNI +import CSwiftJavaJNI #if canImport(Android) typealias JNINativeInterface_ = JNINativeInterface diff --git a/Sources/SwiftJava/JavaObject+Inheritance.swift b/Sources/SwiftJava/JavaObject+Inheritance.swift index aa80fa54..f306b9c6 100644 --- a/Sources/SwiftJava/JavaObject+Inheritance.swift +++ b/Sources/SwiftJava/JavaObject+Inheritance.swift @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -import CJNI +import CSwiftJavaJNI extension AnyJavaObject { /// Look up the other class type diff --git a/Sources/SwiftJava/JavaObject+MethodCalls.swift b/Sources/SwiftJava/JavaObject+MethodCalls.swift index 1a62d0f4..4880f750 100644 --- a/Sources/SwiftJava/JavaObject+MethodCalls.swift +++ b/Sources/SwiftJava/JavaObject+MethodCalls.swift @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -import CJNI +import CSwiftJavaJNI import JavaTypes /// Produce the mangling for a method with the given argument and result types. diff --git a/Sources/SwiftJava/JavaObjectHolder.swift b/Sources/SwiftJava/JavaObjectHolder.swift index 50f60a82..319a09e8 100644 --- a/Sources/SwiftJava/JavaObjectHolder.swift +++ b/Sources/SwiftJava/JavaObjectHolder.swift @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -import CJNI +import CSwiftJavaJNI /// Stores a reference to a Java object, managing it as a global reference so /// that the Java virtual machine will not move or deallocate the object diff --git a/Sources/SwiftJava/JavaRuntime+Reexport.swift b/Sources/SwiftJava/JavaRuntime+Reexport.swift index f1a19e1c..9b2c02a8 100644 --- a/Sources/SwiftJava/JavaRuntime+Reexport.swift +++ b/Sources/SwiftJava/JavaRuntime+Reexport.swift @@ -12,4 +12,4 @@ // //===----------------------------------------------------------------------===// -@_exported import CJNI +@_exported import CSwiftJavaJNI diff --git a/Sources/SwiftJava/JavaValue.swift b/Sources/SwiftJava/JavaValue.swift index a740eb50..46efdb3f 100644 --- a/Sources/SwiftJava/JavaValue.swift +++ b/Sources/SwiftJava/JavaValue.swift @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -import CJNI +import CSwiftJavaJNI import JavaTypes /// Describes a type that can be bridged with Java. diff --git a/Sources/SwiftJava/Optional+JavaObject.swift b/Sources/SwiftJava/Optional+JavaObject.swift index f34ef2b3..46fd9970 100644 --- a/Sources/SwiftJava/Optional+JavaObject.swift +++ b/Sources/SwiftJava/Optional+JavaObject.swift @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -import CJNI +import CSwiftJavaJNI import JavaTypes extension Optional: JavaValue where Wrapped: AnyJavaObject { diff --git a/Sources/SwiftJava/generated/Appendable.swift b/Sources/SwiftJava/generated/Appendable.swift index 7ff4f97e..b0c67ec5 100644 --- a/Sources/SwiftJava/generated/Appendable.swift +++ b/Sources/SwiftJava/generated/Appendable.swift @@ -1,5 +1,5 @@ // Auto-generated by Java-to-Swift wrapper generator. -import CJNI +import CSwiftJavaJNI @JavaInterface("java.lang.Appendable") public struct Appendable { diff --git a/Sources/SwiftJava/generated/CharSequence.swift b/Sources/SwiftJava/generated/CharSequence.swift index c6e3d5be..eadc509e 100644 --- a/Sources/SwiftJava/generated/CharSequence.swift +++ b/Sources/SwiftJava/generated/CharSequence.swift @@ -1,5 +1,5 @@ // Auto-generated by Java-to-Swift wrapper generator. -import CJNI +import CSwiftJavaJNI @JavaInterface("java.lang.CharSequence") public struct CharSequence { diff --git a/Sources/SwiftJava/generated/Exception.swift b/Sources/SwiftJava/generated/Exception.swift index 8361f1b0..e87684cb 100644 --- a/Sources/SwiftJava/generated/Exception.swift +++ b/Sources/SwiftJava/generated/Exception.swift @@ -1,5 +1,5 @@ // Auto-generated by Java-to-Swift wrapper generator. -import CJNI +import CSwiftJavaJNI @JavaClass("java.lang.Exception") open class Exception: Throwable { diff --git a/Sources/SwiftJava/generated/JavaArray.swift b/Sources/SwiftJava/generated/JavaArray.swift index 65d3f88f..ae182208 100644 --- a/Sources/SwiftJava/generated/JavaArray.swift +++ b/Sources/SwiftJava/generated/JavaArray.swift @@ -1,5 +1,5 @@ // Auto-generated by Java-to-Swift wrapper generator. -import CJNI +import CSwiftJavaJNI @JavaClass("java.lang.reflect.Array") open class JavaArray: JavaObject { diff --git a/Sources/SwiftJava/generated/JavaBoolean.swift b/Sources/SwiftJava/generated/JavaBoolean.swift index 995afc57..bdf21df9 100644 --- a/Sources/SwiftJava/generated/JavaBoolean.swift +++ b/Sources/SwiftJava/generated/JavaBoolean.swift @@ -1,5 +1,5 @@ // Auto-generated by Java-to-Swift wrapper generator. -import CJNI +import CSwiftJavaJNI @JavaClass("java.lang.Boolean") open class JavaBoolean: JavaObject { diff --git a/Sources/SwiftJava/generated/JavaByte.swift b/Sources/SwiftJava/generated/JavaByte.swift index a9ed639b..e3f67c78 100644 --- a/Sources/SwiftJava/generated/JavaByte.swift +++ b/Sources/SwiftJava/generated/JavaByte.swift @@ -1,5 +1,5 @@ // Auto-generated by Java-to-Swift wrapper generator. -import CJNI +import CSwiftJavaJNI @JavaClass("java.lang.Byte") open class JavaByte: JavaNumber { diff --git a/Sources/SwiftJava/generated/JavaCharacter.swift b/Sources/SwiftJava/generated/JavaCharacter.swift index 308a7fce..406b45ee 100644 --- a/Sources/SwiftJava/generated/JavaCharacter.swift +++ b/Sources/SwiftJava/generated/JavaCharacter.swift @@ -1,5 +1,5 @@ // Auto-generated by Java-to-Swift wrapper generator. -import CJNI +import CSwiftJavaJNI @JavaClass("java.lang.Character") open class JavaCharacter: JavaObject { diff --git a/Sources/SwiftJava/generated/JavaClass.swift b/Sources/SwiftJava/generated/JavaClass.swift index 1144482f..0f1af1cd 100644 --- a/Sources/SwiftJava/generated/JavaClass.swift +++ b/Sources/SwiftJava/generated/JavaClass.swift @@ -1,5 +1,5 @@ // Auto-generated by Java-to-Swift wrapper generator. -import CJNI +import CSwiftJavaJNI @JavaClass("java.lang.Class") open class JavaClass: JavaObject { diff --git a/Sources/SwiftJava/generated/JavaClassLoader.swift b/Sources/SwiftJava/generated/JavaClassLoader.swift index b6fabea4..349cba8d 100644 --- a/Sources/SwiftJava/generated/JavaClassLoader.swift +++ b/Sources/SwiftJava/generated/JavaClassLoader.swift @@ -1,5 +1,5 @@ // Auto-generated by Java-to-Swift wrapper generator. -import CJNI +import CSwiftJavaJNI @JavaClass("java.lang.ClassLoader") open class JavaClassLoader: JavaObject { diff --git a/Sources/SwiftJava/generated/JavaDouble.swift b/Sources/SwiftJava/generated/JavaDouble.swift index 9d979fb3..8d54f8de 100644 --- a/Sources/SwiftJava/generated/JavaDouble.swift +++ b/Sources/SwiftJava/generated/JavaDouble.swift @@ -1,5 +1,5 @@ // Auto-generated by Java-to-Swift wrapper generator. -import CJNI +import CSwiftJavaJNI @JavaClass("java.lang.Double") open class JavaDouble: JavaNumber { diff --git a/Sources/SwiftJava/generated/JavaError.swift b/Sources/SwiftJava/generated/JavaError.swift index da3c4218..4ba9d2ca 100644 --- a/Sources/SwiftJava/generated/JavaError.swift +++ b/Sources/SwiftJava/generated/JavaError.swift @@ -1,5 +1,5 @@ // Auto-generated by Java-to-Swift wrapper generator. -import CJNI +import CSwiftJavaJNI @JavaClass("java.lang.Error") open class JavaError: Throwable { diff --git a/Sources/SwiftJava/generated/JavaFloat.swift b/Sources/SwiftJava/generated/JavaFloat.swift index 9b11957e..ac989531 100644 --- a/Sources/SwiftJava/generated/JavaFloat.swift +++ b/Sources/SwiftJava/generated/JavaFloat.swift @@ -1,5 +1,5 @@ // Auto-generated by Java-to-Swift wrapper generator. -import CJNI +import CSwiftJavaJNI @JavaClass("java.lang.Float") open class JavaFloat: JavaNumber { diff --git a/Sources/SwiftJava/generated/JavaInteger.swift b/Sources/SwiftJava/generated/JavaInteger.swift index 286bc525..94800037 100644 --- a/Sources/SwiftJava/generated/JavaInteger.swift +++ b/Sources/SwiftJava/generated/JavaInteger.swift @@ -1,5 +1,5 @@ // Auto-generated by Java-to-Swift wrapper generator. -import CJNI +import CSwiftJavaJNI @JavaClass("java.lang.Integer") open class JavaInteger: JavaNumber { diff --git a/Sources/SwiftJava/generated/JavaLong.swift b/Sources/SwiftJava/generated/JavaLong.swift index 9e4a183e..a986e9ef 100644 --- a/Sources/SwiftJava/generated/JavaLong.swift +++ b/Sources/SwiftJava/generated/JavaLong.swift @@ -1,5 +1,5 @@ // Auto-generated by Java-to-Swift wrapper generator. -import CJNI +import CSwiftJavaJNI @JavaClass("java.lang.Long") open class JavaLong: JavaNumber { diff --git a/Sources/SwiftJava/generated/JavaNumber.swift b/Sources/SwiftJava/generated/JavaNumber.swift index 81d0bacd..78f988f1 100644 --- a/Sources/SwiftJava/generated/JavaNumber.swift +++ b/Sources/SwiftJava/generated/JavaNumber.swift @@ -1,5 +1,5 @@ // Auto-generated by Java-to-Swift wrapper generator. -import CJNI +import CSwiftJavaJNI @JavaClass("java.lang.Number") open class JavaNumber: JavaObject { diff --git a/Sources/SwiftJava/generated/JavaObject.swift b/Sources/SwiftJava/generated/JavaObject.swift index 37e48b2d..7db8a965 100644 --- a/Sources/SwiftJava/generated/JavaObject.swift +++ b/Sources/SwiftJava/generated/JavaObject.swift @@ -1,5 +1,5 @@ // Auto-generated by Java-to-Swift wrapper generator. -import CJNI +import CSwiftJavaJNI @JavaClass("java.lang.Object") open class JavaObject { diff --git a/Sources/SwiftJava/generated/JavaOptional.swift b/Sources/SwiftJava/generated/JavaOptional.swift index 7615c738..08cc764a 100644 --- a/Sources/SwiftJava/generated/JavaOptional.swift +++ b/Sources/SwiftJava/generated/JavaOptional.swift @@ -1,5 +1,5 @@ // Auto-generated by Java-to-Swift wrapper generator. -import CJNI +import CSwiftJavaJNI @JavaClass("java.util.Optional") open class JavaOptional: JavaObject { diff --git a/Sources/SwiftJava/generated/JavaOptionalDouble.swift b/Sources/SwiftJava/generated/JavaOptionalDouble.swift index 8f1514be..0d0e2eae 100644 --- a/Sources/SwiftJava/generated/JavaOptionalDouble.swift +++ b/Sources/SwiftJava/generated/JavaOptionalDouble.swift @@ -1,5 +1,5 @@ // Auto-generated by Java-to-Swift wrapper generator. -import CJNI +import CSwiftJavaJNI @JavaClass("java.util.OptionalDouble") open class JavaOptionalDouble: JavaObject { diff --git a/Sources/SwiftJava/generated/JavaOptionalInt.swift b/Sources/SwiftJava/generated/JavaOptionalInt.swift index 9543d090..2270e66e 100644 --- a/Sources/SwiftJava/generated/JavaOptionalInt.swift +++ b/Sources/SwiftJava/generated/JavaOptionalInt.swift @@ -1,5 +1,5 @@ // Auto-generated by Java-to-Swift wrapper generator. -import CJNI +import CSwiftJavaJNI @JavaClass("java.util.OptionalInt") open class JavaOptionalInt: JavaObject { diff --git a/Sources/SwiftJava/generated/JavaOptionalLong.swift b/Sources/SwiftJava/generated/JavaOptionalLong.swift index ac9b4409..10c3fbd0 100644 --- a/Sources/SwiftJava/generated/JavaOptionalLong.swift +++ b/Sources/SwiftJava/generated/JavaOptionalLong.swift @@ -1,5 +1,5 @@ // Auto-generated by Java-to-Swift wrapper generator. -import CJNI +import CSwiftJavaJNI @JavaClass("java.util.OptionalLong") open class JavaOptionalLong: JavaObject { diff --git a/Sources/SwiftJava/generated/JavaShort.swift b/Sources/SwiftJava/generated/JavaShort.swift index 12ca1dd2..4f387b36 100644 --- a/Sources/SwiftJava/generated/JavaShort.swift +++ b/Sources/SwiftJava/generated/JavaShort.swift @@ -1,5 +1,5 @@ // Auto-generated by Java-to-Swift wrapper generator. -import CJNI +import CSwiftJavaJNI @JavaClass("java.lang.Short") open class JavaShort: JavaNumber { diff --git a/Sources/SwiftJava/generated/JavaString.swift b/Sources/SwiftJava/generated/JavaString.swift index 393c1acf..f3372f65 100644 --- a/Sources/SwiftJava/generated/JavaString.swift +++ b/Sources/SwiftJava/generated/JavaString.swift @@ -1,5 +1,5 @@ // Auto-generated by Java-to-Swift wrapper generator. -import CJNI +import CSwiftJavaJNI @JavaClass("java.lang.String", implements: CharSequence.self) open class JavaString: JavaObject { diff --git a/Sources/SwiftJava/generated/JavaVoid.swift b/Sources/SwiftJava/generated/JavaVoid.swift index b2976196..54decbbc 100644 --- a/Sources/SwiftJava/generated/JavaVoid.swift +++ b/Sources/SwiftJava/generated/JavaVoid.swift @@ -1,5 +1,5 @@ // Auto-generated by Java-to-Swift wrapper generator. -import CJNI +import CSwiftJavaJNI @JavaClass("java.lang.Void") open class JavaVoid: JavaObject { diff --git a/Sources/SwiftJava/generated/RuntimeException.swift b/Sources/SwiftJava/generated/RuntimeException.swift index aacd2362..14516ed1 100644 --- a/Sources/SwiftJava/generated/RuntimeException.swift +++ b/Sources/SwiftJava/generated/RuntimeException.swift @@ -1,5 +1,5 @@ // Auto-generated by Java-to-Swift wrapper generator. -import CJNI +import CSwiftJavaJNI @JavaClass("java.lang.RuntimeException") open class RuntimeException: Exception { diff --git a/Sources/SwiftJava/generated/Throwable.swift b/Sources/SwiftJava/generated/Throwable.swift index 823486d8..7df74b7e 100644 --- a/Sources/SwiftJava/generated/Throwable.swift +++ b/Sources/SwiftJava/generated/Throwable.swift @@ -1,5 +1,5 @@ // Auto-generated by Java-to-Swift wrapper generator. -import CJNI +import CSwiftJavaJNI @JavaClass("java.lang.Throwable") open class Throwable: JavaObject { diff --git a/Sources/SwiftJavaTool/Java/JavaClassLoader.swift b/Sources/SwiftJavaTool/Java/JavaClassLoader.swift index bd1ec3f2..d465a206 100644 --- a/Sources/SwiftJavaTool/Java/JavaClassLoader.swift +++ b/Sources/SwiftJavaTool/Java/JavaClassLoader.swift @@ -14,7 +14,7 @@ import SwiftJavaToolLib import SwiftJavaShared -import CJNI +import CSwiftJavaJNI import SwiftJava @JavaClass("java.lang.ClassLoader") diff --git a/Sources/SwiftJavaToolLib/JavaTranslator.swift b/Sources/SwiftJavaToolLib/JavaTranslator.swift index 2f6f280c..7cb8a7ee 100644 --- a/Sources/SwiftJavaToolLib/JavaTranslator.swift +++ b/Sources/SwiftJavaToolLib/JavaTranslator.swift @@ -94,7 +94,7 @@ extension JavaTranslator { /// Default set of modules that will always be imported. private static let defaultImportedSwiftModules: Set = [ "SwiftJava", - "CJNI", + "CSwiftJavaJNI", ] } From 5744562b36b8c893448c5983742465c8e1a534f4 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Thu, 28 Aug 2025 16:57:44 +0900 Subject: [PATCH 354/426] Avoid jextracting +SwiftJava files (#378) --- Sources/JExtractSwiftLib/Swift2Java.swift | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/Sources/JExtractSwiftLib/Swift2Java.swift b/Sources/JExtractSwiftLib/Swift2Java.swift index e6271993..19241592 100644 --- a/Sources/JExtractSwiftLib/Swift2Java.swift +++ b/Sources/JExtractSwiftLib/Swift2Java.swift @@ -124,8 +124,15 @@ public struct SwiftToJava { } func canExtract(from file: URL) -> Bool { - file.lastPathComponent.hasSuffix(".swift") || - file.lastPathComponent.hasSuffix(".swiftinterface") + guard file.lastPathComponent.hasSuffix(".swift") || + file.lastPathComponent.hasSuffix(".swiftinterface") else { + return false + } + if file.lastPathComponent.hasSuffix("+SwiftJava.swift") { + return false + } + + return true } } From 73d7882fc69ab0ef9d2067c1544983a0a286367a Mon Sep 17 00:00:00 2001 From: Mads Odgaard Date: Fri, 29 Aug 2025 08:30:40 +0200 Subject: [PATCH 355/426] [JExtract/JNI] Add support for protocols as parameter types (#376) --- .../MySwiftLibrary/ConcreteProtocolAB.swift | 28 ++ .../Sources/MySwiftLibrary/ProtocolA.swift | 24 ++ .../Sources/MySwiftLibrary/ProtocolB.swift | 29 +++ .../java/com/example/swift/EnumBenchmark.java | 0 .../com/example/swift/AlignmentEnumTest.java | 1 + .../java/com/example/swift/ProtocolTest.java | 75 ++++++ .../Convenience/SwiftSyntax+Extensions.swift | 6 +- .../FFM/CDeclLowering/CRepresentation.swift | 2 +- ...Swift2JavaGenerator+FunctionLowering.swift | 9 +- ...t2JavaGenerator+JavaBindingsPrinting.swift | 7 +- ...MSwift2JavaGenerator+JavaTranslation.swift | 5 +- Sources/JExtractSwiftLib/ImportedDecls.swift | 6 +- ...t2JavaGenerator+JavaBindingsPrinting.swift | 138 ++++++++-- ...ISwift2JavaGenerator+JavaTranslation.swift | 157 +++++++++-- ...wift2JavaGenerator+NativeTranslation.swift | 160 ++++++++++-- ...ift2JavaGenerator+SwiftThunkPrinting.swift | 33 +++ .../JNI/JNISwift2JavaGenerator.swift | 2 + Sources/JExtractSwiftLib/JavaParameter.swift | 45 +++- .../Swift2JavaTranslator.swift | 8 +- .../JExtractSwiftLib/Swift2JavaVisitor.swift | 10 +- .../SwiftNominalTypeDeclaration.swift | 4 + ...ype.swift => SwiftType+GenericTypes.swift} | 32 +++ .../SwiftTypes/SwiftType.swift | 20 +- .../Documentation.docc/SupportedFeatures.md | 56 +++- .../swift/swiftkit/core/JNISwiftInstance.java | 33 +-- .../swift/swiftkit/core/SwiftInstance.java | 20 +- .../org/swift/swiftkit/AutoArenaTest.java | 25 +- .../swift/swiftkit/ffm/FFMSwiftInstance.java | 18 +- .../org/swift/swiftkit/ffm/AutoArenaTest.java | 1 + .../JNI/JNIClassTests.swift | 25 +- .../JExtractSwiftTests/JNI/JNIEnumTests.swift | 21 +- .../JNI/JNIModuleTests.swift | 1 + .../JNI/JNIOptionalTests.swift | 10 +- .../JNI/JNIProtocolTests.swift | 246 ++++++++++++++++++ .../JNI/JNIStructTests.swift | 14 +- Tests/JExtractSwiftTests/SendableTests.swift | 4 +- 36 files changed, 1121 insertions(+), 154 deletions(-) create mode 100644 Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/ConcreteProtocolAB.swift create mode 100644 Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/ProtocolA.swift create mode 100644 Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/ProtocolB.swift rename Samples/{JExtractJNISampleApp => SwiftJavaExtractJNISampleApp}/src/jmh/java/com/example/swift/EnumBenchmark.java (100%) create mode 100644 Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/ProtocolTest.java rename Sources/JExtractSwiftLib/SwiftTypes/{SwiftType+RepresentativeConcreteeType.swift => SwiftType+GenericTypes.swift} (72%) create mode 100644 Tests/JExtractSwiftTests/JNI/JNIProtocolTests.swift diff --git a/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/ConcreteProtocolAB.swift b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/ConcreteProtocolAB.swift new file mode 100644 index 00000000..ed55d039 --- /dev/null +++ b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/ConcreteProtocolAB.swift @@ -0,0 +1,28 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +public class ConcreteProtocolAB: ProtocolA, ProtocolB { + public let constantA: Int64 + public let constantB: Int64 + public var mutable: Int64 = 0 + + public func name() -> String { + return "ConcreteProtocolAB" + } + + public init(constantA: Int64, constantB: Int64) { + self.constantA = constantA + self.constantB = constantB + } +} diff --git a/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/ProtocolA.swift b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/ProtocolA.swift new file mode 100644 index 00000000..d5281b81 --- /dev/null +++ b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/ProtocolA.swift @@ -0,0 +1,24 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +public protocol ProtocolA { + var constantA: Int64 { get } + var mutable: Int64 { get set } + + func name() -> String +} + +public func takeProtocol(_ proto1: any ProtocolA, _ proto2: some ProtocolA) -> Int64 { + return proto1.constantA + proto2.constantA +} diff --git a/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/ProtocolB.swift b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/ProtocolB.swift new file mode 100644 index 00000000..70d075c2 --- /dev/null +++ b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/ProtocolB.swift @@ -0,0 +1,29 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +public protocol ProtocolB { + var constantB: Int64 { get } +} + +public func takeCombinedProtocol(_ proto: some ProtocolA & ProtocolB) -> Int64 { + return proto.constantA + proto.constantB +} + +public func takeGenericProtocol(_ proto1: First, _ proto2: Second) -> Int64 { + return proto1.constantA + proto2.constantB +} + +public func takeCombinedGenericProtocol(_ proto: T) -> Int64 { + return proto.constantA + proto.constantB +} diff --git a/Samples/JExtractJNISampleApp/src/jmh/java/com/example/swift/EnumBenchmark.java b/Samples/SwiftJavaExtractJNISampleApp/src/jmh/java/com/example/swift/EnumBenchmark.java similarity index 100% rename from Samples/JExtractJNISampleApp/src/jmh/java/com/example/swift/EnumBenchmark.java rename to Samples/SwiftJavaExtractJNISampleApp/src/jmh/java/com/example/swift/EnumBenchmark.java diff --git a/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/AlignmentEnumTest.java b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/AlignmentEnumTest.java index 6be85c75..5bf05951 100644 --- a/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/AlignmentEnumTest.java +++ b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/AlignmentEnumTest.java @@ -16,6 +16,7 @@ import org.junit.jupiter.api.Test; import org.swift.swiftkit.core.ConfinedSwiftMemorySession; +import org.swift.swiftkit.core.JNISwiftInstance; import org.swift.swiftkit.core.SwiftArena; import java.util.Optional; diff --git a/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/ProtocolTest.java b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/ProtocolTest.java new file mode 100644 index 00000000..c095a42a --- /dev/null +++ b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/ProtocolTest.java @@ -0,0 +1,75 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package com.example.swift; + +import org.junit.jupiter.api.Test; +import org.swift.swiftkit.core.SwiftArena; + +import static org.junit.jupiter.api.Assertions.*; + +public class ProtocolTest { + @Test + void takeProtocol() { + try (var arena = SwiftArena.ofConfined()) { + ConcreteProtocolAB proto1 = ConcreteProtocolAB.init(10, 5, arena); + ConcreteProtocolAB proto2 = ConcreteProtocolAB.init(20, 1, arena); + assertEquals(30, MySwiftLibrary.takeProtocol(proto1, proto2)); + } + } + + @Test + void takeCombinedProtocol() { + try (var arena = SwiftArena.ofConfined()) { + ConcreteProtocolAB proto1 = ConcreteProtocolAB.init(10, 5, arena); + assertEquals(15, MySwiftLibrary.takeCombinedProtocol(proto1)); + } + } + + @Test + void takeGenericProtocol() { + try (var arena = SwiftArena.ofConfined()) { + ConcreteProtocolAB proto1 = ConcreteProtocolAB.init(10, 5, arena); + ConcreteProtocolAB proto2 = ConcreteProtocolAB.init(20, 1, arena); + assertEquals(11, MySwiftLibrary.takeGenericProtocol(proto1, proto2)); + } + } + + @Test + void takeCombinedGenericProtocol() { + try (var arena = SwiftArena.ofConfined()) { + ConcreteProtocolAB proto1 = ConcreteProtocolAB.init(10, 5, arena); + assertEquals(15, MySwiftLibrary.takeCombinedGenericProtocol(proto1)); + } + } + + @Test + void protocolVariables() { + try (var arena = SwiftArena.ofConfined()) { + ProtocolA proto1 = ConcreteProtocolAB.init(10, 5, arena); + assertEquals(10, proto1.getConstantA()); + assertEquals(0, proto1.getMutable()); + proto1.setMutable(3); + assertEquals(3, proto1.getMutable()); + } + } + + @Test + void protocolMethod() { + try (var arena = SwiftArena.ofConfined()) { + ProtocolA proto1 = ConcreteProtocolAB.init(10, 5, arena); + assertEquals("ConcreteProtocolAB", proto1.name()); + } + } +} \ No newline at end of file diff --git a/Sources/JExtractSwiftLib/Convenience/SwiftSyntax+Extensions.swift b/Sources/JExtractSwiftLib/Convenience/SwiftSyntax+Extensions.swift index 3719d99d..8a58f42a 100644 --- a/Sources/JExtractSwiftLib/Convenience/SwiftSyntax+Extensions.swift +++ b/Sources/JExtractSwiftLib/Convenience/SwiftSyntax+Extensions.swift @@ -95,7 +95,11 @@ extension DeclModifierSyntax { } extension WithModifiersSyntax { - var isPublic: Bool { + func isPublic(in type: NominalTypeDeclSyntaxNode?) -> Bool { + if let type, case .protocolDecl(let protocolDecl) = Syntax(type).as(SyntaxEnum.self) { + return protocolDecl.isPublic(in: nil) + } + return self.modifiers.contains { modifier in modifier.isPublic } diff --git a/Sources/JExtractSwiftLib/FFM/CDeclLowering/CRepresentation.swift b/Sources/JExtractSwiftLib/FFM/CDeclLowering/CRepresentation.swift index d2a71def..193b545f 100644 --- a/Sources/JExtractSwiftLib/FFM/CDeclLowering/CRepresentation.swift +++ b/Sources/JExtractSwiftLib/FFM/CDeclLowering/CRepresentation.swift @@ -68,7 +68,7 @@ extension CType { case .optional(let wrapped) where wrapped.isPointer: try self.init(cdeclType: wrapped) - case .genericParameter, .metatype, .optional, .tuple, .opaque, .existential: + case .genericParameter, .metatype, .optional, .tuple, .opaque, .existential, .composite: throw CDeclToCLoweringError.invalidCDeclType(cdeclType) } } diff --git a/Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift b/Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift index 0a61708e..5dfa5b71 100644 --- a/Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift +++ b/Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift @@ -344,6 +344,9 @@ struct CdeclLowering { case .optional(let wrapped): return try lowerOptionalParameter(wrapped, convention: convention, parameterName: parameterName, genericParameters: genericParameters, genericRequirements: genericRequirements) + + case .composite: + throw LoweringError.unhandledType(type) } } @@ -412,7 +415,7 @@ struct CdeclLowering { } throw LoweringError.unhandledType(.optional(wrappedType)) - case .function, .metatype, .optional: + case .function, .metatype, .optional, .composite: throw LoweringError.unhandledType(.optional(wrappedType)) } } @@ -513,7 +516,7 @@ struct CdeclLowering { // Custom types are not supported yet. throw LoweringError.unhandledType(type) - case .genericParameter, .function, .metatype, .optional, .tuple, .existential, .opaque: + case .genericParameter, .function, .metatype, .optional, .tuple, .existential, .opaque, .composite: // TODO: Implement throw LoweringError.unhandledType(type) } @@ -667,7 +670,7 @@ struct CdeclLowering { conversion: .tupleExplode(conversions, name: outParameterName) ) - case .genericParameter, .function, .optional, .existential, .opaque: + case .genericParameter, .function, .optional, .existential, .opaque, .composite: throw LoweringError.unhandledType(type) } } diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift index 84a90275..188f5e8b 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift @@ -396,9 +396,12 @@ extension FFMSwift2JavaGenerator { // Indirect return receivers. for outParameter in translatedSignature.result.outParameters { - let memoryLayout = renderMemoryLayoutValue(for: outParameter.type) + guard case .concrete(let type) = outParameter.type else { + continue + } + let memoryLayout = renderMemoryLayoutValue(for: type) - let arena = if let className = outParameter.type.className, + let arena = if let className = type.className, analysis.importedTypes[className] != nil { // Use passed-in 'SwiftArena' for 'SwiftValue'. "swiftArena$" diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift index 00fa60e7..438393cb 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift @@ -472,6 +472,9 @@ extension FFMSwift2JavaGenerator { genericParameters: genericParameters, genericRequirements: genericRequirements ) + + case .composite: + throw JavaTranslationError.unhandledType(swiftType) } } @@ -691,7 +694,7 @@ extension FFMSwift2JavaGenerator { // TODO: Implement. throw JavaTranslationError.unhandledType(swiftType) - case .genericParameter, .optional, .function, .existential, .opaque: + case .genericParameter, .optional, .function, .existential, .opaque, .composite: throw JavaTranslationError.unhandledType(swiftType) } diff --git a/Sources/JExtractSwiftLib/ImportedDecls.swift b/Sources/JExtractSwiftLib/ImportedDecls.swift index 5655af00..7a071d9a 100644 --- a/Sources/JExtractSwiftLib/ImportedDecls.swift +++ b/Sources/JExtractSwiftLib/ImportedDecls.swift @@ -34,9 +34,13 @@ package class ImportedNominalType: ImportedDecl { package var methods: [ImportedFunc] = [] package var variables: [ImportedFunc] = [] package var cases: [ImportedEnumCase] = [] + var inheritedTypes: [SwiftType] - init(swiftNominal: SwiftNominalTypeDeclaration) { + init(swiftNominal: SwiftNominalTypeDeclaration, lookupContext: SwiftTypeLookupContext) throws { self.swiftNominal = swiftNominal + self.inheritedTypes = swiftNominal.inheritanceTypes?.compactMap { + try? SwiftType($0.type, lookupContext: lookupContext) + } ?? [] } var swiftType: SwiftType { diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift index 9351252e..258b537e 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift @@ -22,6 +22,7 @@ extension JNISwift2JavaGenerator { "org.swift.swiftkit.core.*", "org.swift.swiftkit.core.util.*", "java.util.*", + "java.util.concurrent.atomic.AtomicBoolean", // NonNull, Unsigned and friends "org.swift.swiftkit.core.annotations.*", @@ -101,6 +102,35 @@ extension JNISwift2JavaGenerator { printPackage(&printer) printImports(&printer) + switch decl.swiftNominal.kind { + case .actor, .class, .enum, .struct: + printConcreteType(&printer, decl) + case .protocol: + printProtocol(&printer, decl) + } + } + + private func printProtocol(_ printer: inout CodePrinter, _ decl: ImportedNominalType) { + let extends = ["JNISwiftInstance"] + printer.printBraceBlock("public interface \(decl.swiftNominal.name) extends \(extends.joined(separator: ", "))") { printer in + for initializer in decl.initializers { + printFunctionDowncallMethods(&printer, initializer, signaturesOnly: true) + printer.println() + } + + for method in decl.methods { + printFunctionDowncallMethods(&printer, method, signaturesOnly: true) + printer.println() + } + + for variable in decl.variables { + printFunctionDowncallMethods(&printer, variable, signaturesOnly: true) + printer.println() + } + } + } + + private func printConcreteType(_ printer: inout CodePrinter, _ decl: ImportedNominalType) { printNominal(&printer, decl) { printer in printer.print( """ @@ -117,8 +147,18 @@ extension JNISwift2JavaGenerator { printer.print( """ + /** + * The designated constructor of any imported Swift types. + * + * @param selfPointer a pointer to the memory containing the value + * @param swiftArena the arena this object belongs to. When the arena goes out of scope, this value is destroyed. + */ private \(decl.swiftNominal.name)(long selfPointer, SwiftArena swiftArena) { - super(selfPointer, swiftArena); + SwiftObjects.requireNonZero(selfPointer, "selfPointer"); + this.selfPointer = selfPointer; + + // Only register once we have fully initialized the object since this will need the object pointer. + swiftArena.register(this); } /** @@ -136,6 +176,25 @@ extension JNISwift2JavaGenerator { """ ) + printer.print( + """ + /** Pointer to the "self". */ + private final long selfPointer; + + /** Used to track additional state of the underlying object, e.g. if it was explicitly destroyed. */ + private final AtomicBoolean $state$destroyed = new AtomicBoolean(false); + + public long $memoryAddress() { + return this.selfPointer; + } + + @Override + public AtomicBoolean $statusDestroyedFlag() { + return $state$destroyed; + } + """ + ) + printer.println() if decl.swiftNominal.kind == .enum { @@ -158,6 +217,8 @@ extension JNISwift2JavaGenerator { printer.println() } + printTypeMetadataAddressFunction(&printer, decl) + printer.println() printDestroyFunction(&printer, decl) } } @@ -194,7 +255,13 @@ extension JNISwift2JavaGenerator { if decl.swiftNominal.isSendable { printer.print("@ThreadSafe // Sendable") } - printer.printBraceBlock("public final class \(decl.swiftNominal.name) extends JNISwiftInstance") { printer in + var implements = ["JNISwiftInstance"] + implements += decl.inheritedTypes + .compactMap(\.asNominalTypeDeclaration) + .filter { $0.kind == .protocol } + .map(\.name) + let implementsClause = implements.joined(separator: ", ") + printer.printBraceBlock("public final class \(decl.swiftNominal.name) implements \(implementsClause)") { printer in body(&printer) } } @@ -279,14 +346,15 @@ extension JNISwift2JavaGenerator { printer.print("record $NativeParameters(\(nativeParameters.joined(separator: ", "))) {}") } - self.printJavaBindingWrapperMethod(&printer, translatedCase.getAsCaseFunction) + self.printJavaBindingWrapperMethod(&printer, translatedCase.getAsCaseFunction, signaturesOnly: false) printer.println() } } private func printFunctionDowncallMethods( _ printer: inout CodePrinter, - _ decl: ImportedFunc + _ decl: ImportedFunc, + signaturesOnly: Bool = false ) { guard translatedDecl(for: decl) != nil else { // Failed to translate. Skip. @@ -297,7 +365,7 @@ extension JNISwift2JavaGenerator { printJavaBindingWrapperHelperClass(&printer, decl) - printJavaBindingWrapperMethod(&printer, decl) + printJavaBindingWrapperMethod(&printer, decl, signaturesOnly: signaturesOnly) } /// Print the helper type container for a user-facing Java API. @@ -340,17 +408,18 @@ extension JNISwift2JavaGenerator { ) } - private func printJavaBindingWrapperMethod(_ printer: inout CodePrinter, _ decl: ImportedFunc) { + private func printJavaBindingWrapperMethod(_ printer: inout CodePrinter, _ decl: ImportedFunc, signaturesOnly: Bool) { guard let translatedDecl = translatedDecl(for: decl) else { fatalError("Decl was not translated, \(decl)") } - printJavaBindingWrapperMethod(&printer, translatedDecl, importedFunc: decl) + printJavaBindingWrapperMethod(&printer, translatedDecl, importedFunc: decl, signaturesOnly: signaturesOnly) } private func printJavaBindingWrapperMethod( _ printer: inout CodePrinter, _ translatedDecl: TranslatedFunctionDecl, - importedFunc: ImportedFunc? = nil + importedFunc: ImportedFunc? = nil, + signaturesOnly: Bool ) { var modifiers = ["public"] if translatedDecl.isStatic { @@ -362,6 +431,19 @@ extension JNISwift2JavaGenerator { var parameters = translatedDecl.translatedFunctionSignature.parameters.map { $0.parameter.renderParameter() } let throwsClause = translatedDecl.isThrowing ? " throws Exception" : "" + let generics = translatedDecl.translatedFunctionSignature.parameters.reduce(into: [(String, [JavaType])]()) { generics, parameter in + guard case .generic(let name, let extends) = parameter.parameter.type else { + return + } + generics.append((name, extends)) + } + .map { "\($0) extends \($1.compactMap(\.className).joined(separator: " & "))" } + .joined(separator: ", ") + + if !generics.isEmpty { + modifiers.append("<" + generics + ">") + } + var annotationsStr = translatedSignature.annotations.map({ $0.render() }).joined(separator: "\n") if !annotationsStr.isEmpty { annotationsStr += "\n" } @@ -372,9 +454,7 @@ extension JNISwift2JavaGenerator { if let importedFunc { printDeclDocumentation(&printer, importedFunc) } - printer.printBraceBlock( - "\(annotationsStr)\(modifiers.joined(separator: " ")) \(resultType) \(translatedDecl.name)(\(parametersStr))\(throwsClause)" - ) { printer in + printer.printBraceBlock("\(annotationsStr)\(modifiers.joined(separator: " ")) \(resultType) \(translatedDecl.name)(\(parametersStr))\(throwsClause)") { printer in let globalArenaName = "SwiftMemoryManagement.GLOBAL_SWIFT_JAVA_ARENA" let arguments = translatedDecl.translatedFunctionSignature.parameters.map(\.parameter.name) + [globalArenaName] let call = "\(translatedDecl.name)(\(arguments.joined(separator: ", ")))" @@ -393,13 +473,17 @@ extension JNISwift2JavaGenerator { if let importedFunc { printDeclDocumentation(&printer, importedFunc) } - printer.printBraceBlock( - "\(annotationsStr)\(modifiers.joined(separator: " ")) \(resultType) \(translatedDecl.name)(\(parameters.joined(separator: ", ")))\(throwsClause)" - ) { printer in - printDowncall(&printer, translatedDecl) + let signature = "\(annotationsStr)\(modifiers.joined(separator: " ")) \(resultType) \(translatedDecl.name)(\(parameters.joined(separator: ", ")))\(throwsClause)" + if signaturesOnly { + printer.print("\(signature);") + } else { + printer.printBraceBlock(signature) { printer in + printDowncall(&printer, translatedDecl) + } + + printNativeFunction(&printer, translatedDecl) } - printNativeFunction(&printer, translatedDecl) } private func printNativeFunction(_ printer: inout CodePrinter, _ translatedDecl: TranslatedFunctionDecl) { @@ -470,13 +554,33 @@ extension JNISwift2JavaGenerator { ) } + private func printTypeMetadataAddressFunction(_ printer: inout CodePrinter, _ type: ImportedNominalType) { + printer.print("private static native long $typeMetadataAddressDowncall();") + + let funcName = "$typeMetadataAddress" + printer.print("@Override") + printer.printBraceBlock("public long $typeMetadataAddress()") { printer in + printer.print( + """ + long self$ = this.$memoryAddress(); + if (CallTraces.TRACE_DOWNCALLS) { + CallTraces.traceDowncall("\(type.swiftNominal.name).\(funcName)", + "this", this, + "self", self$); + } + return \(type.swiftNominal.name).$typeMetadataAddressDowncall(); + """ + ) + } + } + /// Prints the destroy function for a `JNISwiftInstance` private func printDestroyFunction(_ printer: inout CodePrinter, _ type: ImportedNominalType) { printer.print("private static native void $destroy(long selfPointer);") let funcName = "$createDestroyFunction" printer.print("@Override") - printer.printBraceBlock("protected Runnable \(funcName)()") { printer in + printer.printBraceBlock("public Runnable \(funcName)()") { printer in printer.print( """ long self$ = this.$memoryAddress(); diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift index 073883a2..a0178d3c 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift @@ -29,7 +29,8 @@ extension JNISwift2JavaGenerator { config: config, swiftModuleName: swiftModuleName, javaPackage: self.javaPackage, - javaClassLookupTable: self.javaClassLookupTable + javaClassLookupTable: self.javaClassLookupTable, + knownTypes: SwiftKnownTypes(symbolTable: lookupContext.symbolTable) ) translated = try translation.translate(decl) } catch { @@ -54,7 +55,8 @@ extension JNISwift2JavaGenerator { config: config, swiftModuleName: swiftModuleName, javaPackage: self.javaPackage, - javaClassLookupTable: self.javaClassLookupTable + javaClassLookupTable: self.javaClassLookupTable, + knownTypes: SwiftKnownTypes(symbolTable: lookupContext.symbolTable) ) translated = try translation.translate(enumCase: decl) } catch { @@ -71,12 +73,14 @@ extension JNISwift2JavaGenerator { let swiftModuleName: String let javaPackage: String let javaClassLookupTable: JavaClassLookupTable + var knownTypes: SwiftKnownTypes func translate(enumCase: ImportedEnumCase) throws -> TranslatedEnumCase { let nativeTranslation = NativeJavaTranslation( config: self.config, javaPackage: self.javaPackage, - javaClassLookupTable: self.javaClassLookupTable + javaClassLookupTable: self.javaClassLookupTable, + knownTypes: self.knownTypes ) let methodName = "" // TODO: Used for closures, replace with better name? @@ -85,7 +89,9 @@ extension JNISwift2JavaGenerator { let translatedValues = try self.translateParameters( enumCase.parameters.map { ($0.name, $0.type) }, methodName: methodName, - parentName: parentName + parentName: parentName, + genericParameters: [], + genericRequirements: [] ) let conversions = try enumCase.parameters.enumerated().map { idx, parameter in @@ -160,7 +166,8 @@ extension JNISwift2JavaGenerator { let nativeTranslation = NativeJavaTranslation( config: self.config, javaPackage: self.javaPackage, - javaClassLookupTable: self.javaClassLookupTable + javaClassLookupTable: self.javaClassLookupTable, + knownTypes: self.knownTypes ) // Types with no parent will be outputted inside a "module" class. @@ -228,7 +235,15 @@ extension JNISwift2JavaGenerator { for (i, param) in swiftType.parameters.enumerated() { let paramName = param.parameterName ?? "_\(i)" translatedParams.append( - try translateParameter(swiftType: param.type, parameterName: paramName, methodName: name, parentName: parentName) + try translateParameter( + swiftType: param.type, + parameterName: paramName, + methodName: name, + parentName: parentName, + genericParameters: [], + genericRequirements: [], + parameterPosition: nil + ) ) } @@ -250,11 +265,19 @@ extension JNISwift2JavaGenerator { let parameters = try translateParameters( functionSignature.parameters.map { ($0.parameterName, $0.type )}, methodName: methodName, - parentName: parentName + parentName: parentName, + genericParameters: functionSignature.genericParameters, + genericRequirements: functionSignature.genericRequirements ) // 'self' - let selfParameter = try self.translateSelfParameter(functionSignature.selfParameter, methodName: methodName, parentName: parentName) + let selfParameter = try self.translateSelfParameter( + functionSignature.selfParameter, + methodName: methodName, + parentName: parentName, + genericParameters: functionSignature.genericParameters, + genericRequirements: functionSignature.genericRequirements + ) let resultType = try translate(swiftResult: functionSignature.result) @@ -268,22 +291,43 @@ extension JNISwift2JavaGenerator { func translateParameters( _ parameters: [(name: String?, type: SwiftType)], methodName: String, - parentName: String + parentName: String, + genericParameters: [SwiftGenericParameterDeclaration], + genericRequirements: [SwiftGenericRequirement] ) throws -> [TranslatedParameter] { - try parameters.enumerated().map { idx, param in + try parameters.enumerated().map { + idx, + param in let parameterName = param.name ?? "arg\(idx)" - return try translateParameter(swiftType: param.type, parameterName: parameterName, methodName: methodName, parentName: parentName) + return try translateParameter( + swiftType: param.type, + parameterName: parameterName, + methodName: methodName, + parentName: parentName, + genericParameters: genericParameters, + genericRequirements: genericRequirements, + parameterPosition: idx + ) } } - func translateSelfParameter(_ selfParameter: SwiftSelfParameter?, methodName: String, parentName: String) throws -> TranslatedParameter? { + func translateSelfParameter( + _ selfParameter: SwiftSelfParameter?, + methodName: String, + parentName: String, + genericParameters: [SwiftGenericParameterDeclaration], + genericRequirements: [SwiftGenericRequirement] + ) throws -> TranslatedParameter? { // 'self' if case .instance(let swiftSelf) = selfParameter { return try self.translateParameter( swiftType: swiftSelf.type, parameterName: swiftSelf.parameterName ?? "self", methodName: methodName, - parentName: parentName + parentName: parentName, + genericParameters: genericParameters, + genericRequirements: genericRequirements, + parameterPosition: nil ) } else { return nil @@ -294,7 +338,10 @@ extension JNISwift2JavaGenerator { swiftType: SwiftType, parameterName: String, methodName: String, - parentName: String + parentName: String, + genericParameters: [SwiftGenericParameterDeclaration], + genericRequirements: [SwiftGenericRequirement], + parameterPosition: Int? ) throws -> TranslatedParameter { // If the result type should cause any annotations on the method, include them here. @@ -354,7 +401,7 @@ extension JNISwift2JavaGenerator { return TranslatedParameter( parameter: JavaParameter( name: parameterName, - type: .class(package: nil, name: nominalTypeName), + type: .concrete(.class(package: nil, name: nominalTypeName)), annotations: parameterAnnotations ), conversion: .valueMemoryAddress(.placeholder) @@ -382,7 +429,29 @@ extension JNISwift2JavaGenerator { parameterName: parameterName ) - case .metatype, .tuple, .existential, .opaque, .genericParameter: + case .opaque(let proto), .existential(let proto): + guard let parameterPosition else { + fatalError("Cannot extract opaque or existential type that is not a parameter: \(proto)") + } + + return try translateProtocolParameter( + protocolType: proto, + parameterName: parameterName, + javaGenericName: "$T\(parameterPosition)" + ) + + case .genericParameter(let generic): + if let concreteTy = swiftType.typeIn(genericParameters: genericParameters, genericRequirements: genericRequirements) { + return try translateProtocolParameter( + protocolType: concreteTy, + parameterName: parameterName, + javaGenericName: generic.name + ) + } + + throw JavaTranslationError.unsupportedSwiftType(swiftType) + + case .metatype, .tuple, .composite: throw JavaTranslationError.unsupportedSwiftType(swiftType) } } @@ -401,6 +470,50 @@ extension JNISwift2JavaGenerator { } } + func translateProtocolParameter( + protocolType: SwiftType, + parameterName: String, + javaGenericName: String + ) throws -> TranslatedParameter { + switch protocolType { + case .nominal: + return try translateProtocolParameter(protocolTypes: [protocolType], parameterName: parameterName, javaGenericName: javaGenericName) + + case .composite(let types): + return try translateProtocolParameter(protocolTypes: types, parameterName: parameterName, javaGenericName: javaGenericName) + + default: + throw JavaTranslationError.unsupportedSwiftType(protocolType) + } + } + + private func translateProtocolParameter( + protocolTypes: [SwiftType], + parameterName: String, + javaGenericName: String + ) throws -> TranslatedParameter { + let javaProtocolTypes = try protocolTypes.map { + switch $0 { + case .nominal(let nominalType): + let nominalTypeName = nominalType.nominalTypeDecl.name + return JavaType.class(package: nil, name: nominalTypeName) + + default: + throw JavaTranslationError.unsupportedSwiftType($0) + } + } + + // We assume this is a JExtract class. + return TranslatedParameter( + parameter: JavaParameter( + name: parameterName, + type: .generic(name: javaGenericName, extends: javaProtocolTypes), + annotations: [] + ), + conversion: .commaSeparated([.valueMemoryAddress(.placeholder), .typeMetadataAddress(.placeholder)]) + ) + } + func translateOptionalParameter( wrappedType swiftType: SwiftType, parameterName: String @@ -519,7 +632,7 @@ extension JNISwift2JavaGenerator { case .optional(let wrapped): return try translateOptionalResult(wrappedType: wrapped, resultName: resultName) - case .metatype, .tuple, .function, .existential, .opaque, .genericParameter: + case .metatype, .tuple, .function, .existential, .opaque, .genericParameter, .composite: throw JavaTranslationError.unsupportedSwiftType(swiftType) } } @@ -743,6 +856,9 @@ extension JNISwift2JavaGenerator { /// `value.$memoryAddress()` indirect case valueMemoryAddress(JavaNativeConversionStep) + /// `value.$typeMetadataAddress()` + indirect case typeMetadataAddress(JavaNativeConversionStep) + /// Call `new \(Type)(\(placeholder), swiftArena$)` indirect case constructSwiftValue(JavaNativeConversionStep, JavaType) @@ -816,6 +932,10 @@ extension JNISwift2JavaGenerator { case .valueMemoryAddress: return "\(placeholder).$memoryAddress()" + case .typeMetadataAddress(let inner): + let inner = inner.render(&printer, placeholder) + return "\(inner).$typeMetadataAddress()" + case .constructSwiftValue(let inner, let javaType): let inner = inner.render(&printer, placeholder) return "new \(javaType.className!)(\(inner), swiftArena$)" @@ -922,6 +1042,9 @@ extension JNISwift2JavaGenerator { case .valueMemoryAddress(let inner): return inner.requiresSwiftArena + case .typeMetadataAddress(let inner): + return inner.requiresSwiftArena + case .commaSeparated(let list): return list.contains(where: { $0.requiresSwiftArena }) diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift index 03273e68..bdbfe2f1 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift @@ -21,6 +21,7 @@ extension JNISwift2JavaGenerator { let config: Configuration let javaPackage: String let javaClassLookupTable: JavaClassLookupTable + var knownTypes: SwiftKnownTypes /// Translates a Swift function into the native JNI method signature. func translate( @@ -33,22 +34,26 @@ extension JNISwift2JavaGenerator { translatedParameter, swiftParameter in let parameterName = translatedParameter.parameter.name - return try translate( - swiftParameter: swiftParameter, + return try translateParameter( + type: swiftParameter.type, parameterName: parameterName, methodName: methodName, - parentName: parentName + parentName: parentName, + genericParameters: functionSignature.genericParameters, + genericRequirements: functionSignature.genericRequirements ) } // Lower the self parameter. let nativeSelf: NativeParameter? = switch functionSignature.selfParameter { case .instance(let selfParameter): - try translate( - swiftParameter: selfParameter, + try translateParameter( + type: selfParameter.type, parameterName: selfParameter.parameterName ?? "self", methodName: methodName, - parentName: parentName + parentName: parentName, + genericParameters: functionSignature.genericParameters, + genericRequirements: functionSignature.genericRequirements ) case nil, .initializer(_), .staticMethod(_): nil @@ -65,26 +70,32 @@ extension JNISwift2JavaGenerator { _ parameters: [SwiftParameter], translatedParameters: [TranslatedParameter], methodName: String, - parentName: String + parentName: String, + genericParameters: [SwiftGenericParameterDeclaration], + genericRequirements: [SwiftGenericRequirement] ) throws -> [NativeParameter] { try zip(translatedParameters, parameters).map { translatedParameter, swiftParameter in let parameterName = translatedParameter.parameter.name - return try translate( - swiftParameter: swiftParameter, + return try translateParameter( + type: swiftParameter.type, parameterName: parameterName, methodName: methodName, - parentName: parentName + parentName: parentName, + genericParameters: genericParameters, + genericRequirements: genericRequirements ) } } - func translate( - swiftParameter: SwiftParameter, + func translateParameter( + type: SwiftType, parameterName: String, methodName: String, - parentName: String + parentName: String, + genericParameters: [SwiftGenericParameterDeclaration], + genericRequirements: [SwiftGenericRequirement] ) throws -> NativeParameter { - switch swiftParameter.type { + switch type { case .nominal(let nominalType): let nominalTypeName = nominalType.nominalTypeDecl.name @@ -92,7 +103,7 @@ extension JNISwift2JavaGenerator { switch knownType { case .optional: guard let genericArgs = nominalType.genericArguments, genericArgs.count == 1 else { - throw JavaTranslationError.unsupportedSwiftType(swiftParameter.type) + throw JavaTranslationError.unsupportedSwiftType(type) } return try translateOptionalParameter( wrappedType: genericArgs[0], @@ -102,14 +113,14 @@ extension JNISwift2JavaGenerator { default: guard let javaType = JNIJavaTypeTranslator.translate(knownType: knownType, config: self.config), javaType.implementsJavaValue else { - throw JavaTranslationError.unsupportedSwiftType(swiftParameter.type) + throw JavaTranslationError.unsupportedSwiftType(type) } return NativeParameter( parameters: [ JavaParameter(name: parameterName, type: javaType) ], - conversion: .initFromJNI(.placeholder, swiftType: swiftParameter.type) + conversion: .initFromJNI(.placeholder, swiftType: type) ) } @@ -117,7 +128,7 @@ extension JNISwift2JavaGenerator { if nominalType.isJavaKitWrapper { guard let javaType = nominalTypeName.parseJavaClassFromJavaKitName(in: self.javaClassLookupTable) else { - throw JavaTranslationError.wrappedJavaClassTranslationNotProvided(swiftParameter.type) + throw JavaTranslationError.wrappedJavaClassTranslationNotProvided(type) } return NativeParameter( @@ -140,7 +151,7 @@ extension JNISwift2JavaGenerator { parameters: [ JavaParameter(name: parameterName, type: .long) ], - conversion: .pointee(.extractSwiftValue(.placeholder, swiftType: swiftParameter.type)) + conversion: .pointee(.extractSwiftValue(.placeholder, swiftType: type)) ) case .tuple([]): @@ -180,11 +191,68 @@ extension JNISwift2JavaGenerator { parameterName: parameterName ) - case .metatype, .tuple, .existential, .opaque, .genericParameter: - throw JavaTranslationError.unsupportedSwiftType(swiftParameter.type) + case .opaque(let proto), .existential(let proto): + return try translateProtocolParameter( + protocolType: proto, + parameterName: parameterName + ) + + case .genericParameter: + if let concreteTy = type.typeIn(genericParameters: genericParameters, genericRequirements: genericRequirements) { + return try translateProtocolParameter( + protocolType: concreteTy, + parameterName: parameterName + ) + } + + throw JavaTranslationError.unsupportedSwiftType(type) + + case .metatype, .tuple, .composite: + throw JavaTranslationError.unsupportedSwiftType(type) + } + } + + func translateProtocolParameter( + protocolType: SwiftType, + parameterName: String + ) throws -> NativeParameter { + switch protocolType { + case .nominal(let nominalType): + let protocolName = nominalType.nominalTypeDecl.qualifiedName + return try translateProtocolParameter(protocolNames: [protocolName], parameterName: parameterName) + + case .composite(let types): + let protocolNames = try types.map { + guard let nominalTypeName = $0.asNominalType?.nominalTypeDecl.qualifiedName else { + throw JavaTranslationError.unsupportedSwiftType($0) + } + return nominalTypeName + } + + return try translateProtocolParameter(protocolNames: protocolNames, parameterName: parameterName) + + default: + throw JavaTranslationError.unsupportedSwiftType(protocolType) } } + private func translateProtocolParameter( + protocolNames: [String], + parameterName: String + ) throws -> NativeParameter { + return NativeParameter( + parameters: [ + JavaParameter(name: parameterName, type: .long), + JavaParameter(name: "\(parameterName)_typeMetadataAddress", type: .long) + ], + conversion: .extractSwiftProtocolValue( + .placeholder, + typeMetadataVariableName: .combinedName(component: "typeMetadataAddress"), + protocolNames: protocolNames + ) + ) + } + func translateOptionalParameter( wrappedType swiftType: SwiftType, parameterName: String @@ -351,7 +419,7 @@ extension JNISwift2JavaGenerator { outParameters: [] ) - case .function, .metatype, .optional, .tuple, .existential, .opaque, .genericParameter: + case .function, .metatype, .optional, .tuple, .existential, .opaque, .genericParameter, .composite: throw JavaTranslationError.unsupportedSwiftType(type) } } @@ -380,7 +448,7 @@ extension JNISwift2JavaGenerator { // Custom types are not supported yet. throw JavaTranslationError.unsupportedSwiftType(type) - case .function, .metatype, .optional, .tuple, .existential, .opaque, .genericParameter: + case .function, .metatype, .optional, .tuple, .existential, .opaque, .genericParameter, .composite: throw JavaTranslationError.unsupportedSwiftType(type) } } @@ -432,7 +500,7 @@ extension JNISwift2JavaGenerator { case .optional(let wrapped): return try translateOptionalResult(wrappedType: wrapped, resultName: resultName) - case .metatype, .tuple, .function, .existential, .opaque, .genericParameter: + case .metatype, .tuple, .function, .existential, .opaque, .genericParameter, .composite: throw JavaTranslationError.unsupportedSwiftType(swiftResult.type) } } @@ -480,6 +548,12 @@ extension JNISwift2JavaGenerator { /// `SwiftType(from: value, in: environment!)` indirect case initFromJNI(NativeSwiftConversionStep, swiftType: SwiftType) + indirect case extractSwiftProtocolValue( + NativeSwiftConversionStep, + typeMetadataVariableName: NativeSwiftConversionStep, + protocolNames: [String] + ) + /// Extracts a swift type at a pointer given by a long. indirect case extractSwiftValue( NativeSwiftConversionStep, @@ -540,6 +614,35 @@ extension JNISwift2JavaGenerator { let inner = inner.render(&printer, placeholder) return "\(swiftType)(fromJNI: \(inner), in: environment!)" + case .extractSwiftProtocolValue(let inner, let typeMetadataVariableName, let protocolNames): + let inner = inner.render(&printer, placeholder) + let typeMetadataVariableName = typeMetadataVariableName.render(&printer, placeholder) + let existentialName = "\(inner)Existential$" + + let compositeProtocolName = "(\(protocolNames.joined(separator: " & ")))" + + // TODO: Remove the _openExistential when we decide to only support language mode v6+ + printer.print( + """ + guard let \(inner)TypeMetadataPointer$ = UnsafeRawPointer(bitPattern: Int(Int64(fromJNI: \(typeMetadataVariableName), in: environment!))) else { + fatalError("\(typeMetadataVariableName) memory address was null") + } + let \(inner)DynamicType$: Any.Type = unsafeBitCast(\(inner)TypeMetadataPointer$, to: Any.Type.self) + guard let \(inner)RawPointer$ = UnsafeMutableRawPointer(bitPattern: Int(Int64(fromJNI: \(inner), in: environment!))) else { + fatalError("\(inner) memory address was null") + } + #if hasFeature(ImplicitOpenExistentials) + let \(existentialName) = \(inner)RawPointer$.load(as: \(inner)DynamicType$) as! any \(compositeProtocolName) + #else + func \(inner)DoLoad(_ ty: Ty.Type) -> any \(compositeProtocolName) { + \(inner)RawPointer$.load(as: ty) as! any \(compositeProtocolName) + } + let \(existentialName) = _openExistential(\(inner)DynamicType$, do: \(inner)DoLoad) + #endif + """ + ) + return existentialName + case .extractSwiftValue(let inner, let swiftType, let allowNil): let inner = inner.render(&printer, placeholder) let pointerName = "\(inner)$" @@ -584,7 +687,14 @@ extension JNISwift2JavaGenerator { let methodSignature = MethodSignature( resultType: nativeResult.javaType, - parameterTypes: parameters.flatMap { $0.parameters.map(\.type) } + parameterTypes: parameters.flatMap { + $0.parameters.map { parameter in + guard case .concrete(let type) = parameter.type else { + fatalError("Closures do not support Java generics") + } + return type + } + } ) let names = parameters.flatMap { $0.parameters.map(\.name) } diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift index 329b7dfd..3848ceac 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift @@ -109,6 +109,15 @@ extension JNISwift2JavaGenerator { printJNICache(&printer, type) printer.println() + switch type.swiftNominal.kind { + case .actor, .class, .enum, .struct: + printConcreteTypeThunks(&printer, type) + case .protocol: + printProtocolThunks(&printer, type) + } + } + + private func printConcreteTypeThunks(_ printer: inout CodePrinter, _ type: ImportedNominalType) { for initializer in type.initializers { printSwiftFunctionThunk(&printer, initializer) printer.println() @@ -134,9 +143,16 @@ extension JNISwift2JavaGenerator { printer.println() } + printTypeMetadataAddressThunk(&printer, type) + printer.println() printDestroyFunctionThunk(&printer, type) } + private func printProtocolThunks(_ printer: inout CodePrinter, _ type: ImportedNominalType) { + let protocolName = type.swiftNominal.name + } + + private func printEnumDiscriminator(_ printer: inout CodePrinter, _ type: ImportedNominalType) { let selfPointerParam = JavaParameter(name: "selfPointer", type: .long) printCDecl( @@ -415,6 +431,23 @@ extension JNISwift2JavaGenerator { ) } + private func printTypeMetadataAddressThunk(_ printer: inout CodePrinter, _ type: ImportedNominalType) { + printCDecl( + &printer, + javaMethodName: "$typeMetadataAddressDowncall", + parentName: type.swiftNominal.name, + parameters: [], + resultType: .long + ) { printer in + printer.print( + """ + let metadataPointer = unsafeBitCast(\(type.swiftNominal.qualifiedName).self, to: UnsafeRawPointer.self) + return Int64(Int(bitPattern: metadataPointer)).getJNIValue(in: environment) + """ + ) + } + } + /// Prints the implementation of the destroy function. private func printDestroyFunctionThunk(_ printer: inout CodePrinter, _ type: ImportedNominalType) { let selfPointerParam = JavaParameter(name: "selfPointer", type: .long) diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator.swift index f9b99f6b..a677bcde 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator.swift @@ -28,6 +28,7 @@ package class JNISwift2JavaGenerator: Swift2JavaGenerator { let javaPackage: String let swiftOutputDirectory: String let javaOutputDirectory: String + let lookupContext: SwiftTypeLookupContext let javaClassLookupTable: JavaClassLookupTable @@ -61,6 +62,7 @@ package class JNISwift2JavaGenerator: Swift2JavaGenerator { self.swiftOutputDirectory = swiftOutputDirectory self.javaOutputDirectory = javaOutputDirectory self.javaClassLookupTable = javaClassLookupTable + self.lookupContext = translator.lookupContext // If we are forced to write empty files, construct the expected outputs if translator.config.writeEmptyFiles ?? false { diff --git a/Sources/JExtractSwiftLib/JavaParameter.swift b/Sources/JExtractSwiftLib/JavaParameter.swift index a12b13b2..43f5a2b4 100644 --- a/Sources/JExtractSwiftLib/JavaParameter.swift +++ b/Sources/JExtractSwiftLib/JavaParameter.swift @@ -16,17 +16,56 @@ import JavaTypes /// Represent a parameter in Java code. struct JavaParameter { - let name: String - let type: JavaType + enum ParameterType: CustomStringConvertible { + case concrete(JavaType) + case generic(name: String, extends: [JavaType]) + + var jniTypeSignature: String { + switch self { + case .concrete(let type): + return type.jniTypeSignature + case .generic(_, let extends): + guard !extends.isEmpty else { + return "Ljava/lang/Object;" + } + + // Generics only use the first type for JNI + return extends.first!.jniTypeSignature + } + } + + var jniTypeName: String { + switch self { + case .concrete(let type): type.jniTypeName + case .generic: "jobject?" + } + } + + var description: String { + switch self { + case .concrete(let type): type.description + case .generic(let name, _): name + } + } + } + var name: String + var type: ParameterType + /// Parameter annotations are used in parameter declarations like this: `@Annotation int example` let annotations: [JavaAnnotation] - init(name: String, type: JavaType, annotations: [JavaAnnotation] = []) { + init(name: String, type: ParameterType, annotations: [JavaAnnotation] = []) { self.name = name self.type = type self.annotations = annotations } + init(name: String, type: JavaType, annotations: [JavaAnnotation] = []) { + self.name = name + self.type = .concrete(type) + self.annotations = annotations + } + func renderParameter() -> String { if annotations.isEmpty { return "\(type) \(name)" diff --git a/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift b/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift index 02049ed4..ccbbd274 100644 --- a/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift +++ b/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift @@ -146,6 +146,8 @@ extension Swift2JavaTranslator { return check(ty) case .existential(let ty), .opaque(let ty): return check(ty) + case .composite(let types): + return types.contains(where: check) case .genericParameter: return false } @@ -200,7 +202,7 @@ extension Swift2JavaTranslator { _ nominalNode: some DeclGroupSyntax & NamedDeclSyntax & WithModifiersSyntax & WithAttributesSyntax, parent: ImportedNominalType? ) -> ImportedNominalType? { - if !nominalNode.shouldExtract(config: config, log: log) { + if !nominalNode.shouldExtract(config: config, log: log, in: parent) { return nil } @@ -225,7 +227,7 @@ extension Swift2JavaTranslator { guard swiftNominalDecl.moduleName == self.swiftModuleName else { return nil } - guard swiftNominalDecl.syntax!.shouldExtract(config: config, log: log) else { + guard swiftNominalDecl.syntax!.shouldExtract(config: config, log: log, in: nil) else { return nil } @@ -239,7 +241,7 @@ extension Swift2JavaTranslator { return alreadyImported } - let importedNominal = ImportedNominalType(swiftNominal: nominal) + let importedNominal = try? ImportedNominalType(swiftNominal: nominal, lookupContext: lookupContext) importedTypes[fullName] = importedNominal return importedNominal diff --git a/Sources/JExtractSwiftLib/Swift2JavaVisitor.swift b/Sources/JExtractSwiftLib/Swift2JavaVisitor.swift index 9b183cb6..13185a5c 100644 --- a/Sources/JExtractSwiftLib/Swift2JavaVisitor.swift +++ b/Sources/JExtractSwiftLib/Swift2JavaVisitor.swift @@ -105,7 +105,7 @@ final class Swift2JavaVisitor { } func visit(functionDecl node: FunctionDeclSyntax, in typeContext: ImportedNominalType?) { - guard node.shouldExtract(config: config, log: log) else { + guard node.shouldExtract(config: config, log: log, in: typeContext) else { return } @@ -183,7 +183,7 @@ final class Swift2JavaVisitor { } func visit(variableDecl node: VariableDeclSyntax, in typeContext: ImportedNominalType?) { - guard node.shouldExtract(config: config, log: log) else { + guard node.shouldExtract(config: config, log: log, in: typeContext) else { return } @@ -237,7 +237,7 @@ final class Swift2JavaVisitor { self.log.info("Initializer must be within a current type; \(node)") return } - guard node.shouldExtract(config: config, log: log) else { + guard node.shouldExtract(config: config, log: log, in: typeContext) else { return } @@ -293,10 +293,10 @@ final class Swift2JavaVisitor { } extension DeclSyntaxProtocol where Self: WithModifiersSyntax & WithAttributesSyntax { - func shouldExtract(config: Configuration, log: Logger) -> Bool { + func shouldExtract(config: Configuration, log: Logger, in parent: ImportedNominalType?) -> Bool { let meetsRequiredAccessLevel: Bool = switch config.effectiveMinimumInputAccessLevelMode { - case .public: self.isPublic + case .public: self.isPublic(in: parent?.swiftNominal.syntax) case .package: self.isAtLeastPackage case .internal: self.isAtLeastInternal } diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftNominalTypeDeclaration.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftNominalTypeDeclaration.swift index 335979a4..763a5da2 100644 --- a/Sources/JExtractSwiftLib/SwiftTypes/SwiftNominalTypeDeclaration.swift +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftNominalTypeDeclaration.swift @@ -93,6 +93,10 @@ package class SwiftNominalTypeDeclaration: SwiftTypeDeclaration { return firstInheritanceType.type }() + var inheritanceTypes: InheritedTypeListSyntax? { + self.syntax?.inheritanceClause?.inheritedTypes + } + /// Returns true if this type conforms to `Sendable` and therefore is "threadsafe". lazy var isSendable: Bool = { // Check if Sendable is in the inheritance list diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftType+RepresentativeConcreteeType.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftType+GenericTypes.swift similarity index 72% rename from Sources/JExtractSwiftLib/SwiftTypes/SwiftType+RepresentativeConcreteeType.swift rename to Sources/JExtractSwiftLib/SwiftTypes/SwiftType+GenericTypes.swift index ce668485..1a658513 100644 --- a/Sources/JExtractSwiftLib/SwiftTypes/SwiftType+RepresentativeConcreteeType.swift +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftType+GenericTypes.swift @@ -27,6 +27,38 @@ extension SwiftType { genericRequirements: genericRequirements ) } + + /// Returns the protocol type if this is a generic parameter in the list + func typeIn( + genericParameters: [SwiftGenericParameterDeclaration], + genericRequirements: [SwiftGenericRequirement] + ) -> SwiftType? { + switch self { + case .genericParameter(let genericParam): + if genericParameters.contains(genericParam) { + let types: [SwiftType] = genericRequirements.compactMap { + guard case .inherits(let left, let right) = $0, left == self else { + return nil + } + return right + } + + if types.isEmpty { + // TODO: Any?? + return nil + } else if types.count == 1 { + return types.first! + } else { + return .composite(types) + } + } + + return nil + + default: + return nil + } + } } private func representativeConcreteType( diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftType.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftType.swift index 58bb65c3..81afe637 100644 --- a/Sources/JExtractSwiftLib/SwiftTypes/SwiftType.swift +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftType.swift @@ -37,6 +37,9 @@ enum SwiftType: Equatable { /// `some ` indirect case opaque(SwiftType) + /// `type1` & `type2` + indirect case composite([SwiftType]) + static var void: Self { return .tuple([]) } @@ -45,7 +48,7 @@ enum SwiftType: Equatable { switch self { case .nominal(let nominal): nominal case .tuple(let elements): elements.count == 1 ? elements[0].asNominalType : nil - case .genericParameter, .function, .metatype, .optional, .existential, .opaque: nil + case .genericParameter, .function, .metatype, .optional, .existential, .opaque, .composite: nil } } @@ -88,7 +91,7 @@ enum SwiftType: Equatable { return nominal.nominalTypeDecl.isReferenceType case .metatype, .function: return true - case .genericParameter, .optional, .tuple, .existential, .opaque: + case .genericParameter, .optional, .tuple, .existential, .opaque, .composite: return false } } @@ -123,7 +126,7 @@ extension SwiftType: CustomStringConvertible { /// requires parentheses. private var postfixRequiresParentheses: Bool { switch self { - case .function, .existential, .opaque: true + case .function, .existential, .opaque, .composite: true case .genericParameter, .metatype, .nominal, .optional, .tuple: false } } @@ -147,6 +150,8 @@ extension SwiftType: CustomStringConvertible { return "any \(constraintType)" case .opaque(let constraintType): return "some \(constraintType)" + case .composite(let types): + return types.map(\.description).joined(separator: " & ") } } } @@ -208,7 +213,7 @@ extension SwiftNominalType { extension SwiftType { init(_ type: TypeSyntax, lookupContext: SwiftTypeLookupContext) throws { switch type.as(TypeSyntaxEnum.self) { - case .arrayType, .classRestrictionType, .compositionType, + case .arrayType, .classRestrictionType, .dictionaryType, .missingType, .namedOpaqueReturnType, .packElementType, .packExpansionType, .suppressedType: throw TypeTranslationError.unimplementedType(type) @@ -311,6 +316,13 @@ extension SwiftType { } else { self = .opaque(try SwiftType(someOrAntType.constraint, lookupContext: lookupContext)) } + + case .compositionType(let compositeType): + let types = try compositeType.elements.map { + try SwiftType($0.type, lookupContext: lookupContext) + } + + self = .composite(types) } } diff --git a/Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md b/Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md index 8d193149..5884270a 100644 --- a/Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md +++ b/Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md @@ -60,10 +60,17 @@ SwiftJava's `swift-java jextract` tool automates generating Java bindings from S | Async functions `func async` and properties: `var { get async {} }` | ❌ | ❌ | | Arrays: `[UInt8]`, `[T]` | ❌ | ❌ | | Dictionaries: `[String: Int]`, `[K:V]` | ❌ | ❌ | -| Generic functions | ❌ | ❌ | -| `Foundation.Data`, `any Foundation.DataProtocol` | ✅ | ❌ | +| Generic parameters in functions: `func f(x: T)` | ❌ | ✅ | +| Generic return values in functions: `func f() -> T` | ❌ | ❌ | | Tuples: `(Int, String)`, `(A, B, C)` | ❌ | ❌ | -| Protocols: `protocol`, existential parameters `any Collection` | ❌ | ❌ | +| Protocols: `protocol` | ❌ | ✅ | +| Protocols: `protocol` with associated types | ❌ | ❌ | +| Existential parameters `f(x: any SomeProtocol) ` | ❌ | ✅ | +| Existential parameters `f(x: any (A & B)) ` | ❌ | ✅ | +| Existential return types `f() -> any Collection ` | ❌ | ❌ | +| Foundation Data and DataProtocol: `f(x: any DataProtocol) -> Data` | ✅ | ❌ | +| Opaque parameters: `func take(worker: some Builder) -> some Builder` | ❌ | ✅ | +| Opaque return types: `func get() -> some Builder` | ❌ | ❌ | | Optional parameters: `func f(i: Int?, class: MyClass?)` | ✅ | ✅ | | Optional return types: `func f() -> Int?`, `func g() -> MyClass?` | ❌ | ✅ | | Primitive types: `Bool`, `Int`, `Int8`, `Int16`, `Int32`, `Int64`, `Float`, `Double` | ✅ | ✅ | @@ -90,7 +97,6 @@ SwiftJava's `swift-java jextract` tool automates generating Java bindings from S | Result builders | ❌ | ❌ | | Automatic Reference Counting of class types / lifetime safety | ✅ | ✅ | | Value semantic types (e.g. struct copying) | ❌ | ❌ | -| Opaque types: `func get() -> some Builder`, func take(worker: some Worker) | ❌ | ❌ | | Swift concurrency: `func async`, `actor`, `distribued actor` | ❌ | ❌ | | | | | | | | | @@ -266,5 +272,47 @@ try (var arena = SwiftArena.ofConfined()) { } ``` +### Protocols +> Note: Protocols are currently only supported in JNI mode. +> +> With the exception of `any DataProtocol` which is handled as `Foundation.Data` in the FFM mode. +Swift `protocol` types are imported as Java `interface`s. For now, we require that all +concrete types of an interface wrap a Swift instance. In the future, we will add support +for providing Java-based implementations of interfaces, that you can pass to Java functions. + +Consider the following Swift protocol: +```swift +protocol Named { + var name: String { get } + + func describe() -> String +} +``` +will be exported as +```java +interface Named extends JNISwiftInstance { + public String getName(); + + public String describe(); +} +``` + +#### Parameters +Any opaque, existential or generic parameters are imported as Java generics. +This means that the following function: +```swift +func f(x: S, y: any C, z: some D) +``` +will be exported as +```java + void f(S x, T1 y, T2 z) +``` +On the Java side, only SwiftInstance implementing types may be passed; +so this isn't a way for compatibility with just any arbitrary Java interfaces, +but specifically, for allowing passing concrete binding types generated by jextract from Swift types +which conform a to a given Swift protocol. + +#### Returning protocol types +Protocols are not yet supported as return types. diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/JNISwiftInstance.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/JNISwiftInstance.java index 95f1e5a0..4e3b8378 100644 --- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/JNISwiftInstance.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/JNISwiftInstance.java @@ -14,32 +14,7 @@ package org.swift.swiftkit.core; -import java.util.Objects; -import java.util.concurrent.atomic.AtomicBoolean; - -public abstract class JNISwiftInstance extends SwiftInstance { - // Pointer to the "self". - protected final long selfPointer; - - /** - * The designated constructor of any imported Swift types. - * - * @param selfPointer a pointer to the memory containing the value - * @param arena the arena this object belongs to. When the arena goes out of scope, this value is destroyed. - */ - protected JNISwiftInstance(long selfPointer, SwiftArena arena) { - SwiftObjects.requireNonZero(selfPointer, "selfPointer"); - this.selfPointer = selfPointer; - - // Only register once we have fully initialized the object since this will need the object pointer. - arena.register(this); - } - - @Override - public long $memoryAddress() { - return this.selfPointer; - } - +public interface JNISwiftInstance extends SwiftInstance { /** * Creates a function that will be called when the value should be destroyed. * This will be code-generated to call a native method to do deinitialization and deallocation. @@ -52,10 +27,12 @@ protected JNISwiftInstance(long selfPointer, SwiftArena arena) { * * @return a function that is called when the value should be destroyed. */ - protected abstract Runnable $createDestroyFunction(); + Runnable $createDestroyFunction(); + + long $typeMetadataAddress(); @Override - public SwiftInstanceCleanup $createCleanup() { + default SwiftInstanceCleanup $createCleanup() { var statusDestroyedFlag = $statusDestroyedFlag(); Runnable markAsDestroyed = () -> statusDestroyedFlag.set(true); diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftInstance.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftInstance.java index 44955cc6..3ab07ffb 100644 --- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftInstance.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftInstance.java @@ -16,12 +16,7 @@ import java.util.concurrent.atomic.AtomicBoolean; -public abstract class SwiftInstance { - - // TODO: make this a flagset integer and/or use a field updater - /** Used to track additional state of the underlying object, e.g. if it was explicitly destroyed. */ - private final AtomicBoolean $state$destroyed = new AtomicBoolean(false); - +public interface SwiftInstance { /** * Pointer to the {@code self} of the underlying Swift object or value. * @@ -29,14 +24,14 @@ public abstract class SwiftInstance { * is kept alive using some means (e.g. a class remains retained), as * this function does not ensure safety of the address in any way. */ - public abstract long $memoryAddress(); + long $memoryAddress(); /** * Called when the arena has decided the value should be destroyed. *

* Warning: The cleanup action must not capture {@code this}. */ - public abstract SwiftInstanceCleanup $createCleanup(); + SwiftInstanceCleanup $createCleanup(); /** * Exposes a boolean value which can be used to indicate if the object was destroyed. @@ -45,10 +40,7 @@ public abstract class SwiftInstance { * form a strong reference to the {@code SwiftInstance} which could prevent the cleanup from running, * if using an GC managed instance (e.g. using an {@code AutoSwiftMemorySession}. */ - public final AtomicBoolean $statusDestroyedFlag() { - return this.$state$destroyed; - } - + AtomicBoolean $statusDestroyedFlag(); /** * Ensures that this instance has not been destroyed. *

@@ -56,8 +48,8 @@ public abstract class SwiftInstance { * to be thrown. This check should be performed before accessing {@code $memorySegment} to prevent * use-after-free errors. */ - protected final void $ensureAlive() { - if (this.$state$destroyed.get()) { + default void $ensureAlive() { + if (this.$statusDestroyedFlag().get()) { throw new IllegalStateException("Attempted to call method on already destroyed instance of " + getClass().getSimpleName() + "!"); } } diff --git a/SwiftKitCore/src/test/java/org/swift/swiftkit/AutoArenaTest.java b/SwiftKitCore/src/test/java/org/swift/swiftkit/AutoArenaTest.java index b414962f..12093421 100644 --- a/SwiftKitCore/src/test/java/org/swift/swiftkit/AutoArenaTest.java +++ b/SwiftKitCore/src/test/java/org/swift/swiftkit/AutoArenaTest.java @@ -18,6 +18,8 @@ import org.swift.swiftkit.core.JNISwiftInstance; import org.swift.swiftkit.core.SwiftArena; +import java.util.concurrent.atomic.AtomicBoolean; + public class AutoArenaTest { @Test @@ -45,13 +47,30 @@ public void cleaner_releases_native_resource() { } } - private static class FakeSwiftInstance extends JNISwiftInstance { + private static class FakeSwiftInstance implements JNISwiftInstance { + AtomicBoolean $state$destroyed = new AtomicBoolean(false); + public FakeSwiftInstance(SwiftArena arena) { - super(1, arena); + arena.register(this); } - protected Runnable $createDestroyFunction() { + public Runnable $createDestroyFunction() { return () -> {}; } + + @Override + public long $typeMetadataAddress() { + return 0; + } + + @Override + public long $memoryAddress() { + return 0; + } + + @Override + public AtomicBoolean $statusDestroyedFlag() { + return $state$destroyed; + } } } diff --git a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMSwiftInstance.java b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMSwiftInstance.java index 1236bad2..70324c94 100644 --- a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMSwiftInstance.java +++ b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMSwiftInstance.java @@ -18,10 +18,15 @@ import org.swift.swiftkit.core.SwiftInstanceCleanup; import java.lang.foreign.MemorySegment; +import java.util.concurrent.atomic.AtomicBoolean; -public abstract class FFMSwiftInstance extends SwiftInstance { +public abstract class FFMSwiftInstance implements SwiftInstance { private final MemorySegment memorySegment; + // TODO: make this a flagset integer and/or use a field updater + /** Used to track additional state of the underlying object, e.g. if it was explicitly destroyed. */ + private final AtomicBoolean $state$destroyed = new AtomicBoolean(false); + /** * The designated constructor of any imported Swift types. * @@ -52,6 +57,16 @@ protected FFMSwiftInstance(MemorySegment segment, AllocatingSwiftArena arena) { */ public abstract SwiftAnyType $swiftType(); + /** + * Exposes a boolean value which can be used to indicate if the object was destroyed. + *

+ * This is exposing the object, rather than performing the action because we don't want to accidentally + * form a strong reference to the {@code SwiftInstance} which could prevent the cleanup from running, + * if using an GC managed instance (e.g. using an {@code AutoSwiftMemorySession}. + */ + public final AtomicBoolean $statusDestroyedFlag() { + return this.$state$destroyed; + } @Override public SwiftInstanceCleanup $createCleanup() { @@ -65,7 +80,6 @@ protected FFMSwiftInstance(MemorySegment segment, AllocatingSwiftArena arena) { ); } - /** * Returns `true` if this swift instance is a reference type, i.e. a `class` or (`distributed`) `actor`. * diff --git a/SwiftKitFFM/src/test/java/org/swift/swiftkit/ffm/AutoArenaTest.java b/SwiftKitFFM/src/test/java/org/swift/swiftkit/ffm/AutoArenaTest.java index b95f6c45..18c0a5af 100644 --- a/SwiftKitFFM/src/test/java/org/swift/swiftkit/ffm/AutoArenaTest.java +++ b/SwiftKitFFM/src/test/java/org/swift/swiftkit/ffm/AutoArenaTest.java @@ -18,6 +18,7 @@ import java.lang.foreign.GroupLayout; import java.lang.foreign.MemorySegment; +import java.util.concurrent.atomic.AtomicBoolean; public class AutoArenaTest { diff --git a/Tests/JExtractSwiftTests/JNI/JNIClassTests.swift b/Tests/JExtractSwiftTests/JNI/JNIClassTests.swift index 30bb7433..a7527aa8 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIClassTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIClassTests.swift @@ -55,9 +55,12 @@ struct JNIClassTests { import org.swift.swiftkit.core.*; import org.swift.swiftkit.core.util.*; + import java.util.*; + import java.util.concurrent.atomic.AtomicBoolean; + import org.swift.swiftkit.core.annotations.*; """, """ - public final class MyClass extends JNISwiftInstance { + public final class MyClass implements JNISwiftInstance { static final String LIB_NAME = "SwiftModule"; @SuppressWarnings("unused") @@ -68,9 +71,21 @@ struct JNIClassTests { } """, """ - private MyClass(long selfPointer, SwiftArena swiftArena) { - super(selfPointer, swiftArena); - } + private final long selfPointer; + """, + """ + public long $memoryAddress() { + return this.selfPointer; + } + """, + """ + private MyClass(long selfPointer, SwiftArena swiftArena) { + SwiftObjects.requireNonZero(selfPointer, "selfPointer"); + this.selfPointer = selfPointer; + + // Only register once we have fully initialized the object since this will need the object pointer. + swiftArena.register(this); + } """, """ public static MyClass wrapMemoryAddressUnsafe(long selfPointer, SwiftArena swiftArena) { @@ -92,7 +107,7 @@ struct JNIClassTests { expectedChunks: [ """ @Override - protected Runnable $createDestroyFunction() { + public Runnable $createDestroyFunction() { long self$ = this.$memoryAddress(); if (CallTraces.TRACE_DOWNCALLS) { CallTraces.traceDowncall("MyClass.$createDestroyFunction", diff --git a/Tests/JExtractSwiftTests/JNI/JNIEnumTests.swift b/Tests/JExtractSwiftTests/JNI/JNIEnumTests.swift index 47765043..c6aaf923 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIEnumTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIEnumTests.swift @@ -39,9 +39,12 @@ struct JNIEnumTests { import org.swift.swiftkit.core.*; import org.swift.swiftkit.core.util.*; + import java.util.*; + import java.util.concurrent.atomic.AtomicBoolean; + import org.swift.swiftkit.core.annotations.*; """, """ - public final class MyEnum extends JNISwiftInstance { + public final class MyEnum implements JNISwiftInstance { static final String LIB_NAME = "SwiftModule"; @SuppressWarnings("unused") @@ -53,7 +56,19 @@ struct JNIEnumTests { """, """ private MyEnum(long selfPointer, SwiftArena swiftArena) { - super(selfPointer, swiftArena); + SwiftObjects.requireNonZero(selfPointer, "selfPointer"); + this.selfPointer = selfPointer; + + // Only register once we have fully initialized the object since this will need the object pointer. + swiftArena.register(this); + } + """, + """ + private final long selfPointer; + """, + """ + public long $memoryAddress() { + return this.selfPointer; } """, """ @@ -66,7 +81,7 @@ struct JNIEnumTests { """, """ @Override - protected Runnable $createDestroyFunction() { + public Runnable $createDestroyFunction() { long self$ = this.$memoryAddress(); if (CallTraces.TRACE_DOWNCALLS) { CallTraces.traceDowncall("MyEnum.$createDestroyFunction", diff --git a/Tests/JExtractSwiftTests/JNI/JNIModuleTests.swift b/Tests/JExtractSwiftTests/JNI/JNIModuleTests.swift index ad55f491..27b0cdea 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIModuleTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIModuleTests.swift @@ -46,6 +46,7 @@ struct JNIModuleTests { import org.swift.swiftkit.core.*; import org.swift.swiftkit.core.util.*; import java.util.*; + import java.util.concurrent.atomic.AtomicBoolean; import org.swift.swiftkit.core.annotations.*; public final class SwiftModule { diff --git a/Tests/JExtractSwiftTests/JNI/JNIOptionalTests.swift b/Tests/JExtractSwiftTests/JNI/JNIOptionalTests.swift index 548a2eac..be2e0f6a 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIOptionalTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIOptionalTests.swift @@ -127,12 +127,12 @@ struct JNIOptionalTests { result$ = innerResult$.getJNIValue(in: environment!) var flag$ = Int8(1) environment.interface.SetByteArrayRegion(environment, result_discriminator$, 0, 1, &flag$) - } // render(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+NativeTranslation.swift:649 + } else { result$ = String.jniPlaceholderValue var flag$ = Int8(0) environment.interface.SetByteArrayRegion(environment, result_discriminator$, 0, 1, &flag$) - } // render(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+NativeTranslation.swift:659 + } return result$ } """ @@ -190,12 +190,12 @@ struct JNIOptionalTests { result$ = _resultBits$.getJNIValue(in: environment!) var flag$ = Int8(1) environment.interface.SetByteArrayRegion(environment, result_discriminator$, 0, 1, &flag$) - } // render(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+NativeTranslation.swift:649 + } else { result$ = 0 var flag$ = Int8(0) environment.interface.SetByteArrayRegion(environment, result_discriminator$, 0, 1, &flag$) - } // render(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+NativeTranslation.swift:659 + } return result$ } """ @@ -243,7 +243,7 @@ struct JNIOptionalTests { func Java_com_example_swift_SwiftModule__00024optionalJavaKitClass__Ljava_lang_Long_2(environment: UnsafeMutablePointer!, thisClass: jclass, arg: jobject?) { SwiftModule.optionalJavaKitClass(arg.map { return JavaLong(javaThis: $0, environment: environment!) - } // render(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+NativeTranslation.swift:691 + } ) } """ diff --git a/Tests/JExtractSwiftTests/JNI/JNIProtocolTests.swift b/Tests/JExtractSwiftTests/JNI/JNIProtocolTests.swift new file mode 100644 index 00000000..b5a0fcdb --- /dev/null +++ b/Tests/JExtractSwiftTests/JNI/JNIProtocolTests.swift @@ -0,0 +1,246 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import JExtractSwiftLib +import Testing + +@Suite +struct JNIProtocolTests { + let source = """ + public protocol SomeProtocol { + var x: Int64 { get set } + + public func method() {} + } + + public protocol B {} + + public class SomeClass: SomeProtocol {} + + public func takeProtocol(x: some SomeProtocol, y: any SomeProtocol) + public func takeGeneric(s: S) + public func takeComposite(x: any SomeProtocol & B) + """ + + @Test + func generatesJavaInterface() throws { + try assertOutput( + input: source, + .jni, .java, + detectChunkByInitialLines: 1, + expectedChunks: [ + """ + // Generated by jextract-swift + // Swift module: SwiftModule + + package com.example.swift; + + import org.swift.swiftkit.core.*; + import org.swift.swiftkit.core.util.*; + """, + """ + public interface SomeProtocol extends JNISwiftInstance { + ... + } + """, + """ + public long getX(); + """, + """ + public void setX(long newValue); + """, + """ + public void method(); + """ + ]) + } + + @Test + func generatesJavaClassWithExtends() throws { + try assertOutput( + input: source, + .jni, .java, + detectChunkByInitialLines: 1, + expectedChunks: [ + """ + public final class SomeClass implements JNISwiftInstance, SomeProtocol { + """ + ]) + } + + @Test + func takeProtocol_java() throws { + try assertOutput( + input: source, + .jni, .java, + detectChunkByInitialLines: 1, + expectedChunks: [ + """ + public static <$T0 extends SomeProtocol, $T1 extends SomeProtocol> void takeProtocol($T0 x, $T1 y) { + SwiftModule.$takeProtocol(x.$memoryAddress(), x.$typeMetadataAddress(), y.$memoryAddress(), y.$typeMetadataAddress()); + } + """, + """ + private static native void $takeProtocol(long x, long x_typeMetadataAddress, long y, long y_typeMetadataAddress); + """ + ]) + } + + @Test + func takeProtocol_swift() throws { + try assertOutput( + input: source, + .jni, .swift, + detectChunkByInitialLines: 1, + expectedChunks: [ + """ + @_cdecl("Java_com_example_swift_SwiftModule__00024takeProtocol__JJJJ") + func Java_com_example_swift_SwiftModule__00024takeProtocol__JJJJ(environment: UnsafeMutablePointer!, thisClass: jclass, x: jlong, x_typeMetadataAddress: jlong, y: jlong, y_typeMetadataAddress: jlong) { + guard let xTypeMetadataPointer$ = UnsafeRawPointer(bitPattern: Int(Int64(fromJNI: x_typeMetadataAddress, in: environment!))) else { + fatalError("x_typeMetadataAddress memory address was null") + } + let xDynamicType$: Any.Type = unsafeBitCast(xTypeMetadataPointer$, to: Any.Type.self) + guard let xRawPointer$ = UnsafeMutableRawPointer(bitPattern: Int(Int64(fromJNI: x, in: environment!))) else { + fatalError("x memory address was null") + } + #if hasFeature(ImplicitOpenExistentials) + let xExistential$ = xRawPointer$.load(as: xDynamicType$) as! any (SomeProtocol) + #else + func xDoLoad(_ ty: Ty.Type) -> any (SomeProtocol) { + xRawPointer$.load(as: ty) as! any (SomeProtocol) + } + let xExistential$ = _openExistential(xDynamicType$, do: xDoLoad) + #endif + guard let yTypeMetadataPointer$ = UnsafeRawPointer(bitPattern: Int(Int64(fromJNI: y_typeMetadataAddress, in: environment!))) else { + fatalError("y_typeMetadataAddress memory address was null") + } + let yDynamicType$: Any.Type = unsafeBitCast(yTypeMetadataPointer$, to: Any.Type.self) + guard let yRawPointer$ = UnsafeMutableRawPointer(bitPattern: Int(Int64(fromJNI: y, in: environment!))) else { + fatalError("y memory address was null") + } + #if hasFeature(ImplicitOpenExistentials) + let yExistential$ = yRawPointer$.load(as: yDynamicType$) as! any (SomeProtocol) + #else + func yDoLoad(_ ty: Ty.Type) -> any (SomeProtocol) { + yRawPointer$.load(as: ty) as! any (SomeProtocol) + } + let yExistential$ = _openExistential(yDynamicType$, do: yDoLoad) + #endif + SwiftModule.takeProtocol(x: xExistential$, y: yExistential$) + } + """ + ] + ) + } + + @Test + func takeGeneric_java() throws { + try assertOutput( + input: source, + .jni, .java, + detectChunkByInitialLines: 1, + expectedChunks: [ + """ + public static void takeGeneric(S s) { + SwiftModule.$takeGeneric(s.$memoryAddress(), s.$typeMetadataAddress()); + } + """, + """ + private static native void $takeGeneric(long s, long s_typeMetadataAddress); + """ + ]) + } + + @Test + func takeGeneric_swift() throws { + try assertOutput( + input: source, + .jni, .swift, + detectChunkByInitialLines: 1, + expectedChunks: [ + """ + @_cdecl("Java_com_example_swift_SwiftModule__00024takeGeneric__JJ") + func Java_com_example_swift_SwiftModule__00024takeGeneric__JJ(environment: UnsafeMutablePointer!, thisClass: jclass, s: jlong, s_typeMetadataAddress: jlong) { + guard let sTypeMetadataPointer$ = UnsafeRawPointer(bitPattern: Int(Int64(fromJNI: s_typeMetadataAddress, in: environment!))) else { + fatalError("s_typeMetadataAddress memory address was null") + } + let sDynamicType$: Any.Type = unsafeBitCast(sTypeMetadataPointer$, to: Any.Type.self) + guard let sRawPointer$ = UnsafeMutableRawPointer(bitPattern: Int(Int64(fromJNI: s, in: environment!))) else { + fatalError("s memory address was null") + } + #if hasFeature(ImplicitOpenExistentials) + let sExistential$ = sRawPointer$.load(as: sDynamicType$) as! any (SomeProtocol) + #else + func sDoLoad(_ ty: Ty.Type) -> any (SomeProtocol) { + sRawPointer$.load(as: ty) as! any (SomeProtocol) + } + let sExistential$ = _openExistential(sDynamicType$, do: sDoLoad) + #endif + SwiftModule.takeGeneric(s: sExistential$) + } + """ + ] + ) + } + + @Test + func takeComposite_java() throws { + try assertOutput( + input: source, + .jni, .java, + detectChunkByInitialLines: 1, + expectedChunks: [ + """ + public static <$T0 extends SomeProtocol & B> void takeComposite($T0 x) { + SwiftModule.$takeComposite(x.$memoryAddress(), x.$typeMetadataAddress()); + } + """, + """ + private static native void $takeComposite(long x, long x_typeMetadataAddress); + """ + ]) + } + + @Test + func takeComposite_swift() throws { + try assertOutput( + input: source, + .jni, .swift, + detectChunkByInitialLines: 1, + expectedChunks: [ + """ + @_cdecl("Java_com_example_swift_SwiftModule__00024takeComposite__JJ") + func Java_com_example_swift_SwiftModule__00024takeComposite__JJ(environment: UnsafeMutablePointer!, thisClass: jclass, x: jlong, x_typeMetadataAddress: jlong) { + guard let xTypeMetadataPointer$ = UnsafeRawPointer(bitPattern: Int(Int64(fromJNI: x_typeMetadataAddress, in: environment!))) else { + fatalError("x_typeMetadataAddress memory address was null") + } + let xDynamicType$: Any.Type = unsafeBitCast(xTypeMetadataPointer$, to: Any.Type.self) + guard let xRawPointer$ = UnsafeMutableRawPointer(bitPattern: Int(Int64(fromJNI: x, in: environment!))) else { + fatalError("x memory address was null") + } + #if hasFeature(ImplicitOpenExistentials) + let xExistential$ = xRawPointer$.load(as: xDynamicType$) as! any (SomeProtocol & B) + #else + func xDoLoad(_ ty: Ty.Type) -> any (SomeProtocol & B) { + xRawPointer$.load(as: ty) as! any (SomeProtocol & B) + } + let xExistential$ = _openExistential(xDynamicType$, do: xDoLoad) + #endif + SwiftModule.takeComposite(x: xExistential$) + } + """ + ] + ) + } +} diff --git a/Tests/JExtractSwiftTests/JNI/JNIStructTests.swift b/Tests/JExtractSwiftTests/JNI/JNIStructTests.swift index 7f54fa7e..a7c689aa 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIStructTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIStructTests.swift @@ -47,7 +47,7 @@ struct JNIStructTests { """,]) try assertOutput(input: source, .jni, .java, expectedChunks: [ """ - public final class MyStruct extends JNISwiftInstance { + public final class MyStruct implements JNISwiftInstance { static final String LIB_NAME = "SwiftModule"; @SuppressWarnings("unused") @@ -58,9 +58,13 @@ struct JNIStructTests { } """, """ - private MyStruct(long selfPointer, SwiftArena swiftArena) { - super(selfPointer, swiftArena); - } + private MyStruct(long selfPointer, SwiftArena swiftArena) { + SwiftObjects.requireNonZero(selfPointer, "selfPointer"); + this.selfPointer = selfPointer; + + // Only register once we have fully initialized the object since this will need the object pointer. + swiftArena.register(this); + } """, """ public static MyStruct wrapMemoryAddressUnsafe(long selfPointer, SwiftArena swiftArena) { @@ -80,7 +84,7 @@ struct JNIStructTests { expectedChunks: [ """ @Override - protected Runnable $createDestroyFunction() { + public Runnable $createDestroyFunction() { long self$ = this.$memoryAddress(); if (CallTraces.TRACE_DOWNCALLS) { CallTraces.traceDowncall("MyStruct.$createDestroyFunction", diff --git a/Tests/JExtractSwiftTests/SendableTests.swift b/Tests/JExtractSwiftTests/SendableTests.swift index d6d0d2d6..5116fc03 100644 --- a/Tests/JExtractSwiftTests/SendableTests.swift +++ b/Tests/JExtractSwiftTests/SendableTests.swift @@ -46,11 +46,11 @@ final class SendableTests { expectedChunks: [ """ @ThreadSafe // Sendable - public final class SendableStruct extends JNISwiftInstance { + public final class SendableStruct implements JNISwiftInstance { static final String LIB_NAME = "SwiftModule"; """, ] ) } -} \ No newline at end of file +} From 67c8153984abbcdbfa258006f9e109b10c500264 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Fri, 29 Aug 2025 16:55:17 +0900 Subject: [PATCH 356/426] Add destructuring pattern match example to enum docs (#381) --- .../Documentation.docc/SupportedFeatures.md | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md b/Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md index 5884270a..d4c12083 100644 --- a/Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md +++ b/Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md @@ -209,10 +209,10 @@ Vehicle vehicle = ...; switch (vehicle.getDiscriminator()) { case BICYCLE: System.out.println("I am a bicycle!"); - break + break; case CAR: System.out.println("I am a car!"); - break + break; } ``` If you also want access to the associated values, you have various options @@ -223,12 +223,24 @@ Vehicle vehicle = ...; switch (vehicle.getCase()) { case Vehicle.Bicycle b: System.out.println("Bicycle maker: " + b.maker()); - break + break; case Vehicle.Car c: System.out.println("Car: " + c.arg0()); - break + break; } ``` +or even, destructuring the records in the switch statement's pattern match directly: +```java +Vehicle vehicle = ...; +switch (vehicle.getCase()) { + case Vehicle.Car(var name, var unused): + System.out.println("Car: " + name); + break; + default: + break; +} +``` + For Java 16+ you can use [pattern matching for instanceof](https://openjdk.org/jeps/394) ```java Vehicle vehicle = ...; From 899dc23a992eb0265215c8b4bc3fb50b8d012983 Mon Sep 17 00:00:00 2001 From: David Ko Date: Fri, 29 Aug 2025 21:51:27 -0400 Subject: [PATCH 357/426] Update README and SupportedFeatures (#383) * update gitgnore * align with README JExtract from Java to Swift * add watch to 'you may want to this' * add intro to SwiftJavaDocumentation index.md * add intro to SwiftJavaDocumentation index.md * add intro to SwiftJavaDocumentation index.md * align documentation with module rename * SwiftJavaDocumentation correction * Revert "SwiftJavaDocumentation correction" This reverts commit f65061cf242697f10cbd738fbe76a21875c57a39. * revert ConfigureCommand formatting * revert SupportFeatures.md * update benchmark sample project name * renaming JavaKit to SwiftJava * renaming JavaKit to SwiftJava in SupportedFeatures --- README.md | 12 ++++++------ .../Documentation.docc/SupportedFeatures.md | 10 +++++----- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index c15db541..52c61bb4 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ This repository contains two approaches to Swift/Java interoperability. -- Swift library (`JavaKit`) and bindings generator that allows a Swift program to make use of Java libraries by wrapping Java classes in corresponding Swift types, allowing Swift to directly call any wrapped Java API. +- Swift library (`SwiftJava`) and bindings generator that allows a Swift program to make use of Java libraries by wrapping Java classes in corresponding Swift types, allowing Swift to directly call any wrapped Java API. - The `swift-java` tool which which offers automated ways to import or "extract" bindings to sources or libraries in either language. The results are bindings for Swift or Java. ## :construction: :construction: :construction: Early Development :construction: :construction: :construction: @@ -19,11 +19,11 @@ The primary purpose of this repository is to create an environment for collabora This project consists of different modules which have different Swift and Java runtime requirements. -## JavaKit macros +## SwiftJava macros -JavaKit is a Swift library offering macros which simplify writing JNI code "by hand" but also calling Java code from Swift. +SwiftJava is a Swift library offering macros which simplify writing JNI code "by hand" but also calling Java code from Swift. -It is possible to generate Swift bindings to Java libraries using JavaKit by using the `swift-java wrap-java` command. +It is possible to generate Swift bindings to Java libraries using SwiftJava by using the `swift-java wrap-java` command. Required language/runtime versions: - **JDK 17+**, any recent JDK installation should be sufficient, as only general reflection and JNI APIs are used by this integration @@ -124,12 +124,12 @@ Please always use the gradle wrapper (`./gradlew`) to make sure to use the appro Sample apps are located in the `Samples/` directory, and they showcase full "roundtrip" usage of the library and/or tools. -#### JavaKit (Swift -> Java) +#### SwiftJava (Swift -> Java) To run a simple app showcasing a Swift process calling into a Java library you can run: ```bash -cd Samples/JavaKitSampleApp +cd Samples/SwiftJavaExtractFFMSampleApp ./ci-validate.sh # which is just `swift build` and a `java -cp ...` invocation of the compiled program ``` diff --git a/Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md b/Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md index d4c12083..997e680e 100644 --- a/Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md +++ b/Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md @@ -4,13 +4,13 @@ Summary of features supported by the swift-java interoperability libraries and t ## Overview -JavaKit supports both directions of interoperability, using Swift macros and source generation +SwiftJava supports both directions of interoperability, using Swift macros and source generation (via the `swift-java wrap-java` command). ### Java -> Swift -It is possible to use JavaKit macros and the `wrap-java` command to simplify implementing -Java `native` functions. JavaKit simplifies the type conversions +It is possible to use SwiftJava macros and the `wrap-java` command to simplify implementing +Java `native` functions. SwiftJava simplifies the type conversions > tip: This direction of interoperability is covered in the WWDC2025 session 'Explore Swift and Java interoperability' > around the [7-minute mark](https://youtu.be/QSHO-GUGidA?si=vUXxphTeO-CHVZ3L&t=448). @@ -74,8 +74,8 @@ SwiftJava's `swift-java jextract` tool automates generating Java bindings from S | Optional parameters: `func f(i: Int?, class: MyClass?)` | ✅ | ✅ | | Optional return types: `func f() -> Int?`, `func g() -> MyClass?` | ❌ | ✅ | | Primitive types: `Bool`, `Int`, `Int8`, `Int16`, `Int32`, `Int64`, `Float`, `Double` | ✅ | ✅ | -| Parameters: JavaKit wrapped types `JavaLong`, `JavaInteger` | ❌ | ✅ | -| Return values: JavaKit wrapped types `JavaLong`, `JavaInteger` | ❌ | ❌ | +| Parameters: SwiftJava wrapped types `JavaLong`, `JavaInteger` | ❌ | ✅ | +| Return values: SwiftJava wrapped types `JavaLong`, `JavaInteger` | ❌ | ❌ | | Unsigned primitive types: `UInt`, `UInt8`, `UInt16`, `UInt32`, `UInt64` | ✅ * | ✅ * | | String (with copying data) | ✅ | ✅ | | Variadic parameters: `T...` | ❌ | ❌ | From e187ad6f6ef72122218778b7b8af8bbd4c871a3e Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Mon, 1 Sep 2025 15:34:49 +0900 Subject: [PATCH 358/426] Rename reexport file to match reexported module (#385) --- .../{JavaRuntime+Reexport.swift => CSwiftJavaJNI+Reexport.swift} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Sources/SwiftJava/{JavaRuntime+Reexport.swift => CSwiftJavaJNI+Reexport.swift} (100%) diff --git a/Sources/SwiftJava/JavaRuntime+Reexport.swift b/Sources/SwiftJava/CSwiftJavaJNI+Reexport.swift similarity index 100% rename from Sources/SwiftJava/JavaRuntime+Reexport.swift rename to Sources/SwiftJava/CSwiftJavaJNI+Reexport.swift From 748961d69abdde19ebe5463800fbe4cf6883c204 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Wed, 3 Sep 2025 20:03:06 +0900 Subject: [PATCH 359/426] Correct "running in ... mode" message This takes into account the settings file, so we should use the configured mode. Noticed when we printed "ffm mode" while we were actually in JNI mode --- Sources/SwiftJavaTool/Commands/JExtractCommand.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/SwiftJavaTool/Commands/JExtractCommand.swift b/Sources/SwiftJavaTool/Commands/JExtractCommand.swift index 29db6081..6fc5c2fd 100644 --- a/Sources/SwiftJavaTool/Commands/JExtractCommand.swift +++ b/Sources/SwiftJavaTool/Commands/JExtractCommand.swift @@ -103,7 +103,7 @@ extension SwiftJava.JExtractCommand { config.inputSwiftDirectory = "\(FileManager.default.currentDirectoryPath)/Sources/\(swiftModule)" } - print("[debug][swift-java] Running 'swift-java jextract' in mode: " + "\(self.mode)".bold) + print("[debug][swift-java] Running 'swift-java jextract' in mode: " + "\(config.mode ?? .ffm)".bold) // Load all of the dependent configurations and associate them with Swift modules. let dependentConfigs = try loadDependentConfigs(dependsOn: self.dependsOn) From 4b392128fca13aa014accda44543d21b71fcd65d Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Wed, 10 Sep 2025 09:20:26 +0900 Subject: [PATCH 360/426] Start using Swift 6.1.3 in CI (#388) It contains a patch for swiftpm issues we've been facing during build https://forums.swift.org/t/announcing-swift-6-1-3/82022 --- .github/workflows/pull_request.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 0a2b6949..e0a3ee23 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -27,7 +27,7 @@ jobs: strategy: fail-fast: true matrix: - swift_version: ['6.1.2'] + swift_version: ['6.1.3'] os_version: ['jammy'] jdk_vendor: ['corretto'] steps: @@ -45,7 +45,7 @@ jobs: strategy: fail-fast: true matrix: - swift_version: ['6.1.2', 'nightly'] + swift_version: ['6.1.3', 'nightly'] os_version: ['jammy'] jdk_vendor: ['corretto'] container: @@ -71,7 +71,7 @@ jobs: strategy: fail-fast: true matrix: - swift_version: ['6.1.2'] + swift_version: ['6.1.3'] os_version: ['macos'] jdk_vendor: ['corretto'] env: @@ -95,7 +95,7 @@ jobs: strategy: fail-fast: true matrix: - swift_version: ['6.1.2'] + swift_version: ['6.1.3'] os_version: ['jammy'] jdk_vendor: ['corretto'] container: @@ -115,7 +115,7 @@ jobs: strategy: fail-fast: false matrix: - swift_version: ['6.1.2', 'nightly'] + swift_version: ['6.1.3', 'nightly'] os_version: ['jammy'] jdk_vendor: ['corretto'] container: @@ -137,7 +137,7 @@ jobs: strategy: fail-fast: false matrix: - swift_version: ['6.1.2'] + swift_version: ['6.1.3'] os_version: ['macos'] jdk_vendor: ['corretto'] env: @@ -157,7 +157,7 @@ jobs: strategy: fail-fast: false matrix: - swift_version: ['6.1.2', 'nightly'] + swift_version: ['6.1.3', 'nightly'] os_version: ['jammy'] jdk_vendor: ['corretto'] sample_app: [ # TODO: use a reusable-workflow to generate those names @@ -185,7 +185,7 @@ jobs: strategy: fail-fast: false matrix: - swift_version: ['6.1.2'] # no nightly testing on macOS + swift_version: ['6.1.3'] # no nightly testing on macOS os_version: ['macos'] jdk_vendor: ['corretto'] sample_app: [ # TODO: use a reusable-workflow to generate those names From 3d9433f95f6323b2707590b29474f12247ae842c Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Wed, 10 Sep 2025 11:43:49 +0900 Subject: [PATCH 361/426] [SwiftJava] Fix Android build by making JNINativeInterface_ public (#387) --- Sources/SwiftJava/JavaEnvironment.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/SwiftJava/JavaEnvironment.swift b/Sources/SwiftJava/JavaEnvironment.swift index a533a932..9506dbea 100644 --- a/Sources/SwiftJava/JavaEnvironment.swift +++ b/Sources/SwiftJava/JavaEnvironment.swift @@ -15,7 +15,7 @@ import CSwiftJavaJNI #if canImport(Android) -typealias JNINativeInterface_ = JNINativeInterface +public typealias JNINativeInterface_ = JNINativeInterface #endif extension UnsafeMutablePointer { From 94e87becdf38118760dd25e3b6cd6febf8d133f3 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Mon, 22 Sep 2025 16:05:44 +0900 Subject: [PATCH 362/426] Fix error handling for JNI mode unsigned numbers Flip the assertion, the failure was in the wrong branch in JNI mode --- Sources/SwiftJavaTool/Commands/JExtractCommand.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/SwiftJavaTool/Commands/JExtractCommand.swift b/Sources/SwiftJavaTool/Commands/JExtractCommand.swift index 6fc5c2fd..ec7c0aeb 100644 --- a/Sources/SwiftJavaTool/Commands/JExtractCommand.swift +++ b/Sources/SwiftJavaTool/Commands/JExtractCommand.swift @@ -117,9 +117,9 @@ extension SwiftJava.JExtractCommand { if self.mode == .jni { switch self.unsignedNumbers { case .annotate: - throw IllegalModeCombinationError("JNI mode does not support '\(JExtractUnsignedIntegerMode.wrapGuava)' Unsigned integer mode! \(Self.helpMessage)") - case .wrapGuava: () // OK + case .wrapGuava: + throw IllegalModeCombinationError("JNI mode does not support '\(JExtractUnsignedIntegerMode.wrapGuava)' Unsigned integer mode! \(Self.helpMessage)") } } else if self.mode == .ffm { guard self.memoryManagementMode == .explicit else { From ebe04bbddd822179df2f179645c5cc132353d6d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Greg=C3=B3rio=20Gevartosky=20Torrezan?= Date: Sun, 28 Sep 2025 03:42:27 -0300 Subject: [PATCH 363/426] Fixing export JAVA_HOME command missing quote (#390) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 52c61bb4..a1a18d79 100644 --- a/README.md +++ b/README.md @@ -94,7 +94,7 @@ The use of JDK 24 is required to build the project, even though the libraries be When using sdkman the easiest way to export JAVA_HOME is to export the "current" used JDK's home, like this: ```bash -export JAVA_HOME="$(sdk home java current) +export JAVA_HOME="$(sdk home java current)" ``` ### Testing your changes From a1dc8484f0f89dd08210ada9362f6b294a091e31 Mon Sep 17 00:00:00 2001 From: Thomas Krajacic Date: Tue, 7 Oct 2025 14:48:10 +0200 Subject: [PATCH 364/426] Add note about installing JDK (#394) Co-authored-by: Konrad `ktoso` Malawski --- README.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/README.md b/README.md index a1a18d79..2cdeec9c 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,23 @@ The primary purpose of this repository is to create an environment for collabora This project consists of different modules which have different Swift and Java runtime requirements. +On macOS for example, you can install the JDK with [homebrew](https://brew.sh) using + +```bash +$ brew install openjdk +# and create a symlink into /Library/Java/JavaVirtualMachines +$ sudo ln -sfn /opt/homebrew/opt/openjdk/libexec/openjdk.jdk /Library/Java/JavaVirtualMachines/openjdk.jdk + +# or if you have a distribution as cask it will be installed into /Library/Java/JavaVirtualMachines +$ brew install --cask corretto +``` + +or you can use a JDK manager like [sdkman](https://sdkman.io/install/) and set your `JAVA_HOME` environment variable + +```bash +$ export JAVA_HOME="$(sdk home java current)" +``` + ## SwiftJava macros SwiftJava is a Swift library offering macros which simplify writing JNI code "by hand" but also calling Java code from Swift. From a9d733236136d3756aca9a236e80c09b4a9df09a Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Tue, 7 Oct 2025 21:48:38 +0900 Subject: [PATCH 365/426] Explain self-publishing swiftkit (#395) --- README.md | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 2cdeec9c..ff643c49 100644 --- a/README.md +++ b/README.md @@ -5,14 +5,37 @@ This repository contains two approaches to Swift/Java interoperability. - Swift library (`SwiftJava`) and bindings generator that allows a Swift program to make use of Java libraries by wrapping Java classes in corresponding Swift types, allowing Swift to directly call any wrapped Java API. - The `swift-java` tool which which offers automated ways to import or "extract" bindings to sources or libraries in either language. The results are bindings for Swift or Java. -## :construction: :construction: :construction: Early Development :construction: :construction: :construction: +## :construction: Early Development :construction: -**:construction: :construction: :construction: This is a *very early* prototype and everything is subject to change. :construction: :construction: :construction:** +**:construction: This is a *very early* prototype and everything is subject to change. :construction:** Parts of this project are incomplete, not fleshed out, and subject to change without any notice. The primary purpose of this repository is to create an environment for collaboration and joint exploration of the Swift/Java interoperability story. The project will transition to a more structured approach once key goals have been outlined. +### :construction: Self-publish support Java libraries (SwiftKit) + +While we work out how to provide the necessary support libraries for the Java side of Java code generated by `swift-java jextract`, +you will currently need to publish them locally and depend on them this way; + +To publish the libraries to your local maven repository (`$HOME/.m2`), you can run: + +``` +// in swift-java/ +./gradlew publishToMavenLocal +``` + +To consume these libraries in your Java project built using Gradle, you can then include the local repository in the repositories to resolve dependencies from: + +``` +repositories { + mavenLocal() + mavenCentral() +} +``` + +We anticipate simplifying this in the future. + ## Dependencies ### Required JDK versions From 92361949bf5809e48e6e22d053ef611cccfa09ee Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Tue, 7 Oct 2025 22:15:41 +0900 Subject: [PATCH 366/426] CI: Update macOS Swift from 6.1.3 to 6.2.0 (#396) * CI: Update macOS Swift from 6.1.3 to 6.2.0 * only change macOS in this PR --- .github/workflows/pull_request.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index e0a3ee23..ffc42e3c 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -71,7 +71,7 @@ jobs: strategy: fail-fast: true matrix: - swift_version: ['6.1.3'] + swift_version: ['6.2.0'] os_version: ['macos'] jdk_vendor: ['corretto'] env: @@ -95,7 +95,7 @@ jobs: strategy: fail-fast: true matrix: - swift_version: ['6.1.3'] + swift_version: ['6.2.0'] os_version: ['jammy'] jdk_vendor: ['corretto'] container: @@ -137,7 +137,7 @@ jobs: strategy: fail-fast: false matrix: - swift_version: ['6.1.3'] + swift_version: ['6.2.0'] os_version: ['macos'] jdk_vendor: ['corretto'] env: @@ -185,7 +185,7 @@ jobs: strategy: fail-fast: false matrix: - swift_version: ['6.1.3'] # no nightly testing on macOS + swift_version: ['6.2.0'] # no nightly testing on macOS os_version: ['macos'] jdk_vendor: ['corretto'] sample_app: [ # TODO: use a reusable-workflow to generate those names From 5cd11e5788a7677f339132a1dbd1fbf7f4e446e8 Mon Sep 17 00:00:00 2001 From: Mads Odgaard Date: Mon, 13 Oct 2025 06:19:14 +0200 Subject: [PATCH 367/426] Minimum changes for Android support (#401) --- Package.swift | 2 +- Sources/CSwiftJavaJNI/AndroidSupport.cpp | 98 ++++++++++++++++++++++++ 2 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 Sources/CSwiftJavaJNI/AndroidSupport.cpp diff --git a/Package.swift b/Package.swift index 1c0e9481..52ec7ae7 100644 --- a/Package.swift +++ b/Package.swift @@ -362,7 +362,7 @@ let package = Package( name: "CSwiftJavaJNI", swiftSettings: [ .swiftLanguageMode(.v5), - .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) + .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"], .when(platforms: [.macOS, .linux, .windows])) ] ), diff --git a/Sources/CSwiftJavaJNI/AndroidSupport.cpp b/Sources/CSwiftJavaJNI/AndroidSupport.cpp new file mode 100644 index 00000000..a223530a --- /dev/null +++ b/Sources/CSwiftJavaJNI/AndroidSupport.cpp @@ -0,0 +1,98 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +#ifdef __ANDROID__ + +#include +#include +#include + +// these are not exported by the Android SDK + +extern "C" { + using JavaRuntime_GetDefaultJavaVMInitArgs_fn = jint (*)(void *vm_args); + using JavaRuntime_CreateJavaVM_fn = jint (*)(JavaVM **, JNIEnv **, void *); + using JavaRuntime_GetCreatedJavaVMs_fn = jint (*)(JavaVM **, jsize, jsize *); +} + +static JavaRuntime_GetDefaultJavaVMInitArgs_fn + JavaRuntime_GetDefaultJavaVMInitArgs; +static JavaRuntime_CreateJavaVM_fn JavaRuntime_CreateJavaVM; +static JavaRuntime_GetCreatedJavaVMs_fn JavaRuntime_GetCreatedJavaVMs; + +static void *JavaRuntime_dlhandle; + +__attribute__((constructor)) static void JavaRuntime_init(void) { + JavaRuntime_dlhandle = dlopen("libnativehelper.so", RTLD_NOW | RTLD_LOCAL); + if (JavaRuntime_dlhandle == nullptr) { + __android_log_print(ANDROID_LOG_FATAL, "JavaRuntime", + "failed to open libnativehelper.so: %s", dlerror()); + return; + } + + JavaRuntime_GetDefaultJavaVMInitArgs = + reinterpret_cast( + dlsym(JavaRuntime_dlhandle, "JNI_GetDefaultJavaVMInitArgs")); + if (JavaRuntime_GetDefaultJavaVMInitArgs == nullptr) + __android_log_print(ANDROID_LOG_FATAL, "JavaRuntime", + "JNI_GetDefaultJavaVMInitArgs not found: %s", + dlerror()); + + JavaRuntime_CreateJavaVM = reinterpret_cast( + dlsym(JavaRuntime_dlhandle, "JNI_CreateJavaVM")); + if (JavaRuntime_CreateJavaVM == nullptr) + __android_log_print(ANDROID_LOG_FATAL, "JavaRuntime", + "JNI_CreateJavaVM not found: %s", dlerror()); + + JavaRuntime_GetCreatedJavaVMs = + reinterpret_cast( + dlsym(JavaRuntime_dlhandle, "JNI_GetCreatedJavaVMs")); + if (JavaRuntime_GetCreatedJavaVMs == nullptr) + __android_log_print(ANDROID_LOG_FATAL, "JavaRuntime", + "JNI_GetCreatedJavaVMs not found: %s", dlerror()); +} + +__attribute__((destructor)) static void JavaRuntime_deinit(void) { + if (JavaRuntime_dlhandle) { + dlclose(JavaRuntime_dlhandle); + JavaRuntime_dlhandle = nullptr; + } + + JavaRuntime_GetDefaultJavaVMInitArgs = nullptr; + JavaRuntime_CreateJavaVM = nullptr; + JavaRuntime_GetCreatedJavaVMs = nullptr; +} + +jint JNI_GetDefaultJavaVMInitArgs(void *vm_args) { + if (JavaRuntime_GetDefaultJavaVMInitArgs == nullptr) + return JNI_ERR; + + return (*JavaRuntime_GetDefaultJavaVMInitArgs)(vm_args); +} + +jint JNI_CreateJavaVM(JavaVM **vm, JNIEnv **env, void *vm_args) { + if (JavaRuntime_CreateJavaVM == nullptr) + return JNI_ERR; + + return (*JavaRuntime_CreateJavaVM)(vm, env, vm_args); +} + +jint JNI_GetCreatedJavaVMs(JavaVM **vmBuf, jsize bufLen, jsize *nVMs) { + if (JavaRuntime_GetCreatedJavaVMs == nullptr) + return JNI_ERR; + + return (*JavaRuntime_GetCreatedJavaVMs)(vmBuf, bufLen, nVMs); +} + +#endif From 791e734856e7155e9c9da7b5e9983b0ca12b4e3d Mon Sep 17 00:00:00 2001 From: Melissa Kilby Date: Wed, 15 Oct 2025 02:00:00 -0700 Subject: [PATCH 368/426] chore: restrict GitHub workflow permissions - future-proof (#399) --- .github/workflows/pull_request.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index ffc42e3c..35cdd448 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -1,5 +1,8 @@ name: pull_request +permissions: + contents: read + on: pull_request: types: [opened, reopened, synchronize] From c77273e035a2358cbd6a5fd951b4af579bbb4c17 Mon Sep 17 00:00:00 2001 From: rayman-zhao <128336994+rayman-zhao@users.noreply.github.com> Date: Wed, 15 Oct 2025 19:29:56 +0800 Subject: [PATCH 369/426] Fixed problems when build JavaKitSampleApp on Windows (#400) --- .../JavaCompilerPlugin.swift | 20 ++++++++++++------- Samples/JavaKitSampleApp/Package.swift | 5 ++--- .../JavaKitVM/JavaVirtualMachine.swift | 14 ++++++++++--- .../JavaKitVM/ThreadLocalStorage.swift | 2 +- .../Platforms/Subprocess+Windows.swift | 3 +-- 5 files changed, 28 insertions(+), 16 deletions(-) diff --git a/Plugins/JavaCompilerPlugin/JavaCompilerPlugin.swift b/Plugins/JavaCompilerPlugin/JavaCompilerPlugin.swift index e12e13e8..f90150fd 100644 --- a/Plugins/JavaCompilerPlugin/JavaCompilerPlugin.swift +++ b/Plugins/JavaCompilerPlugin/JavaCompilerPlugin.swift @@ -30,11 +30,11 @@ struct JavaCompilerBuildToolPlugin: BuildToolPlugin { // Note: Target doesn't have a directoryURL counterpart to directory, // so we cannot eliminate this deprecation warning. - let sourceDir = target.directory.string + let sourceDir = URL(filePath: target.directory.string) // The name of the configuration file SwiftJava.config from the target for // which we are generating Swift wrappers for Java classes. - let configFile = URL(filePath: sourceDir).appending(path: "swift-java.config") + let configFile = sourceDir.appending(path: "swift-java.config") let config: Configuration? if let configData = try? Data(contentsOf: configFile) { @@ -51,13 +51,14 @@ struct JavaCompilerBuildToolPlugin: BuildToolPlugin { } let sourceFilePath = sourceFileURL.path - guard sourceFilePath.starts(with: sourceDir) else { + let sourceDirPath = sourceDir.path + guard sourceFilePath.starts(with: sourceDirPath) else { fatalError("Could not get relative path for source file \(sourceFilePath)") } return URL(filePath: context.pluginWorkDirectoryURL.path) .appending(path: "Java") - .appending(path: String(sourceFilePath.dropFirst(sourceDir.count))) + .appending(path: String(sourceFilePath.dropFirst(sourceDirPath.count))) .deletingPathExtension() .appendingPathExtension("class") } @@ -65,14 +66,19 @@ struct JavaCompilerBuildToolPlugin: BuildToolPlugin { let javaHome = URL(filePath: findJavaHome()) let javaClassFileURL = context.pluginWorkDirectoryURL .appending(path: "Java") + #if os(Windows) + let javac = "javac.exe" + #else + let javac = "javac" + #endif return [ .buildCommand( displayName: "Compiling \(javaFiles.count) Java files for target \(sourceModule.name) to \(javaClassFileURL)", executable: javaHome .appending(path: "bin") - .appending(path: "javac"), - arguments: javaFiles.map { $0.path(percentEncoded: false) } + [ - "-d", javaClassFileURL.path(), + .appending(path: javac), + arguments: javaFiles.map { $0.path } + [ + "-d", javaClassFileURL.path, "-parameters", // keep parameter names, which allows us to emit them in generated Swift decls ] + (config?.compilerVersionArgs ?? []), inputFiles: javaFiles, diff --git a/Samples/JavaKitSampleApp/Package.swift b/Samples/JavaKitSampleApp/Package.swift index 32451e92..881b8d0b 100644 --- a/Samples/JavaKitSampleApp/Package.swift +++ b/Samples/JavaKitSampleApp/Package.swift @@ -35,9 +35,8 @@ let javaIncludePath = "\(javaHome)/include" let javaPlatformIncludePath = "\(javaIncludePath)/linux" #elseif os(macOS) let javaPlatformIncludePath = "\(javaIncludePath)/darwin" -#else - // TODO: Handle windows as well - #error("Currently only macOS and Linux platforms are supported, this may change in the future.") +#elseif os(Windows) + let javaPlatformIncludePath = "\(javaIncludePath)/win32)" #endif let package = Package( diff --git a/Sources/SwiftJava/JavaKitVM/JavaVirtualMachine.swift b/Sources/SwiftJava/JavaKitVM/JavaVirtualMachine.swift index edbddbb7..7443039a 100644 --- a/Sources/SwiftJava/JavaKitVM/JavaVirtualMachine.swift +++ b/Sources/SwiftJava/JavaKitVM/JavaVirtualMachine.swift @@ -25,6 +25,14 @@ typealias JNIEnvPointer = UnsafeMutablePointer typealias JNIEnvPointer = UnsafeMutableRawPointer #endif +extension FileManager { +#if os(Windows) + static let pathSeparator = ";" +#else + static let pathSeparator = ":" +#endif +} + public final class JavaVirtualMachine: @unchecked Sendable { /// The JNI version that we depend on. static let jniVersion = JNI_VERSION_1_6 @@ -81,8 +89,8 @@ public final class JavaVirtualMachine: @unchecked Sendable { print("[warning][swift-java][JavaVirtualMachine] Missing classpath element: \(URL(fileURLWithPath: path).absoluteString)") // TODO: stderr } } - let colonSeparatedClassPath = classpath.joined(separator: ":") - allVMOptions.append("-Djava.class.path=\(colonSeparatedClassPath)") + let pathSeparatedClassPath = classpath.joined(separator: FileManager.pathSeparator) + allVMOptions.append("-Djava.class.path=\(pathSeparatedClassPath)") } allVMOptions.append(contentsOf: vmOptions) @@ -237,7 +245,7 @@ extension JavaVirtualMachine { ignoreUnrecognized: Bool = false, replace: Bool = false ) throws -> JavaVirtualMachine { - precondition(!classpath.contains(where: { $0.contains(":") }), "Classpath element must not contain `:`! Split the path into elements! Was: \(classpath)") + precondition(!classpath.contains(where: { $0.contains(FileManager.pathSeparator) }), "Classpath element must not contain `\(FileManager.pathSeparator)`! Split the path into elements! Was: \(classpath)") return try sharedJVM.withLock { (sharedJVMPointer: inout JavaVirtualMachine?) in // If we already have a JavaVirtualMachine instance, return it. diff --git a/Sources/SwiftJava/JavaKitVM/ThreadLocalStorage.swift b/Sources/SwiftJava/JavaKitVM/ThreadLocalStorage.swift index 7ea0b50a..037e328b 100644 --- a/Sources/SwiftJava/JavaKitVM/ThreadLocalStorage.swift +++ b/Sources/SwiftJava/JavaKitVM/ThreadLocalStorage.swift @@ -56,7 +56,7 @@ package struct ThreadLocalStorage: ~Copyable { _key = 0 pthread_key_create(&_key, onThreadExit) #elseif canImport(WinSDK) - key = FlsAlloc(onThreadExit) + _key = FlsAlloc(onThreadExit) #endif } diff --git a/Sources/_Subprocess/Platforms/Subprocess+Windows.swift b/Sources/_Subprocess/Platforms/Subprocess+Windows.swift index aaf53ea0..e84d1414 100644 --- a/Sources/_Subprocess/Platforms/Subprocess+Windows.swift +++ b/Sources/_Subprocess/Platforms/Subprocess+Windows.swift @@ -1213,8 +1213,7 @@ extension UInt8 { extension OutputProtocol { internal func output(from data: [UInt8]) throws -> OutputType { return try data.withUnsafeBytes { - let span = RawSpan(_unsafeBytes: $0) - return try self.output(from: span) + return try self.output(from: $0) } } } From 3173f82db004ad6068ffc4779ddc7a7936a12559 Mon Sep 17 00:00:00 2001 From: Mads Odgaard Date: Tue, 21 Oct 2025 11:46:45 +0200 Subject: [PATCH 370/426] Fix release build and enable benchmarks (#406) --- .github/workflows/pull_request.yml | 22 ++++++++++++++++++++++ Package.swift | 3 ++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 35cdd448..f2a1db71 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -112,6 +112,28 @@ jobs: - name: Gradle compile JMH benchmarks run: ./gradlew compileJmh --info + benchmark-swift: + name: Benchmark (Swift) (${{ matrix.os_version }} swift:${{ matrix.swift_version }} jdk:${{matrix.jdk_vendor}}) + runs-on: ubuntu-latest + strategy: + fail-fast: true + matrix: + swift_version: ['6.2.0'] + os_version: ['jammy'] + jdk_vendor: ['corretto'] + container: + image: ${{ (contains(matrix.swift_version, 'nightly') && 'swiftlang/swift') || 'swift' }}:${{ matrix.swift_version }}-${{ matrix.os_version }} + env: + SWIFT_JAVA_VERBOSE: true + steps: + - uses: actions/checkout@v4 + - name: Prepare CI Environment + uses: ./.github/actions/prepare_env + - name: Install jemalloc + run: apt-get update && apt-get install -y libjemalloc-dev + - name: Swift Benchmarks + run: swift package --package-path Benchmarks/ benchmark + test-swift: name: Test (Swift) (${{ matrix.os_version }} swift:${{ matrix.swift_version }} jdk:${{matrix.jdk_vendor}}) runs-on: ubuntu-latest diff --git a/Package.swift b/Package.swift index 52ec7ae7..f6cc83e7 100644 --- a/Package.swift +++ b/Package.swift @@ -245,7 +245,8 @@ let package = Package( exclude: ["swift-java.config"], swiftSettings: [ .swiftLanguageMode(.v5), - .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"], .when(platforms: [.macOS, .linux, .windows])) + .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"], .when(platforms: [.macOS, .linux, .windows])), + .unsafeFlags(["-Xfrontend", "-sil-verify-none"], .when(configuration: .release)), // Workaround for https://github.com/swiftlang/swift/issues/84899 ], linkerSettings: [ .unsafeFlags( From 782af4738b2fb79755bb9c797a26d818d3e87040 Mon Sep 17 00:00:00 2001 From: Mads Odgaard Date: Wed, 22 Oct 2025 23:13:15 +0200 Subject: [PATCH 371/426] Change `SwiftKitCore` to Java 11 instead of 17 (#407) --- SwiftKitCore/build.gradle | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/SwiftKitCore/build.gradle b/SwiftKitCore/build.gradle index 82874e20..b61074a6 100644 --- a/SwiftKitCore/build.gradle +++ b/SwiftKitCore/build.gradle @@ -43,11 +43,13 @@ publishing { java { toolchain { - languageVersion.set(JavaLanguageVersion.of(17)) + languageVersion.set(JavaLanguageVersion.of(24)) } - // Support Android 6+ (Java 7) - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 +} + +tasks.withType(JavaCompile).configureEach { + // Support Java 11 + options.release.set(11) } dependencies { From d006f9a785738a1287fd7f6e7a67e9732e635cad Mon Sep 17 00:00:00 2001 From: Nakaoka Rei Date: Fri, 24 Oct 2025 12:13:04 +1300 Subject: [PATCH 372/426] docs: fix typo in README.md (#408) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ff643c49..48658747 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ This repository contains two approaches to Swift/Java interoperability. - Swift library (`SwiftJava`) and bindings generator that allows a Swift program to make use of Java libraries by wrapping Java classes in corresponding Swift types, allowing Swift to directly call any wrapped Java API. -- The `swift-java` tool which which offers automated ways to import or "extract" bindings to sources or libraries in either language. The results are bindings for Swift or Java. +- The `swift-java` tool which offers automated ways to import or "extract" bindings to sources or libraries in either language. The results are bindings for Swift or Java. ## :construction: Early Development :construction: From f7485cc6e7864276061bc5b748a13fa8ca721c57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Bukowiecki?= Date: Fri, 24 Oct 2025 01:13:26 +0200 Subject: [PATCH 373/426] Fix passed JExtractGenerationMode not being used by JExtractCommand. (#404) Co-authored-by: pelekon <13712101+pelekon@users.noreply.github.com> --- Sources/SwiftJavaTool/Commands/JExtractCommand.swift | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Sources/SwiftJavaTool/Commands/JExtractCommand.swift b/Sources/SwiftJavaTool/Commands/JExtractCommand.swift index ec7c0aeb..c730cbf6 100644 --- a/Sources/SwiftJavaTool/Commands/JExtractCommand.swift +++ b/Sources/SwiftJavaTool/Commands/JExtractCommand.swift @@ -40,7 +40,7 @@ extension SwiftJava { @OptionGroup var commonOptions: SwiftJava.CommonOptions @Option(help: "The mode of generation to use for the output files. Used with jextract mode.") - var mode: JExtractGenerationMode = .ffm + var mode: JExtractGenerationMode? @Option(help: "The name of the Swift module into which the resulting Swift types will be generated.") var swiftModule: String @@ -86,6 +86,11 @@ extension SwiftJava.JExtractCommand { if let javaPackage { config.javaPackage = javaPackage } + if let mode { + config.mode = mode + } else if config.mode == nil { + config.mode = .ffm + } config.swiftModule = self.effectiveSwiftModule config.outputJavaDirectory = outputJava config.outputSwiftDirectory = outputSwift From cfbcf6c62dd8a81b6f240cc771464beeec5138d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Bukowiecki?= Date: Fri, 24 Oct 2025 04:10:09 +0200 Subject: [PATCH 374/426] Properly extract usage of Data type from FoundationEssentials. (#405) Co-authored-by: pelekon <13712101+pelekon@users.noreply.github.com> --- .../FFM/CDeclLowering/CRepresentation.swift | 4 +- ...Swift2JavaGenerator+FunctionLowering.swift | 10 +-- ...MSwift2JavaGenerator+JavaTranslation.swift | 6 +- ...ift2JavaGenerator+SwiftThunkPrinting.swift | 46 +++++++++- .../JNI/JNIJavaTypeTranslator.swift | 2 +- .../Swift2JavaTranslator.swift | 8 +- .../SwiftTypes/DependencyScanner.swift | 65 ++++++++++++++- .../SwiftTypes/ImportedSwiftModule.swift | 36 ++++++++ .../SwiftTypes/SwiftKnownModules.swift | 28 ++++++- .../SwiftTypes/SwiftKnownTypeDecls.swift | 8 +- .../SwiftTypes/SwiftKnownTypes.swift | 9 +- .../SwiftTypes/SwiftModuleSymbolTable.swift | 20 +++++ .../SwiftParsedModuleSymbolTableBuilder.swift | 13 ++- .../SwiftTypes/SwiftSymbolTable.swift | 21 +++-- .../JExtractSwiftTests/DataImportTests.swift | 83 ++++++++++++++----- 15 files changed, 303 insertions(+), 56 deletions(-) create mode 100644 Sources/JExtractSwiftLib/SwiftTypes/ImportedSwiftModule.swift diff --git a/Sources/JExtractSwiftLib/FFM/CDeclLowering/CRepresentation.swift b/Sources/JExtractSwiftLib/FFM/CDeclLowering/CRepresentation.swift index 193b545f..2621dd8b 100644 --- a/Sources/JExtractSwiftLib/FFM/CDeclLowering/CRepresentation.swift +++ b/Sources/JExtractSwiftLib/FFM/CDeclLowering/CRepresentation.swift @@ -125,7 +125,9 @@ extension SwiftKnownTypeDeclKind { .qualified(const: true, volatile: false, type: .void) ) case .void: .void - case .unsafePointer, .unsafeMutablePointer, .unsafeRawBufferPointer, .unsafeMutableRawBufferPointer, .unsafeBufferPointer, .unsafeMutableBufferPointer, .string, .data, .dataProtocol, .optional: + case .unsafePointer, .unsafeMutablePointer, .unsafeRawBufferPointer, .unsafeMutableRawBufferPointer, + .unsafeBufferPointer, .unsafeMutableBufferPointer, .string, .foundationData, .foundationDataProtocol, + .essentialsData, .essentialsDataProtocol, .optional: nil } } diff --git a/Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift b/Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift index 5dfa5b71..7c8d7ab2 100644 --- a/Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift +++ b/Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift @@ -282,7 +282,7 @@ struct CdeclLowering { ) } - case .data: + case .foundationData, .essentialsData: break default: @@ -375,7 +375,7 @@ struct CdeclLowering { case .nominal(let nominal): if let knownType = nominal.nominalTypeDecl.knownTypeKind { switch knownType { - case .data: + case .foundationData, .essentialsData: break case .unsafeRawPointer, .unsafeMutableRawPointer: throw LoweringError.unhandledType(.optional(wrappedType)) @@ -387,7 +387,7 @@ struct CdeclLowering { throw LoweringError.unhandledType(.optional(wrappedType)) case .void, .string: throw LoweringError.unhandledType(.optional(wrappedType)) - case .dataProtocol: + case .foundationDataProtocol, .essentialsDataProtocol: throw LoweringError.unhandledType(.optional(wrappedType)) default: // Unreachable? Should be handled by `CType(cdeclType:)` lowering above. @@ -505,7 +505,7 @@ struct CdeclLowering { ]) ) - case .data: + case .foundationData, .essentialsData: break default: @@ -606,7 +606,7 @@ struct CdeclLowering { case .void: return LoweredResult(cdeclResultType: .void, cdeclOutParameters: [], conversion: .placeholder) - case .data: + case .foundationData, .essentialsData: break case .string, .optional: diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift index 438393cb..5d38a0f9 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift @@ -411,7 +411,7 @@ extension FFMSwift2JavaGenerator { conversion: .call(.placeholder, function: "SwiftRuntime.toCString", withArena: true) ) - case .data: + case .foundationData, .essentialsData: break default: @@ -515,7 +515,7 @@ extension FFMSwift2JavaGenerator { case .nominal(let nominal): if let knownType = nominal.nominalTypeDecl.knownTypeKind { switch knownType { - case .data, .dataProtocol: + case .foundationData, .foundationDataProtocol, .essentialsData, .essentialsDataProtocol: break default: throw JavaTranslationError.unhandledType(.optional(swiftType)) @@ -658,7 +658,7 @@ extension FFMSwift2JavaGenerator { ) ) - case .data: + case .foundationData, .essentialsData: break case .unsafePointer, .unsafeMutablePointer: diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+SwiftThunkPrinting.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+SwiftThunkPrinting.swift index f35973eb..e43ea4c5 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+SwiftThunkPrinting.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+SwiftThunkPrinting.swift @@ -125,11 +125,55 @@ extension FFMSwift2JavaGenerator { } func printSwiftThunkImports(_ printer: inout CodePrinter) { + let mainSymbolSourceModules = Set( + self.lookupContext.symbolTable.importedModules.values.filter { $0.alternativeModules?.isMainSourceOfSymbols ?? false }.map(\.moduleName) + ) + for module in self.lookupContext.symbolTable.importedModules.keys.sorted() { guard module != "Swift" else { continue } - printer.print("import \(module)") + + guard let alternativeModules = self.lookupContext.symbolTable.importedModules[module]?.alternativeModules else { + printer.print("import \(module)") + continue + } + + // Try to print only on main module from relation chain as it has every other module. + guard !mainSymbolSourceModules.isDisjoint(with: alternativeModules.moduleNames) || alternativeModules.isMainSourceOfSymbols else { + if !alternativeModules.isMainSourceOfSymbols { + printer.print("import \(module)") + } + continue + } + + var importGroups: [String: [String]] = [:] + for name in alternativeModules.moduleNames { + guard let otherModule = self.lookupContext.symbolTable.importedModules[name] else { continue } + + let groupKey = otherModule.requiredAvailablityOfModuleWithName ?? otherModule.moduleName + importGroups[groupKey, default: []].append(otherModule.moduleName) + } + + for (index, group) in importGroups.keys.sorted().enumerated() { + if index > 0 && importGroups.keys.count > 1 { + printer.print("#elseif canImport(\(group))") + } else { + printer.print("#if canImport(\(group))") + } + + for groupModule in importGroups[group] ?? [] { + printer.print("import \(groupModule)") + } + } + + if (importGroups.keys.isEmpty) { + printer.print("import \(module)") + } else { + printer.print("#else") + printer.print("import \(module)") + printer.print("#endif") + } } printer.println() } diff --git a/Sources/JExtractSwiftLib/JNI/JNIJavaTypeTranslator.swift b/Sources/JExtractSwiftLib/JNI/JNIJavaTypeTranslator.swift index 983396ac..0d1fc675 100644 --- a/Sources/JExtractSwiftLib/JNI/JNIJavaTypeTranslator.swift +++ b/Sources/JExtractSwiftLib/JNI/JNIJavaTypeTranslator.swift @@ -50,7 +50,7 @@ enum JNIJavaTypeTranslator { .unsafePointer, .unsafeMutablePointer, .unsafeRawBufferPointer, .unsafeMutableRawBufferPointer, .unsafeBufferPointer, .unsafeMutableBufferPointer, - .optional, .data, .dataProtocol: + .optional, .foundationData, .foundationDataProtocol, .essentialsData, .essentialsDataProtocol: return nil } } diff --git a/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift b/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift index ccbbd274..9dcba340 100644 --- a/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift +++ b/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift @@ -108,10 +108,10 @@ extension Swift2JavaTranslator { visitor.visit(sourceFile: input.syntax) } - // If any API uses 'Foundation.Data', import 'Data' as if it's declared in - // this module. - if let dataDecl = self.symbolTable[.data] { - let dataProtocolDecl = self.symbolTable[.dataProtocol]! + // If any API uses 'Foundation.Data' or 'FoundationEssentials.Data', + // import 'Data' as if it's declared in this module. + if let dataDecl = self.symbolTable[.foundationData] ?? self.symbolTable[.essentialsData] { + let dataProtocolDecl = (self.symbolTable[.foundationDataProtocol] ?? self.symbolTable[.essentialsDataProtocol])! if self.isUsing(where: { $0 == dataDecl || $0 == dataProtocolDecl }) { visitor.visit(nominalDecl: dataDecl.syntax!.asNominal!, in: nil) } diff --git a/Sources/JExtractSwiftLib/SwiftTypes/DependencyScanner.swift b/Sources/JExtractSwiftLib/SwiftTypes/DependencyScanner.swift index 409c81a7..79abe981 100644 --- a/Sources/JExtractSwiftLib/SwiftTypes/DependencyScanner.swift +++ b/Sources/JExtractSwiftLib/SwiftTypes/DependencyScanner.swift @@ -15,15 +15,74 @@ import SwiftSyntax /// Scan importing modules. -func importingModuleNames(sourceFile: SourceFileSyntax) -> [String] { - var importingModuleNames: [String] = [] +func importingModules(sourceFile: SourceFileSyntax) -> [ImportedSwiftModule] { + var importingModuleNames: [ImportedSwiftModule] = [] for item in sourceFile.statements { if let importDecl = item.item.as(ImportDeclSyntax.self) { guard let moduleName = importDecl.path.first?.name.text else { continue } - importingModuleNames.append(moduleName) + importingModuleNames.append(ImportedSwiftModule(name: moduleName, availableWithModuleName: nil, alternativeModuleNames: [])) + } else if let ifConfigDecl = item.item.as(IfConfigDeclSyntax.self) { + importingModuleNames.append(contentsOf: modules(from: ifConfigDecl)) } } return importingModuleNames } + +private func modules(from ifConfigDecl: IfConfigDeclSyntax) -> [ImportedSwiftModule] { + guard + let firstClause = ifConfigDecl.clauses.first, + let calledExpression = firstClause.condition?.as(FunctionCallExprSyntax.self)?.calledExpression.as(DeclReferenceExprSyntax.self), + calledExpression.baseName.text == "canImport" else { + return [] + } + + var modules: [ImportedSwiftModule] = [] + modules.reserveCapacity(ifConfigDecl.clauses.count) + + for (index, clause) in ifConfigDecl.clauses.enumerated() { + let importedModuleNames = clause.elements?.as(CodeBlockItemListSyntax.self)? + .compactMap { CodeBlockItemSyntax($0) } + .compactMap { $0.item.as(ImportDeclSyntax.self) } + .compactMap { $0.path.first?.name.text } ?? [] + + let importModuleName: String? = if + let funcCallExpr = clause.condition?.as(FunctionCallExprSyntax.self), + let calledDeclReference = funcCallExpr.calledExpression.as(DeclReferenceExprSyntax.self), + calledDeclReference.baseName.text == "canImport", + let moduleNameSyntax = funcCallExpr.arguments.first?.expression.as(DeclReferenceExprSyntax.self) { + moduleNameSyntax.baseName.text + } else { + nil + } + + let clauseModules = importedModuleNames.map { + ImportedSwiftModule(name: $0, + availableWithModuleName: importModuleName, + alternativeModuleNames: []) + } + + // Assume single import from #else statement is fallback and use it as main source of symbols + if + clauseModules.count == 1 && + index == (ifConfigDecl.clauses.count - 1) && + clause.poundKeyword.tokenKind == .poundElse { + var fallbackModule: ImportedSwiftModule = clauseModules[0] + var moduleNames: [String] = [] + moduleNames.reserveCapacity(modules.count) + + for i in 0.. + var isMainSourceOfSymbols: Bool + + init(name: String, availableWithModuleName: String? = nil, alternativeModuleNames: Set = [], isMainSourceOfSymbols: Bool = false) { + self.name = name + self.availableWithModuleName = availableWithModuleName + self.alternativeModuleNames = alternativeModuleNames + self.isMainSourceOfSymbols = isMainSourceOfSymbols + } + + static func ==(lhs: Self, rhs: Self) -> Bool { + lhs.name == rhs.name + } + + func hash(into hasher: inout Hasher) { + hasher.combine(name) + } +} \ No newline at end of file diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownModules.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownModules.swift index 938d0c4a..45d5df5a 100644 --- a/Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownModules.swift +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownModules.swift @@ -18,6 +18,7 @@ import SwiftSyntaxBuilder enum SwiftKnownModule: String { case swift = "Swift" case foundation = "Foundation" + case foundationEssentials = "FoundationEssentials" var name: String { return self.rawValue @@ -27,13 +28,15 @@ enum SwiftKnownModule: String { return switch self { case .swift: swiftSymbolTable case .foundation: foundationSymbolTable + case .foundationEssentials: foundationEssentialsSymbolTable } } var sourceFile: SourceFileSyntax { return switch self { case .swift: swiftSourceFile - case .foundation: foundationSourceFile + case .foundation: foundationEssentialsSourceFile + case .foundationEssentials: foundationEssentialsSourceFile } } } @@ -44,8 +47,21 @@ private var swiftSymbolTable: SwiftModuleSymbolTable { return builder.finalize() } +private var foundationEssentialsSymbolTable: SwiftModuleSymbolTable { + var builder = SwiftParsedModuleSymbolTableBuilder( + moduleName: "FoundationEssentials", + requiredAvailablityOfModuleWithName: "FoundationEssentials", + alternativeModules: .init(isMainSourceOfSymbols: false, moduleNames: ["Foundation"]), + importedModules: ["Swift": swiftSymbolTable]) + builder.handle(sourceFile: foundationEssentialsSourceFile) + return builder.finalize() +} + private var foundationSymbolTable: SwiftModuleSymbolTable { - var builder = SwiftParsedModuleSymbolTableBuilder(moduleName: "Foundation", importedModules: ["Swift": swiftSymbolTable]) + var builder = SwiftParsedModuleSymbolTableBuilder( + moduleName: "Foundation", + alternativeModules: .init(isMainSourceOfSymbols: true, moduleNames: ["FoundationEssentials"]), + importedModules: ["Swift": swiftSymbolTable]) builder.handle(sourceFile: foundationSourceFile) return builder.finalize() } @@ -87,7 +103,7 @@ private let swiftSourceFile: SourceFileSyntax = """ } """ -private let foundationSourceFile: SourceFileSyntax = """ +private let foundationEssentialsSourceFile: SourceFileSyntax = """ public protocol DataProtocol {} public struct Data: DataProtocol { @@ -96,3 +112,9 @@ private let foundationSourceFile: SourceFileSyntax = """ public func withUnsafeBytes(_ body: (UnsafeRawBufferPointer) -> Void) } """ + +private var foundationSourceFile: SourceFileSyntax { + // On platforms other than Darwin, imports such as FoundationEssentials, FoundationNetworking, etc. are used, + // so this file should be created by combining the files of the aforementioned modules. + foundationEssentialsSourceFile +} \ No newline at end of file diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownTypeDecls.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownTypeDecls.swift index 11ff25c4..809f2aa1 100644 --- a/Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownTypeDecls.swift +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownTypeDecls.swift @@ -15,6 +15,7 @@ import SwiftSyntax enum SwiftKnownTypeDeclKind: String, Hashable { + // Swift case bool = "Swift.Bool" case int = "Swift.Int" case uint = "Swift.UInt" @@ -40,8 +41,11 @@ enum SwiftKnownTypeDeclKind: String, Hashable { case void = "Swift.Void" case string = "Swift.String" - case dataProtocol = "Foundation.DataProtocol" - case data = "Foundation.Data" + // Foundation + case foundationDataProtocol = "Foundation.DataProtocol" + case essentialsDataProtocol = "FoundationEssentials.DataProtocol" + case foundationData = "Foundation.Data" + case essentialsData = "FoundationEssentials.Data" var moduleAndName: (module: String, name: String) { let qualified = self.rawValue diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownTypes.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownTypes.swift index 8c70f7e2..25b1135a 100644 --- a/Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownTypes.swift +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownTypes.swift @@ -35,8 +35,10 @@ struct SwiftKnownTypes { var unsafeRawPointer: SwiftType { .nominal(SwiftNominalType(nominalTypeDecl: symbolTable[.unsafeRawPointer])) } var unsafeMutableRawPointer: SwiftType { .nominal(SwiftNominalType(nominalTypeDecl: symbolTable[.unsafeMutableRawPointer])) } - var dataProtocol: SwiftType { .nominal(SwiftNominalType(nominalTypeDecl: symbolTable[.dataProtocol])) } - var data: SwiftType { .nominal(SwiftNominalType(nominalTypeDecl: symbolTable[.data])) } + var foundationDataProtocol: SwiftType { .nominal(SwiftNominalType(nominalTypeDecl: symbolTable[.foundationDataProtocol])) } + var foundationData: SwiftType { .nominal(SwiftNominalType(nominalTypeDecl: symbolTable[.foundationData])) } + var essentialsDataProtocol: SwiftType { .nominal(SwiftNominalType(nominalTypeDecl: symbolTable[.essentialsDataProtocol])) } + var essentialsData: SwiftType { .nominal(SwiftNominalType(nominalTypeDecl: symbolTable[.essentialsData])) } func unsafePointer(_ pointeeType: SwiftType) -> SwiftType { .nominal( @@ -78,7 +80,8 @@ struct SwiftKnownTypes { /// given protocol kind. E.g. `String` for `StringProtocol` func representativeType(of knownProtocol: SwiftKnownTypeDeclKind) -> SwiftType? { switch knownProtocol { - case .dataProtocol: return self.data + case .foundationDataProtocol: return self.foundationData + case .essentialsDataProtocol: return self.essentialsData default: return nil } } diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftModuleSymbolTable.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftModuleSymbolTable.swift index f1bbaa12..6328045f 100644 --- a/Sources/JExtractSwiftLib/SwiftTypes/SwiftModuleSymbolTable.swift +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftModuleSymbolTable.swift @@ -19,6 +19,12 @@ struct SwiftModuleSymbolTable: SwiftSymbolTableProtocol { /// The name of this module. let moduleName: String + /// The name of module required to be imported and checked via canImport statement. + let requiredAvailablityOfModuleWithName: String? + + /// Data about alternative modules which provides desired symbos e.g. FoundationEssentials is non-Darwin platform alternative for Foundation + let alternativeModules: AlternativeModuleNamesData? + /// The top-level nominal types, found by name. var topLevelTypes: [String: SwiftNominalTypeDeclaration] = [:] @@ -36,4 +42,18 @@ struct SwiftModuleSymbolTable: SwiftSymbolTableProtocol { func lookupNestedType(_ name: String, parent: SwiftNominalTypeDeclaration) -> SwiftNominalTypeDeclaration? { nestedTypes[parent]?[name] } + + func isAlternative(for moduleName: String) -> Bool { + alternativeModules.flatMap { $0.moduleNames.contains(moduleName) } ?? false + } } + +extension SwiftModuleSymbolTable { + struct AlternativeModuleNamesData { + /// Flag indicating module should be used as source of symbols to avoid duplication of symbols. + let isMainSourceOfSymbols: Bool + + /// Names of modules which are alternative for currently checked module. + let moduleNames: Set + } +} \ No newline at end of file diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftParsedModuleSymbolTableBuilder.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftParsedModuleSymbolTableBuilder.swift index 9b8ef236..8abb21f5 100644 --- a/Sources/JExtractSwiftLib/SwiftTypes/SwiftParsedModuleSymbolTableBuilder.swift +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftParsedModuleSymbolTableBuilder.swift @@ -26,9 +26,18 @@ struct SwiftParsedModuleSymbolTableBuilder { /// Extension decls their extended type hasn't been resolved. var unresolvedExtensions: [ExtensionDeclSyntax] - init(moduleName: String, importedModules: [String: SwiftModuleSymbolTable], log: Logger? = nil) { + init( + moduleName: String, + requiredAvailablityOfModuleWithName: String? = nil, + alternativeModules: SwiftModuleSymbolTable.AlternativeModuleNamesData? = nil, + importedModules: [String: SwiftModuleSymbolTable], + log: Logger? = nil + ) { self.log = log - self.symbolTable = .init(moduleName: moduleName) + self.symbolTable = .init( + moduleName: moduleName, + requiredAvailablityOfModuleWithName: requiredAvailablityOfModuleWithName, + alternativeModules: alternativeModules) self.importedModules = importedModules self.unresolvedExtensions = [] } diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftSymbolTable.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftSymbolTable.swift index 239d38c4..4271e297 100644 --- a/Sources/JExtractSwiftLib/SwiftTypes/SwiftSymbolTable.swift +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftSymbolTable.swift @@ -42,6 +42,9 @@ package class SwiftSymbolTable { let parsedModule:SwiftModuleSymbolTable private var knownTypeToNominal: [SwiftKnownTypeDeclKind: SwiftNominalTypeDeclaration] = [:] + private var prioritySortedImportedModules: [SwiftModuleSymbolTable] { + importedModules.values.sorted(by: { ($0.alternativeModules?.isMainSourceOfSymbols ?? false) && $0.moduleName < $1.moduleName }) + } init(parsedModule: SwiftModuleSymbolTable, importedModules: [String: SwiftModuleSymbolTable]) { self.parsedModule = parsedModule @@ -58,18 +61,22 @@ extension SwiftSymbolTable { // Prepare imported modules. // FIXME: Support arbitrary dependencies. - var moduleNames: Set = [] + var modules: Set = [] for sourceFile in sourceFiles { - moduleNames.formUnion(importingModuleNames(sourceFile: sourceFile)) + modules.formUnion(importingModules(sourceFile: sourceFile)) } var importedModules: [String: SwiftModuleSymbolTable] = [:] importedModules[SwiftKnownModule.swift.name] = SwiftKnownModule.swift.symbolTable - for moduleName in moduleNames.sorted() { + for module in modules { + // We don't need duplicates of symbols, first known definition is enough to parse module + // e.g Data from FoundationEssentials and Foundation collide and lead to different results due to random order of keys in Swift's Dictionary + // guard module.isMainSourceOfSymbols || !importedModules.contains(where: { $0.value.isAlternative(for: String)}) else { continue } + if - importedModules[moduleName] == nil, - let knownModule = SwiftKnownModule(rawValue: moduleName) + importedModules[module.name] == nil, + let knownModule = SwiftKnownModule(rawValue: module.name) { - importedModules[moduleName] = knownModule.symbolTable + importedModules[module.name] = knownModule.symbolTable } } @@ -95,7 +102,7 @@ extension SwiftSymbolTable: SwiftSymbolTableProtocol { return parsedResult } - for importedModule in importedModules.values { + for importedModule in prioritySortedImportedModules { if let result = importedModule.lookupTopLevelNominalType(name) { return result } diff --git a/Tests/JExtractSwiftTests/DataImportTests.swift b/Tests/JExtractSwiftTests/DataImportTests.swift index cf4ed387..bad4174d 100644 --- a/Tests/JExtractSwiftTests/DataImportTests.swift +++ b/Tests/JExtractSwiftTests/DataImportTests.swift @@ -16,7 +16,14 @@ import JExtractSwiftLib import Testing final class DataImportTests { - let data_interfaceFile = + private static let ifConfigImport = """ + #if canImport(FoundationEssentials) + import FoundationEssentials + #else + import Foundation + #endif + """ + private static let foundationData_interfaceFile = """ import Foundation @@ -24,23 +31,53 @@ final class DataImportTests { public func returnData() -> Data """ - let dataProtocol_interfaceFile = + private static let foundationDataProtocol_interfaceFile = """ import Foundation public func receiveDataProtocol(dat: some DataProtocol, dat2: T?) """ + private static let essentialsData_interfaceFile = + """ + import FoundationEssentials + + public func receiveData(dat: Data) + public func returnData() -> Data + """ - @Test("Import Data: Swift thunks") - func data_swiftThunk() throws { + private static let essentialsDataProtocol_interfaceFile = + """ + import FoundationEssentials + + public func receiveDataProtocol(dat: some DataProtocol, dat2: T?) + """ + private static let ifConfigData_interfaceFile = + """ + \(ifConfigImport) + + public func receiveData(dat: Data) + public func returnData() -> Data + """ + + private static let ifConfigDataProtocol_interfaceFile = + """ + \(ifConfigImport) + + public func receiveDataProtocol(dat: some DataProtocol, dat2: T?) + """ + + @Test("Import Data: Swift thunks", arguments: zip( + [Self.foundationData_interfaceFile, Self.essentialsData_interfaceFile, Self.ifConfigData_interfaceFile], + ["import Foundation", "import FoundationEssentials", Self.ifConfigImport] + )) + func data_swiftThunk(fileContent: String, expectedImportChunk: String) throws { try assertOutput( - input: data_interfaceFile, .ffm, .swift, + input: fileContent, .ffm, .swift, + detectChunkByInitialLines: 10, expectedChunks: [ - """ - import Foundation - """, + expectedImportChunk, """ @_cdecl("swiftjava_SwiftModule_receiveData_dat") public func swiftjava_SwiftModule_receiveData_dat(_ dat: UnsafeRawPointer) { @@ -87,11 +124,12 @@ final class DataImportTests { ) } - @Test("Import Data: JavaBindings") - func data_javaBindings() throws { - + @Test("Import Data: JavaBindings", arguments: [ + Self.foundationData_interfaceFile, Self.essentialsData_interfaceFile, Self.ifConfigData_interfaceFile + ]) + func data_javaBindings(fileContent: String) throws { try assertOutput( - input: data_interfaceFile, .ffm, .java, + input: fileContent, .ffm, .java, expectedChunks: [ """ /** @@ -333,14 +371,15 @@ final class DataImportTests { ) } - @Test("Import DataProtocol: Swift thunks") - func dataProtocol_swiftThunk() throws { + @Test("Import DataProtocol: Swift thunks", arguments: zip( + [Self.foundationDataProtocol_interfaceFile, Self.essentialsDataProtocol_interfaceFile, Self.ifConfigDataProtocol_interfaceFile], + ["import Foundation", "import FoundationEssentials", Self.ifConfigImport] + )) + func dataProtocol_swiftThunk(fileContent: String, expectedImportChunk: String) throws { try assertOutput( - input: dataProtocol_interfaceFile, .ffm, .swift, + input: fileContent, .ffm, .swift, expectedChunks: [ - """ - import Foundation - """, + expectedImportChunk, """ @_cdecl("swiftjava_SwiftModule_receiveDataProtocol_dat_dat2") public func swiftjava_SwiftModule_receiveDataProtocol_dat_dat2(_ dat: UnsafeRawPointer, _ dat2: UnsafeRawPointer?) { @@ -356,11 +395,13 @@ final class DataImportTests { ) } - @Test("Import DataProtocol: JavaBindings") - func dataProtocol_javaBindings() throws { + @Test("Import DataProtocol: JavaBindings", arguments: [ + Self.foundationDataProtocol_interfaceFile, Self.essentialsDataProtocol_interfaceFile, Self.ifConfigDataProtocol_interfaceFile + ]) + func dataProtocol_javaBindings(fileContent: String) throws { try assertOutput( - input: dataProtocol_interfaceFile, .ffm, .java, + input: fileContent, .ffm, .java, expectedChunks: [ """ /** From e072b2e35528fe364bdd6ab5527f4c7516f2fec6 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Fri, 24 Oct 2025 11:38:42 +0900 Subject: [PATCH 375/426] Revise project status and API stability notes in README Updated README to clarify project status and API stability. --- README.md | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 48658747..7f25914d 100644 --- a/README.md +++ b/README.md @@ -7,11 +7,9 @@ This repository contains two approaches to Swift/Java interoperability. ## :construction: Early Development :construction: -**:construction: This is a *very early* prototype and everything is subject to change. :construction:** +**:construction: This project is in early development, please keep this in mind as you try out the project and do provide feedback about any issues you encounter. :construction:** -Parts of this project are incomplete, not fleshed out, and subject to change without any notice. - -The primary purpose of this repository is to create an environment for collaboration and joint exploration of the Swift/Java interoperability story. The project will transition to a more structured approach once key goals have been outlined. +There is no guarantee about API stability of this package, neither in the Java or Swift parts, until the project releases a stable 1.0 release; APIs may change without prior notice. ### :construction: Self-publish support Java libraries (SwiftKit) @@ -66,7 +64,7 @@ SwiftJava is a Swift library offering macros which simplify writing JNI code "by It is possible to generate Swift bindings to Java libraries using SwiftJava by using the `swift-java wrap-java` command. Required language/runtime versions: -- **JDK 17+**, any recent JDK installation should be sufficient, as only general reflection and JNI APIs are used by this integration +- **JDK 17+**, any recent JDK installation should be sufficient, as only general reflection and JNI APIs are used by this integratio - **Swift 6.0.x**, because the library uses modern Swift macros **swift-java jextract** @@ -83,8 +81,7 @@ This is the primary way we envision calling Swift code from server-side Java lib Required language/runtime versions: - **Swift 6.1**, because of dependence on rich swift interface files -- **JDK 24+** - - We are validating the implementation using the currently supported non-LTE release, which at present means JDK-24. +- **JDK 25+**, the most recent LTS release which includes the stable Foreign Function and Memory APIs. ## swift-java jextract --mode=jni From d7e195949c3bb625c6c6e2944dc7ce3f88d96214 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Fri, 24 Oct 2025 15:17:57 +0900 Subject: [PATCH 376/426] Update JDK from 24 to 25 (#409) --- .github/actions/prepare_env/action.yml | 10 +++++----- ...d-logic.java-common-conventions.gradle.kts | 2 +- README.md | 13 ++++++------ Samples/SwiftAndJavaJarSampleLib/build.gradle | 17 ++++++++-------- .../SwiftAndJavaJarSampleLib/ci-validate.sh | 14 ++++++------- .../SwiftJavaExtractFFMSampleApp/build.gradle | 17 ++++++++-------- .../SwiftJavaExtractJNISampleApp/build.gradle | 17 ++++++++-------- SwiftKitCore/build.gradle | 3 ++- SwiftKitFFM/build.gradle | 3 ++- docker/Dockerfile | 2 +- docker/install_jdk.sh | 20 +++++++++---------- gradle.properties | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- 13 files changed, 64 insertions(+), 58 deletions(-) diff --git a/.github/actions/prepare_env/action.yml b/.github/actions/prepare_env/action.yml index 3fdd5d4b..90854db0 100644 --- a/.github/actions/prepare_env/action.yml +++ b/.github/actions/prepare_env/action.yml @@ -12,7 +12,7 @@ runs: with: distribution: ${{ matrix.jdk_vendor }} java-version: | - 24 + 25 17 cache: 'gradle' - name: Set JAVA_HOME_{N} @@ -23,10 +23,10 @@ runs: elif [[ -n "$JAVA_HOME_21_ARM64" ]]; then echo "JAVA_HOME_21=$JAVA_HOME_21_ARM64" >> $GITHUB_ENV fi - if [[ -n "$JAVA_HOME_24_X64" ]]; then - echo "JAVA_HOME_24=$JAVA_HOME_24_X64" >> $GITHUB_ENV - elif [[ -n "$JAVA_HOME_24_ARM64" ]]; then - echo "JAVA_HOME_24=$JAVA_HOME_24_ARM64" >> $GITHUB_ENV + if [[ -n "$JAVA_HOME_25_X64" ]]; then + echo "JAVA_HOME_25=$JAVA_HOME_25_X64" >> $GITHUB_ENV + elif [[ -n "$JAVA_HOME_25_ARM64" ]]; then + echo "JAVA_HOME_25=$JAVA_HOME_25_ARM64" >> $GITHUB_ENV fi # - name: Check Java environment # shell: bash diff --git a/BuildLogic/src/main/kotlin/build-logic.java-common-conventions.gradle.kts b/BuildLogic/src/main/kotlin/build-logic.java-common-conventions.gradle.kts index df0a6633..1f2df6e5 100644 --- a/BuildLogic/src/main/kotlin/build-logic.java-common-conventions.gradle.kts +++ b/BuildLogic/src/main/kotlin/build-logic.java-common-conventions.gradle.kts @@ -23,7 +23,7 @@ plugins { java { toolchain { - languageVersion = JavaLanguageVersion.of(24) + languageVersion = JavaLanguageVersion.of(25) } } diff --git a/README.md b/README.md index 7f25914d..da56781c 100644 --- a/README.md +++ b/README.md @@ -80,8 +80,9 @@ This does require the use of the relatively recent [JEP-454: Foreign Function & This is the primary way we envision calling Swift code from server-side Java libraries and applications. Required language/runtime versions: -- **Swift 6.1**, because of dependence on rich swift interface files -- **JDK 25+**, the most recent LTS release which includes the stable Foreign Function and Memory APIs. +- **Swift 6.1**, because of dependence on rich swift interface files +- **JDK 25+** + - We are validating the implementation using the currently supported non-LTE release, which at present means JDK-25. ## swift-java jextract --mode=jni @@ -101,7 +102,7 @@ This project contains multiple builds, living side by side together. You will need to have: - Swift (6.1.x+) -- Java (24+ for FFM, even though we support lower JDK targets) +- Java (25+ for FFM, even though we support lower JDK targets) - Gradle (installed by "Gradle wrapper" automatically when you run gradle through `./gradlew`) ### Preparing your environment @@ -120,12 +121,12 @@ however any recent enough Java distribution should work correctly. You can use s # Install sdkman from: https://sdkman.io curl -s "https://get.sdkman.io" | bash sdk install java 17.0.15-amzn -sdk install java 24.0.1-amzn +sdk install java 25.0.1-amzn -sdk use java 24.0.1-amzn +sdk use java 25.0.1-amzn ``` -The use of JDK 24 is required to build the project, even though the libraries being published may target lower Java versions. +The use of JDK 25 is required to build the project, even though the libraries being published may target lower Java versions. ❗️ Please make sure to `export JAVA_HOME` such that swift-java can find the necessary java libraries! When using sdkman the easiest way to export JAVA_HOME is to export the "current" used JDK's home, like this: diff --git a/Samples/SwiftAndJavaJarSampleLib/build.gradle b/Samples/SwiftAndJavaJarSampleLib/build.gradle index 96b25e22..3ad59fe5 100644 --- a/Samples/SwiftAndJavaJarSampleLib/build.gradle +++ b/Samples/SwiftAndJavaJarSampleLib/build.gradle @@ -38,7 +38,7 @@ repositories { java { toolchain { - languageVersion.set(JavaLanguageVersion.of(24)) + languageVersion.set(JavaLanguageVersion.of(25)) } } @@ -46,6 +46,7 @@ dependencies { implementation(project(':SwiftKitCore')) implementation(project(':SwiftKitFFM')) + testRuntimeOnly("org.junit.platform:junit-platform-launcher") // TODO: workaround for not finding junit: https://github.com/gradle/gradle/issues/34512 testImplementation(platform("org.junit:junit-bom:5.10.0")) testImplementation("org.junit.jupiter:junit-jupiter") } @@ -54,16 +55,16 @@ def swiftProductsWithJExtractPlugin() { def stdout = new ByteArrayOutputStream() def stderr = new ByteArrayOutputStream() - def result = exec { - commandLine 'swift', 'package', 'describe', '--type', 'json' - standardOutput = stdout - errorOutput = stderr - ignoreExitValue = true - } + def processBuilder = new ProcessBuilder('swift', 'package', 'describe', '--type', 'json') + def process = processBuilder.start() + + process.consumeProcessOutput(stdout, stderr) + process.waitFor() + def exitValue = process.exitValue() def jsonOutput = stdout.toString() - if (result.exitValue == 0) { + if (exitValue == 0) { def json = new JsonSlurper().parseText(jsonOutput) def products = json.targets .findAll { target -> diff --git a/Samples/SwiftAndJavaJarSampleLib/ci-validate.sh b/Samples/SwiftAndJavaJarSampleLib/ci-validate.sh index 4fde0ef0..2daddc61 100755 --- a/Samples/SwiftAndJavaJarSampleLib/ci-validate.sh +++ b/Samples/SwiftAndJavaJarSampleLib/ci-validate.sh @@ -10,19 +10,19 @@ SWIFT_VERSION="$(swift -version | awk '/Swift version/ { print $3 }')" # This is how env variables are set by setup-java if [ "$(uname -m)" = 'arm64' ]; then ARCH=ARM64 - JAVAC="${JAVA_HOME_24_ARM64}/bin/javac" - JAVA="${JAVA_HOME_24_ARM64}/bin/java" + JAVAC="${JAVA_HOME_25_ARM64}/bin/javac" + JAVA="${JAVA_HOME_25_ARM64}/bin/java" else ARCH=X64 - JAVAC="${JAVA_HOME_24_X64}/bin/javac" - JAVA="${JAVA_HOME_24_X64}/bin/java" + JAVAC="${JAVA_HOME_25_X64}/bin/javac" + JAVA="${JAVA_HOME_25_X64}/bin/java" fi -if [ -n "$JAVA_HOME_24_$ARCH" ]; then - export JAVA_HOME="$JAVA_HOME_24_$ARCH" +if [ -n "$JAVA_HOME_25_$ARCH" ]; then + export JAVA_HOME="$JAVA_HOME_25_$ARCH" elif [ "$(uname -s)" = 'Linux' ] then - export PATH="${PATH}:/usr/lib/jvm/jdk-24/bin" # we need to make sure to use the latest JDK to actually compile/run the executable + export PATH="${PATH}:/usr/lib/jvm/jdk-25/bin" # we need to make sure to use the latest JDK to actually compile/run the executable fi # check if we can compile a plain Example file that uses the generated Java bindings that should be in the generated jar diff --git a/Samples/SwiftJavaExtractFFMSampleApp/build.gradle b/Samples/SwiftJavaExtractFFMSampleApp/build.gradle index 048c984d..0200f234 100644 --- a/Samples/SwiftJavaExtractFFMSampleApp/build.gradle +++ b/Samples/SwiftJavaExtractFFMSampleApp/build.gradle @@ -31,7 +31,7 @@ repositories { java { toolchain { - languageVersion.set(JavaLanguageVersion.of(24)) + languageVersion.set(JavaLanguageVersion.of(25)) } } @@ -39,16 +39,16 @@ def swiftProductsWithJExtractPlugin() { def stdout = new ByteArrayOutputStream() def stderr = new ByteArrayOutputStream() - def result = exec { - commandLine 'swift', 'package', 'describe', '--type', 'json' - standardOutput = stdout - errorOutput = stderr - ignoreExitValue = true - } + def processBuilder = new ProcessBuilder('swift', 'package', 'describe', '--type', 'json') + def process = processBuilder.start() + + process.consumeProcessOutput(stdout, stderr) + process.waitFor() + def exitValue = process.exitValue() def jsonOutput = stdout.toString() - if (result.exitValue == 0) { + if (exitValue == 0) { def json = new JsonSlurper().parseText(jsonOutput) def products = json.targets .findAll { target -> @@ -150,6 +150,7 @@ dependencies { implementation(project(':SwiftKitCore')) implementation(project(':SwiftKitFFM')) + testRuntimeOnly("org.junit.platform:junit-platform-launcher") // TODO: workaround for not finding junit: https://github.com/gradle/gradle/issues/34512 // TODO: workaround for not finding junit: https://github.com/gradle/gradle/issues/34512 testImplementation(platform("org.junit:junit-bom:5.10.0")) testImplementation("org.junit.jupiter:junit-jupiter") } diff --git a/Samples/SwiftJavaExtractJNISampleApp/build.gradle b/Samples/SwiftJavaExtractJNISampleApp/build.gradle index 54bd725a..b1aa8490 100644 --- a/Samples/SwiftJavaExtractJNISampleApp/build.gradle +++ b/Samples/SwiftJavaExtractJNISampleApp/build.gradle @@ -32,7 +32,7 @@ repositories { java { toolchain { - languageVersion.set(JavaLanguageVersion.of(24)) + languageVersion.set(JavaLanguageVersion.of(25)) } } @@ -40,16 +40,16 @@ def swiftProductsWithJExtractPlugin() { def stdout = new ByteArrayOutputStream() def stderr = new ByteArrayOutputStream() - def result = exec { - commandLine 'swift', 'package', 'describe', '--type', 'json' - standardOutput = stdout - errorOutput = stderr - ignoreExitValue = true - } + def processBuilder = new ProcessBuilder('swift', 'package', 'describe', '--type', 'json') + def process = processBuilder.start() + + process.consumeProcessOutput(stdout, stderr) + process.waitFor() + def exitValue = process.exitValue() def jsonOutput = stdout.toString() - if (result.exitValue == 0) { + if (exitValue == 0) { def json = new JsonSlurper().parseText(jsonOutput) def products = json.targets .findAll { target -> @@ -150,6 +150,7 @@ tasks.clean { dependencies { implementation(project(':SwiftKitCore')) + testRuntimeOnly("org.junit.platform:junit-platform-launcher") // TODO: workaround for not finding junit: https://github.com/gradle/gradle/issues/34512 testImplementation(platform("org.junit:junit-bom:5.10.0")) testImplementation("org.junit.jupiter:junit-jupiter") } diff --git a/SwiftKitCore/build.gradle b/SwiftKitCore/build.gradle index b61074a6..9e4891dc 100644 --- a/SwiftKitCore/build.gradle +++ b/SwiftKitCore/build.gradle @@ -43,7 +43,7 @@ publishing { java { toolchain { - languageVersion.set(JavaLanguageVersion.of(24)) + languageVersion.set(JavaLanguageVersion.of(25)) } } @@ -53,6 +53,7 @@ tasks.withType(JavaCompile).configureEach { } dependencies { + testRuntimeOnly("org.junit.platform:junit-platform-launcher") // TODO: workaround for not finding junit: https://github.com/gradle/gradle/issues/34512 testImplementation(platform("org.junit:junit-bom:5.10.0")) testImplementation("org.junit.jupiter:junit-jupiter") } diff --git a/SwiftKitFFM/build.gradle b/SwiftKitFFM/build.gradle index d818586d..c04b1017 100644 --- a/SwiftKitFFM/build.gradle +++ b/SwiftKitFFM/build.gradle @@ -42,13 +42,14 @@ publishing { java { toolchain { - languageVersion.set(JavaLanguageVersion.of(24)) + languageVersion.set(JavaLanguageVersion.of(25)) } } dependencies { implementation(project(':SwiftKitCore')) + testRuntimeOnly("org.junit.platform:junit-platform-launcher") // TODO: workaround for not finding junit: https://github.com/gradle/gradle/issues/34512 testImplementation(platform("org.junit:junit-bom:5.10.0")) testImplementation("org.junit.jupiter:junit-jupiter") } diff --git a/docker/Dockerfile b/docker/Dockerfile index c3568b54..1109dab3 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -20,7 +20,7 @@ ENV LANGUAGE=en_US.UTF-8 # JDK dependency RUN curl -s "https://get.sdkman.io" | bash -RUN bash -c "source /root/.sdkman/bin/sdkman-init.sh && sdk install java 24.0.1-amzn" +RUN bash -c "source /root/.sdkman/bin/sdkman-init.sh && sdk install java 25.0.1-amzn" RUN curl -O https://download.swift.org/swiftly/linux/swiftly-$(uname -m).tar.gz && \ tar zxf swiftly-$(uname -m).tar.gz && \ diff --git a/docker/install_jdk.sh b/docker/install_jdk.sh index 8746e3ab..b69545f9 100755 --- a/docker/install_jdk.sh +++ b/docker/install_jdk.sh @@ -14,7 +14,7 @@ ##===----------------------------------------------------------------------===## set -euo pipefail -# We need JDK 24 because that's the supported version with latest FFM +# We need JDK 25 because that's the supported version with latest FFM # However, we also need JDK 23 at most because Gradle does not support 24. # Supported JDKs: corretto @@ -36,9 +36,9 @@ download_and_install_jdk() { if [ "$JDK_VENDOR" = 'corretto' ]; then if [ "$(uname -m)" = 'aarch64' ]; then case "$jdk_version" in - "24") - jdk_url="https://corretto.aws/downloads/latest/amazon-corretto-24-aarch64-linux-jdk.tar.gz" - expected_md5="3b543f4e971350b73d0ab6d8174cc030" + "25") + jdk_url="https://corretto.aws/downloads/latest/amazon-corretto-25-aarch64-linux-jdk.tar.gz" + expected_md5="37588d5d2a24b26525b9c563ad65cc77" ;; *) echo "Unsupported JDK version: '$jdk_version'" @@ -47,9 +47,9 @@ download_and_install_jdk() { esac else case "$jdk_version" in - "24") - jdk_url="https://corretto.aws/downloads/latest/amazon-corretto-24-x64-linux-jdk.tar.gz" - expected_md5="130885ded3cbfc712fbe9f7dace45a52" + "25") + jdk_url="https://corretto.aws/downloads/latest/amazon-corretto-25-x64-linux-jdk.tar.gz" + expected_md5="7e56b1a9d71637ce4dc4047b23d0453e" ;; *) echo "Unsupported JDK version: '$jdk_version'" @@ -94,12 +94,12 @@ download_and_install_jdk() { cd "$HOME" } -# Usage: Install JDK 24 -download_and_install_jdk "24" +# Usage: Install JDK 25 +download_and_install_jdk "25" ls -la /usr/lib/jvm/ cd /usr/lib/jvm/ -ln -s jdk-24 default-jdk +ln -s jdk-25 default-jdk find . | grep java | grep bin echo "JAVA_HOME = /usr/lib/jvm/default-jdk" /usr/lib/jvm/default-jdk/bin/java -version \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 679a1a1f..182db452 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1 +1 @@ -org.gradle.java.installations.fromEnv=JAVA_HOME_24,JAVA_HOME_24_X64,JAVA_HOME_24_ARM64 \ No newline at end of file +org.gradle.java.installations.fromEnv=JAVA_HOME_25,JAVA_HOME_25_X64,JAVA_HOME_25_ARM64 \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index ff23a68d..2e111328 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.1.0-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME From 6168c628759ca85088d84fa0ae2c1e98d0ca8985 Mon Sep 17 00:00:00 2001 From: Dave Lester <18080+davelester@users.noreply.github.com> Date: Fri, 24 Oct 2025 13:55:21 -0700 Subject: [PATCH 377/426] Updates swift-java project README (#411) * Updates project README.md to clarify its current status, make the language around self-publication of supporting libraries more accessible, and remove the construction emoji that previously appeared. * Update README.md Co-authored-by: Honza Dvorsky --------- Co-authored-by: Dave Lester Co-authored-by: Konrad `ktoso` Malawski Co-authored-by: Honza Dvorsky --- README.md | 57 +++++++++++++++++++++++++++---------------------------- 1 file changed, 28 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index da56781c..2688f288 100644 --- a/README.md +++ b/README.md @@ -5,16 +5,32 @@ This repository contains two approaches to Swift/Java interoperability. - Swift library (`SwiftJava`) and bindings generator that allows a Swift program to make use of Java libraries by wrapping Java classes in corresponding Swift types, allowing Swift to directly call any wrapped Java API. - The `swift-java` tool which offers automated ways to import or "extract" bindings to sources or libraries in either language. The results are bindings for Swift or Java. -## :construction: Early Development :construction: +## Dependencies + +### Required JDK versions + +Note that this project consists of multiple modules which currently have different Swift and Java runtime requirements. + +You'll need to install the necessary JDK version locally. On macOS for example, you can install the JDK with [homebrew](https://brew.sh) using: + +```bash +$ brew install openjdk +# and create a symlink into /Library/Java/JavaVirtualMachines +$ sudo ln -sfn /opt/homebrew/opt/openjdk/libexec/openjdk.jdk /Library/Java/JavaVirtualMachines/openjdk.jdk -**:construction: This project is in early development, please keep this in mind as you try out the project and do provide feedback about any issues you encounter. :construction:** +# or if you have a distribution as cask it will be installed into /Library/Java/JavaVirtualMachines +$ brew install --cask corretto +``` -There is no guarantee about API stability of this package, neither in the Java or Swift parts, until the project releases a stable 1.0 release; APIs may change without prior notice. +Alternatively, you can use a JDK manager like [sdkman](https://sdkman.io/install/) and set your `JAVA_HOME` environment variable: + +```bash +$ export JAVA_HOME="$(sdk home java current)" +``` -### :construction: Self-publish support Java libraries (SwiftKit) +## Self-publish supporting Java libraries -While we work out how to provide the necessary support libraries for the Java side of Java code generated by `swift-java jextract`, -you will currently need to publish them locally and depend on them this way; +Swift-java relies on supporting libraries that are under active development and not yet published to Maven Central. To use the project, you'll need to self-publish these libraries locally so your Java project can depend on them. To publish the libraries to your local maven repository (`$HOME/.m2`), you can run: @@ -34,29 +50,6 @@ repositories { We anticipate simplifying this in the future. -## Dependencies - -### Required JDK versions - -This project consists of different modules which have different Swift and Java runtime requirements. - -On macOS for example, you can install the JDK with [homebrew](https://brew.sh) using - -```bash -$ brew install openjdk -# and create a symlink into /Library/Java/JavaVirtualMachines -$ sudo ln -sfn /opt/homebrew/opt/openjdk/libexec/openjdk.jdk /Library/Java/JavaVirtualMachines/openjdk.jdk - -# or if you have a distribution as cask it will be installed into /Library/Java/JavaVirtualMachines -$ brew install --cask corretto -``` - -or you can use a JDK manager like [sdkman](https://sdkman.io/install/) and set your `JAVA_HOME` environment variable - -```bash -$ export JAVA_HOME="$(sdk home java current)" -``` - ## SwiftJava macros SwiftJava is a Swift library offering macros which simplify writing JNI code "by hand" but also calling Java code from Swift. @@ -231,3 +224,9 @@ xcrun docc preview Sources/SwiftJavaDocumentation/Documentation.docc # Monitoring /Users/ktoso/code/swift-java/Sources/SwiftJavaDocumentation/Documentation.docc for changes... ``` + +## Project Status + +**This project is under active development. We welcome feedback about any issues you encounter.** + +There is no guarantee about API stability until the project reaches a 1.0 release. \ No newline at end of file From 89b2bcc8b66a17fd94779f0b9d6ceb2df32e120b Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Sat, 25 Oct 2025 07:19:45 +0900 Subject: [PATCH 378/426] jextract: generate one output swift file per input file (#403) --- .../JExtractSwiftPlugin.swift | 8 +- .../MySwiftLibrary/MultiplePublicTypes.swift | 26 ++++++ .../ci-validate.sh | 2 + .../MultipleTypesFromSingleFileTest.java | 36 +++++++++ .../MySwiftLibrary/MultiplePublicTypes.swift | 26 ++++++ .../SwiftJavaExtractJNISampleApp/build.gradle | 3 +- .../ci-validate.sh | 2 + .../MultipleTypesFromSingleFileTest.java | 36 +++++++++ Sources/JExtractSwiftLib/CodePrinter.swift | 34 ++++++-- ...ift2JavaGenerator+SwiftThunkPrinting.swift | 47 ++++++++--- .../FFM/FFMSwift2JavaGenerator.swift | 20 ++--- Sources/JExtractSwiftLib/ImportedDecls.swift | 8 +- ...ift2JavaGenerator+SwiftThunkPrinting.swift | 47 ++++++++--- .../JNI/JNISwift2JavaGenerator.swift | 6 +- .../Swift2JavaTranslator.swift | 29 +++---- .../JExtractSwiftLib/Swift2JavaVisitor.swift | 80 +++++++++++++------ .../SwiftTypes/SwiftFunctionSignature.swift | 2 +- .../SwiftTypes/SwiftKnownModules.swift | 6 +- .../SwiftNominalTypeDeclaration.swift | 27 ++++++- .../SwiftParsedModuleSymbolTableBuilder.swift | 26 +++--- .../SwiftTypes/SwiftSymbolTable.swift | 13 +-- .../SwiftTypes/SwiftTypeLookupContext.swift | 25 +++--- .../JavaKitVM/JavaVirtualMachine.swift | 2 +- .../Asserts/TextAssertions.swift | 2 +- .../FuncCallbackImportTests.swift | 6 +- .../FunctionDescriptorImportTests.swift | 4 +- .../MethodImportTests.swift | 18 ++--- .../SwiftSymbolTableTests.swift | 5 +- 28 files changed, 399 insertions(+), 147 deletions(-) create mode 100644 Samples/SwiftJavaExtractFFMSampleApp/Sources/MySwiftLibrary/MultiplePublicTypes.swift create mode 100644 Samples/SwiftJavaExtractFFMSampleApp/src/test/java/com/example/swift/MultipleTypesFromSingleFileTest.java create mode 100644 Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/MultiplePublicTypes.swift create mode 100644 Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/MultipleTypesFromSingleFileTest.java diff --git a/Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift b/Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift index 49ed3c4d..8d0be455 100644 --- a/Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift +++ b/Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift @@ -93,6 +93,7 @@ struct JExtractSwiftBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin { $0.pathExtension == "swift" } + // Output Swift files are just Java filename based converted to Swift files one-to-one var outputSwiftFiles: [URL] = swiftFiles.compactMap { sourceFileURL in guard sourceFileURL.isFileURL else { return nil as URL? @@ -102,7 +103,7 @@ struct JExtractSwiftBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin { guard sourceFilePath.starts(with: sourceDir) else { fatalError("Could not get relative path for source file \(sourceFilePath)") } - var outputURL = outputSwiftDirectory + let outputURL = outputSwiftDirectory .appending(path: String(sourceFilePath.dropFirst(sourceDir.count).dropLast(sourceFileURL.lastPathComponent.count + 1))) let inputFileName = sourceFileURL.deletingPathExtension().lastPathComponent @@ -116,11 +117,12 @@ struct JExtractSwiftBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin { // If the module uses 'Data' type, the thunk file is emitted as if 'Data' is declared // in that module. Declare the thunk file as the output. - // FIXME: Make this conditional. outputSwiftFiles += [ - outputSwiftDirectory.appending(path: "Data+SwiftJava.swift") + outputSwiftDirectory.appending(path: "Foundation+SwiftJava.swift") ] + print("[swift-java-plugin] Output swift files:\n - \(outputSwiftFiles.map({$0.absoluteString}).joined(separator: "\n - "))") + return [ .buildCommand( displayName: "Generate Java wrappers for Swift types", diff --git a/Samples/SwiftJavaExtractFFMSampleApp/Sources/MySwiftLibrary/MultiplePublicTypes.swift b/Samples/SwiftJavaExtractFFMSampleApp/Sources/MySwiftLibrary/MultiplePublicTypes.swift new file mode 100644 index 00000000..234cb357 --- /dev/null +++ b/Samples/SwiftJavaExtractFFMSampleApp/Sources/MySwiftLibrary/MultiplePublicTypes.swift @@ -0,0 +1,26 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +// This file exists to exercise the swiftpm plugin generating separate output Java files +// for the public types; because Java public types must be in a file with the same name as the type. + +public struct PublicTypeOne { + public init() {} + public func test() {} +} + +public struct PublicTypeTwo { + public init() {} + public func test() {} +} \ No newline at end of file diff --git a/Samples/SwiftJavaExtractFFMSampleApp/ci-validate.sh b/Samples/SwiftJavaExtractFFMSampleApp/ci-validate.sh index c7a68d22..8758bbee 100755 --- a/Samples/SwiftJavaExtractFFMSampleApp/ci-validate.sh +++ b/Samples/SwiftJavaExtractFFMSampleApp/ci-validate.sh @@ -3,5 +3,7 @@ set -x set -e +swift build # as a workaround for building swift build from within gradle having issues on CI sometimes + ./gradlew run ./gradlew test \ No newline at end of file diff --git a/Samples/SwiftJavaExtractFFMSampleApp/src/test/java/com/example/swift/MultipleTypesFromSingleFileTest.java b/Samples/SwiftJavaExtractFFMSampleApp/src/test/java/com/example/swift/MultipleTypesFromSingleFileTest.java new file mode 100644 index 00000000..d3cd791c --- /dev/null +++ b/Samples/SwiftJavaExtractFFMSampleApp/src/test/java/com/example/swift/MultipleTypesFromSingleFileTest.java @@ -0,0 +1,36 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package com.example.swift; + +import org.junit.jupiter.api.Test; +import org.swift.swiftkit.core.*; +import org.swift.swiftkit.ffm.*; + +import java.lang.foreign.Arena; +import java.util.Optional; +import java.util.OptionalInt; + +import static org.junit.jupiter.api.Assertions.*; + +public class MultipleTypesFromSingleFileTest { + + @Test + void bothTypesMustHaveBeenGenerated() { + try (var arena = AllocatingSwiftArena.ofConfined()) { + PublicTypeOne.init(arena); + PublicTypeTwo.init(arena); + } + } +} \ No newline at end of file diff --git a/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/MultiplePublicTypes.swift b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/MultiplePublicTypes.swift new file mode 100644 index 00000000..b7a02d78 --- /dev/null +++ b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/MultiplePublicTypes.swift @@ -0,0 +1,26 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +// This file exists to exercise the swiftpm plugin generating separate output Java files +// for the public types; because Java public types must be in a file with the same name as the type. + +public struct PublicTypeOne { + public init() {} + public func test() {} +} + +public struct PublicTypeTwo { + public init() {} + public func test() {} +} \ No newline at end of file diff --git a/Samples/SwiftJavaExtractJNISampleApp/build.gradle b/Samples/SwiftJavaExtractJNISampleApp/build.gradle index b1aa8490..d92c96fb 100644 --- a/Samples/SwiftJavaExtractJNISampleApp/build.gradle +++ b/Samples/SwiftJavaExtractJNISampleApp/build.gradle @@ -102,7 +102,8 @@ def jextract = tasks.register("jextract", Exec) { workingDir = layout.projectDirectory commandLine "swift" - args("build") // since Swift targets which need to be jextract-ed have the jextract build plugin, we just need to build + // TODO: -v for debugging build issues... + args("build", "-v") // since Swift targets which need to be jextract-ed have the jextract build plugin, we just need to build // If we wanted to execute a specific subcommand, we can like this: // args("run",/* // "swift-java", "jextract", diff --git a/Samples/SwiftJavaExtractJNISampleApp/ci-validate.sh b/Samples/SwiftJavaExtractJNISampleApp/ci-validate.sh index c7a68d22..8758bbee 100755 --- a/Samples/SwiftJavaExtractJNISampleApp/ci-validate.sh +++ b/Samples/SwiftJavaExtractJNISampleApp/ci-validate.sh @@ -3,5 +3,7 @@ set -x set -e +swift build # as a workaround for building swift build from within gradle having issues on CI sometimes + ./gradlew run ./gradlew test \ No newline at end of file diff --git a/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/MultipleTypesFromSingleFileTest.java b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/MultipleTypesFromSingleFileTest.java new file mode 100644 index 00000000..ae02b872 --- /dev/null +++ b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/MultipleTypesFromSingleFileTest.java @@ -0,0 +1,36 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package com.example.swift; + +import org.junit.jupiter.api.Test; +import org.swift.swiftkit.core.ConfinedSwiftMemorySession; +import org.swift.swiftkit.core.SwiftArena; + +import java.lang.foreign.Arena; +import java.util.Optional; +import java.util.OptionalInt; + +import static org.junit.jupiter.api.Assertions.*; + +public class MultipleTypesFromSingleFileTest { + + @Test + void bothTypesMustHaveBeenGenerated() { + try (var arena = SwiftArena.ofConfined()) { + PublicTypeOne.init(arena); + PublicTypeTwo.init(arena); + } + } +} \ No newline at end of file diff --git a/Sources/JExtractSwiftLib/CodePrinter.swift b/Sources/JExtractSwiftLib/CodePrinter.swift index 8c22fbee..c5f04d51 100644 --- a/Sources/JExtractSwiftLib/CodePrinter.swift +++ b/Sources/JExtractSwiftLib/CodePrinter.swift @@ -216,14 +216,28 @@ extension CodePrinter { /// - Returns: the output path of the generated file, if any (i.e. not in accumulate in memory mode) package mutating func writeContents( - outputDirectory: String, + outputDirectory _outputDirectory: String, javaPackagePath: String?, - filename: String + filename _filename: String ) throws -> URL? { + + // We handle 'filename' that has a path, since that simplifies passing paths from root output directory enourmously. + // This just moves the directory parts into the output directory part in order for us to create the sub-directories. + let outputDirectory: String + let filename: String + if _filename.contains(PATH_SEPARATOR) { + let parts = _filename.split(separator: PATH_SEPARATOR) + outputDirectory = _outputDirectory.appending(PATH_SEPARATOR).appending(parts.dropLast().joined(separator: PATH_SEPARATOR)) + filename = "\(parts.last!)" + } else { + outputDirectory = _outputDirectory + filename = _filename + } + guard self.mode != .accumulateAll else { // if we're accumulating everything, we don't want to finalize/flush any contents // let's mark that this is where a write would have happened though: - print("// ^^^^ Contents of: \(outputDirectory)/\(filename)") + print("// ^^^^ Contents of: \(outputDirectory)\(PATH_SEPARATOR)\(filename)") return nil } @@ -233,7 +247,7 @@ extension CodePrinter { "// ==== ---------------------------------------------------------------------------------------------------" ) if let javaPackagePath { - print("// \(javaPackagePath)/\(filename)") + print("// \(javaPackagePath)\(PATH_SEPARATOR)\(filename)") } else { print("// \(filename)") } @@ -242,9 +256,15 @@ extension CodePrinter { } let targetDirectory = [outputDirectory, javaPackagePath].compactMap { $0 }.joined(separator: PATH_SEPARATOR) - log.trace("Prepare target directory: \(targetDirectory)") - try FileManager.default.createDirectory( - atPath: targetDirectory, withIntermediateDirectories: true) + log.debug("Prepare target directory: '\(targetDirectory)' for file \(filename.bold)") + do { + try FileManager.default.createDirectory( + atPath: targetDirectory, withIntermediateDirectories: true) + } catch { + // log and throw since it can be confusing what the reason for failing the write was otherwise + log.warning("Failed to create directory: \(targetDirectory)") + throw error + } let outputPath = Foundation.URL(fileURLWithPath: targetDirectory).appendingPathComponent(filename) try contents.write( diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+SwiftThunkPrinting.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+SwiftThunkPrinting.swift index e43ea4c5..5ef266c8 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+SwiftThunkPrinting.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+SwiftThunkPrinting.swift @@ -22,8 +22,16 @@ extension FFMSwift2JavaGenerator { } package func writeSwiftExpectedEmptySources() throws { + let pendingFileCount = self.expectedOutputSwiftFiles.count + guard pendingFileCount > 0 else { + return // no need to write any empty files, yay + } + + print("[swift-java] Write empty [\(self.expectedOutputSwiftFiles.count)] 'expected' files in: \(swiftOutputDirectory)/") + for expectedFileName in self.expectedOutputSwiftFiles { - log.trace("Write empty file: \(expectedFileName) ...") + log.debug("Write SwiftPM-'expected' empty file: \(expectedFileName.bold)") + var printer = CodePrinter() printer.print("// Empty file generated on purpose") @@ -46,7 +54,7 @@ extension FFMSwift2JavaGenerator { outputDirectory: self.swiftOutputDirectory, javaPackagePath: nil, filename: moduleFilename) { - print("[swift-java] Generated: \(moduleFilenameBase.bold).swift (at \(outputFile))") + log.info("Generated: \(moduleFilenameBase.bold).swift (at \(outputFile.absoluteString))") self.expectedOutputSwiftFiles.remove(moduleFilename) } } catch { @@ -54,24 +62,41 @@ extension FFMSwift2JavaGenerator { } // === All types - // FIXME: write them all into the same file they were declared from +SwiftJava - for (_, ty) in self.analysis.importedTypes.sorted(by: { (lhs, rhs) in lhs.key < rhs.key }) { - let fileNameBase = "\(ty.swiftNominal.qualifiedName)+SwiftJava" - let filename = "\(fileNameBase).swift" - log.debug("Printing contents: \(filename)") + // We have to write all types to their corresponding output file that matches the file they were declared in, + // because otherwise SwiftPM plugins will not pick up files apropriately -- we expect 1 output +SwiftJava.swift file for every input. + for group: (key: String, value: [Dictionary.Element]) in Dictionary(grouping: self.analysis.importedTypes, by: { $0.value.sourceFilePath }) { + log.warning("Writing types in file group: \(group.key): \(group.value.map(\.key))") + + let importedTypesForThisFile = group.value + .map(\.value) + .sorted(by: { $0.qualifiedName < $1.qualifiedName }) + + let inputFileName = "\(group.key)".split(separator: "/").last ?? "__Unknown.swift" + let filename = "\(inputFileName)".replacing(".swift", with: "+SwiftJava.swift") + + for ty in importedTypesForThisFile { + log.info("Printing Swift thunks for type: \(ty.qualifiedName.bold)") + printer.printSeparator("Thunks for \(ty.qualifiedName)") + + do { + try printSwiftThunkSources(&printer, ty: ty) + } catch { + log.warning("Failed to print to Swift thunks for type'\(ty.qualifiedName)' to '\(filename)', error: \(error)") + } + + } + log.warning("Write Swift thunks file: \(filename.bold)") do { - try printSwiftThunkSources(&printer, ty: ty) - if let outputFile = try printer.writeContents( outputDirectory: self.swiftOutputDirectory, javaPackagePath: nil, filename: filename) { - print("[swift-java] Generated: \(fileNameBase.bold).swift (at \(outputFile))") + log.info("Done writing Swift thunks to: \(outputFile.absoluteString)") self.expectedOutputSwiftFiles.remove(filename) } } catch { - log.warning("Failed to write to Swift thunks: \(filename)") + log.warning("Failed to write to Swift thunks: \(filename), error: \(error)") } } } diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift index c9a5028b..f9ba88b9 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift @@ -60,16 +60,14 @@ package class FFMSwift2JavaGenerator: Swift2JavaGenerator { // If we are forced to write empty files, construct the expected outputs if translator.config.writeEmptyFiles ?? false { self.expectedOutputSwiftFiles = Set(translator.inputs.compactMap { (input) -> String? in - guard let filePathPart = input.filePath.split(separator: "/\(translator.swiftModuleName)/").last else { + guard let filePathPart = input.path.split(separator: "/\(translator.swiftModuleName)/").last else { return nil } return String(filePathPart.replacing(".swift", with: "+SwiftJava.swift")) }) self.expectedOutputSwiftFiles.insert("\(translator.swiftModuleName)Module+SwiftJava.swift") - - // FIXME: Can we avoid this? - self.expectedOutputSwiftFiles.insert("Data+SwiftJava.swift") + self.expectedOutputSwiftFiles.insert("Foundation+SwiftJava.swift") } else { self.expectedOutputSwiftFiles = [] } @@ -77,16 +75,12 @@ package class FFMSwift2JavaGenerator: Swift2JavaGenerator { func generate() throws { try writeSwiftThunkSources() - print("[swift-java] Generated Swift sources (module: '\(self.swiftModuleName)') in: \(swiftOutputDirectory)/") + log.info("Generated Swift sources (module: '\(self.swiftModuleName)') in: \(swiftOutputDirectory)/") try writeExportedJavaSources() - print("[swift-java] Generated Java sources (package: '\(javaPackage)') in: \(javaOutputDirectory)/") + log.info("Generated Java sources (package: '\(javaPackage)') in: \(javaOutputDirectory)/") - let pendingFileCount = self.expectedOutputSwiftFiles.count - if pendingFileCount > 0 { - print("[swift-java] Write empty [\(pendingFileCount)] 'expected' files in: \(swiftOutputDirectory)/") - try writeSwiftExpectedEmptySources() - } + try writeSwiftExpectedEmptySources() } } @@ -134,7 +128,7 @@ extension FFMSwift2JavaGenerator { javaPackagePath: javaPackagePath, filename: filename ) { - print("[swift-java] Generated: \(ty.swiftNominal.name.bold).java (at \(outputFile))") + log.info("Generated: \((ty.swiftNominal.name.bold + ".java").bold) (at \(outputFile.absoluteString))") } } @@ -148,7 +142,7 @@ extension FFMSwift2JavaGenerator { javaPackagePath: javaPackagePath, filename: filename) { - print("[swift-java] Generated: \(self.swiftModuleName).java (at \(outputFile))") + log.info("Generated: \((self.swiftModuleName + ".java").bold) (at \(outputFile.absoluteString))") } } } diff --git a/Sources/JExtractSwiftLib/ImportedDecls.swift b/Sources/JExtractSwiftLib/ImportedDecls.swift index 7a071d9a..1f0d3efc 100644 --- a/Sources/JExtractSwiftLib/ImportedDecls.swift +++ b/Sources/JExtractSwiftLib/ImportedDecls.swift @@ -27,9 +27,15 @@ package enum SwiftAPIKind { /// Describes a Swift nominal type (e.g., a class, struct, enum) that has been /// imported and is being translated into Java. -package class ImportedNominalType: ImportedDecl { +package final class ImportedNominalType: ImportedDecl { let swiftNominal: SwiftNominalTypeDeclaration + // The short path from module root to the file in which this nominal was originally declared. + // E.g. for `Sources/Example/My/Types.swift` it would be `My/Types.swift`. + package var sourceFilePath: String { + self.swiftNominal.sourceFilePath + } + package var initializers: [ImportedFunc] = [] package var methods: [ImportedFunc] = [] package var variables: [ImportedFunc] = [] diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift index 3848ceac..1d4f81dc 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift @@ -26,8 +26,16 @@ extension JNISwift2JavaGenerator { } package func writeSwiftExpectedEmptySources() throws { + let pendingFileCount = self.expectedOutputSwiftFiles.count + guard pendingFileCount > 0 else { + return // no need to write any empty files, yay + } + + print("[swift-java] Write empty [\(self.expectedOutputSwiftFiles.count)] 'expected' files in: \(swiftOutputDirectory)/") + for expectedFileName in self.expectedOutputSwiftFiles { - logger.trace("Write empty file: \(expectedFileName) ...") + logger.debug("Write SwiftPM-'expected' empty file: \(expectedFileName.bold)") + var printer = CodePrinter() printer.print("// Empty file generated on purpose") @@ -52,27 +60,46 @@ extension JNISwift2JavaGenerator { javaPackagePath: nil, filename: moduleFilename ) { - print("[swift-java] Generated: \(moduleFilenameBase.bold).swift (at \(outputFile))") + logger.info("Generated: \(moduleFilenameBase.bold).swift (at \(outputFile.absoluteString))") self.expectedOutputSwiftFiles.remove(moduleFilename) } - for (_, ty) in self.analysis.importedTypes.sorted(by: { (lhs, rhs) in lhs.key < rhs.key }) { - let fileNameBase = "\(ty.swiftNominal.qualifiedName)+SwiftJava" - let filename = "\(fileNameBase).swift" - logger.debug("Printing contents: \(filename)") + // === All types + // We have to write all types to their corresponding output file that matches the file they were declared in, + // because otherwise SwiftPM plugins will not pick up files apropriately -- we expect 1 output +SwiftJava.swift file for every input. + for group: (key: String, value: [Dictionary.Element]) in Dictionary(grouping: self.analysis.importedTypes, by: { $0.value.sourceFilePath }) { + logger.warning("Writing types in file group: \(group.key): \(group.value.map(\.key))") - do { - try printNominalTypeThunks(&printer, ty) + let importedTypesForThisFile = group.value + .map(\.value) + .sorted(by: { $0.qualifiedName < $1.qualifiedName }) + let inputFileName = "\(group.key)".split(separator: "/").last ?? "__Unknown.swift" + let filename = "\(inputFileName)".replacing(".swift", with: "+SwiftJava.swift") + + for ty in importedTypesForThisFile { + logger.info("Printing Swift thunks for type: \(ty.qualifiedName.bold)") + printer.printSeparator("Thunks for \(ty.qualifiedName)") + + do { + try printNominalTypeThunks(&printer, ty) + } catch { + logger.warning("Failed to print to Swift thunks for type'\(ty.qualifiedName)' to '\(filename)', error: \(error)") + } + + } + + logger.warning("Write Swift thunks file: \(filename.bold)") + do { if let outputFile = try printer.writeContents( outputDirectory: self.swiftOutputDirectory, javaPackagePath: nil, filename: filename) { - print("[swift-java] Generated: \(fileNameBase.bold).swift (at \(outputFile))") + logger.info("Done writing Swift thunks to: \(outputFile.absoluteString)") self.expectedOutputSwiftFiles.remove(filename) } } catch { - logger.warning("Failed to write to Swift thunks: \(filename)") + logger.warning("Failed to write to Swift thunks: \(filename), error: \(error)") } } } catch { diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator.swift index a677bcde..3b84cfb9 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator.swift @@ -67,16 +67,14 @@ package class JNISwift2JavaGenerator: Swift2JavaGenerator { // If we are forced to write empty files, construct the expected outputs if translator.config.writeEmptyFiles ?? false { self.expectedOutputSwiftFiles = Set(translator.inputs.compactMap { (input) -> String? in - guard let filePathPart = input.filePath.split(separator: "/\(translator.swiftModuleName)/").last else { + guard let filePathPart = input.path.split(separator: "/\(translator.swiftModuleName)/").last else { return nil } return String(filePathPart.replacing(".swift", with: "+SwiftJava.swift")) }) self.expectedOutputSwiftFiles.insert("\(translator.swiftModuleName)Module+SwiftJava.swift") - - // FIXME: Can we avoid this? - self.expectedOutputSwiftFiles.insert("Data+SwiftJava.swift") + self.expectedOutputSwiftFiles.insert("Foundation+SwiftJava.swift") } else { self.expectedOutputSwiftFiles = [] } diff --git a/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift b/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift index 9dcba340..7de792c0 100644 --- a/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift +++ b/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift @@ -32,12 +32,7 @@ public final class Swift2JavaTranslator { // ==== Input - struct Input { - let filePath: String - let syntax: SourceFileSyntax - } - - var inputs: [Input] = [] + var inputs: [SwiftJavaInputFile] = [] /// A list of used Swift class names that live in dependencies, e.g. `JavaInteger` package var dependenciesClasses: [String] = [] @@ -85,15 +80,12 @@ extension Swift2JavaTranslator { package func add(filePath: String, text: String) { log.trace("Adding: \(filePath)") let sourceFileSyntax = Parser.parse(source: text) - self.inputs.append(Input(filePath: filePath, syntax: sourceFileSyntax)) + self.inputs.append(SwiftJavaInputFile(syntax: sourceFileSyntax, path: filePath)) } /// Convenient method for analyzing single file. - package func analyze( - file: String, - text: String - ) throws { - self.add(filePath: file, text: text) + package func analyze(path: String, text: String) throws { + self.add(filePath: path, text: text) try self.analyze() } @@ -104,8 +96,8 @@ extension Swift2JavaTranslator { let visitor = Swift2JavaVisitor(translator: self) for input in self.inputs { - log.trace("Analyzing \(input.filePath)") - visitor.visit(sourceFile: input.syntax) + log.trace("Analyzing \(input.path)") + visitor.visit(inputFile: input) } // If any API uses 'Foundation.Data' or 'FoundationEssentials.Data', @@ -113,7 +105,7 @@ extension Swift2JavaTranslator { if let dataDecl = self.symbolTable[.foundationData] ?? self.symbolTable[.essentialsData] { let dataProtocolDecl = (self.symbolTable[.foundationDataProtocol] ?? self.symbolTable[.essentialsDataProtocol])! if self.isUsing(where: { $0 == dataDecl || $0 == dataProtocolDecl }) { - visitor.visit(nominalDecl: dataDecl.syntax!.asNominal!, in: nil) + visitor.visit(nominalDecl: dataDecl.syntax!.asNominal!, in: nil, sourceFilePath: "Foundation/FAKE_FOUNDATION_DATA.swift") } } } @@ -123,7 +115,7 @@ extension Swift2JavaTranslator { let symbolTable = SwiftSymbolTable.setup( moduleName: self.swiftModuleName, - inputs.map({ $0.syntax }) + [dependenciesSource], + inputs + [dependenciesSource], log: self.log ) self.lookupContext = SwiftTypeLookupContext(symbolTable: symbolTable) @@ -184,13 +176,14 @@ extension Swift2JavaTranslator { } /// Returns a source file that contains all the available dependency classes. - private func buildDependencyClassesSourceFile() -> SourceFileSyntax { + private func buildDependencyClassesSourceFile() -> SwiftJavaInputFile { let contents = self.dependenciesClasses.map { "public class \($0) {}" } .joined(separator: "\n") - return SourceFileSyntax(stringLiteral: contents) + let syntax = SourceFileSyntax(stringLiteral: contents) + return SwiftJavaInputFile(syntax: syntax, path: "FakeDependencyClassesSourceFile.swift") } } diff --git a/Sources/JExtractSwiftLib/Swift2JavaVisitor.swift b/Sources/JExtractSwiftLib/Swift2JavaVisitor.swift index 13185a5c..247b2662 100644 --- a/Sources/JExtractSwiftLib/Swift2JavaVisitor.swift +++ b/Sources/JExtractSwiftLib/Swift2JavaVisitor.swift @@ -29,41 +29,42 @@ final class Swift2JavaVisitor { var log: Logger { translator.log } - func visit(sourceFile node: SourceFileSyntax) { + func visit(inputFile: SwiftJavaInputFile) { + let node = inputFile.syntax for codeItem in node.statements { if let declNode = codeItem.item.as(DeclSyntax.self) { - self.visit(decl: declNode, in: nil) + self.visit(decl: declNode, in: nil, sourceFilePath: inputFile.path) } } } - func visit(decl node: DeclSyntax, in parent: ImportedNominalType?) { + func visit(decl node: DeclSyntax, in parent: ImportedNominalType?, sourceFilePath: String) { switch node.as(DeclSyntaxEnum.self) { case .actorDecl(let node): - self.visit(nominalDecl: node, in: parent) + self.visit(nominalDecl: node, in: parent, sourceFilePath: sourceFilePath) case .classDecl(let node): - self.visit(nominalDecl: node, in: parent) + self.visit(nominalDecl: node, in: parent, sourceFilePath: sourceFilePath) case .structDecl(let node): - self.visit(nominalDecl: node, in: parent) + self.visit(nominalDecl: node, in: parent, sourceFilePath: sourceFilePath) case .enumDecl(let node): - self.visit(enumDecl: node, in: parent) + self.visit(enumDecl: node, in: parent, sourceFilePath: sourceFilePath) case .protocolDecl(let node): - self.visit(nominalDecl: node, in: parent) + self.visit(nominalDecl: node, in: parent, sourceFilePath: sourceFilePath) case .extensionDecl(let node): - self.visit(extensionDecl: node, in: parent) + self.visit(extensionDecl: node, in: parent, sourceFilePath: sourceFilePath) case .typeAliasDecl: break // TODO: Implement; https://github.com/swiftlang/swift-java/issues/338 case .associatedTypeDecl: - break // TODO: Implement + break // TODO: Implement associated types case .initializerDecl(let node): self.visit(initializerDecl: node, in: parent) case .functionDecl(let node): - self.visit(functionDecl: node, in: parent) + self.visit(functionDecl: node, in: parent, sourceFilePath: sourceFilePath) case .variableDecl(let node): - self.visit(variableDecl: node, in: parent) + self.visit(variableDecl: node, in: parent, sourceFilePath: sourceFilePath) case .subscriptDecl: - // TODO: Implement + // TODO: Implement subscripts break case .enumCaseDecl(let node): self.visit(enumCaseDecl: node, in: parent) @@ -75,23 +76,32 @@ final class Swift2JavaVisitor { func visit( nominalDecl node: some DeclSyntaxProtocol & DeclGroupSyntax & NamedDeclSyntax & WithAttributesSyntax & WithModifiersSyntax, - in parent: ImportedNominalType? + in parent: ImportedNominalType?, + sourceFilePath: String ) { guard let importedNominalType = translator.importedNominalType(node, parent: parent) else { return } for memberItem in node.memberBlock.members { - self.visit(decl: memberItem.decl, in: importedNominalType) + self.visit(decl: memberItem.decl, in: importedNominalType, sourceFilePath: sourceFilePath) } } - func visit(enumDecl node: EnumDeclSyntax, in parent: ImportedNominalType?) { - self.visit(nominalDecl: node, in: parent) + func visit( + enumDecl node: EnumDeclSyntax, + in parent: ImportedNominalType?, + sourceFilePath: String + ) { + self.visit(nominalDecl: node, in: parent, sourceFilePath: sourceFilePath) self.synthesizeRawRepresentableConformance(enumDecl: node, in: parent) } - func visit(extensionDecl node: ExtensionDeclSyntax, in parent: ImportedNominalType?) { + func visit( + extensionDecl node: ExtensionDeclSyntax, + in parent: ImportedNominalType?, + sourceFilePath: String + ) { guard parent == nil else { // 'extension' in a nominal type is invalid. Ignore return @@ -100,11 +110,15 @@ final class Swift2JavaVisitor { return } for memberItem in node.memberBlock.members { - self.visit(decl: memberItem.decl, in: importedNominalType) + self.visit(decl: memberItem.decl, in: importedNominalType, sourceFilePath: sourceFilePath) } } - func visit(functionDecl node: FunctionDeclSyntax, in typeContext: ImportedNominalType?) { + func visit( + functionDecl node: FunctionDeclSyntax, + in typeContext: ImportedNominalType?, + sourceFilePath: String + ) { guard node.shouldExtract(config: config, log: log, in: typeContext) else { return } @@ -139,7 +153,10 @@ final class Swift2JavaVisitor { } } - func visit(enumCaseDecl node: EnumCaseDeclSyntax, in typeContext: ImportedNominalType?) { + func visit( + enumCaseDecl node: EnumCaseDeclSyntax, + in typeContext: ImportedNominalType? + ) { guard let typeContext else { self.log.info("Enum case must be within a current type; \(node)") return @@ -182,7 +199,11 @@ final class Swift2JavaVisitor { } } - func visit(variableDecl node: VariableDeclSyntax, in typeContext: ImportedNominalType?) { + func visit( + variableDecl node: VariableDeclSyntax, + in typeContext: ImportedNominalType?, + sourceFilePath: String + ) { guard node.shouldExtract(config: config, log: log, in: typeContext) else { return } @@ -232,7 +253,10 @@ final class Swift2JavaVisitor { } } - func visit(initializerDecl node: InitializerDeclSyntax, in typeContext: ImportedNominalType?) { + func visit( + initializerDecl node: InitializerDeclSyntax, + in typeContext: ImportedNominalType?, + ) { guard let typeContext else { self.log.info("Initializer must be within a current type; \(node)") return @@ -265,7 +289,10 @@ final class Swift2JavaVisitor { typeContext.initializers.append(imported) } - private func synthesizeRawRepresentableConformance(enumDecl node: EnumDeclSyntax, in parent: ImportedNominalType?) { + private func synthesizeRawRepresentableConformance( + enumDecl node: EnumDeclSyntax, + in parent: ImportedNominalType? + ) { guard let imported = translator.importedNominalType(node, parent: parent) else { return } @@ -279,14 +306,15 @@ final class Swift2JavaVisitor { { if !imported.variables.contains(where: { $0.name == "rawValue" && $0.functionSignature.result.type != inheritanceType }) { let decl: DeclSyntax = "public var rawValue: \(raw: inheritanceType.description) { get }" - self.visit(decl: decl, in: imported) + self.visit(decl: decl, in: imported, sourceFilePath: imported.sourceFilePath) } + // FIXME: why is this un-used imported.variables.first?.signatureString if !imported.initializers.contains(where: { $0.functionSignature.parameters.count == 1 && $0.functionSignature.parameters.first?.parameterName == "rawValue" && $0.functionSignature.parameters.first?.type == inheritanceType }) { let decl: DeclSyntax = "public init?(rawValue: \(raw: inheritanceType))" - self.visit(decl: decl, in: imported) + self.visit(decl: decl, in: imported, sourceFilePath: imported.sourceFilePath) } } } diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftFunctionSignature.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftFunctionSignature.swift index a5b01bee..7e0f4885 100644 --- a/Sources/JExtractSwiftLib/SwiftTypes/SwiftFunctionSignature.swift +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftFunctionSignature.swift @@ -195,7 +195,7 @@ extension SwiftFunctionSignature { guard parameterNode.specifier == nil else { throw SwiftFunctionTranslationError.genericParameterSpecifier(parameterNode) } - let param = try lookupContext.typeDeclaration(for: parameterNode) as! SwiftGenericParameterDeclaration + let param = try lookupContext.typeDeclaration(for: parameterNode, sourceFilePath: "FIXME_HAS_NO_PATH.swift") as! SwiftGenericParameterDeclaration params.append(param) if let inheritedNode = parameterNode.inheritedType { let inherited = try SwiftType(inheritedNode, lookupContext: lookupContext) diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownModules.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownModules.swift index 45d5df5a..7acb1199 100644 --- a/Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownModules.swift +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownModules.swift @@ -43,7 +43,7 @@ enum SwiftKnownModule: String { private var swiftSymbolTable: SwiftModuleSymbolTable { var builder = SwiftParsedModuleSymbolTableBuilder(moduleName: "Swift", importedModules: [:]) - builder.handle(sourceFile: swiftSourceFile) + builder.handle(sourceFile: swiftSourceFile, sourceFilePath: "SwiftStdlib.swift") // FIXME: missing path here return builder.finalize() } @@ -53,7 +53,7 @@ private var foundationEssentialsSymbolTable: SwiftModuleSymbolTable { requiredAvailablityOfModuleWithName: "FoundationEssentials", alternativeModules: .init(isMainSourceOfSymbols: false, moduleNames: ["Foundation"]), importedModules: ["Swift": swiftSymbolTable]) - builder.handle(sourceFile: foundationEssentialsSourceFile) + builder.handle(sourceFile: foundationEssentialsSourceFile, sourceFilePath: "FakeFoundation.swift") return builder.finalize() } @@ -62,7 +62,7 @@ private var foundationSymbolTable: SwiftModuleSymbolTable { moduleName: "Foundation", alternativeModules: .init(isMainSourceOfSymbols: true, moduleNames: ["FoundationEssentials"]), importedModules: ["Swift": swiftSymbolTable]) - builder.handle(sourceFile: foundationSourceFile) + builder.handle(sourceFile: foundationSourceFile, sourceFilePath: "Foundation.swift") return builder.finalize() } diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftNominalTypeDeclaration.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftNominalTypeDeclaration.swift index 763a5da2..0b8b5651 100644 --- a/Sources/JExtractSwiftLib/SwiftTypes/SwiftNominalTypeDeclaration.swift +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftNominalTypeDeclaration.swift @@ -19,20 +19,37 @@ import SwiftSyntax public typealias NominalTypeDeclSyntaxNode = any DeclGroupSyntax & NamedDeclSyntax & WithAttributesSyntax & WithModifiersSyntax package class SwiftTypeDeclaration { + + // The short path from module root to the file in which this nominal was originally declared. + // E.g. for `Sources/Example/My/Types.swift` it would be `My/Types.swift`. + let sourceFilePath: String + /// The module in which this nominal type is defined. If this is a nested type, the /// module might be different from that of the parent type, if this nominal type /// is defined in an extension within another module. let moduleName: String - /// The name of this nominal type, e.g., 'MyCollection'. + /// The name of this nominal type, e.g. 'MyCollection'. let name: String - init(moduleName: String, name: String) { + init(sourceFilePath: String, moduleName: String, name: String) { + self.sourceFilePath = sourceFilePath self.moduleName = moduleName self.name = name } } +/// A syntax node paired with a simple file path +package struct SwiftJavaInputFile { + let syntax: SourceFileSyntax + /// Simple file path of the file from which the syntax node was parsed. + let path: String + package init(syntax: SourceFileSyntax, path: String) { + self.syntax = syntax + self.path = path + } +} + /// Describes a nominal type declaration, which can be of any kind (class, struct, etc.) /// and has a name, parent type (if nested), and owning module. package class SwiftNominalTypeDeclaration: SwiftTypeDeclaration { @@ -66,6 +83,7 @@ package class SwiftNominalTypeDeclaration: SwiftTypeDeclaration { /// Create a nominal type declaration from the syntax node for a nominal type /// declaration. init( + sourceFilePath: String, moduleName: String, parent: SwiftNominalTypeDeclaration?, node: NominalTypeDeclSyntaxNode @@ -82,7 +100,7 @@ package class SwiftNominalTypeDeclaration: SwiftTypeDeclaration { case .structDecl: self.kind = .struct default: fatalError("Not a nominal type declaration") } - super.init(moduleName: moduleName, name: node.name.text) + super.init(sourceFilePath: sourceFilePath, moduleName: moduleName, name: node.name.text) } lazy var firstInheritanceType: TypeSyntax? = { @@ -145,11 +163,12 @@ package class SwiftGenericParameterDeclaration: SwiftTypeDeclaration { let syntax: GenericParameterSyntax init( + sourceFilePath: String, moduleName: String, node: GenericParameterSyntax ) { self.syntax = node - super.init(moduleName: moduleName, name: node.name.text) + super.init(sourceFilePath: sourceFilePath, moduleName: moduleName, name: node.name.text) } } diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftParsedModuleSymbolTableBuilder.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftParsedModuleSymbolTableBuilder.swift index 8abb21f5..c5586410 100644 --- a/Sources/JExtractSwiftLib/SwiftTypes/SwiftParsedModuleSymbolTableBuilder.swift +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftParsedModuleSymbolTableBuilder.swift @@ -50,7 +50,8 @@ struct SwiftParsedModuleSymbolTableBuilder { extension SwiftParsedModuleSymbolTableBuilder { mutating func handle( - sourceFile: SourceFileSyntax + sourceFile: SourceFileSyntax, + sourceFilePath: String ) { // Find top-level type declarations. for statement in sourceFile.statements { @@ -60,10 +61,10 @@ extension SwiftParsedModuleSymbolTableBuilder { } if let nominalTypeNode = decl.asNominal { - self.handle(nominalTypeDecl: nominalTypeNode, parent: nil) + self.handle(sourceFilePath: sourceFilePath, nominalTypeDecl: nominalTypeNode, parent: nil) } if let extensionNode = decl.as(ExtensionDeclSyntax.self) { - self.handle(extensionDecl: extensionNode) + self.handle(extensionDecl: extensionNode, sourceFilePath: sourceFilePath) } } } @@ -71,6 +72,7 @@ extension SwiftParsedModuleSymbolTableBuilder { /// Add a nominal type declaration and all of the nested types within it to the symbol /// table. mutating func handle( + sourceFilePath: String, nominalTypeDecl node: NominalTypeDeclSyntaxNode, parent: SwiftNominalTypeDeclaration? ) { @@ -83,6 +85,7 @@ extension SwiftParsedModuleSymbolTableBuilder { // Otherwise, create the nominal type declaration. let nominalTypeDecl = SwiftNominalTypeDeclaration( + sourceFilePath: sourceFilePath, moduleName: moduleName, parent: parent, node: node @@ -96,26 +99,28 @@ extension SwiftParsedModuleSymbolTableBuilder { symbolTable.topLevelTypes[nominalTypeDecl.name] = nominalTypeDecl } - self.handle(memberBlock: node.memberBlock, parent: nominalTypeDecl) + self.handle(sourceFilePath: sourceFilePath, memberBlock: node.memberBlock, parent: nominalTypeDecl) } mutating func handle( + sourceFilePath: String, memberBlock node: MemberBlockSyntax, parent: SwiftNominalTypeDeclaration ) { for member in node.members { // Find any nested types within this nominal type and add them. if let nominalMember = member.decl.asNominal { - self.handle(nominalTypeDecl: nominalMember, parent: parent) + self.handle(sourceFilePath: sourceFilePath, nominalTypeDecl: nominalMember, parent: parent) } } } mutating func handle( - extensionDecl node: ExtensionDeclSyntax + extensionDecl node: ExtensionDeclSyntax, + sourceFilePath: String ) { - if !self.tryHandle(extension: node) { + if !self.tryHandle(extension: node, sourceFilePath: sourceFilePath) { self.unresolvedExtensions.append(node) } } @@ -123,7 +128,8 @@ extension SwiftParsedModuleSymbolTableBuilder { /// Add any nested types within the given extension to the symbol table. /// If the extended nominal type can't be resolved, returns false. mutating func tryHandle( - extension node: ExtensionDeclSyntax + extension node: ExtensionDeclSyntax, + sourceFilePath: String ) -> Bool { // Try to resolve the type referenced by this extension declaration. // If it fails, we'll try again later. @@ -141,7 +147,7 @@ extension SwiftParsedModuleSymbolTableBuilder { } // Find any nested types within this extension and add them. - self.handle(memberBlock: node.memberBlock, parent: extendedNominal) + self.handle(sourceFilePath: sourceFilePath, memberBlock: node.memberBlock, parent: extendedNominal) return true } @@ -158,7 +164,7 @@ extension SwiftParsedModuleSymbolTableBuilder { while !unresolvedExtensions.isEmpty { var extensions = self.unresolvedExtensions extensions.removeAll(where: { - self.tryHandle(extension: $0) + self.tryHandle(extension: $0, sourceFilePath: "FIXME_MISSING_FILEPATH.swift") // FIXME: missing filepath here in finalize }) // If we didn't resolve anything, we're done. diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftSymbolTable.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftSymbolTable.swift index 4271e297..ef299bab 100644 --- a/Sources/JExtractSwiftLib/SwiftTypes/SwiftSymbolTable.swift +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftSymbolTable.swift @@ -39,7 +39,7 @@ extension SwiftSymbolTableProtocol { package class SwiftSymbolTable { let importedModules: [String: SwiftModuleSymbolTable] - let parsedModule:SwiftModuleSymbolTable + let parsedModule: SwiftModuleSymbolTable private var knownTypeToNominal: [SwiftKnownTypeDeclKind: SwiftNominalTypeDeclaration] = [:] private var prioritySortedImportedModules: [SwiftModuleSymbolTable] { @@ -55,15 +55,16 @@ package class SwiftSymbolTable { extension SwiftSymbolTable { package static func setup( moduleName: String, - _ sourceFiles: some Collection, + _ inputFiles: some Collection, log: Logger ) -> SwiftSymbolTable { // Prepare imported modules. // FIXME: Support arbitrary dependencies. var modules: Set = [] - for sourceFile in sourceFiles { - modules.formUnion(importingModules(sourceFile: sourceFile)) + for inputFile in inputFiles { + let importedModules = importingModules(sourceFile: inputFile.syntax) + modules.formUnion(importedModules) } var importedModules: [String: SwiftModuleSymbolTable] = [:] importedModules[SwiftKnownModule.swift.name] = SwiftKnownModule.swift.symbolTable @@ -84,8 +85,8 @@ extension SwiftSymbolTable { var builder = SwiftParsedModuleSymbolTableBuilder(moduleName: moduleName, importedModules: importedModules, log: log) // First, register top-level and nested nominal types to the symbol table. - for sourceFile in sourceFiles { - builder.handle(sourceFile: sourceFile) + for sourceFile in inputFiles { + builder.handle(sourceFile: sourceFile.syntax, sourceFilePath: sourceFile.path) } let parsedModule = builder.finalize() return SwiftSymbolTable(parsedModule: parsedModule, importedModules: importedModules) diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftTypeLookupContext.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftTypeLookupContext.swift index 9ede2b1b..f47669b5 100644 --- a/Sources/JExtractSwiftLib/SwiftTypes/SwiftTypeLookupContext.swift +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftTypeLookupContext.swift @@ -48,7 +48,7 @@ class SwiftTypeLookupContext { } case .lookInMembers(let scopeNode): - if let nominalDecl = try typeDeclaration(for: scopeNode) { + if let nominalDecl = try typeDeclaration(for: scopeNode, sourceFilePath: "FIXME.swift") { // FIXME: no path here // implement some node -> file if let found = symbolTable.lookupNestedType(name.name, parent: nominalDecl as! SwiftNominalTypeDeclaration) { return found } @@ -74,9 +74,9 @@ class SwiftTypeLookupContext { for name in names { switch name { case .identifier(let identifiableSyntax, _): - return try? typeDeclaration(for: identifiableSyntax) + return try? typeDeclaration(for: identifiableSyntax, sourceFilePath: "FIXME_NO_PATH.swift") // FIXME: how to get path here? case .declaration(let namedDeclSyntax): - return try? typeDeclaration(for: namedDeclSyntax) + return try? typeDeclaration(for: namedDeclSyntax, sourceFilePath: "FIXME_NO_PATH.swift") // FIXME: how to get path here? case .implicit(let implicitDecl): // TODO: Implement _ = implicitDecl @@ -90,7 +90,7 @@ class SwiftTypeLookupContext { /// Returns the type declaration object associated with the `Syntax` node. /// If there's no declaration created, create an instance on demand, and cache it. - func typeDeclaration(for node: some SyntaxProtocol) throws -> SwiftTypeDeclaration? { + func typeDeclaration(for node: some SyntaxProtocol, sourceFilePath: String) throws -> SwiftTypeDeclaration? { if let found = typeDecls[node.id] { return found } @@ -98,17 +98,17 @@ class SwiftTypeLookupContext { let typeDecl: SwiftTypeDeclaration switch Syntax(node).as(SyntaxEnum.self) { case .genericParameter(let node): - typeDecl = SwiftGenericParameterDeclaration(moduleName: symbolTable.moduleName, node: node) + typeDecl = SwiftGenericParameterDeclaration(sourceFilePath: sourceFilePath, moduleName: symbolTable.moduleName, node: node) case .classDecl(let node): - typeDecl = try nominalTypeDeclaration(for: node) + typeDecl = try nominalTypeDeclaration(for: node, sourceFilePath: sourceFilePath) case .actorDecl(let node): - typeDecl = try nominalTypeDeclaration(for: node) + typeDecl = try nominalTypeDeclaration(for: node, sourceFilePath: sourceFilePath) case .structDecl(let node): - typeDecl = try nominalTypeDeclaration(for: node) + typeDecl = try nominalTypeDeclaration(for: node, sourceFilePath: sourceFilePath) case .enumDecl(let node): - typeDecl = try nominalTypeDeclaration(for: node) + typeDecl = try nominalTypeDeclaration(for: node, sourceFilePath: sourceFilePath) case .protocolDecl(let node): - typeDecl = try nominalTypeDeclaration(for: node) + typeDecl = try nominalTypeDeclaration(for: node, sourceFilePath: sourceFilePath) case .typeAliasDecl: fatalError("typealias not implemented") case .associatedTypeDecl: @@ -122,8 +122,9 @@ class SwiftTypeLookupContext { } /// Create a nominal type declaration instance for the specified syntax node. - private func nominalTypeDeclaration(for node: NominalTypeDeclSyntaxNode) throws -> SwiftNominalTypeDeclaration { + private func nominalTypeDeclaration(for node: NominalTypeDeclSyntaxNode, sourceFilePath: String) throws -> SwiftNominalTypeDeclaration { SwiftNominalTypeDeclaration( + sourceFilePath: sourceFilePath, moduleName: self.symbolTable.moduleName, parent: try parentTypeDecl(for: node), node: node @@ -136,7 +137,7 @@ class SwiftTypeLookupContext { while let parentDecl = node.ancestorDecl { switch parentDecl.as(DeclSyntaxEnum.self) { case .structDecl, .classDecl, .actorDecl, .enumDecl, .protocolDecl: - return (try typeDeclaration(for: parentDecl) as! SwiftNominalTypeDeclaration) + return (try typeDeclaration(for: parentDecl, sourceFilePath: "FIXME_NO_SOURCE_FILE.swift") as! SwiftNominalTypeDeclaration) // FIXME: need to get the source file of the parent default: node = parentDecl continue diff --git a/Sources/SwiftJava/JavaKitVM/JavaVirtualMachine.swift b/Sources/SwiftJava/JavaKitVM/JavaVirtualMachine.swift index 7443039a..bb574c8a 100644 --- a/Sources/SwiftJava/JavaKitVM/JavaVirtualMachine.swift +++ b/Sources/SwiftJava/JavaKitVM/JavaVirtualMachine.swift @@ -190,8 +190,8 @@ extension JavaVirtualMachine { // If we failed to attach, report that. if let attachError = VMError(fromJNIError: attachResult) { + // throw attachError fatalError("JVM Error: \(attachError)") - throw attachError } JavaVirtualMachine.destroyTLS.set(jniEnv!) diff --git a/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift b/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift index 66563fee..001d34fa 100644 --- a/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift +++ b/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift @@ -42,7 +42,7 @@ func assertOutput( let translator = Swift2JavaTranslator(config: config) translator.dependenciesClasses = Array(javaClassLookupTable.keys) - try! translator.analyze(file: "/fake/Fake.swiftinterface", text: input) + try! translator.analyze(path: "/fake/Fake.swiftinterface", text: input) let output: String var printer: CodePrinter = CodePrinter(mode: .accumulateAll) diff --git a/Tests/JExtractSwiftTests/FuncCallbackImportTests.swift b/Tests/JExtractSwiftTests/FuncCallbackImportTests.swift index 82747ec9..79b51c19 100644 --- a/Tests/JExtractSwiftTests/FuncCallbackImportTests.swift +++ b/Tests/JExtractSwiftTests/FuncCallbackImportTests.swift @@ -42,7 +42,7 @@ final class FuncCallbackImportTests { let st = Swift2JavaTranslator(config: config) st.log.logLevel = .error - try st.analyze(file: "Fake.swift", text: Self.class_interfaceFile) + try st.analyze(path: "Fake.swift", text: Self.class_interfaceFile) let funcDecl = st.importedGlobalFuncs.first { $0.name == "callMe" }! @@ -131,7 +131,7 @@ final class FuncCallbackImportTests { config.swiftModule = "__FakeModule" let st = Swift2JavaTranslator(config: config) - try st.analyze(file: "Fake.swift", text: Self.class_interfaceFile) + try st.analyze(path: "Fake.swift", text: Self.class_interfaceFile) let funcDecl = st.importedGlobalFuncs.first { $0.name == "callMeMore" }! @@ -247,7 +247,7 @@ final class FuncCallbackImportTests { let st = Swift2JavaTranslator(config: config) st.log.logLevel = .error - try st.analyze(file: "Fake.swift", text: Self.class_interfaceFile) + try st.analyze(path: "Fake.swift", text: Self.class_interfaceFile) let funcDecl = st.importedGlobalFuncs.first { $0.name == "withBuffer" }! diff --git a/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift b/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift index ff19f4a2..b6ae6f6c 100644 --- a/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift +++ b/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift @@ -239,7 +239,7 @@ extension FunctionDescriptorTests { let st = Swift2JavaTranslator(config: config) st.log.logLevel = logLevel - try st.analyze(file: "/fake/Sample.swiftinterface", text: interfaceFile) + try st.analyze(path: "/fake/Sample.swiftinterface", text: interfaceFile) let funcDecl = st.importedGlobalFuncs.first { $0.name == methodIdentifier @@ -273,7 +273,7 @@ extension FunctionDescriptorTests { let st = Swift2JavaTranslator(config: config) st.log.logLevel = logLevel - try st.analyze(file: "/fake/Sample.swiftinterface", text: interfaceFile) + try st.analyze(path: "/fake/Sample.swiftinterface", text: interfaceFile) let generator = FFMSwift2JavaGenerator( config: config, diff --git a/Tests/JExtractSwiftTests/MethodImportTests.swift b/Tests/JExtractSwiftTests/MethodImportTests.swift index 938b5e7f..6ba93016 100644 --- a/Tests/JExtractSwiftTests/MethodImportTests.swift +++ b/Tests/JExtractSwiftTests/MethodImportTests.swift @@ -70,7 +70,7 @@ final class MethodImportTests { let st = Swift2JavaTranslator(config: config) st.log.logLevel = .error - try st.analyze(file: "Fake.swift", text: class_interfaceFile) + try st.analyze(path: "Fake.swift", text: class_interfaceFile) let generator = FFMSwift2JavaGenerator( config: config, @@ -110,7 +110,7 @@ final class MethodImportTests { let st = Swift2JavaTranslator(config: config) st.log.logLevel = .error - try st.analyze(file: "Fake.swift", text: class_interfaceFile) + try st.analyze(path: "Fake.swift", text: class_interfaceFile) let funcDecl = st.importedGlobalFuncs.first { $0.name == "globalTakeInt" @@ -152,7 +152,7 @@ final class MethodImportTests { let st = Swift2JavaTranslator(config: config) st.log.logLevel = .error - try st.analyze(file: "Fake.swift", text: class_interfaceFile) + try st.analyze(path: "Fake.swift", text: class_interfaceFile) let funcDecl = st.importedGlobalFuncs.first { $0.name == "globalTakeIntLongString" @@ -196,7 +196,7 @@ final class MethodImportTests { let st = Swift2JavaTranslator(config: config) st.log.logLevel = .error - try st.analyze(file: "Fake.swift", text: class_interfaceFile) + try st.analyze(path: "Fake.swift", text: class_interfaceFile) let funcDecl = st.importedGlobalFuncs.first { $0.name == "globalReturnClass" @@ -240,7 +240,7 @@ final class MethodImportTests { let st = Swift2JavaTranslator(config: config) st.log.logLevel = .error - try st.analyze(file: "Fake.swift", text: class_interfaceFile) + try st.analyze(path: "Fake.swift", text: class_interfaceFile) let funcDecl = st.importedGlobalFuncs.first { $0.name == "swapRawBufferPointer" @@ -287,7 +287,7 @@ final class MethodImportTests { let st = Swift2JavaTranslator(config: config) st.log.logLevel = .error - try st.analyze(file: "Fake.swift", text: class_interfaceFile) + try st.analyze(path: "Fake.swift", text: class_interfaceFile) let funcDecl: ImportedFunc = st.importedTypes["MySwiftClass"]!.methods.first { $0.name == "helloMemberFunction" @@ -330,7 +330,7 @@ final class MethodImportTests { let st = Swift2JavaTranslator(config: config) st.log.logLevel = .info - try st.analyze(file: "Fake.swift", text: class_interfaceFile) + try st.analyze(path: "Fake.swift", text: class_interfaceFile) let funcDecl: ImportedFunc = st.importedTypes["MySwiftClass"]!.methods.first { $0.name == "makeInt" @@ -373,7 +373,7 @@ final class MethodImportTests { let st = Swift2JavaTranslator(config: config) st.log.logLevel = .info - try st.analyze(file: "Fake.swift", text: class_interfaceFile) + try st.analyze(path: "Fake.swift", text: class_interfaceFile) let initDecl: ImportedFunc = st.importedTypes["MySwiftClass"]!.initializers.first { $0.name == "init" @@ -418,7 +418,7 @@ final class MethodImportTests { st.log.logLevel = .info - try st.analyze(file: "Fake.swift", text: class_interfaceFile) + try st.analyze(path: "Fake.swift", text: class_interfaceFile) let initDecl: ImportedFunc = st.importedTypes["MySwiftStruct"]!.initializers.first { $0.name == "init" diff --git a/Tests/JExtractSwiftTests/SwiftSymbolTableTests.swift b/Tests/JExtractSwiftTests/SwiftSymbolTableTests.swift index fdbf2d5f..b437454c 100644 --- a/Tests/JExtractSwiftTests/SwiftSymbolTableTests.swift +++ b/Tests/JExtractSwiftTests/SwiftSymbolTableTests.swift @@ -34,7 +34,10 @@ struct SwiftSymbolTableSuite { """ let symbolTable = SwiftSymbolTable.setup( moduleName: "MyModule", - [sourceFile1, sourceFile2], + [ + .init(syntax: sourceFile1, path: "Fake.swift"), + .init(syntax: sourceFile2, path: "Fake2.swift") + ], log: Logger(label: "swift-java", logLevel: .critical) ) From 8560a5b0048ba09f4b2d974daafd9c8c2617fa5a Mon Sep 17 00:00:00 2001 From: Mads Odgaard Date: Fri, 31 Oct 2025 16:07:32 +0100 Subject: [PATCH 379/426] [JExtract/JNI] Add support for `async` Swift methods (#413) --- .github/workflows/pull_request.yml | 20 +- Package.swift | 31 +- README.md | 12 +- .../SwiftAndJavaJarSampleLib/Package.swift | 2 +- .../Package.swift | 2 +- .../Package.swift | 4 +- .../Sources/MySwiftLibrary/Async.swift | 38 ++ .../Sources/MySwiftLibrary/MySwiftError.swift | 17 + .../Sources/MySwiftLibrary/Optionals.swift | 4 + .../com/example/swift/AsyncBenchmark.java | 60 +++ .../java/com/example/swift/AsyncTest.java | 77 ++++ .../com/example/swift/MySwiftClassTest.java | 8 + .../java/com/example/swift/OptionalsTest.java | 13 +- .../Convenience/JavaType+Extensions.swift | 28 +- .../Convenience/SwiftSyntax+Extensions.swift | 4 +- ...t2JavaGenerator+JavaBindingsPrinting.swift | 2 +- ...ift2JavaGenerator+SwiftThunkPrinting.swift | 4 +- .../FFM/FFMSwift2JavaGenerator.swift | 4 +- Sources/JExtractSwiftLib/ImportedDecls.swift | 4 + ...t2JavaGenerator+JavaBindingsPrinting.swift | 5 +- ...ISwift2JavaGenerator+JavaTranslation.swift | 97 ++++- ...wift2JavaGenerator+NativeTranslation.swift | 141 +++++-- ...ift2JavaGenerator+SwiftThunkPrinting.swift | 48 ++- Sources/JExtractSwiftLib/JavaParameter.swift | 1 + .../JavaTypes/JavaType+JDK.swift | 5 + .../SwiftTypes/SwiftEffectSpecifier.swift | 1 + .../SwiftTypes/SwiftFunctionSignature.swift | 14 +- .../SwiftTypes/SwiftType.swift | 2 +- .../SwiftTypes/SwiftTypeLookupContext.swift | 16 +- Sources/JavaTypes/JavaType+JNI.swift | 6 +- Sources/JavaTypes/JavaType+JavaSource.swift | 14 +- Sources/JavaTypes/JavaType+SwiftNames.swift | 6 +- Sources/JavaTypes/JavaType.swift | 2 +- Sources/JavaTypes/Mangling.swift | 2 +- .../Configuration.swift | 6 + .../JExtract/JExtractAsyncFuncMode.swift | 33 ++ .../JExtract/JExtractGenerationMode.swift | 22 ++ .../JExtractMemoryManagementMode.swift | 34 ++ .../JExtractMinimumAccessLevelMode.swift | 26 ++ .../JExtractUnsignedIntegerMode.swift} | 45 +-- .../Documentation.docc/SupportedFeatures.md | 21 +- .../DefaultCaches.swift | 67 ++++ .../_JNIBoxedConversions.swift | 105 ++++++ .../_JNIMethodIDCache.swift | 21 +- .../Commands/JExtractCommand.swift | 5 + .../SwiftRuntimeFunctions.swift} | 0 SwiftKitCore/build.gradle | 6 +- .../core/ConfinedSwiftMemorySession.java | 13 +- .../org/swift/swiftkit/core/SwiftArena.java | 2 +- .../swift/swiftkit/core/SwiftLibraries.java | 12 +- SwiftKitFFM/build.gradle | 6 +- .../swiftkit/ffm/AllocatingSwiftArena.java | 2 +- .../ffm/FFMConfinedSwiftMemorySession.java | 4 +- .../org/swift/swiftkit/ffm/SwiftRuntime.java | 10 +- .../JNI/JNIAsyncTests.swift | 348 ++++++++++++++++++ .../JNI/JNIClassTests.swift | 20 +- .../JNI/JNIClosureTests.swift | 14 +- .../JExtractSwiftTests/JNI/JNIEnumTests.swift | 14 +- .../JNI/JNIJavaKitTests.swift | 2 +- .../JNI/JNIModuleTests.swift | 8 +- .../JNI/JNIOptionalTests.swift | 14 +- .../JNI/JNIProtocolTests.swift | 16 +- .../JNI/JNIStructTests.swift | 8 +- .../JNI/JNIVariablesTests.swift | 22 +- 64 files changed, 1338 insertions(+), 262 deletions(-) create mode 100644 Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/Async.swift create mode 100644 Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftError.swift create mode 100644 Samples/SwiftJavaExtractJNISampleApp/src/jmh/java/com/example/swift/AsyncBenchmark.java create mode 100644 Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/AsyncTest.java create mode 100644 Sources/SwiftJavaConfigurationShared/JExtract/JExtractAsyncFuncMode.swift create mode 100644 Sources/SwiftJavaConfigurationShared/JExtract/JExtractGenerationMode.swift create mode 100644 Sources/SwiftJavaConfigurationShared/JExtract/JExtractMemoryManagementMode.swift create mode 100644 Sources/SwiftJavaConfigurationShared/JExtract/JExtractMinimumAccessLevelMode.swift rename Sources/SwiftJavaConfigurationShared/{GenerationMode.swift => JExtract/JExtractUnsignedIntegerMode.swift} (68%) create mode 100644 Sources/SwiftJavaRuntimeSupport/DefaultCaches.swift create mode 100644 Sources/SwiftJavaRuntimeSupport/_JNIBoxedConversions.swift rename Sources/{SwiftJava/Helpers => SwiftJavaRuntimeSupport}/_JNIMethodIDCache.swift (67%) rename Sources/{SwiftKitSwift/SwiftKit.swift => SwiftRuntimeFunctions/SwiftRuntimeFunctions.swift} (100%) create mode 100644 Tests/JExtractSwiftTests/JNI/JNIAsyncTests.swift diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index f2a1db71..5e5b767a 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -26,11 +26,11 @@ jobs: name: Documentation check runs-on: ubuntu-latest container: - image: 'swift:6.1-noble' + image: 'swift:6.2-noble' strategy: fail-fast: true matrix: - swift_version: ['6.1.3'] + swift_version: ['6.2'] os_version: ['jammy'] jdk_vendor: ['corretto'] steps: @@ -48,7 +48,7 @@ jobs: strategy: fail-fast: true matrix: - swift_version: ['6.1.3', 'nightly'] + swift_version: ['6.2', 'nightly'] os_version: ['jammy'] jdk_vendor: ['corretto'] container: @@ -74,7 +74,7 @@ jobs: strategy: fail-fast: true matrix: - swift_version: ['6.2.0'] + swift_version: ['6.2'] os_version: ['macos'] jdk_vendor: ['corretto'] env: @@ -98,7 +98,7 @@ jobs: strategy: fail-fast: true matrix: - swift_version: ['6.2.0'] + swift_version: ['6.2'] os_version: ['jammy'] jdk_vendor: ['corretto'] container: @@ -118,7 +118,7 @@ jobs: strategy: fail-fast: true matrix: - swift_version: ['6.2.0'] + swift_version: ['6.2'] os_version: ['jammy'] jdk_vendor: ['corretto'] container: @@ -140,7 +140,7 @@ jobs: strategy: fail-fast: false matrix: - swift_version: ['6.1.3', 'nightly'] + swift_version: ['6.2', 'nightly'] os_version: ['jammy'] jdk_vendor: ['corretto'] container: @@ -162,7 +162,7 @@ jobs: strategy: fail-fast: false matrix: - swift_version: ['6.2.0'] + swift_version: ['6.2'] os_version: ['macos'] jdk_vendor: ['corretto'] env: @@ -182,7 +182,7 @@ jobs: strategy: fail-fast: false matrix: - swift_version: ['6.1.3', 'nightly'] + swift_version: ['6.2', 'nightly'] os_version: ['jammy'] jdk_vendor: ['corretto'] sample_app: [ # TODO: use a reusable-workflow to generate those names @@ -210,7 +210,7 @@ jobs: strategy: fail-fast: false matrix: - swift_version: ['6.2.0'] # no nightly testing on macOS + swift_version: ['6.2'] # no nightly testing on macOS os_version: ['macos'] jdk_vendor: ['corretto'] sample_app: [ # TODO: use a reusable-workflow to generate those names diff --git a/Package.swift b/Package.swift index f6cc83e7..09743135 100644 --- a/Package.swift +++ b/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version: 6.0 +// swift-tools-version: 6.2 // The swift-tools-version declares the minimum version of Swift required to build this package. import CompilerPluginSupport @@ -169,9 +169,14 @@ let package = Package( // Support library written in Swift for SwiftKit "Java" .library( - name: "SwiftKitSwift", + name: "SwiftJavaRuntimeSupport", + targets: ["SwiftJavaRuntimeSupport"] + ), + + .library( + name: "SwiftRuntimeFunctions", type: .dynamic, - targets: ["SwiftKitSwift"] + targets: ["SwiftRuntimeFunctions"] ), .library( @@ -197,7 +202,7 @@ let package = Package( ], dependencies: [ - .package(url: "https://github.com/swiftlang/swift-syntax", from: "601.0.1"), + .package(url: "https://github.com/swiftlang/swift-syntax", from: "602.0.0"), .package(url: "https://github.com/apple/swift-argument-parser", from: "1.5.0"), .package(url: "https://github.com/apple/swift-system", from: "1.4.0"), @@ -213,7 +218,8 @@ let package = Package( name: "SwiftJavaDocumentation", dependencies: [ "SwiftJava", - "SwiftKitSwift", + "SwiftJavaRuntimeSupport", + "SwiftRuntimeFunctions", ] ), @@ -351,8 +357,19 @@ let package = Package( ] ), .target( - name: "SwiftKitSwift", - dependencies: [], + name: "SwiftJavaRuntimeSupport", + dependencies: [ + "CSwiftJavaJNI", + "SwiftJava" + ], + swiftSettings: [ + .swiftLanguageMode(.v5), + .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) + ] + ), + + .target( + name: "SwiftRuntimeFunctions", swiftSettings: [ .swiftLanguageMode(.v5), .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) diff --git a/README.md b/README.md index 2688f288..6f9a5fde 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,7 @@ It is possible to generate Swift bindings to Java libraries using SwiftJava by u Required language/runtime versions: - **JDK 17+**, any recent JDK installation should be sufficient, as only general reflection and JNI APIs are used by this integratio -- **Swift 6.0.x**, because the library uses modern Swift macros +- **Swift 6.2.x**, because the library uses modern Swift macros **swift-java jextract** @@ -73,7 +73,7 @@ This does require the use of the relatively recent [JEP-454: Foreign Function & This is the primary way we envision calling Swift code from server-side Java libraries and applications. Required language/runtime versions: -- **Swift 6.1**, because of dependence on rich swift interface files +- **Swift 6.2**, because of dependence on rich swift interface files - **JDK 25+** - We are validating the implementation using the currently supported non-LTE release, which at present means JDK-25. @@ -85,7 +85,7 @@ This mode is more limited in some performance and flexibility that it can offer, We recommend this mode when FFM is not available, or wide ranging deployment compatibility is your priority. When performance is paramaunt, we recommend the FFM mode instead. Required language/runtime versions: -- **Swift 6.1**, because of dependence on rich swift interface files +- **Swift 6.2**, because of dependence on rich swift interface files - **Java 7+**, including @@ -94,7 +94,7 @@ Required language/runtime versions: This project contains multiple builds, living side by side together. You will need to have: -- Swift (6.1.x+) +- Swift (6.2.x+) - Java (25+ for FFM, even though we support lower JDK targets) - Gradle (installed by "Gradle wrapper" automatically when you run gradle through `./gradlew`) @@ -104,7 +104,7 @@ Install **Swift**, the easiest way to do this is to use **Swiftly**: [swift.org/ This should automatically install a recent Swift, but you can always make sure by running: ```bash -swiftly install 6.1.2 --use +swiftly install 6.2 --use ``` Install a recent enough Java distribution. We validate this project using Corretto so you can choose to use that as well, @@ -229,4 +229,4 @@ xcrun docc preview Sources/SwiftJavaDocumentation/Documentation.docc **This project is under active development. We welcome feedback about any issues you encounter.** -There is no guarantee about API stability until the project reaches a 1.0 release. \ No newline at end of file +There is no guarantee about API stability until the project reaches a 1.0 release. diff --git a/Samples/SwiftAndJavaJarSampleLib/Package.swift b/Samples/SwiftAndJavaJarSampleLib/Package.swift index c350a0e7..32ffbb28 100644 --- a/Samples/SwiftAndJavaJarSampleLib/Package.swift +++ b/Samples/SwiftAndJavaJarSampleLib/Package.swift @@ -63,7 +63,7 @@ let package = Package( .target( name: "MySwiftLibrary", dependencies: [ - .product(name: "SwiftKitSwift", package: "swift-java"), + .product(name: "SwiftRuntimeFunctions", package: "swift-java"), ], exclude: [ "swift-java.config", diff --git a/Samples/SwiftJavaExtractFFMSampleApp/Package.swift b/Samples/SwiftJavaExtractFFMSampleApp/Package.swift index b9765c24..98d1bd33 100644 --- a/Samples/SwiftJavaExtractFFMSampleApp/Package.swift +++ b/Samples/SwiftJavaExtractFFMSampleApp/Package.swift @@ -65,7 +65,7 @@ let package = Package( dependencies: [ .product(name: "SwiftJava", package: "swift-java"), .product(name: "CSwiftJavaJNI", package: "swift-java"), - .product(name: "SwiftKitSwift", package: "swift-java"), + .product(name: "SwiftRuntimeFunctions", package: "swift-java"), ], exclude: [ "swift-java.config", diff --git a/Samples/SwiftJavaExtractJNISampleApp/Package.swift b/Samples/SwiftJavaExtractJNISampleApp/Package.swift index c7d5d717..33a35c49 100644 --- a/Samples/SwiftJavaExtractJNISampleApp/Package.swift +++ b/Samples/SwiftJavaExtractJNISampleApp/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version: 6.0 +// swift-tools-version: 6.2 // The swift-tools-version declares the minimum version of Swift required to build this package. import CompilerPluginSupport @@ -62,7 +62,7 @@ let package = Package( dependencies: [ .product(name: "SwiftJava", package: "swift-java"), .product(name: "CSwiftJavaJNI", package: "swift-java"), - .product(name: "SwiftKitSwift", package: "swift-java"), + .product(name: "SwiftJavaRuntimeSupport", package: "swift-java"), ], exclude: [ "swift-java.config" diff --git a/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/Async.swift b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/Async.swift new file mode 100644 index 00000000..ebef1892 --- /dev/null +++ b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/Async.swift @@ -0,0 +1,38 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import SwiftJava + +public func asyncSum(i1: Int64, i2: Int64) async -> Int64 { + return i1 + i2 +} + +public func asyncSleep() async throws { + try await Task.sleep(for: .milliseconds(500)) +} + +public func asyncCopy(myClass: MySwiftClass) async throws -> MySwiftClass { + let new = MySwiftClass(x: myClass.x, y: myClass.y) + try await Task.sleep(for: .milliseconds(500)) + return new +} + +public func asyncOptional(i: Int64) async throws -> Int64? { + try await Task.sleep(for: .milliseconds(100)) + return i +} + +public func asyncThrows() async throws { + throw MySwiftError.swiftError +} diff --git a/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftError.swift b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftError.swift new file mode 100644 index 00000000..d9d77d38 --- /dev/null +++ b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftError.swift @@ -0,0 +1,17 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +enum MySwiftError: Error { + case swiftError +} diff --git a/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/Optionals.swift b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/Optionals.swift index 3e122102..ca1d7458 100644 --- a/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/Optionals.swift +++ b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/Optionals.swift @@ -62,6 +62,10 @@ public func optionalJavaKitLong(input: Optional) -> Int64? { } } +public func optionalThrowing() throws -> Int64? { + throw MySwiftError.swiftError +} + public func multipleOptionals( input1: Optional, input2: Optional, diff --git a/Samples/SwiftJavaExtractJNISampleApp/src/jmh/java/com/example/swift/AsyncBenchmark.java b/Samples/SwiftJavaExtractJNISampleApp/src/jmh/java/com/example/swift/AsyncBenchmark.java new file mode 100644 index 00000000..9cc74246 --- /dev/null +++ b/Samples/SwiftJavaExtractJNISampleApp/src/jmh/java/com/example/swift/AsyncBenchmark.java @@ -0,0 +1,60 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package com.example.swift; + +import org.openjdk.jmh.annotations.*; +import org.openjdk.jmh.infra.Blackhole; +import org.swift.swiftkit.core.ClosableSwiftArena; +import org.swift.swiftkit.core.ConfinedSwiftMemorySession; +import org.swift.swiftkit.core.SwiftArena; + +import java.util.*; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.AverageTime) +@Warmup(iterations = 5, time = 200, timeUnit = TimeUnit.MILLISECONDS) +@Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) +@OutputTimeUnit(TimeUnit.MICROSECONDS) +@State(Scope.Benchmark) +@Fork(value = 1, jvmArgsAppend = { "--enable-native-access=ALL-UNNAMED" }) +public class AsyncBenchmark { + /** + * Parameter for the number of parallel tasks to launch. + */ + @Param({"100", "500", "1000"}) + public int taskCount; + + @Setup(Level.Trial) + public void beforeAll() {} + + @TearDown(Level.Trial) + public void afterAll() {} + + @Benchmark + public void asyncSum(Blackhole bh) { + CompletableFuture[] futures = new CompletableFuture[taskCount]; + + // Launch all tasks in parallel using supplyAsync on our custom executor + for (int i = 0; i < taskCount; i++) { + futures[i] = MySwiftLibrary.asyncSum(10, 5).thenAccept(bh::consume); + } + + // Wait for all futures to complete. + CompletableFuture.allOf(futures).join(); + } +} \ No newline at end of file diff --git a/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/AsyncTest.java b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/AsyncTest.java new file mode 100644 index 00000000..ae6e7cc7 --- /dev/null +++ b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/AsyncTest.java @@ -0,0 +1,77 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package com.example.swift; + +import com.example.swift.MySwiftClass; +import com.example.swift.MySwiftLibrary; +import org.junit.jupiter.api.Test; +import org.swift.swiftkit.core.SwiftArena; + +import java.time.Duration; +import java.util.Optional; +import java.util.OptionalDouble; +import java.util.OptionalInt; +import java.util.OptionalLong; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; + +import static org.junit.jupiter.api.Assertions.*; + +public class AsyncTest { + @Test + void asyncSum() { + CompletableFuture future = MySwiftLibrary.asyncSum(10, 12); + + Long result = future.join(); + assertEquals(22, result); + } + + @Test + void asyncSleep() { + CompletableFuture future = MySwiftLibrary.asyncSleep(); + future.join(); + } + + @Test + void asyncCopy() { + try (var arena = SwiftArena.ofConfined()) { + MySwiftClass obj = MySwiftClass.init(10, 5, arena); + CompletableFuture future = MySwiftLibrary.asyncCopy(obj, arena); + + MySwiftClass result = future.join(); + + assertEquals(10, result.getX()); + assertEquals(5, result.getY()); + } + } + + @Test + void asyncThrows() { + CompletableFuture future = MySwiftLibrary.asyncThrows(); + + ExecutionException ex = assertThrows(ExecutionException.class, future::get); + + Throwable cause = ex.getCause(); + assertNotNull(cause); + assertEquals(Exception.class, cause.getClass()); + assertEquals("swiftError", cause.getMessage()); + } + + @Test + void asyncOptional() { + CompletableFuture future = MySwiftLibrary.asyncOptional(42); + assertEquals(OptionalLong.of(42), future.join()); + } +} \ No newline at end of file diff --git a/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/MySwiftClassTest.java b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/MySwiftClassTest.java index 2e9a7e62..fba8f13f 100644 --- a/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/MySwiftClassTest.java +++ b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/MySwiftClassTest.java @@ -152,4 +152,12 @@ void addXWithJavaLong() { assertEquals(70, c1.addXWithJavaLong(javaLong)); } } + + @Test + void getAsyncVariable() { + try (var arena = SwiftArena.ofConfined()) { + MySwiftClass c1 = MySwiftClass.init(20, 10, arena); + assertEquals(42, c1.getGetAsync().join()); + } + } } \ No newline at end of file diff --git a/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/OptionalsTest.java b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/OptionalsTest.java index d60ff6d5..d26de1d1 100644 --- a/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/OptionalsTest.java +++ b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/OptionalsTest.java @@ -14,6 +14,7 @@ package com.example.swift; +import com.example.swift.MySwiftLibrary; import org.junit.jupiter.api.Test; import org.swift.swiftkit.core.SwiftArena; @@ -22,8 +23,7 @@ import java.util.OptionalInt; import java.util.OptionalLong; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.*; public class OptionalsTest { @Test @@ -113,4 +113,13 @@ void multipleOptionals() { assertEquals(result, OptionalLong.of(1L)); } } + + @Test + void optionalThrows() { + try (var arena = SwiftArena.ofConfined()) { + Exception exception = assertThrows(Exception.class, () -> MySwiftLibrary.optionalThrowing()); + + assertEquals("swiftError", exception.getMessage()); + } + } } \ No newline at end of file diff --git a/Sources/JExtractSwiftLib/Convenience/JavaType+Extensions.swift b/Sources/JExtractSwiftLib/Convenience/JavaType+Extensions.swift index cb849e79..3b29fcd3 100644 --- a/Sources/JExtractSwiftLib/Convenience/JavaType+Extensions.swift +++ b/Sources/JExtractSwiftLib/Convenience/JavaType+Extensions.swift @@ -25,7 +25,7 @@ extension JavaType { case .long: return "J" case .float: return "F" case .double: return "D" - case .class(let package, let name): + case .class(let package, let name, _): let nameWithInnerClasses = name.replacingOccurrences(of: ".", with: "$") if let package { return "L\(package.replacingOccurrences(of: ".", with: "/"))/\(nameWithInnerClasses);" @@ -111,4 +111,30 @@ extension JavaType { false } } + + /// Returns the boxed type, or self if the type is already a Java class. + var boxedType: JavaType { + switch self { + case .boolean: + return .class(package: "java.lang", name: "Boolean") + case .byte: + return .class(package: "java.lang", name: "Byte") + case .char: + return .class(package: "java.lang", name: "Character") + case .short: + return .class(package: "java.lang", name: "Short") + case .int: + return .class(package: "java.lang", name: "Integer") + case .long: + return .class(package: "java.lang", name: "Long") + case .float: + return .class(package: "java.lang", name: "Float") + case .double: + return .class(package: "java.lang", name: "Double") + case .void: + return .class(package: "java.lang", name: "Void") + default: + return self + } + } } diff --git a/Sources/JExtractSwiftLib/Convenience/SwiftSyntax+Extensions.swift b/Sources/JExtractSwiftLib/Convenience/SwiftSyntax+Extensions.swift index 8a58f42a..d3902aa4 100644 --- a/Sources/JExtractSwiftLib/Convenience/SwiftSyntax+Extensions.swift +++ b/Sources/JExtractSwiftLib/Convenience/SwiftSyntax+Extensions.swift @@ -13,7 +13,7 @@ //===----------------------------------------------------------------------===// import SwiftDiagnostics -import SwiftSyntax +@_spi(ExperimentalLanguageFeatures) import SwiftSyntax extension WithModifiersSyntax { var accessControlModifiers: DeclModifierListSyntax { @@ -218,6 +218,8 @@ extension DeclSyntaxProtocol { } else { "var" } + case .usingDecl(let node): + node.nameForDebug } } diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift index 188f5e8b..a4485fff 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift @@ -453,7 +453,7 @@ extension FFMSwift2JavaGenerator { func renderMemoryLayoutValue(for javaType: JavaType) -> String { if let layout = ForeignValueLayout(javaType: javaType) { return layout.description - } else if case .class(package: _, name: let customClass) = javaType { + } else if case .class(package: _, name: let customClass, _) = javaType { return ForeignValueLayout(customType: customClass).description } else { fatalError("renderMemoryLayoutValue not supported for \(javaType)") diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+SwiftThunkPrinting.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+SwiftThunkPrinting.swift index 5ef266c8..f233ef00 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+SwiftThunkPrinting.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+SwiftThunkPrinting.swift @@ -108,7 +108,7 @@ extension FFMSwift2JavaGenerator { """ // Generated by swift-java - import SwiftKitSwift + import SwiftRuntimeFunctions """) @@ -136,7 +136,7 @@ extension FFMSwift2JavaGenerator { """ // Generated by swift-java - import SwiftKitSwift + import SwiftRuntimeFunctions """ ) diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift index f9ba88b9..c445d5c9 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift @@ -189,7 +189,7 @@ extension FFMSwift2JavaGenerator { private static final boolean INITIALIZED_LIBS = initializeLibs(); static boolean initializeLibs() { System.loadLibrary(SwiftLibraries.LIB_NAME_SWIFT_CORE); - System.loadLibrary(SwiftLibraries.LIB_NAME_SWIFTKITSWIFT); + System.loadLibrary(SwiftLibraries.LIB_NAME_SWIFT_RUNTIME_FUNCTIONS); System.loadLibrary(LIB_NAME); return true; } @@ -339,7 +339,7 @@ extension FFMSwift2JavaGenerator { private static SymbolLookup getSymbolLookup() { if (SwiftLibraries.AUTO_LOAD_LIBS) { System.loadLibrary(SwiftLibraries.LIB_NAME_SWIFT_CORE); - System.loadLibrary(SwiftLibraries.LIB_NAME_SWIFTKITSWIFT); + System.loadLibrary(SwiftLibraries.LIB_NAME_SWIFT_RUNTIME_FUNCTIONS); System.loadLibrary(LIB_NAME); } diff --git a/Sources/JExtractSwiftLib/ImportedDecls.swift b/Sources/JExtractSwiftLib/ImportedDecls.swift index 1f0d3efc..84cc43c0 100644 --- a/Sources/JExtractSwiftLib/ImportedDecls.swift +++ b/Sources/JExtractSwiftLib/ImportedDecls.swift @@ -192,6 +192,10 @@ public final class ImportedFunc: ImportedDecl, CustomStringConvertible { self.functionSignature.effectSpecifiers.contains(.throws) } + var isAsync: Bool { + self.functionSignature.isAsync + } + init( module: String, swiftDecl: any DeclSyntaxProtocol, diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift index 258b537e..ce6ec18e 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift @@ -429,7 +429,7 @@ extension JNISwift2JavaGenerator { let translatedSignature = translatedDecl.translatedFunctionSignature let resultType = translatedSignature.resultType.javaType var parameters = translatedDecl.translatedFunctionSignature.parameters.map { $0.parameter.renderParameter() } - let throwsClause = translatedDecl.isThrowing ? " throws Exception" : "" + let throwsClause = translatedDecl.isThrowing && !translatedDecl.isAsync ? " throws Exception" : "" let generics = translatedDecl.translatedFunctionSignature.parameters.reduce(into: [(String, [JavaType])]()) { generics, parameter in guard case .generic(let name, let extends) = parameter.parameter.type else { @@ -483,7 +483,6 @@ extension JNISwift2JavaGenerator { printNativeFunction(&printer, translatedDecl) } - } private func printNativeFunction(_ printer: inout CodePrinter, _ translatedDecl: TranslatedFunctionDecl) { @@ -523,7 +522,7 @@ extension JNISwift2JavaGenerator { // Indirect return receivers for outParameter in translatedFunctionSignature.resultType.outParameters { - printer.print("\(outParameter.type) \(outParameter.name) = \(outParameter.allocation.render());") + printer.print("\(outParameter.type) \(outParameter.name) = \(outParameter.allocation.render(type: outParameter.type));") arguments.append(outParameter.name) } diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift index a0178d3c..56174e3e 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift @@ -118,6 +118,7 @@ extension JNISwift2JavaGenerator { name: getAsCaseName, isStatic: false, isThrowing: false, + isAsync: false, nativeFunctionName: "$\(getAsCaseName)", parentName: enumName, functionTypes: [], @@ -181,13 +182,13 @@ extension JNISwift2JavaGenerator { } // Swift -> Java - let translatedFunctionSignature = try translate( + var translatedFunctionSignature = try translate( functionSignature: decl.functionSignature, methodName: javaName, parentName: parentName ) // Java -> Java (native) - let nativeFunctionSignature = try nativeTranslation.translate( + var nativeFunctionSignature = try nativeTranslation.translate( functionSignature: decl.functionSignature, translatedFunctionSignature: translatedFunctionSignature, methodName: javaName, @@ -212,10 +213,21 @@ extension JNISwift2JavaGenerator { } } + // Handle async methods + if decl.functionSignature.isAsync { + self.convertToAsync( + translatedFunctionSignature: &translatedFunctionSignature, + nativeFunctionSignature: &nativeFunctionSignature, + originalFunctionSignature: decl.functionSignature, + mode: config.effectiveAsyncFuncMode + ) + } + return TranslatedFunctionDecl( name: javaName, isStatic: decl.isStatic || !decl.hasParent || decl.isInitializer, isThrowing: decl.isThrowing, + isAsync: decl.isAsync, nativeFunctionName: "$\(javaName)", parentName: parentName, functionTypes: funcTypes, @@ -470,6 +482,50 @@ extension JNISwift2JavaGenerator { } } + func convertToAsync( + translatedFunctionSignature: inout TranslatedFunctionSignature, + nativeFunctionSignature: inout NativeFunctionSignature, + originalFunctionSignature: SwiftFunctionSignature, + mode: JExtractAsyncFuncMode + ) { + switch mode { + case .completableFuture: + // Update translated function + + let nativeFutureType = JavaType.completableFuture(nativeFunctionSignature.result.javaType) + + let futureOutParameter = OutParameter( + name: "$future", + type: nativeFutureType, + allocation: .new + ) + + let result = translatedFunctionSignature.resultType + translatedFunctionSignature.resultType = TranslatedResult( + javaType: .completableFuture(translatedFunctionSignature.resultType.javaType), + annotations: result.annotations, + outParameters: result.outParameters + [futureOutParameter], + conversion: .aggregate(variable: nil, [ + .print(.placeholder), // Make the downcall + .method(.constant("$future"), function: "thenApply", arguments: [ + .lambda(args: ["futureResult$"], body: .replacingPlaceholder(result.conversion, placeholder: "futureResult$")) + ]) + ]) + ) + + // Update native function + nativeFunctionSignature.result.javaType = .void + nativeFunctionSignature.result.conversion = .asyncCompleteFuture( + nativeFunctionSignature.result.conversion, + swiftFunctionResultType: originalFunctionSignature.result.type, + nativeReturnType: nativeFunctionSignature.result.javaType, + outParameters: nativeFunctionSignature.result.outParameters, + isThrowing: originalFunctionSignature.isThrowing + ) + nativeFunctionSignature.result.outParameters.append(.init(name: "result_future", type: nativeFutureType)) + } + } + func translateProtocolParameter( protocolType: SwiftType, parameterName: String, @@ -753,6 +809,8 @@ extension JNISwift2JavaGenerator { let isThrowing: Bool + let isAsync: Bool + /// The name of the native function let nativeFunctionName: String @@ -812,11 +870,15 @@ extension JNISwift2JavaGenerator { struct OutParameter { enum Allocation { case newArray(JavaType, size: Int) + case new - func render() -> String { + func render(type: JavaType) -> String { switch self { case .newArray(let javaType, let size): "new \(javaType)[\(size)]" + + case .new: + "new \(type)()" } } } @@ -912,6 +974,12 @@ extension JNISwift2JavaGenerator { /// Access a member of the value indirect case replacingPlaceholder(JavaNativeConversionStep, placeholder: String) + /// `(args) -> { return body; }` + indirect case lambda(args: [String] = [], body: JavaNativeConversionStep) + + /// Prints the conversion step, ignoring the output. + indirect case print(JavaNativeConversionStep) + /// Returns the conversion string applied to the placeholder. func render(_ printer: inout CodePrinter, _ placeholder: String) -> String { // NOTE: 'printer' is used if the conversion wants to cause side-effects. @@ -1024,6 +1092,23 @@ extension JNISwift2JavaGenerator { case .replacingPlaceholder(let inner, let placeholder): return inner.render(&printer, placeholder) + + case .lambda(let args, let body): + var printer = CodePrinter() + printer.printBraceBlock("(\(args.joined(separator: ", "))) ->") { printer in + let body = body.render(&printer, placeholder) + if !body.isEmpty { + printer.print("return \(body);") + } else { + printer.print("return;") + } + } + return printer.finalize() + + case .print(let inner): + let inner = inner.render(&printer, placeholder) + printer.print("\(inner);") + return "" } } @@ -1074,6 +1159,12 @@ extension JNISwift2JavaGenerator { case .replacingPlaceholder(let inner, _): return inner.requiresSwiftArena + + case .lambda(_, let body): + return body.requiresSwiftArena + + case .print(let inner): + return inner.requiresSwiftArena } } } diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift index bdbfe2f1..45208d7b 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift @@ -59,34 +59,15 @@ extension JNISwift2JavaGenerator { nil } - return try NativeFunctionSignature( + let result = try translate(swiftResult: functionSignature.result) + + return NativeFunctionSignature( selfParameter: nativeSelf, parameters: parameters, - result: translate(swiftResult: functionSignature.result) + result: result ) } - func translateParameters( - _ parameters: [SwiftParameter], - translatedParameters: [TranslatedParameter], - methodName: String, - parentName: String, - genericParameters: [SwiftGenericParameterDeclaration], - genericRequirements: [SwiftGenericRequirement] - ) throws -> [NativeParameter] { - try zip(translatedParameters, parameters).map { translatedParameter, swiftParameter in - let parameterName = translatedParameter.parameter.name - return try translateParameter( - type: swiftParameter.type, - parameterName: parameterName, - methodName: methodName, - parentName: parentName, - genericParameters: genericParameters, - genericRequirements: genericRequirements - ) - } - } - func translateParameter( type: SwiftType, parameterName: String, @@ -508,8 +489,8 @@ extension JNISwift2JavaGenerator { struct NativeFunctionSignature { let selfParameter: NativeParameter? - let parameters: [NativeParameter] - let result: NativeResult + var parameters: [NativeParameter] + var result: NativeResult } struct NativeParameter { @@ -522,8 +503,8 @@ extension JNISwift2JavaGenerator { } struct NativeResult { - let javaType: JavaType - let conversion: NativeSwiftConversionStep + var javaType: JavaType + var conversion: NativeSwiftConversionStep /// Out parameters for populating the indirect return values. var outParameters: [JavaParameter] @@ -545,7 +526,7 @@ extension JNISwift2JavaGenerator { /// `value.getJValue(in:)` indirect case getJValue(NativeSwiftConversionStep) - /// `SwiftType(from: value, in: environment!)` + /// `SwiftType(from: value, in: environment)` indirect case initFromJNI(NativeSwiftConversionStep, swiftType: SwiftType) indirect case extractSwiftProtocolValue( @@ -588,6 +569,14 @@ extension JNISwift2JavaGenerator { indirect case unwrapOptional(NativeSwiftConversionStep, name: String, fatalErrorMessage: String) + indirect case asyncCompleteFuture( + NativeSwiftConversionStep, + swiftFunctionResultType: SwiftType, + nativeReturnType: JavaType, + outParameters: [JavaParameter], + isThrowing: Bool + ) + /// Returns the conversion string applied to the placeholder. func render(_ printer: inout CodePrinter, _ placeholder: String) -> String { // NOTE: 'printer' is used if the conversion wants to cause side-effects. @@ -604,15 +593,15 @@ extension JNISwift2JavaGenerator { case .getJNIValue(let inner): let inner = inner.render(&printer, placeholder) - return "\(inner).getJNIValue(in: environment!)" + return "\(inner).getJNIValue(in: environment)" case .getJValue(let inner): let inner = inner.render(&printer, placeholder) - return "\(inner).getJValue(in: environment!)" + return "\(inner).getJValue(in: environment)" case .initFromJNI(let inner, let swiftType): let inner = inner.render(&printer, placeholder) - return "\(swiftType)(fromJNI: \(inner), in: environment!)" + return "\(swiftType)(fromJNI: \(inner), in: environment)" case .extractSwiftProtocolValue(let inner, let typeMetadataVariableName, let protocolNames): let inner = inner.render(&printer, placeholder) @@ -624,11 +613,11 @@ extension JNISwift2JavaGenerator { // TODO: Remove the _openExistential when we decide to only support language mode v6+ printer.print( """ - guard let \(inner)TypeMetadataPointer$ = UnsafeRawPointer(bitPattern: Int(Int64(fromJNI: \(typeMetadataVariableName), in: environment!))) else { + guard let \(inner)TypeMetadataPointer$ = UnsafeRawPointer(bitPattern: Int(Int64(fromJNI: \(typeMetadataVariableName), in: environment))) else { fatalError("\(typeMetadataVariableName) memory address was null") } let \(inner)DynamicType$: Any.Type = unsafeBitCast(\(inner)TypeMetadataPointer$, to: Any.Type.self) - guard let \(inner)RawPointer$ = UnsafeMutableRawPointer(bitPattern: Int(Int64(fromJNI: \(inner), in: environment!))) else { + guard let \(inner)RawPointer$ = UnsafeMutableRawPointer(bitPattern: Int(Int64(fromJNI: \(inner), in: environment))) else { fatalError("\(inner) memory address was null") } #if hasFeature(ImplicitOpenExistentials) @@ -651,7 +640,7 @@ extension JNISwift2JavaGenerator { } printer.print( """ - let \(inner)Bits$ = Int(Int64(fromJNI: \(inner), in: environment!)) + let \(inner)Bits$ = Int(Int64(fromJNI: \(inner), in: environment)) let \(pointerName) = UnsafeMutablePointer<\(swiftType)>(bitPattern: \(inner)Bits$) """ ) @@ -709,13 +698,13 @@ extension JNISwift2JavaGenerator { printer.print( """ - let class$ = environment!.interface.GetObjectClass(environment, \(placeholder)) - let methodID$ = environment!.interface.GetMethodID(environment, class$, "apply", "\(methodSignature.mangledName)")! + let class$ = environment.interface.GetObjectClass(environment, \(placeholder)) + let methodID$ = environment.interface.GetMethodID(environment, class$, "apply", "\(methodSignature.mangledName)")! let arguments$: [jvalue] = [\(arguments.joined(separator: ", "))] """ ) - let upcall = "environment!.interface.\(nativeResult.javaType.jniCallMethodAName)(environment, \(placeholder), methodID$, arguments$)" + let upcall = "environment.interface.\(nativeResult.javaType.jniCallMethodAName)(environment, \(placeholder), methodID$, arguments$)" let result = nativeResult.conversion.render(&printer, upcall) if nativeResult.javaType.isVoid { @@ -731,7 +720,7 @@ extension JNISwift2JavaGenerator { case .initializeJavaKitWrapper(let inner, let wrapperName): let inner = inner.render(&printer, placeholder) - return "\(wrapperName)(javaThis: \(inner), environment: environment!)" + return "\(wrapperName)(javaThis: \(inner), environment: environment)" case .optionalLowering(let valueConversion, let discriminatorName, let valueName): let value = valueConversion.render(&printer, valueName) @@ -815,6 +804,82 @@ extension JNISwift2JavaGenerator { """ ) return unwrappedName + + case .asyncCompleteFuture( + let inner, + let swiftFunctionResultType, + let nativeReturnType, + let outParameters, + let isThrowing + ): + // Global ref all indirect returns + for outParameter in outParameters { + printer.print("let \(outParameter.name) = environment.interface.NewGlobalRef(environment, \(outParameter.name))") + } + + printer.print( + """ + let globalFuture = environment.interface.NewGlobalRef(environment, result_future) + """ + ) + + func printDo(printer: inout CodePrinter) { + printer.print("let swiftResult$ = await \(placeholder)") + printer.print("environment = try JavaVirtualMachine.shared().environment()") + let inner = inner.render(&printer, "swiftResult$") + if swiftFunctionResultType.isVoid { + printer.print("environment.interface.CallBooleanMethodA(environment, globalFuture, _JNIMethodIDCache.CompletableFuture.complete, [jvalue(l: nil)])") + } else { + printer.printBraceBlock("withVaList([SwiftJavaRuntimeSupport._JNIBoxedConversions.box(\(inner), in: environment)])") { printer in + printer.print("environment.interface.CallBooleanMethodV(environment, globalFuture, _JNIMethodIDCache.CompletableFuture.complete, $0)") + } + } + } + + func printTask(printer: inout CodePrinter) { + printer.printBraceBlock("defer") { printer in + // Defer might on any thread, so we need to attach environment. + printer.print("let deferEnvironment = try! JavaVirtualMachine.shared().environment()") + printer.print("environment.interface.DeleteGlobalRef(deferEnvironment, globalFuture)") + for outParameter in outParameters { + printer.print("environment.interface.DeleteGlobalRef(deferEnvironment, \(outParameter.name))") + } + } + if isThrowing { + printer.printBraceBlock("do") { printer in + printDo(printer: &printer) + } + printer.printBraceBlock("catch") { printer in + // We might not be on the same thread after the suspension, so we need to attach the thread again. + printer.print( + """ + let catchEnvironment = try! JavaVirtualMachine.shared().environment() + let exception = catchEnvironment.interface.NewObjectA(catchEnvironment, _JNIMethodIDCache.Exception.class, _JNIMethodIDCache.Exception.constructWithMessage, [String(describing: error).getJValue(in: catchEnvironment)]) + catchEnvironment.interface.CallBooleanMethodA(catchEnvironment, globalFuture, _JNIMethodIDCache.CompletableFuture.completeExceptionally, [jvalue(l: exception)]) + """ + ) + } + } else { + printDo(printer: &printer) + } + } + + printer.printBraceBlock("if #available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, *)") { printer in + printer.printBraceBlock("Task.immediate") { printer in + // Immediate runs on the caller thread, so we don't need to attach the environment again. + printer.print("var environment = environment!") // this is to ensure we always use the same environment name, even though we are rebinding it. + printTask(printer: &printer) + } + } + printer.printBraceBlock("else") { printer in + printer.printBraceBlock("Task") { printer in + // We can be on any thread, so we need to attach the thread. + printer.print("var environment = try! JavaVirtualMachine.shared().environment()") + printTask(printer: &printer) + } + } + + return "" } } } diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift index 1d4f81dc..5403ae40 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift @@ -353,29 +353,42 @@ extension JNISwift2JavaGenerator { } // Lower the result. - let innerBody: String - if !decl.functionSignature.result.type.isVoid { + func innerBody(in printer: inout CodePrinter) -> String { let loweredResult = nativeSignature.result.conversion.render(&printer, result) - innerBody = "return \(loweredResult)" - } else { - innerBody = result + + if !decl.functionSignature.result.type.isVoid { + return "return \(loweredResult)" + } else { + return loweredResult + } } - if decl.isThrowing { - // TODO: Handle classes for dummy value - let dummyReturn = !nativeSignature.result.javaType.isVoid ? "return \(decl.functionSignature.result.type).jniPlaceholderValue" : "" + if decl.isThrowing, !decl.isAsync { + let dummyReturn: String + + if nativeSignature.result.javaType.isVoid { + dummyReturn = "" + } else { + // We assume it is something that implements JavaValue + dummyReturn = "return \(nativeSignature.result.javaType.swiftTypeName(resolver: { _ in "" })).jniPlaceholderValue" + } + + printer.print("do {") + printer.indent() + printer.print(innerBody(in: &printer)) + printer.outdent() + printer.print("} catch {") + printer.indent() printer.print( - """ - do { - \(innerBody) - } catch { - environment.throwAsException(error) - \(dummyReturn) - } - """ + """ + environment.throwAsException(error) + \(dummyReturn) + """ ) + printer.outdent() + printer.print("}") } else { - printer.print(innerBody) + printer.print(innerBody(in: &printer)) } } @@ -453,6 +466,7 @@ extension JNISwift2JavaGenerator { import SwiftJava import CSwiftJavaJNI + import SwiftJavaRuntimeSupport """ ) diff --git a/Sources/JExtractSwiftLib/JavaParameter.swift b/Sources/JExtractSwiftLib/JavaParameter.swift index 43f5a2b4..2670e6ee 100644 --- a/Sources/JExtractSwiftLib/JavaParameter.swift +++ b/Sources/JExtractSwiftLib/JavaParameter.swift @@ -24,6 +24,7 @@ struct JavaParameter { switch self { case .concrete(let type): return type.jniTypeSignature + case .generic(_, let extends): guard !extends.isEmpty else { return "Ljava/lang/Object;" diff --git a/Sources/JExtractSwiftLib/JavaTypes/JavaType+JDK.swift b/Sources/JExtractSwiftLib/JavaTypes/JavaType+JDK.swift index 02850801..5e5a7268 100644 --- a/Sources/JExtractSwiftLib/JavaTypes/JavaType+JDK.swift +++ b/Sources/JExtractSwiftLib/JavaTypes/JavaType+JDK.swift @@ -39,4 +39,9 @@ extension JavaType { static var javaLangThrowable: JavaType { .class(package: "java.lang", name: "Throwable") } + + /// The description of the type java.util.concurrent.CompletableFuture + static func completableFuture(_ T: JavaType) -> JavaType { + .class(package: "java.util.concurrent", name: "CompletableFuture", typeParameters: [T.boxedType]) + } } diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftEffectSpecifier.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftEffectSpecifier.swift index 9ba4d7ad..fb28586b 100644 --- a/Sources/JExtractSwiftLib/SwiftTypes/SwiftEffectSpecifier.swift +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftEffectSpecifier.swift @@ -14,4 +14,5 @@ enum SwiftEffectSpecifier: Equatable { case `throws` + case `async` } diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftFunctionSignature.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftFunctionSignature.swift index 7e0f4885..1f2fbd36 100644 --- a/Sources/JExtractSwiftLib/SwiftTypes/SwiftFunctionSignature.swift +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftFunctionSignature.swift @@ -30,6 +30,14 @@ public struct SwiftFunctionSignature: Equatable { var genericParameters: [SwiftGenericParameterDeclaration] var genericRequirements: [SwiftGenericRequirement] + var isAsync: Bool { + effectSpecifiers.contains(.async) + } + + var isThrowing: Bool { + effectSpecifiers.contains(.throws) + } + init( selfParameter: SwiftSelfParameter? = nil, parameters: [SwiftParameter], @@ -245,8 +253,8 @@ extension SwiftFunctionSignature { if signature.effectSpecifiers?.throwsClause != nil { effectSpecifiers.append(.throws) } - if let asyncSpecifier = signature.effectSpecifiers?.asyncSpecifier { - throw SwiftFunctionTranslationError.async(asyncSpecifier) + if signature.effectSpecifiers?.asyncSpecifier != nil { + effectSpecifiers.append(.async) } let parameters = try signature.parameterClause.parameters.map { param in @@ -331,7 +339,7 @@ extension SwiftFunctionSignature { effectSpecifiers.append(.throws) } if let asyncSpecifier = decl.effectSpecifiers?.asyncSpecifier { - throw SwiftFunctionTranslationError.async(asyncSpecifier) + effectSpecifiers.append(.async) } return effectSpecifiers } diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftType.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftType.swift index 81afe637..3840b3e1 100644 --- a/Sources/JExtractSwiftLib/SwiftTypes/SwiftType.swift +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftType.swift @@ -215,7 +215,7 @@ extension SwiftType { switch type.as(TypeSyntaxEnum.self) { case .arrayType, .classRestrictionType, .dictionaryType, .missingType, .namedOpaqueReturnType, - .packElementType, .packExpansionType, .suppressedType: + .packElementType, .packExpansionType, .suppressedType, .inlineArrayType: throw TypeTranslationError.unimplementedType(type) case .attributedType(let attributedType): diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftTypeLookupContext.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftTypeLookupContext.swift index f47669b5..13f42cfc 100644 --- a/Sources/JExtractSwiftLib/SwiftTypes/SwiftTypeLookupContext.swift +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftTypeLookupContext.swift @@ -42,24 +42,19 @@ class SwiftTypeLookupContext { return typeDeclaration(for: names) } - case .fromFileScope(_, let names): - if !names.isEmpty { - return typeDeclaration(for: names) - } - - case .lookInMembers(let scopeNode): + case .lookForMembers(let scopeNode): if let nominalDecl = try typeDeclaration(for: scopeNode, sourceFilePath: "FIXME.swift") { // FIXME: no path here // implement some node -> file if let found = symbolTable.lookupNestedType(name.name, parent: nominalDecl as! SwiftNominalTypeDeclaration) { return found } } - case .lookInGenericParametersOfExtendedType(let extensionNode): + case .lookForGenericParameters(let extensionNode): // TODO: Implement _ = extensionNode break - case .mightIntroduceDollarIdentifiers: + case .lookForImplicitClosureParameters: // Dollar identifier can't be a type, ignore. break } @@ -81,8 +76,9 @@ class SwiftTypeLookupContext { // TODO: Implement _ = implicitDecl break - case .dollarIdentifier: - break + case .equivalentNames(let equivalentNames): + // TODO: Implement + _ = equivalentNames } } return nil diff --git a/Sources/JavaTypes/JavaType+JNI.swift b/Sources/JavaTypes/JavaType+JNI.swift index 08361bac..b9b00ccb 100644 --- a/Sources/JavaTypes/JavaType+JNI.swift +++ b/Sources/JavaTypes/JavaType+JNI.swift @@ -34,9 +34,9 @@ extension JavaType { case .array(.float): "jfloatArray?" case .array(.double): "jdoubleArray?" case .array: "jobjectArray?" - case .class(package: "java.lang", name: "String"): "jstring?" - case .class(package: "java.lang", name: "Class"): "jclass?" - case .class(package: "java.lang", name: "Throwable"): "jthrowable?" + case .class(package: "java.lang", name: "String", _): "jstring?" + case .class(package: "java.lang", name: "Class", _): "jclass?" + case .class(package: "java.lang", name: "Throwable", _): "jthrowable?" case .class: "jobject?" } } diff --git a/Sources/JavaTypes/JavaType+JavaSource.swift b/Sources/JavaTypes/JavaType+JavaSource.swift index f9e2e0cd..f81f0c6d 100644 --- a/Sources/JavaTypes/JavaType+JavaSource.swift +++ b/Sources/JavaTypes/JavaType+JavaSource.swift @@ -51,9 +51,13 @@ extension JavaType: CustomStringConvertible { case .double: "double" case .void: "void" case .array(let elementType): "\(elementType.description)[]" - case .class(package: let package, name: let name): + case .class(package: let package, name: let name, let typeParameters): if let package { - "\(package).\(name)" + if !typeParameters.isEmpty { + "\(package).\(name)<\(typeParameters.map(\.description).joined(separator: ", "))>" + } else { + "\(package).\(name)" + } } else { name } @@ -64,7 +68,7 @@ extension JavaType: CustomStringConvertible { /// and nil otherwise. public var className: String? { switch self { - case .class(_, let name): + case .class(_, let name, _): return name default: return nil @@ -75,9 +79,9 @@ extension JavaType: CustomStringConvertible { /// and nil otherwise. public var fullyQualifiedClassName: String? { switch self { - case .class(.some(let package), let name): + case .class(.some(let package), let name, _): return "\(package).\(name)" - case .class(nil, let name): + case .class(nil, let name, _): return name default: return nil diff --git a/Sources/JavaTypes/JavaType+SwiftNames.swift b/Sources/JavaTypes/JavaType+SwiftNames.swift index 20de73fc..7015ef91 100644 --- a/Sources/JavaTypes/JavaType+SwiftNames.swift +++ b/Sources/JavaTypes/JavaType+SwiftNames.swift @@ -25,7 +25,7 @@ extension JavaType { .array: return false - case .class(package: "java.lang", name: "String"): + case .class(package: "java.lang", name: "String", _): return !stringIsValueType case .class: @@ -38,7 +38,7 @@ extension JavaType { case .boolean, .byte, .char, .short, .int, .long, .float, .double, .void, .array: return false - case .class(package: "java.lang", name: "Runnable"): + case .class(package: "java.lang", name: "Runnable", _): return true case .class: return false @@ -57,7 +57,7 @@ extension JavaType { case .boolean, .byte, .char, .short, .int, .long, .float, .double, .void, .array: return false - case .class(package: "java.lang", name: "String"): + case .class(package: "java.lang", name: "String", _): return true case .class: return false diff --git a/Sources/JavaTypes/JavaType.swift b/Sources/JavaTypes/JavaType.swift index 2a2d901f..ce7191ba 100644 --- a/Sources/JavaTypes/JavaType.swift +++ b/Sources/JavaTypes/JavaType.swift @@ -28,7 +28,7 @@ public enum JavaType: Equatable, Hashable { /// A Java class separated into its package (e.g., "java.lang") and class name /// (e.g., "Object") - case `class`(package: String?, name: String) + case `class`(package: String?, name: String, typeParameters: [JavaType] = []) /// A Java array. indirect case array(JavaType) diff --git a/Sources/JavaTypes/Mangling.swift b/Sources/JavaTypes/Mangling.swift index f0dbd484..1311b717 100644 --- a/Sources/JavaTypes/Mangling.swift +++ b/Sources/JavaTypes/Mangling.swift @@ -35,7 +35,7 @@ extension JavaType { case .short: "S" case .void: "V" case .array(let elementType): "[" + elementType.mangledName - case .class(package: let package, name: let name): + case .class(package: let package, name: let name, _): "L\(package!).\(name.replacingPeriodsWithDollars());".replacingPeriodsWithSlashes() } } diff --git a/Sources/SwiftJavaConfigurationShared/Configuration.swift b/Sources/SwiftJavaConfigurationShared/Configuration.swift index 2d9b4311..6d8d20e5 100644 --- a/Sources/SwiftJavaConfigurationShared/Configuration.swift +++ b/Sources/SwiftJavaConfigurationShared/Configuration.swift @@ -46,6 +46,7 @@ public struct Configuration: Codable { public var effectiveUnsignedNumbersMode: JExtractUnsignedIntegerMode { unsignedNumbersMode ?? .default } + public var minimumInputAccessLevelMode: JExtractMinimumAccessLevelMode? public var effectiveMinimumInputAccessLevelMode: JExtractMinimumAccessLevelMode { minimumInputAccessLevelMode ?? .default @@ -56,6 +57,11 @@ public struct Configuration: Codable { memoryManagementMode ?? .default } + public var asyncFuncMode: JExtractAsyncFuncMode? + public var effectiveAsyncFuncMode: JExtractAsyncFuncMode { + asyncFuncMode ?? .default + } + // ==== java 2 swift --------------------------------------------------------- /// The Java class path that should be passed along to the swift-java tool. diff --git a/Sources/SwiftJavaConfigurationShared/JExtract/JExtractAsyncFuncMode.swift b/Sources/SwiftJavaConfigurationShared/JExtract/JExtractAsyncFuncMode.swift new file mode 100644 index 00000000..221649c5 --- /dev/null +++ b/Sources/SwiftJavaConfigurationShared/JExtract/JExtractAsyncFuncMode.swift @@ -0,0 +1,33 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +/// Configures how Swift `async` functions should be extracted by jextract. +public enum JExtractAsyncFuncMode: String, Codable { + /// Extract Swift `async` APIs as Java functions that return `CompletableFuture`s. + case completableFuture + + /// Extract Swift `async` APIs as Java functions that return `Future`s. + /// + /// This mode is useful for platforms that do not have `CompletableFuture` support, such as + /// Android 23 and below. + /// + /// - Note: Prefer using the `completableFuture` mode instead, if possible. +// case future +} + +extension JExtractAsyncFuncMode { + public static var `default`: Self { + .completableFuture + } +} diff --git a/Sources/SwiftJavaConfigurationShared/JExtract/JExtractGenerationMode.swift b/Sources/SwiftJavaConfigurationShared/JExtract/JExtractGenerationMode.swift new file mode 100644 index 00000000..8df00cf0 --- /dev/null +++ b/Sources/SwiftJavaConfigurationShared/JExtract/JExtractGenerationMode.swift @@ -0,0 +1,22 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +/// Determines which source generation mode JExtract should be using: JNI or Foreign Function and Memory. +public enum JExtractGenerationMode: String, Codable { + /// Foreign Value and Memory API + case ffm + + /// Java Native Interface + case jni +} diff --git a/Sources/SwiftJavaConfigurationShared/JExtract/JExtractMemoryManagementMode.swift b/Sources/SwiftJavaConfigurationShared/JExtract/JExtractMemoryManagementMode.swift new file mode 100644 index 00000000..be77d27d --- /dev/null +++ b/Sources/SwiftJavaConfigurationShared/JExtract/JExtractMemoryManagementMode.swift @@ -0,0 +1,34 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +/// Configures how memory should be managed by the user +public enum JExtractMemoryManagementMode: String, Codable { + /// Force users to provide an explicit `SwiftArena` to all calls that require them. + case explicit + + /// Provide both explicit `SwiftArena` support + /// and a default global automatic `SwiftArena` that will deallocate memory when the GC decides to. + case allowGlobalAutomatic + + public static var `default`: Self { + .explicit + } + + public var requiresGlobalArena: Bool { + switch self { + case .explicit: false + case .allowGlobalAutomatic: true + } + } +} diff --git a/Sources/SwiftJavaConfigurationShared/JExtract/JExtractMinimumAccessLevelMode.swift b/Sources/SwiftJavaConfigurationShared/JExtract/JExtractMinimumAccessLevelMode.swift new file mode 100644 index 00000000..22fead57 --- /dev/null +++ b/Sources/SwiftJavaConfigurationShared/JExtract/JExtractMinimumAccessLevelMode.swift @@ -0,0 +1,26 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +/// The minimum access level which +public enum JExtractMinimumAccessLevelMode: String, Codable { + case `public` + case `package` + case `internal` +} + +extension JExtractMinimumAccessLevelMode { + public static var `default`: Self { + .public + } +} diff --git a/Sources/SwiftJavaConfigurationShared/GenerationMode.swift b/Sources/SwiftJavaConfigurationShared/JExtract/JExtractUnsignedIntegerMode.swift similarity index 68% rename from Sources/SwiftJavaConfigurationShared/GenerationMode.swift rename to Sources/SwiftJavaConfigurationShared/JExtract/JExtractUnsignedIntegerMode.swift index 22fdd5f5..d7a94070 100644 --- a/Sources/SwiftJavaConfigurationShared/GenerationMode.swift +++ b/Sources/SwiftJavaConfigurationShared/JExtract/JExtractUnsignedIntegerMode.swift @@ -12,15 +12,6 @@ // //===----------------------------------------------------------------------===// -/// Determines which source generation mode JExtract should be using: JNI or Foreign Function and Memory. -public enum JExtractGenerationMode: String, Codable { - /// Foreign Value and Memory API - case ffm - - /// Java Native Interface - case jni -} - /// Configures how Swift unsigned integers should be extracted by jextract. public enum JExtractUnsignedIntegerMode: String, Codable { /// Treat unsigned Swift integers as their signed equivalents in Java signatures, @@ -51,6 +42,7 @@ public enum JExtractUnsignedIntegerMode: String, Codable { // case widenOrAnnotate } + extension JExtractUnsignedIntegerMode { public var needsConversion: Bool { switch self { @@ -63,38 +55,3 @@ extension JExtractUnsignedIntegerMode { .annotate } } - -/// The minimum access level which -public enum JExtractMinimumAccessLevelMode: String, Codable { - case `public` - case `package` - case `internal` -} - -extension JExtractMinimumAccessLevelMode { - public static var `default`: Self { - .public - } -} - - -/// Configures how memory should be managed by the user -public enum JExtractMemoryManagementMode: String, Codable { - /// Force users to provide an explicit `SwiftArena` to all calls that require them. - case explicit - - /// Provide both explicit `SwiftArena` support - /// and a default global automatic `SwiftArena` that will deallocate memory when the GC decides to. - case allowGlobalAutomatic - - public static var `default`: Self { - .explicit - } - - public var requiresGlobalArena: Bool { - switch self { - case .explicit: false - case .allowGlobalAutomatic: true - } - } -} diff --git a/Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md b/Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md index 997e680e..e97ed03e 100644 --- a/Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md +++ b/Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md @@ -57,7 +57,7 @@ SwiftJava's `swift-java jextract` tool automates generating Java bindings from S | Typed throws: `func x() throws(E)` | ❌ | ❌ | | Stored properties: `var`, `let` (with `willSet`, `didSet`) | ✅ | ✅ | | Computed properties: `var` (incl. `throws`) | ✅ / TODO | ✅ | -| Async functions `func async` and properties: `var { get async {} }` | ❌ | ❌ | +| Async functions `func async` and properties: `var { get async {} }` | ❌ | ✅ | | Arrays: `[UInt8]`, `[T]` | ❌ | ❌ | | Dictionaries: `[String: Int]`, `[K:V]` | ❌ | ❌ | | Generic parameters in functions: `func f(x: T)` | ❌ | ✅ | @@ -97,7 +97,6 @@ SwiftJava's `swift-java jextract` tool automates generating Java bindings from S | Result builders | ❌ | ❌ | | Automatic Reference Counting of class types / lifetime safety | ✅ | ✅ | | Value semantic types (e.g. struct copying) | ❌ | ❌ | -| Swift concurrency: `func async`, `actor`, `distribued actor` | ❌ | ❌ | | | | | | | | | @@ -328,3 +327,21 @@ which conform a to a given Swift protocol. #### Returning protocol types Protocols are not yet supported as return types. + +### `async` functions + +> Note: Importing `async` functions is currently only available in the JNI mode of jextract. + +Asynchronous functions in Swift can be extraced using different modes, which are explained below. + +#### Async function mode: completable-future (default) + +In this mode `async` functions in Swift are extracted as Java methods returning a `java.util.concurrent.CompletableFuture`. +This mode gives the most flexibility and should be prefered if your platform supports `CompletableFuture`. + +#### Async mode: future + +This is a mode for legacy platforms, where `CompletableFuture` is not available, such as Android 23 and below. +In this mode `async` functions in Swift are extracted as Java methods returning a `java.util.concurrent.Future`. +To enable this mode pass the `--async-func-mode future` command line option, +or set the `asyncFuncMode` configuration value in `swift-java.config` diff --git a/Sources/SwiftJavaRuntimeSupport/DefaultCaches.swift b/Sources/SwiftJavaRuntimeSupport/DefaultCaches.swift new file mode 100644 index 00000000..1c3079bc --- /dev/null +++ b/Sources/SwiftJavaRuntimeSupport/DefaultCaches.swift @@ -0,0 +1,67 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import SwiftJava + +extension _JNIMethodIDCache { + public enum CompletableFuture { + private static let completeMethod = Method( + name: "complete", + signature: "(Ljava/lang/Object;)Z" + ) + + private static let completeExceptionallyMethod = Method( + name: "completeExceptionally", + signature: "(Ljava/lang/Throwable;)Z" + ) + + private static let cache = _JNIMethodIDCache( + environment: try! JavaVirtualMachine.shared().environment(), + className: "java/util/concurrent/CompletableFuture", + methods: [completeMethod, completeExceptionallyMethod] + ) + + public static var `class`: jclass { + cache.javaClass + } + + /// CompletableFuture.complete(T) + public static var complete: jmethodID { + cache.methods[completeMethod]! + } + + /// CompletableFuture.completeExceptionally(Throwable) + public static var completeExceptionally: jmethodID { + cache.methods[completeExceptionallyMethod]! + } + } + + public enum Exception { + private static let messageConstructor = Method(name: "", signature: "(Ljava/lang/String;)V") + + private static let cache = _JNIMethodIDCache( + environment: try! JavaVirtualMachine.shared().environment(), + className: "java/lang/Exception", + methods: [messageConstructor] + ) + + public static var `class`: jclass { + cache.javaClass + } + + public static var constructWithMessage: jmethodID { + cache.methods[messageConstructor]! + } + } +} diff --git a/Sources/SwiftJavaRuntimeSupport/_JNIBoxedConversions.swift b/Sources/SwiftJavaRuntimeSupport/_JNIBoxedConversions.swift new file mode 100644 index 00000000..68d98ffc --- /dev/null +++ b/Sources/SwiftJavaRuntimeSupport/_JNIBoxedConversions.swift @@ -0,0 +1,105 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import CSwiftJavaJNI +import SwiftJava + +public enum _JNIBoxedConversions { + private static let booleanMethod = _JNIMethodIDCache.Method(name: "valueOf", signature: "(Z)Ljava/lang/Boolean;", isStatic: true) + private static let byteMethod = _JNIMethodIDCache.Method(name: "valueOf", signature: "(B)Ljava/lang/Byte;", isStatic: true) + private static let charMethod = _JNIMethodIDCache.Method(name: "valueOf", signature: "(C)Ljava/lang/Character;", isStatic: true) + private static let shortMethod = _JNIMethodIDCache.Method(name: "valueOf", signature: "(S)Ljava/lang/Short;", isStatic: true) + private static let intMethod = _JNIMethodIDCache.Method(name: "valueOf", signature: "(I)Ljava/lang/Integer;", isStatic: true) + private static let longMethod = _JNIMethodIDCache.Method(name: "valueOf", signature: "(J)Ljava/lang/Long;", isStatic: true) + private static let floatMethod = _JNIMethodIDCache.Method(name: "valueOf", signature: "(F)Ljava/lang/Float;", isStatic: true) + private static let doubleMethod = _JNIMethodIDCache.Method(name: "valueOf", signature: "(D)Ljava/lang/Double;", isStatic: true) + + private static let booleanCache = _JNIMethodIDCache( + environment: try! JavaVirtualMachine.shared().environment(), + className: "java/lang/Boolean", + methods: [booleanMethod] + ) + + private static let byteCache = _JNIMethodIDCache( + environment: try! JavaVirtualMachine.shared().environment(), + className: "java/lang/Byte", + methods: [byteMethod] + ) + private static let charCache = _JNIMethodIDCache( + environment: try! JavaVirtualMachine.shared().environment(), + className: "java/lang/Character", + methods: [charMethod] + ) + + private static let shortCache = _JNIMethodIDCache( + environment: try! JavaVirtualMachine.shared().environment(), + className: "java/lang/Short", + methods: [shortMethod] + ) + private static let intCache = _JNIMethodIDCache( + environment: try! JavaVirtualMachine.shared().environment(), + className: "java/lang/Integer", + methods: [intMethod] + ) + + private static let longCache = _JNIMethodIDCache( + environment: try! JavaVirtualMachine.shared().environment(), + className: "java/lang/Long", + methods: [longMethod] + ) + + private static let floatCache = _JNIMethodIDCache( + environment: try! JavaVirtualMachine.shared().environment(), + className: "java/lang/Float", + methods: [floatMethod] + ) + + private static let doubleCache = _JNIMethodIDCache( + environment: try! JavaVirtualMachine.shared().environment(), + className: "java/lang/Double", + methods: [doubleMethod] + ) + + public static func box(_ value: jboolean, in env: JNIEnvironment) -> jobject { + env.interface.CallStaticObjectMethodA(env, booleanCache.javaClass, booleanCache.methods[booleanMethod]!, [jvalue(z: value)])! + } + + public static func box(_ value: jbyte, in env: JNIEnvironment) -> jobject { + env.interface.CallStaticObjectMethodA(env, byteCache.javaClass, byteCache.methods[byteMethod]!, [jvalue(b: value)])! + } + + public static func box(_ value: jchar, in env: JNIEnvironment) -> jobject { + env.interface.CallStaticObjectMethodA(env, charCache.javaClass, charCache.methods[charMethod]!, [jvalue(c: value)])! + } + + public static func box(_ value: jshort, in env: JNIEnvironment) -> jobject { + env.interface.CallStaticObjectMethodA(env, shortCache.javaClass, shortCache.methods[shortMethod]!, [jvalue(s: value)])! + } + + public static func box(_ value: jint, in env: JNIEnvironment) -> jobject { + env.interface.CallStaticObjectMethodA(env, intCache.javaClass, intCache.methods[intMethod]!, [jvalue(i: value)])! + } + + public static func box(_ value: jlong, in env: JNIEnvironment) -> jobject { + env.interface.CallStaticObjectMethodA(env, longCache.javaClass, longCache.methods[longMethod]!, [jvalue(j: value)])! + } + + public static func box(_ value: jfloat, in env: JNIEnvironment) -> jobject { + env.interface.CallStaticObjectMethodA(env, floatCache.javaClass, floatCache.methods[floatMethod]!, [jvalue(f: value)])! + } + + public static func box(_ value: jdouble, in env: JNIEnvironment) -> jobject { + env.interface.CallStaticObjectMethodA(env, doubleCache.javaClass, doubleCache.methods[doubleMethod]!, [jvalue(d: value)])! + } +} diff --git a/Sources/SwiftJava/Helpers/_JNIMethodIDCache.swift b/Sources/SwiftJavaRuntimeSupport/_JNIMethodIDCache.swift similarity index 67% rename from Sources/SwiftJava/Helpers/_JNIMethodIDCache.swift rename to Sources/SwiftJavaRuntimeSupport/_JNIMethodIDCache.swift index a67d225f..dd7eb5d1 100644 --- a/Sources/SwiftJava/Helpers/_JNIMethodIDCache.swift +++ b/Sources/SwiftJavaRuntimeSupport/_JNIMethodIDCache.swift @@ -12,6 +12,9 @@ // //===----------------------------------------------------------------------===// +import CSwiftJavaJNI +import SwiftJava + /// A cache used to hold references for JNI method and classes. /// /// This type is used internally in by the outputted JExtract wrappers @@ -20,10 +23,12 @@ public final class _JNIMethodIDCache: Sendable { public struct Method: Hashable { public let name: String public let signature: String + public let isStatic: Bool - public init(name: String, signature: String) { + public init(name: String, signature: String, isStatic: Bool = false) { self.name = name self.signature = signature + self.isStatic = isStatic } } @@ -40,10 +45,18 @@ public final class _JNIMethodIDCache: Sendable { } self._class = environment.interface.NewGlobalRef(environment, clazz)! self.methods = methods.reduce(into: [:]) { (result, method) in - if let methodID = environment.interface.GetMethodID(environment, clazz, method.name, method.signature) { - result[method] = methodID + if method.isStatic { + if let methodID = environment.interface.GetStaticMethodID(environment, clazz, method.name, method.signature) { + result[method] = methodID + } else { + fatalError("Static method \(method.signature) with signature \(method.signature) not found in class \(className)") + } } else { - fatalError("Method \(method.signature) with signature \(method.signature) not found in class \(className)") + if let methodID = environment.interface.GetMethodID(environment, clazz, method.name, method.signature) { + result[method] = methodID + } else { + fatalError("Method \(method.signature) with signature \(method.signature) not found in class \(className)") + } } } } diff --git a/Sources/SwiftJavaTool/Commands/JExtractCommand.swift b/Sources/SwiftJavaTool/Commands/JExtractCommand.swift index c730cbf6..aba79983 100644 --- a/Sources/SwiftJavaTool/Commands/JExtractCommand.swift +++ b/Sources/SwiftJavaTool/Commands/JExtractCommand.swift @@ -78,6 +78,9 @@ extension SwiftJava { """ ) var dependsOn: [String] = [] + + @Option(help: "The mode to use for extracting asynchronous Swift functions. By default async methods are extracted as Java functions returning CompletableFuture.") + var asyncFuncMode: JExtractAsyncFuncMode = .default } } @@ -98,6 +101,7 @@ extension SwiftJava.JExtractCommand { config.unsignedNumbersMode = unsignedNumbers config.minimumInputAccessLevelMode = minimumInputAccessLevel config.memoryManagementMode = memoryManagementMode + config.asyncFuncMode = asyncFuncMode try checkModeCompatibility() @@ -162,3 +166,4 @@ extension JExtractGenerationMode: ExpressibleByArgument {} extension JExtractUnsignedIntegerMode: ExpressibleByArgument {} extension JExtractMinimumAccessLevelMode: ExpressibleByArgument {} extension JExtractMemoryManagementMode: ExpressibleByArgument {} +extension JExtractAsyncFuncMode: ExpressibleByArgument {} diff --git a/Sources/SwiftKitSwift/SwiftKit.swift b/Sources/SwiftRuntimeFunctions/SwiftRuntimeFunctions.swift similarity index 100% rename from Sources/SwiftKitSwift/SwiftKit.swift rename to Sources/SwiftRuntimeFunctions/SwiftRuntimeFunctions.swift diff --git a/SwiftKitCore/build.gradle b/SwiftKitCore/build.gradle index 9e4891dc..f4376e94 100644 --- a/SwiftKitCore/build.gradle +++ b/SwiftKitCore/build.gradle @@ -73,10 +73,10 @@ tasks.test { } } -// SwiftKit depends on SwiftKitSwift (Swift library that this Java library calls into) +// SwiftKit depends on SwiftRuntimeFunctions (Swift library that this Java library calls into) def compileSwift = tasks.register("compileSwift", Exec) { - description "Compile the swift-java SwiftKitSwift dynamic library that SwiftKit (Java) calls into" + description "Compile the swift-java SwiftRuntimeFunctions dynamic library that SwiftKit (Java) calls into" inputs.file(new File(rootDir, "Package.swift")) inputs.dir(new File(rootDir, "Sources/")) // a bit generous, but better safe than sorry, and include all Swift source changes @@ -84,7 +84,7 @@ def compileSwift = tasks.register("compileSwift", Exec) { workingDir = rootDir commandLine "swift" - args("build", "--target", "SwiftKitSwift") + args("build", "--target", "SwiftRuntimeFunctions") } tasks.build { dependsOn("compileSwift") diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/ConfinedSwiftMemorySession.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/ConfinedSwiftMemorySession.java index 4383a6fe..3514d9c1 100644 --- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/ConfinedSwiftMemorySession.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/ConfinedSwiftMemorySession.java @@ -16,6 +16,8 @@ import java.util.LinkedList; import java.util.List; +import java.util.Queue; +import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.atomic.AtomicInteger; public class ConfinedSwiftMemorySession implements ClosableSwiftArena { @@ -23,21 +25,17 @@ public class ConfinedSwiftMemorySession implements ClosableSwiftArena { final static int CLOSED = 0; final static int ACTIVE = 1; - final Thread owner; final AtomicInteger state; final ConfinedResourceList resources; - public ConfinedSwiftMemorySession(Thread owner) { - this.owner = owner; + public ConfinedSwiftMemorySession() { this.state = new AtomicInteger(ACTIVE); this.resources = new ConfinedResourceList(); } void checkValid() throws RuntimeException { - if (this.owner != null && this.owner != Thread.currentThread()) { - throw new WrongThreadException(String.format("ConfinedSwift arena is confined to %s but was closed from %s!", this.owner, Thread.currentThread())); - } else if (this.state.get() < ACTIVE) { + if (this.state.get() < ACTIVE) { throw new RuntimeException("SwiftArena is already closed!"); } } @@ -61,8 +59,7 @@ public void register(SwiftInstance instance) { } static final class ConfinedResourceList implements SwiftResourceList { - // TODO: Could use intrusive linked list to avoid one indirection here - final List resourceCleanups = new LinkedList<>(); + final Queue resourceCleanups = new ConcurrentLinkedQueue<>(); void add(SwiftInstanceCleanup cleanup) { resourceCleanups.add(cleanup); diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftArena.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftArena.java index 3b6c4626..96353c37 100644 --- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftArena.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftArena.java @@ -31,7 +31,7 @@ public interface SwiftArena { void register(SwiftInstance instance); static ClosableSwiftArena ofConfined() { - return new ConfinedSwiftMemorySession(Thread.currentThread()); + return new ConfinedSwiftMemorySession(); } static SwiftArena ofAuto() { diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftLibraries.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftLibraries.java index a093cc50..7eccde74 100644 --- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftLibraries.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftLibraries.java @@ -24,10 +24,10 @@ public final class SwiftLibraries { - // Library names of core Swift and SwiftKit + // Library names of core Swift and SwiftRuntimeFunctions public static final String LIB_NAME_SWIFT_CORE = "swiftCore"; public static final String LIB_NAME_SWIFT_CONCURRENCY = "swift_Concurrency"; - public static final String LIB_NAME_SWIFTKITSWIFT = "SwiftKitSwift"; + public static final String LIB_NAME_SWIFT_RUNTIME_FUNCTIONS = "SwiftRuntimeFunctions"; /** * Allows for configuration if jextracted types should automatically attempt to load swiftCore and the library type is from. @@ -42,10 +42,10 @@ public final class SwiftLibraries { @SuppressWarnings("unused") private static final boolean INITIALIZED_LIBS = loadLibraries(false); - public static boolean loadLibraries(boolean loadSwiftKit) { - System.loadLibrary(LIB_NAME_SWIFTKITSWIFT); - if (loadSwiftKit) { - System.loadLibrary(LIB_NAME_SWIFTKITSWIFT); + public static boolean loadLibraries(boolean loadSwiftRuntimeFunctions) { + System.loadLibrary(LIB_NAME_SWIFT_CORE); + if (loadSwiftRuntimeFunctions) { + System.loadLibrary(LIB_NAME_SWIFT_RUNTIME_FUNCTIONS); } return true; } diff --git a/SwiftKitFFM/build.gradle b/SwiftKitFFM/build.gradle index c04b1017..dcbbe8df 100644 --- a/SwiftKitFFM/build.gradle +++ b/SwiftKitFFM/build.gradle @@ -75,10 +75,10 @@ tasks.withType(JavaCompile).configureEach { options.compilerArgs.add("-Xlint:preview") } -// SwiftKit depends on SwiftKitSwift (Swift library that this Java library calls into) +// SwiftKit depends on SwiftRuntimeFunctions (Swift library that this Java library calls into) def compileSwift = tasks.register("compileSwift", Exec) { - description "Compile the swift-java SwiftKitSwift dynamic library that SwiftKit (Java) calls into" + description "Compile the swift-java SwiftRuntimeFunctions dynamic library that SwiftKit (Java) calls into" inputs.file(new File(rootDir, "Package.swift")) inputs.dir(new File(rootDir, "Sources/")) // a bit generous, but better safe than sorry, and include all Swift source changes @@ -86,7 +86,7 @@ def compileSwift = tasks.register("compileSwift", Exec) { workingDir = rootDir commandLine "swift" - args("build", "--target", "SwiftKitSwift") + args("build", "--target", "SwiftRuntimeFunctions") } tasks.build { dependsOn("compileSwift") diff --git a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/AllocatingSwiftArena.java b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/AllocatingSwiftArena.java index 08fad15b..b72818a3 100644 --- a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/AllocatingSwiftArena.java +++ b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/AllocatingSwiftArena.java @@ -24,7 +24,7 @@ public interface AllocatingSwiftArena extends SwiftArena, SegmentAllocator { MemorySegment allocate(long byteSize, long byteAlignment); static ClosableAllocatingSwiftArena ofConfined() { - return new FFMConfinedSwiftMemorySession(Thread.currentThread()); + return new FFMConfinedSwiftMemorySession(); } static AllocatingSwiftArena ofAuto() { diff --git a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMConfinedSwiftMemorySession.java b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMConfinedSwiftMemorySession.java index 424e54b6..05daebd7 100644 --- a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMConfinedSwiftMemorySession.java +++ b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMConfinedSwiftMemorySession.java @@ -22,8 +22,8 @@ final class FFMConfinedSwiftMemorySession extends ConfinedSwiftMemorySession implements AllocatingSwiftArena, ClosableAllocatingSwiftArena { final Arena arena; - public FFMConfinedSwiftMemorySession(Thread owner) { - super(owner); + public FFMConfinedSwiftMemorySession() { + super(); this.arena = Arena.ofConfined(); } diff --git a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/SwiftRuntime.java b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/SwiftRuntime.java index e03b9bfe..74a270c0 100644 --- a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/SwiftRuntime.java +++ b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/SwiftRuntime.java @@ -33,7 +33,7 @@ public class SwiftRuntime { public static final String STDLIB_DYLIB_NAME = "swiftCore"; - public static final String SWIFTKITSWIFT_DYLIB_NAME = "SwiftKitSwift"; + public static final String SWIFT_RUNTIME_FUNCTIONS_DYLIB_NAME = "SwiftRuntimeFunctions"; private static final String STDLIB_MACOS_DYLIB_PATH = "/usr/lib/swift/libswiftCore.dylib"; @@ -42,10 +42,10 @@ public class SwiftRuntime { @SuppressWarnings("unused") private static final boolean INITIALIZED_LIBS = loadLibraries(false); - public static boolean loadLibraries(boolean loadSwiftKit) { + public static boolean loadLibraries(boolean loadSwiftRuntimeFunctions) { System.loadLibrary(STDLIB_DYLIB_NAME); - if (loadSwiftKit) { - System.loadLibrary(SWIFTKITSWIFT_DYLIB_NAME); + if (loadSwiftRuntimeFunctions) { + System.loadLibrary(SWIFT_RUNTIME_FUNCTIONS_DYLIB_NAME); } return true; } @@ -487,4 +487,4 @@ boolean isEnabled() { } throw new IllegalArgumentException("Not handled log group: " + this); } -} \ No newline at end of file +} diff --git a/Tests/JExtractSwiftTests/JNI/JNIAsyncTests.swift b/Tests/JExtractSwiftTests/JNI/JNIAsyncTests.swift new file mode 100644 index 00000000..5f488192 --- /dev/null +++ b/Tests/JExtractSwiftTests/JNI/JNIAsyncTests.swift @@ -0,0 +1,348 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import JExtractSwiftLib +import Testing + +@Suite +struct JNIAsyncTests { + + @Test("Import: async -> Void (Java, CompletableFuture)") + func completableFuture_asyncVoid_java() throws { + try assertOutput( + input: "public func asyncVoid() async", + .jni, .java, + detectChunkByInitialLines: 2, + expectedChunks: [ + """ + /** + * Downcall to Swift: + * {@snippet lang=swift : + * public func asyncVoid() async + * } + */ + public static java.util.concurrent.CompletableFuture asyncVoid() { + java.util.concurrent.CompletableFuture $future = new java.util.concurrent.CompletableFuture(); + SwiftModule.$asyncVoid($future); + return $future.thenApply((futureResult$) -> { + return futureResult$; + } + ); + } + """, + """ + private static native void $asyncVoid(java.util.concurrent.CompletableFuture result_future); + """, + ] + ) + } + + @Test("Import: async -> Void (Swift, CompletableFuture)") + func completableFuture_asyncVoid_swift() throws { + try assertOutput( + input: "public func asyncVoid() async", + .jni, .swift, + detectChunkByInitialLines: 1, + expectedChunks: [ + """ + @_cdecl("Java_com_example_swift_SwiftModule__00024asyncVoid__Ljava_util_concurrent_CompletableFuture_2") + func Java_com_example_swift_SwiftModule__00024asyncVoid__Ljava_util_concurrent_CompletableFuture_2(environment: UnsafeMutablePointer!, thisClass: jclass, result_future: jobject?) { + let globalFuture = environment.interface.NewGlobalRef(environment, result_future) + if #available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, *) { + Task.immediate { + var environment = environment! + defer { + let deferEnvironment = try! JavaVirtualMachine.shared().environment() + environment.interface.DeleteGlobalRef(deferEnvironment, globalFuture) + } + let swiftResult$ = await SwiftModule.asyncVoid() + environment = try JavaVirtualMachine.shared().environment() + environment.interface.CallBooleanMethodA(environment, globalFuture, _JNIMethodIDCache.CompletableFuture.complete, [jvalue(l: nil)]) + } + } + else { + Task { + var environment = try! JavaVirtualMachine.shared().environment() + defer { + let deferEnvironment = try! JavaVirtualMachine.shared().environment() + environment.interface.DeleteGlobalRef(deferEnvironment, globalFuture) + } + let swiftResult$ = await SwiftModule.asyncVoid() + environment = try JavaVirtualMachine.shared().environment() + environment.interface.CallBooleanMethodA(environment, globalFuture, _JNIMethodIDCache.CompletableFuture.complete, [jvalue(l: nil)]) + } + } + } + """ + ] + ) + } + + @Test("Import: async throws -> Void (Java, CompletableFuture)") + func completableFuture_asyncThrowsVoid_java() throws { + try assertOutput( + input: "public func async() async throws", + .jni, .java, + detectChunkByInitialLines: 2, + expectedChunks: [ + """ + /** + * Downcall to Swift: + * {@snippet lang=swift : + * public func async() async throws + * } + */ + public static java.util.concurrent.CompletableFuture async() { + java.util.concurrent.CompletableFuture $future = new java.util.concurrent.CompletableFuture(); + SwiftModule.$async($future); + return $future.thenApply((futureResult$) -> { + return futureResult$; + } + ); + } + """, + """ + private static native void $async(java.util.concurrent.CompletableFuture result_future); + """, + ] + ) + } + + @Test("Import: async throws -> Void (Swift, CompletableFuture)") + func completableFuture_asyncThrowsVoid_swift() throws { + try assertOutput( + input: "public func async() async throws", + .jni, .swift, + detectChunkByInitialLines: 1, + expectedChunks: [ + """ + @_cdecl("Java_com_example_swift_SwiftModule__00024async__Ljava_util_concurrent_CompletableFuture_2") + func Java_com_example_swift_SwiftModule__00024async__Ljava_util_concurrent_CompletableFuture_2(environment: UnsafeMutablePointer!, thisClass: jclass, result_future: jobject?) { + let globalFuture = environment.interface.NewGlobalRef(environment, result_future) + if #available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, *) { + Task.immediate { + var environment = environment! + defer { + let deferEnvironment = try! JavaVirtualMachine.shared().environment() + environment.interface.DeleteGlobalRef(deferEnvironment, globalFuture) + } + do { + let swiftResult$ = await try SwiftModule.async() + environment = try JavaVirtualMachine.shared().environment() + environment.interface.CallBooleanMethodA(environment, globalFuture, _JNIMethodIDCache.CompletableFuture.complete, [jvalue(l: nil)]) + } + catch { + let catchEnvironment = try! JavaVirtualMachine.shared().environment() + let exception = catchEnvironment.interface.NewObjectA(catchEnvironment, _JNIMethodIDCache.Exception.class, _JNIMethodIDCache.Exception.constructWithMessage, [String(describing: error).getJValue(in: catchEnvironment)]) + catchEnvironment.interface.CallBooleanMethodA(catchEnvironment, globalFuture, _JNIMethodIDCache.CompletableFuture.completeExceptionally, [jvalue(l: exception)]) + } + } + } + else { + Task { + var environment = try! JavaVirtualMachine.shared().environment() + defer { + let deferEnvironment = try! JavaVirtualMachine.shared().environment() + environment.interface.DeleteGlobalRef(deferEnvironment, globalFuture) + } + do { + let swiftResult$ = await try SwiftModule.async() + environment = try JavaVirtualMachine.shared().environment() + environment.interface.CallBooleanMethodA(environment, globalFuture, _JNIMethodIDCache.CompletableFuture.complete, [jvalue(l: nil)]) + } + catch { + let catchEnvironment = try! JavaVirtualMachine.shared().environment() + let exception = catchEnvironment.interface.NewObjectA(catchEnvironment, _JNIMethodIDCache.Exception.class, _JNIMethodIDCache.Exception.constructWithMessage, [String(describing: error).getJValue(in: catchEnvironment)]) + catchEnvironment.interface.CallBooleanMethodA(catchEnvironment, globalFuture, _JNIMethodIDCache.CompletableFuture.completeExceptionally, [jvalue(l: exception)]) + } + } + } + } + """ + ] + ) + } + + @Test("Import: (Int64) async -> Int64 (Java, CompletableFuture)") + func completableFuture_asyncIntToInt_java() throws { + try assertOutput( + input: "public func async(i: Int64) async -> Int64", + .jni, .java, + detectChunkByInitialLines: 2, + expectedChunks: [ + """ + /** + * Downcall to Swift: + * {@snippet lang=swift : + * public func async(i: Int64) async -> Int64 + * } + */ + public static java.util.concurrent.CompletableFuture async(long i) { + java.util.concurrent.CompletableFuture $future = new java.util.concurrent.CompletableFuture(); + SwiftModule.$async(i, $future); + return $future.thenApply((futureResult$) -> { + return futureResult$; + } + ); + } + """, + """ + private static native void $async(long i, java.util.concurrent.CompletableFuture result_future); + """, + ] + ) + } + + @Test("Import: (Int64) async -> Int64 (Swift, CompletableFuture)") + func completableFuture_asyncIntToInt_swift() throws { + try assertOutput( + input: "public func async(i: Int64) async -> Int64", + .jni, .swift, + detectChunkByInitialLines: 1, + expectedChunks: [ + """ + @_cdecl("Java_com_example_swift_SwiftModule__00024async__JLjava_util_concurrent_CompletableFuture_2") + func Java_com_example_swift_SwiftModule__00024async__JLjava_util_concurrent_CompletableFuture_2(environment: UnsafeMutablePointer!, thisClass: jclass, i: jlong, result_future: jobject?) { + let globalFuture = environment.interface.NewGlobalRef(environment, result_future) + if #available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, *) { + Task.immediate { + var environment = environment! + defer { + let deferEnvironment = try! JavaVirtualMachine.shared().environment() + environment.interface.DeleteGlobalRef(deferEnvironment, globalFuture) + } + let swiftResult$ = await SwiftModule.async(i: Int64(fromJNI: i, in: environment)) + environment = try JavaVirtualMachine.shared().environment() + withVaList([SwiftJavaRuntimeSupport._JNIBoxedConversions.box(swiftResult$.getJNIValue(in: environment), in: environment)]) { + environment.interface.CallBooleanMethodV(environment, globalFuture, _JNIMethodIDCache.CompletableFuture.complete, $0) + } + } + } + else { + Task { + var environment = try! JavaVirtualMachine.shared().environment() + defer { + let deferEnvironment = try! JavaVirtualMachine.shared().environment() + environment.interface.DeleteGlobalRef(deferEnvironment, globalFuture) + } + let swiftResult$ = await SwiftModule.async(i: Int64(fromJNI: i, in: environment)) + environment = try JavaVirtualMachine.shared().environment() + withVaList([SwiftJavaRuntimeSupport._JNIBoxedConversions.box(swiftResult$.getJNIValue(in: environment), in: environment)]) { + environment.interface.CallBooleanMethodV(environment, globalFuture, _JNIMethodIDCache.CompletableFuture.complete, $0) + } + } + } + return + } + """ + ] + ) + } + + @Test("Import: (MyClass) async -> MyClass (Java, CompletableFuture)") + func completableFuture_asyncMyClassToMyClass_java() throws { + try assertOutput( + input: """ + class MyClass { } + + public func async(c: MyClass) async -> MyClass + """, + .jni, .java, + detectChunkByInitialLines: 2, + expectedChunks: [ + """ + /** + * Downcall to Swift: + * {@snippet lang=swift : + * public func async(c: MyClass) async -> MyClass + * } + */ + public static java.util.concurrent.CompletableFuture async(MyClass c, SwiftArena swiftArena$) { + java.util.concurrent.CompletableFuture $future = new java.util.concurrent.CompletableFuture(); + SwiftModule.$async(c.$memoryAddress(), $future); + return $future.thenApply((futureResult$) -> { + return MyClass.wrapMemoryAddressUnsafe(futureResult$, swiftArena$); + } + ); + } + """, + """ + private static native void $async(long c, java.util.concurrent.CompletableFuture result_future); + """, + ] + ) + } + + @Test("Import: (MyClass) async -> MyClass (Swift, CompletableFuture)") + func completableFuture_asyncMyClassToMyClass_swift() throws { + try assertOutput( + input: """ + class MyClass { } + + public func async(c: MyClass) async -> MyClass + """, + .jni, .swift, + detectChunkByInitialLines: 1, + expectedChunks: [ + """ + @_cdecl("Java_com_example_swift_SwiftModule__00024async__JLjava_util_concurrent_CompletableFuture_2") + func Java_com_example_swift_SwiftModule__00024async__JLjava_util_concurrent_CompletableFuture_2(environment: UnsafeMutablePointer!, thisClass: jclass, c: jlong, result_future: jobject?) { + assert(c != 0, "c memory address was null") + let cBits$ = Int(Int64(fromJNI: c, in: environment)) + let c$ = UnsafeMutablePointer(bitPattern: cBits$) + guard let c$ else { + fatalError("c memory address was null in call to \\(#function)!") + } + let globalFuture = environment.interface.NewGlobalRef(environment, result_future) + if #available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, *) { + Task.immediate { + var environment = environment! + defer { + let deferEnvironment = try! JavaVirtualMachine.shared().environment() + environment.interface.DeleteGlobalRef(deferEnvironment, globalFuture) + } + let swiftResult$ = await SwiftModule.async(c: c$.pointee) + environment = try JavaVirtualMachine.shared().environment() + let result$ = UnsafeMutablePointer.allocate(capacity: 1) + result$.initialize(to: swiftResult$) + let resultBits$ = Int64(Int(bitPattern: result$)) + withVaList([SwiftJavaRuntimeSupport._JNIBoxedConversions.box(resultBits$.getJNIValue(in: environment), in: environment)]) { + environment.interface.CallBooleanMethodV(environment, globalFuture, _JNIMethodIDCache.CompletableFuture.complete, $0) + } + } + } + else { + Task { + var environment = try! JavaVirtualMachine.shared().environment() + defer { + let deferEnvironment = try! JavaVirtualMachine.shared().environment() + environment.interface.DeleteGlobalRef(deferEnvironment, globalFuture) + } + let swiftResult$ = await SwiftModule.async(c: c$.pointee) + environment = try JavaVirtualMachine.shared().environment() + let result$ = UnsafeMutablePointer.allocate(capacity: 1) + result$.initialize(to: swiftResult$) + let resultBits$ = Int64(Int(bitPattern: result$)) + withVaList([SwiftJavaRuntimeSupport._JNIBoxedConversions.box(resultBits$.getJNIValue(in: environment), in: environment)]) { + environment.interface.CallBooleanMethodV(environment, globalFuture, _JNIMethodIDCache.CompletableFuture.complete, $0) + } + } + } + return + } + """ + ] + ) + } +} diff --git a/Tests/JExtractSwiftTests/JNI/JNIClassTests.swift b/Tests/JExtractSwiftTests/JNI/JNIClassTests.swift index a7527aa8..c3102a62 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIClassTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIClassTests.swift @@ -221,9 +221,9 @@ struct JNIClassTests { @_cdecl("Java_com_example_swift_MyClass__00024init__JJ") func Java_com_example_swift_MyClass__00024init__JJ(environment: UnsafeMutablePointer!, thisClass: jclass, x: jlong, y: jlong) -> jlong { let result$ = UnsafeMutablePointer.allocate(capacity: 1) - result$.initialize(to: MyClass.init(x: Int64(fromJNI: x, in: environment!), y: Int64(fromJNI: y, in: environment!))) + result$.initialize(to: MyClass.init(x: Int64(fromJNI: x, in: environment), y: Int64(fromJNI: y, in: environment))) let resultBits$ = Int64(Int(bitPattern: result$)) - return resultBits$.getJNIValue(in: environment!) + return resultBits$.getJNIValue(in: environment) } """, """ @@ -232,7 +232,7 @@ struct JNIClassTests { let result$ = UnsafeMutablePointer.allocate(capacity: 1) result$.initialize(to: MyClass.init()) let resultBits$ = Int64(Int(bitPattern: result$)) - return resultBits$.getJNIValue(in: environment!) + return resultBits$.getJNIValue(in: environment) } """, ] @@ -303,12 +303,12 @@ struct JNIClassTests { @_cdecl("Java_com_example_swift_MyClass__00024doSomething__JJ") func Java_com_example_swift_MyClass__00024doSomething__JJ(environment: UnsafeMutablePointer!, thisClass: jclass, x: jlong, self: jlong) { assert(self != 0, "self memory address was null") - let selfBits$ = Int(Int64(fromJNI: self, in: environment!)) + let selfBits$ = Int(Int64(fromJNI: self, in: environment)) let self$ = UnsafeMutablePointer(bitPattern: selfBits$) guard let self$ else { fatalError("self memory address was null in call to \\(#function)!") } - self$.pointee.doSomething(x: Int64(fromJNI: x, in: environment!)) + self$.pointee.doSomething(x: Int64(fromJNI: x, in: environment)) } """ ] @@ -352,7 +352,7 @@ struct JNIClassTests { @_cdecl("Java_com_example_swift_MyClass__00024copy__J") func Java_com_example_swift_MyClass__00024copy__J(environment: UnsafeMutablePointer!, thisClass: jclass, self: jlong) -> jlong { assert(self != 0, "self memory address was null") - let selfBits$ = Int(Int64(fromJNI: self, in: environment!)) + let selfBits$ = Int(Int64(fromJNI: self, in: environment)) let self$ = UnsafeMutablePointer(bitPattern: selfBits$) guard let self$ else { fatalError("self memory address was null in call to \\(#function)!") @@ -360,7 +360,7 @@ struct JNIClassTests { let result$ = UnsafeMutablePointer.allocate(capacity: 1) result$.initialize(to: self$.pointee.copy()) let resultBits$ = Int64(Int(bitPattern: result$)) - return resultBits$.getJNIValue(in: environment!) + return resultBits$.getJNIValue(in: environment) } """ ] @@ -404,18 +404,18 @@ struct JNIClassTests { @_cdecl("Java_com_example_swift_MyClass__00024isEqual__JJ") func Java_com_example_swift_MyClass__00024isEqual__JJ(environment: UnsafeMutablePointer!, thisClass: jclass, other: jlong, self: jlong) -> jboolean { assert(other != 0, "other memory address was null") - let otherBits$ = Int(Int64(fromJNI: other, in: environment!)) + let otherBits$ = Int(Int64(fromJNI: other, in: environment)) let other$ = UnsafeMutablePointer(bitPattern: otherBits$) guard let other$ else { fatalError("other memory address was null in call to \\(#function)!") } assert(self != 0, "self memory address was null") - let selfBits$ = Int(Int64(fromJNI: self, in: environment!)) + let selfBits$ = Int(Int64(fromJNI: self, in: environment)) let self$ = UnsafeMutablePointer(bitPattern: selfBits$) guard let self$ else { fatalError("self memory address was null in call to \\(#function)!") } - return self$.pointee.isEqual(to: other$.pointee).getJNIValue(in: environment!) + return self$.pointee.isEqual(to: other$.pointee).getJNIValue(in: environment) } """ ] diff --git a/Tests/JExtractSwiftTests/JNI/JNIClosureTests.swift b/Tests/JExtractSwiftTests/JNI/JNIClosureTests.swift index b374d24e..b54749c1 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIClosureTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIClosureTests.swift @@ -63,10 +63,10 @@ struct JNIClosureTests { @_cdecl("Java_com_example_swift_SwiftModule__00024emptyClosure__Lcom_example_swift_SwiftModule_00024emptyClosure_00024closure_2") func Java_com_example_swift_SwiftModule__00024emptyClosure__Lcom_example_swift_SwiftModule_00024emptyClosure_00024closure_2(environment: UnsafeMutablePointer!, thisClass: jclass, closure: jobject?) { SwiftModule.emptyClosure(closure: { - let class$ = environment!.interface.GetObjectClass(environment, closure) - let methodID$ = environment!.interface.GetMethodID(environment, class$, "apply", "()V")! + let class$ = environment.interface.GetObjectClass(environment, closure) + let methodID$ = environment.interface.GetMethodID(environment, class$, "apply", "()V")! let arguments$: [jvalue] = [] - environment!.interface.CallVoidMethodA(environment, closure, methodID$, arguments$) + environment.interface.CallVoidMethodA(environment, closure, methodID$, arguments$) } ) } @@ -115,10 +115,10 @@ struct JNIClosureTests { @_cdecl("Java_com_example_swift_SwiftModule__00024closureWithArgumentsAndReturn__Lcom_example_swift_SwiftModule_00024closureWithArgumentsAndReturn_00024closure_2") func Java_com_example_swift_SwiftModule__00024closureWithArgumentsAndReturn__Lcom_example_swift_SwiftModule_00024closureWithArgumentsAndReturn_00024closure_2(environment: UnsafeMutablePointer!, thisClass: jclass, closure: jobject?) { SwiftModule.closureWithArgumentsAndReturn(closure: { _0, _1 in - let class$ = environment!.interface.GetObjectClass(environment, closure) - let methodID$ = environment!.interface.GetMethodID(environment, class$, "apply", "(JZ)J")! - let arguments$: [jvalue] = [_0.getJValue(in: environment!), _1.getJValue(in: environment!)] - return Int64(fromJNI: environment!.interface.CallLongMethodA(environment, closure, methodID$, arguments$), in: environment!) + let class$ = environment.interface.GetObjectClass(environment, closure) + let methodID$ = environment.interface.GetMethodID(environment, class$, "apply", "(JZ)J")! + let arguments$: [jvalue] = [_0.getJValue(in: environment), _1.getJValue(in: environment)] + return Int64(fromJNI: environment.interface.CallLongMethodA(environment, closure, methodID$, arguments$), in: environment) } ) } diff --git a/Tests/JExtractSwiftTests/JNI/JNIEnumTests.swift b/Tests/JExtractSwiftTests/JNI/JNIEnumTests.swift index c6aaf923..ef422e42 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIEnumTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIEnumTests.swift @@ -224,25 +224,25 @@ struct JNIEnumTests { let result$ = UnsafeMutablePointer.allocate(capacity: 1) result$.initialize(to: MyEnum.first) let resultBits$ = Int64(Int(bitPattern: result$)) - return resultBits$.getJNIValue(in: environment!) + return resultBits$.getJNIValue(in: environment) } """, """ @_cdecl("Java_com_example_swift_MyEnum__00024second__Ljava_lang_String_2") func Java_com_example_swift_MyEnum__00024second__Ljava_lang_String_2(environment: UnsafeMutablePointer!, thisClass: jclass, arg0: jstring?) -> jlong { let result$ = UnsafeMutablePointer.allocate(capacity: 1) - result$.initialize(to: MyEnum.second(String(fromJNI: arg0, in: environment!))) + result$.initialize(to: MyEnum.second(String(fromJNI: arg0, in: environment))) let resultBits$ = Int64(Int(bitPattern: result$)) - return resultBits$.getJNIValue(in: environment!) + return resultBits$.getJNIValue(in: environment) } """, """ @_cdecl("Java_com_example_swift_MyEnum__00024third__JI") func Java_com_example_swift_MyEnum__00024third__JI(environment: UnsafeMutablePointer!, thisClass: jclass, x: jlong, y: jint) -> jlong { let result$ = UnsafeMutablePointer.allocate(capacity: 1) - result$.initialize(to: MyEnum.third(x: Int64(fromJNI: x, in: environment!), y: Int32(fromJNI: y, in: environment!))) + result$.initialize(to: MyEnum.third(x: Int64(fromJNI: x, in: environment), y: Int32(fromJNI: y, in: environment))) let resultBits$ = Int64(Int(bitPattern: result$)) - return resultBits$.getJNIValue(in: environment!) + return resultBits$.getJNIValue(in: environment) } """ ]) @@ -302,7 +302,7 @@ struct JNIEnumTests { let class$ = cache$.javaClass let method$ = _JNIMethodIDCache.Method(name: "", signature: "(Ljava/lang/String;)V") let constructorID$ = cache$[method$] - return withVaList([_0.getJNIValue(in: environment!) ?? 0]) { + return withVaList([_0.getJNIValue(in: environment) ?? 0]) { return environment.interface.NewObjectV(environment, class$, constructorID$, $0) } } @@ -318,7 +318,7 @@ struct JNIEnumTests { let class$ = cache$.javaClass let method$ = _JNIMethodIDCache.Method(name: "", signature: "(JI)V") let constructorID$ = cache$[method$] - return withVaList([x.getJNIValue(in: environment!), y.getJNIValue(in: environment!)]) { + return withVaList([x.getJNIValue(in: environment), y.getJNIValue(in: environment)]) { return environment.interface.NewObjectV(environment, class$, constructorID$, $0) } } diff --git a/Tests/JExtractSwiftTests/JNI/JNIJavaKitTests.swift b/Tests/JExtractSwiftTests/JNI/JNIJavaKitTests.swift index ac6b8384..69d77b73 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIJavaKitTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIJavaKitTests.swift @@ -71,7 +71,7 @@ struct JNIJavaKitTests { guard let javaInteger_unwrapped$ = javaInteger else { fatalError("javaInteger was null in call to \\(#function), but Swift requires non-optional!") } - SwiftModule.function(javaLong: JavaLong(javaThis: javaLong_unwrapped$, environment: environment!), javaInteger: JavaInteger(javaThis: javaInteger_unwrapped$, environment: environment!), int: Int64(fromJNI: int, in: environment!)) + SwiftModule.function(javaLong: JavaLong(javaThis: javaLong_unwrapped$, environment: environment), javaInteger: JavaInteger(javaThis: javaInteger_unwrapped$, environment: environment), int: Int64(fromJNI: int, in: environment)) } """ ] diff --git a/Tests/JExtractSwiftTests/JNI/JNIModuleTests.swift b/Tests/JExtractSwiftTests/JNI/JNIModuleTests.swift index 27b0cdea..dddf1147 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIModuleTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIModuleTests.swift @@ -130,13 +130,13 @@ struct JNIModuleTests { """ @_cdecl("Java_com_example_swift_SwiftModule__00024takeIntegers__BSIJ") func Java_com_example_swift_SwiftModule__00024takeIntegers__BSIJ(environment: UnsafeMutablePointer!, thisClass: jclass, i1: jbyte, i2: jshort, i3: jint, i4: jlong) -> jchar { - return SwiftModule.takeIntegers(i1: Int8(fromJNI: i1, in: environment!), i2: Int16(fromJNI: i2, in: environment!), i3: Int32(fromJNI: i3, in: environment!), i4: Int64(fromJNI: i4, in: environment!)).getJNIValue(in: environment!) + return SwiftModule.takeIntegers(i1: Int8(fromJNI: i1, in: environment), i2: Int16(fromJNI: i2, in: environment), i3: Int32(fromJNI: i3, in: environment), i4: Int64(fromJNI: i4, in: environment)).getJNIValue(in: environment) } """, """ @_cdecl("Java_com_example_swift_SwiftModule__00024otherPrimitives__ZFD") func Java_com_example_swift_SwiftModule__00024otherPrimitives__ZFD(environment: UnsafeMutablePointer!, thisClass: jclass, b: jboolean, f: jfloat, d: jdouble) { - SwiftModule.otherPrimitives(b: Bool(fromJNI: b, in: environment!), f: Float(fromJNI: f, in: environment!), d: Double(fromJNI: d, in: environment!)) + SwiftModule.otherPrimitives(b: Bool(fromJNI: b, in: environment), f: Float(fromJNI: f, in: environment), d: Double(fromJNI: d, in: environment)) } """ ] @@ -179,7 +179,7 @@ struct JNIModuleTests { """ @_cdecl("Java_com_example_swift_SwiftModule__00024copy__Ljava_lang_String_2") func Java_com_example_swift_SwiftModule__00024copy__Ljava_lang_String_2(environment: UnsafeMutablePointer!, thisClass: jclass, string: jstring?) -> jstring? { - return SwiftModule.copy(String(fromJNI: string, in: environment!)).getJNIValue(in: environment!) + return SwiftModule.copy(String(fromJNI: string, in: environment)).getJNIValue(in: environment) } """, ] @@ -247,7 +247,7 @@ struct JNIModuleTests { @_cdecl("Java_com_example_swift_SwiftModule__00024methodB__") func Java_com_example_swift_SwiftModule__00024methodB__(environment: UnsafeMutablePointer!, thisClass: jclass) -> jlong { do { - return try SwiftModule.methodB().getJNIValue(in: environment!) + return try SwiftModule.methodB().getJNIValue(in: environment) } catch { environment.throwAsException(error) return Int64.jniPlaceholderValue diff --git a/Tests/JExtractSwiftTests/JNI/JNIOptionalTests.swift b/Tests/JExtractSwiftTests/JNI/JNIOptionalTests.swift index be2e0f6a..6c931d7b 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIOptionalTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIOptionalTests.swift @@ -72,10 +72,10 @@ struct JNIOptionalTests { """ @_cdecl("Java_com_example_swift_SwiftModule__00024optionalSugar__BJ") func Java_com_example_swift_SwiftModule__00024optionalSugar__BJ(environment: UnsafeMutablePointer!, thisClass: jclass, arg_discriminator: jbyte, arg_value: jlong) -> jlong { - let result_value$ = SwiftModule.optionalSugar(arg_discriminator == 1 ? Int64(fromJNI: arg_value, in: environment!) : nil).map { + let result_value$ = SwiftModule.optionalSugar(arg_discriminator == 1 ? Int64(fromJNI: arg_value, in: environment) : nil).map { Int64($0) << 32 | Int64(1) } ?? 0 - return result_value$.getJNIValue(in: environment!) + return result_value$.getJNIValue(in: environment) } """ ] @@ -123,8 +123,8 @@ struct JNIOptionalTests { @_cdecl("Java_com_example_swift_SwiftModule__00024optionalExplicit__BLjava_lang_String_2_3B") func Java_com_example_swift_SwiftModule__00024optionalExplicit__BLjava_lang_String_2_3B(environment: UnsafeMutablePointer!, thisClass: jclass, arg_discriminator: jbyte, arg_value: jstring?, result_discriminator$: jbyteArray?) -> jstring? { let result$: jstring? - if let innerResult$ = SwiftModule.optionalExplicit(arg_discriminator == 1 ? String(fromJNI: arg_value, in: environment!) : nil) { - result$ = innerResult$.getJNIValue(in: environment!) + if let innerResult$ = SwiftModule.optionalExplicit(arg_discriminator == 1 ? String(fromJNI: arg_value, in: environment) : nil) { + result$ = innerResult$.getJNIValue(in: environment) var flag$ = Int8(1) environment.interface.SetByteArrayRegion(environment, result_discriminator$, 0, 1, &flag$) } @@ -180,14 +180,14 @@ struct JNIOptionalTests { """ @_cdecl("Java_com_example_swift_SwiftModule__00024optionalClass__J_3B") func Java_com_example_swift_SwiftModule__00024optionalClass__J_3B(environment: UnsafeMutablePointer!, thisClass: jclass, arg: jlong, result_discriminator$: jbyteArray?) -> jlong { - let argBits$ = Int(Int64(fromJNI: arg, in: environment!)) + let argBits$ = Int(Int64(fromJNI: arg, in: environment)) let arg$ = UnsafeMutablePointer(bitPattern: argBits$) let result$: jlong if let innerResult$ = SwiftModule.optionalClass(arg$?.pointee) { let _result$ = UnsafeMutablePointer.allocate(capacity: 1) _result$.initialize(to: innerResult$) let _resultBits$ = Int64(Int(bitPattern: _result$)) - result$ = _resultBits$.getJNIValue(in: environment!) + result$ = _resultBits$.getJNIValue(in: environment) var flag$ = Int8(1) environment.interface.SetByteArrayRegion(environment, result_discriminator$, 0, 1, &flag$) } @@ -242,7 +242,7 @@ struct JNIOptionalTests { @_cdecl("Java_com_example_swift_SwiftModule__00024optionalJavaKitClass__Ljava_lang_Long_2") func Java_com_example_swift_SwiftModule__00024optionalJavaKitClass__Ljava_lang_Long_2(environment: UnsafeMutablePointer!, thisClass: jclass, arg: jobject?) { SwiftModule.optionalJavaKitClass(arg.map { - return JavaLong(javaThis: $0, environment: environment!) + return JavaLong(javaThis: $0, environment: environment) } ) } diff --git a/Tests/JExtractSwiftTests/JNI/JNIProtocolTests.swift b/Tests/JExtractSwiftTests/JNI/JNIProtocolTests.swift index b5a0fcdb..c5302ca6 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIProtocolTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIProtocolTests.swift @@ -107,11 +107,11 @@ struct JNIProtocolTests { """ @_cdecl("Java_com_example_swift_SwiftModule__00024takeProtocol__JJJJ") func Java_com_example_swift_SwiftModule__00024takeProtocol__JJJJ(environment: UnsafeMutablePointer!, thisClass: jclass, x: jlong, x_typeMetadataAddress: jlong, y: jlong, y_typeMetadataAddress: jlong) { - guard let xTypeMetadataPointer$ = UnsafeRawPointer(bitPattern: Int(Int64(fromJNI: x_typeMetadataAddress, in: environment!))) else { + guard let xTypeMetadataPointer$ = UnsafeRawPointer(bitPattern: Int(Int64(fromJNI: x_typeMetadataAddress, in: environment))) else { fatalError("x_typeMetadataAddress memory address was null") } let xDynamicType$: Any.Type = unsafeBitCast(xTypeMetadataPointer$, to: Any.Type.self) - guard let xRawPointer$ = UnsafeMutableRawPointer(bitPattern: Int(Int64(fromJNI: x, in: environment!))) else { + guard let xRawPointer$ = UnsafeMutableRawPointer(bitPattern: Int(Int64(fromJNI: x, in: environment))) else { fatalError("x memory address was null") } #if hasFeature(ImplicitOpenExistentials) @@ -122,11 +122,11 @@ struct JNIProtocolTests { } let xExistential$ = _openExistential(xDynamicType$, do: xDoLoad) #endif - guard let yTypeMetadataPointer$ = UnsafeRawPointer(bitPattern: Int(Int64(fromJNI: y_typeMetadataAddress, in: environment!))) else { + guard let yTypeMetadataPointer$ = UnsafeRawPointer(bitPattern: Int(Int64(fromJNI: y_typeMetadataAddress, in: environment))) else { fatalError("y_typeMetadataAddress memory address was null") } let yDynamicType$: Any.Type = unsafeBitCast(yTypeMetadataPointer$, to: Any.Type.self) - guard let yRawPointer$ = UnsafeMutableRawPointer(bitPattern: Int(Int64(fromJNI: y, in: environment!))) else { + guard let yRawPointer$ = UnsafeMutableRawPointer(bitPattern: Int(Int64(fromJNI: y, in: environment))) else { fatalError("y memory address was null") } #if hasFeature(ImplicitOpenExistentials) @@ -172,11 +172,11 @@ struct JNIProtocolTests { """ @_cdecl("Java_com_example_swift_SwiftModule__00024takeGeneric__JJ") func Java_com_example_swift_SwiftModule__00024takeGeneric__JJ(environment: UnsafeMutablePointer!, thisClass: jclass, s: jlong, s_typeMetadataAddress: jlong) { - guard let sTypeMetadataPointer$ = UnsafeRawPointer(bitPattern: Int(Int64(fromJNI: s_typeMetadataAddress, in: environment!))) else { + guard let sTypeMetadataPointer$ = UnsafeRawPointer(bitPattern: Int(Int64(fromJNI: s_typeMetadataAddress, in: environment))) else { fatalError("s_typeMetadataAddress memory address was null") } let sDynamicType$: Any.Type = unsafeBitCast(sTypeMetadataPointer$, to: Any.Type.self) - guard let sRawPointer$ = UnsafeMutableRawPointer(bitPattern: Int(Int64(fromJNI: s, in: environment!))) else { + guard let sRawPointer$ = UnsafeMutableRawPointer(bitPattern: Int(Int64(fromJNI: s, in: environment))) else { fatalError("s memory address was null") } #if hasFeature(ImplicitOpenExistentials) @@ -222,11 +222,11 @@ struct JNIProtocolTests { """ @_cdecl("Java_com_example_swift_SwiftModule__00024takeComposite__JJ") func Java_com_example_swift_SwiftModule__00024takeComposite__JJ(environment: UnsafeMutablePointer!, thisClass: jclass, x: jlong, x_typeMetadataAddress: jlong) { - guard let xTypeMetadataPointer$ = UnsafeRawPointer(bitPattern: Int(Int64(fromJNI: x_typeMetadataAddress, in: environment!))) else { + guard let xTypeMetadataPointer$ = UnsafeRawPointer(bitPattern: Int(Int64(fromJNI: x_typeMetadataAddress, in: environment))) else { fatalError("x_typeMetadataAddress memory address was null") } let xDynamicType$: Any.Type = unsafeBitCast(xTypeMetadataPointer$, to: Any.Type.self) - guard let xRawPointer$ = UnsafeMutableRawPointer(bitPattern: Int(Int64(fromJNI: x, in: environment!))) else { + guard let xRawPointer$ = UnsafeMutableRawPointer(bitPattern: Int(Int64(fromJNI: x, in: environment))) else { fatalError("x memory address was null") } #if hasFeature(ImplicitOpenExistentials) diff --git a/Tests/JExtractSwiftTests/JNI/JNIStructTests.swift b/Tests/JExtractSwiftTests/JNI/JNIStructTests.swift index a7c689aa..f8830b64 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIStructTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIStructTests.swift @@ -142,9 +142,9 @@ struct JNIStructTests { @_cdecl("Java_com_example_swift_MyStruct__00024init__JJ") func Java_com_example_swift_MyStruct__00024init__JJ(environment: UnsafeMutablePointer!, thisClass: jclass, x: jlong, y: jlong) -> jlong { let result$ = UnsafeMutablePointer.allocate(capacity: 1) - result$.initialize(to: MyStruct.init(x: Int64(fromJNI: x, in: environment!), y: Int64(fromJNI: y, in: environment!))) + result$.initialize(to: MyStruct.init(x: Int64(fromJNI: x, in: environment), y: Int64(fromJNI: y, in: environment))) let resultBits$ = Int64(Int(bitPattern: result$)) - return resultBits$.getJNIValue(in: environment!) + return resultBits$.getJNIValue(in: environment) } """ ] @@ -214,12 +214,12 @@ struct JNIStructTests { @_cdecl("Java_com_example_swift_MyStruct__00024doSomething__JJ") func Java_com_example_swift_MyStruct__00024doSomething__JJ(environment: UnsafeMutablePointer!, thisClass: jclass, x: jlong, self: jlong) { assert(self != 0, "self memory address was null") - let selfBits$ = Int(Int64(fromJNI: self, in: environment!)) + let selfBits$ = Int(Int64(fromJNI: self, in: environment)) let self$ = UnsafeMutablePointer(bitPattern: selfBits$) guard let self$ else { fatalError("self memory address was null in call to \\(#function)!") } - self$.pointee.doSomething(x: Int64(fromJNI: x, in: environment!)) + self$.pointee.doSomething(x: Int64(fromJNI: x, in: environment)) } """ ] diff --git a/Tests/JExtractSwiftTests/JNI/JNIVariablesTests.swift b/Tests/JExtractSwiftTests/JNI/JNIVariablesTests.swift index c9d313a5..363c117d 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIVariablesTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIVariablesTests.swift @@ -70,7 +70,7 @@ struct JNIVariablesTests { @_cdecl("Java_com_example_swift_MyClass__00024getConstant__J") func Java_com_example_swift_MyClass__00024getConstant__J(environment: UnsafeMutablePointer!, thisClass: jclass, self: jlong) -> jlong { ... - return self$.pointee.constant.getJNIValue(in: environment!) + return self$.pointee.constant.getJNIValue(in: environment) } """ ] @@ -135,7 +135,7 @@ struct JNIVariablesTests { fatalError("self memory address was null in call to \\(#function)!") } ... - return self$.pointee.mutable.getJNIValue(in: environment!) + return self$.pointee.mutable.getJNIValue(in: environment) } """, """ @@ -143,7 +143,7 @@ struct JNIVariablesTests { func Java_com_example_swift_MyClass__00024setMutable__JJ(environment: UnsafeMutablePointer!, thisClass: jclass, newValue: jlong, self: jlong) { assert(self != 0, "self memory address was null") ... - self$.pointee.mutable = Int64(fromJNI: newValue, in: environment!) + self$.pointee.mutable = Int64(fromJNI: newValue, in: environment) } """ ] @@ -188,7 +188,7 @@ struct JNIVariablesTests { @_cdecl("Java_com_example_swift_MyClass__00024getComputed__J") func Java_com_example_swift_MyClass__00024getComputed__J(environment: UnsafeMutablePointer!, thisClass: jclass, self: jlong) -> jlong { ... - return self$.pointee.computed.getJNIValue(in: environment!) + return self$.pointee.computed.getJNIValue(in: environment) } """, ] @@ -234,7 +234,7 @@ struct JNIVariablesTests { func Java_com_example_swift_MyClass__00024getComputedThrowing__J(environment: UnsafeMutablePointer!, thisClass: jclass, self: jlong) -> jlong { ... do { - return try self$.pointee.computedThrowing.getJNIValue(in: environment!) + return try self$.pointee.computedThrowing.getJNIValue(in: environment) } catch { environment.throwAsException(error) return Int64.jniPlaceholderValue @@ -297,14 +297,14 @@ struct JNIVariablesTests { @_cdecl("Java_com_example_swift_MyClass__00024getGetterAndSetter__J") func Java_com_example_swift_MyClass__00024getGetterAndSetter__J(environment: UnsafeMutablePointer!, thisClass: jclass, self: jlong) -> jlong { ... - return self$.pointee.getterAndSetter.getJNIValue(in: environment!) + return self$.pointee.getterAndSetter.getJNIValue(in: environment) } """, """ @_cdecl("Java_com_example_swift_MyClass__00024setGetterAndSetter__JJ") func Java_com_example_swift_MyClass__00024setGetterAndSetter__JJ(environment: UnsafeMutablePointer!, thisClass: jclass, newValue: jlong, self: jlong) { ... - self$.pointee.getterAndSetter = Int64(fromJNI: newValue, in: environment!) + self$.pointee.getterAndSetter = Int64(fromJNI: newValue, in: environment) } """ ] @@ -363,14 +363,14 @@ struct JNIVariablesTests { @_cdecl("Java_com_example_swift_MyClass__00024isSomeBoolean__J") func Java_com_example_swift_MyClass__00024isSomeBoolean__J(environment: UnsafeMutablePointer!, thisClass: jclass, self: jlong) -> jboolean { ... - return self$.pointee.someBoolean.getJNIValue(in: environment!) + return self$.pointee.someBoolean.getJNIValue(in: environment) } """, """ @_cdecl("Java_com_example_swift_MyClass__00024setSomeBoolean__ZJ") func Java_com_example_swift_MyClass__00024setSomeBoolean__ZJ(environment: UnsafeMutablePointer!, thisClass: jclass, newValue: jboolean, self: jlong) { ... - self$.pointee.someBoolean = Bool(fromJNI: newValue, in: environment!) + self$.pointee.someBoolean = Bool(fromJNI: newValue, in: environment) } """ ] @@ -429,14 +429,14 @@ struct JNIVariablesTests { @_cdecl("Java_com_example_swift_MyClass__00024isBoolean__J") func Java_com_example_swift_MyClass__00024isBoolean__J(environment: UnsafeMutablePointer!, thisClass: jclass, self: jlong) -> jboolean { ... - return self$.pointee.isBoolean.getJNIValue(in: environment!) + return self$.pointee.isBoolean.getJNIValue(in: environment) } """, """ @_cdecl("Java_com_example_swift_MyClass__00024setBoolean__ZJ") func Java_com_example_swift_MyClass__00024setBoolean__ZJ(environment: UnsafeMutablePointer!, thisClass: jclass, newValue: jboolean, self: jlong) { ... - self$.pointee.isBoolean = Bool(fromJNI: newValue, in: environment!) + self$.pointee.isBoolean = Bool(fromJNI: newValue, in: environment) } """ ] From 1de727915763bb3101c6f4bc4e3bdcfc36b7fd99 Mon Sep 17 00:00:00 2001 From: Mads Odgaard Date: Sat, 1 Nov 2025 09:08:20 +0100 Subject: [PATCH 380/426] remove withVaList (#416) --- .../MySwiftLibrary/MySwiftLibrary.swift | 2 ++ ...wift2JavaGenerator+NativeTranslation.swift | 9 ++++++--- ...ift2JavaGenerator+SwiftThunkPrinting.swift | 10 ++++------ .../JNI/JNIAsyncTests.swift | 20 ++++++++----------- .../JExtractSwiftTests/JNI/JNIEnumTests.swift | 10 ++++------ 5 files changed, 24 insertions(+), 27 deletions(-) diff --git a/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift index 09903638..e278326e 100644 --- a/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift +++ b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift @@ -19,6 +19,8 @@ #if os(Linux) import Glibc +#elseif os(Android) + import Android #else import Darwin.C #endif diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift index 45208d7b..727294b1 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift @@ -830,9 +830,12 @@ extension JNISwift2JavaGenerator { if swiftFunctionResultType.isVoid { printer.print("environment.interface.CallBooleanMethodA(environment, globalFuture, _JNIMethodIDCache.CompletableFuture.complete, [jvalue(l: nil)])") } else { - printer.printBraceBlock("withVaList([SwiftJavaRuntimeSupport._JNIBoxedConversions.box(\(inner), in: environment)])") { printer in - printer.print("environment.interface.CallBooleanMethodV(environment, globalFuture, _JNIMethodIDCache.CompletableFuture.complete, $0)") - } + printer.print( + """ + let boxedResult$ = SwiftJavaRuntimeSupport._JNIBoxedConversions.box(\(inner), in: environment) + environment.interface.CallBooleanMethodA(environment, globalFuture, _JNIMethodIDCache.CompletableFuture.complete, [jvalue(l: boxedResult$)]) + """ + ) } } diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift index 5403ae40..c9f8af9e 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift @@ -251,16 +251,14 @@ extension JNISwift2JavaGenerator { """ ) let upcallArguments = zip(enumCase.parameterConversions, caseNames).map { conversion, caseName in - // '0' is treated the same as a null pointer. - let nullConversion = !conversion.native.javaType.isPrimitive ? " ?? 0" : "" + let nullConversion = !conversion.native.javaType.isPrimitive ? " ?? nil" : "" let result = conversion.native.conversion.render(&printer, caseName) - return "\(result)\(nullConversion)" + return "jvalue(\(conversion.native.javaType.jniFieldName): \(result)\(nullConversion))" } printer.print( """ - return withVaList([\(upcallArguments.joined(separator: ", "))]) { - return environment.interface.NewObjectV(environment, class$, constructorID$, $0) - } + let newObjectArgs$: [jvalue] = [\(upcallArguments.joined(separator: ", "))] + return environment.interface.NewObjectA(environment, class$, constructorID$, newObjectArgs$) """ ) } diff --git a/Tests/JExtractSwiftTests/JNI/JNIAsyncTests.swift b/Tests/JExtractSwiftTests/JNI/JNIAsyncTests.swift index 5f488192..6b26c69b 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIAsyncTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIAsyncTests.swift @@ -224,9 +224,8 @@ struct JNIAsyncTests { } let swiftResult$ = await SwiftModule.async(i: Int64(fromJNI: i, in: environment)) environment = try JavaVirtualMachine.shared().environment() - withVaList([SwiftJavaRuntimeSupport._JNIBoxedConversions.box(swiftResult$.getJNIValue(in: environment), in: environment)]) { - environment.interface.CallBooleanMethodV(environment, globalFuture, _JNIMethodIDCache.CompletableFuture.complete, $0) - } + let boxedResult$ = SwiftJavaRuntimeSupport._JNIBoxedConversions.box(swiftResult$.getJNIValue(in: environment), in: environment) + environment.interface.CallBooleanMethodA(environment, globalFuture, _JNIMethodIDCache.CompletableFuture.complete, [jvalue(l: boxedResult$)]) } } else { @@ -238,9 +237,8 @@ struct JNIAsyncTests { } let swiftResult$ = await SwiftModule.async(i: Int64(fromJNI: i, in: environment)) environment = try JavaVirtualMachine.shared().environment() - withVaList([SwiftJavaRuntimeSupport._JNIBoxedConversions.box(swiftResult$.getJNIValue(in: environment), in: environment)]) { - environment.interface.CallBooleanMethodV(environment, globalFuture, _JNIMethodIDCache.CompletableFuture.complete, $0) - } + let boxedResult$ = SwiftJavaRuntimeSupport._JNIBoxedConversions.box(swiftResult$.getJNIValue(in: environment), in: environment) + environment.interface.CallBooleanMethodA(environment, globalFuture, _JNIMethodIDCache.CompletableFuture.complete, [jvalue(l: boxedResult$)]) } } return @@ -317,9 +315,8 @@ struct JNIAsyncTests { let result$ = UnsafeMutablePointer.allocate(capacity: 1) result$.initialize(to: swiftResult$) let resultBits$ = Int64(Int(bitPattern: result$)) - withVaList([SwiftJavaRuntimeSupport._JNIBoxedConversions.box(resultBits$.getJNIValue(in: environment), in: environment)]) { - environment.interface.CallBooleanMethodV(environment, globalFuture, _JNIMethodIDCache.CompletableFuture.complete, $0) - } + let boxedResult$ = SwiftJavaRuntimeSupport._JNIBoxedConversions.box(resultBits$.getJNIValue(in: environment), in: environment) + environment.interface.CallBooleanMethodA(environment, globalFuture, _JNIMethodIDCache.CompletableFuture.complete, [jvalue(l: boxedResult$)]) } } else { @@ -334,9 +331,8 @@ struct JNIAsyncTests { let result$ = UnsafeMutablePointer.allocate(capacity: 1) result$.initialize(to: swiftResult$) let resultBits$ = Int64(Int(bitPattern: result$)) - withVaList([SwiftJavaRuntimeSupport._JNIBoxedConversions.box(resultBits$.getJNIValue(in: environment), in: environment)]) { - environment.interface.CallBooleanMethodV(environment, globalFuture, _JNIMethodIDCache.CompletableFuture.complete, $0) - } + let boxedResult$ = SwiftJavaRuntimeSupport._JNIBoxedConversions.box(resultBits$.getJNIValue(in: environment), in: environment) + environment.interface.CallBooleanMethodA(environment, globalFuture, _JNIMethodIDCache.CompletableFuture.complete, [jvalue(l: boxedResult$)]) } } return diff --git a/Tests/JExtractSwiftTests/JNI/JNIEnumTests.swift b/Tests/JExtractSwiftTests/JNI/JNIEnumTests.swift index ef422e42..38ef8789 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIEnumTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIEnumTests.swift @@ -302,9 +302,8 @@ struct JNIEnumTests { let class$ = cache$.javaClass let method$ = _JNIMethodIDCache.Method(name: "", signature: "(Ljava/lang/String;)V") let constructorID$ = cache$[method$] - return withVaList([_0.getJNIValue(in: environment) ?? 0]) { - return environment.interface.NewObjectV(environment, class$, constructorID$, $0) - } + let newObjectArgs$: [jvalue] = [jvalue(l: _0.getJNIValue(in: environment) ?? nil)] + return environment.interface.NewObjectA(environment, class$, constructorID$, newObjectArgs$) } """, """ @@ -318,9 +317,8 @@ struct JNIEnumTests { let class$ = cache$.javaClass let method$ = _JNIMethodIDCache.Method(name: "", signature: "(JI)V") let constructorID$ = cache$[method$] - return withVaList([x.getJNIValue(in: environment), y.getJNIValue(in: environment)]) { - return environment.interface.NewObjectV(environment, class$, constructorID$, $0) - } + let newObjectArgs$: [jvalue] = [jvalue(j: x.getJNIValue(in: environment)), jvalue(i: y.getJNIValue(in: environment))] + return environment.interface.NewObjectA(environment, class$, constructorID$, newObjectArgs$) } """ ]) From c58bbed1e3dac074df3ea26b32f118b85e45e14d Mon Sep 17 00:00:00 2001 From: Mads Odgaard Date: Tue, 4 Nov 2025 02:01:02 +0100 Subject: [PATCH 381/426] [jextract] Propagate build plugin config to command (#415) Co-authored-by: Konrad `ktoso` Malawski --- Plugins/PluginsShared/PluginUtils.swift | 4 +- .../SwiftJavaExtractJNISampleApp/build.gradle | 3 +- Sources/JExtractSwiftLib/Swift2Java.swift | 4 +- .../Configuration.swift | 3 ++ .../JExtract/JExtractGenerationMode.swift | 4 ++ .../JExtractUnsignedIntegerMode.swift | 1 - .../Documentation.docc/SupportedFeatures.md | 6 +-- .../Commands/JExtractCommand.swift | 52 +++++++++++-------- .../SwiftJavaBaseAsyncParsableCommand.swift | 2 +- 9 files changed, 45 insertions(+), 34 deletions(-) diff --git a/Plugins/PluginsShared/PluginUtils.swift b/Plugins/PluginsShared/PluginUtils.swift index 863cf99c..8278c645 100644 --- a/Plugins/PluginsShared/PluginUtils.swift +++ b/Plugins/PluginsShared/PluginUtils.swift @@ -66,12 +66,12 @@ extension PluginContext { .appending(path: "generated") .appending(path: "java") } - + var outputSwiftDirectory: URL { self.pluginWorkDirectoryURL .appending(path: "Sources") } - + func cachedClasspathFile(swiftModule: String) -> URL { self.pluginWorkDirectoryURL .appending(path: "\(swiftModule)", directoryHint: .notDirectory) diff --git a/Samples/SwiftJavaExtractJNISampleApp/build.gradle b/Samples/SwiftJavaExtractJNISampleApp/build.gradle index d92c96fb..b1aa8490 100644 --- a/Samples/SwiftJavaExtractJNISampleApp/build.gradle +++ b/Samples/SwiftJavaExtractJNISampleApp/build.gradle @@ -102,8 +102,7 @@ def jextract = tasks.register("jextract", Exec) { workingDir = layout.projectDirectory commandLine "swift" - // TODO: -v for debugging build issues... - args("build", "-v") // since Swift targets which need to be jextract-ed have the jextract build plugin, we just need to build + args("build") // since Swift targets which need to be jextract-ed have the jextract build plugin, we just need to build // If we wanted to execute a specific subcommand, we can like this: // args("run",/* // "swift-java", "jextract", diff --git a/Sources/JExtractSwiftLib/Swift2Java.swift b/Sources/JExtractSwiftLib/Swift2Java.swift index 19241592..ed76483e 100644 --- a/Sources/JExtractSwiftLib/Swift2Java.swift +++ b/Sources/JExtractSwiftLib/Swift2Java.swift @@ -95,8 +95,8 @@ public struct SwiftToJava { try translator.analyze() - switch config.mode { - case .some(.ffm), .none: + switch config.effectiveMode { + case .ffm: let generator = FFMSwift2JavaGenerator( config: self.config, translator: translator, diff --git a/Sources/SwiftJavaConfigurationShared/Configuration.swift b/Sources/SwiftJavaConfigurationShared/Configuration.swift index 6d8d20e5..c9d0cedf 100644 --- a/Sources/SwiftJavaConfigurationShared/Configuration.swift +++ b/Sources/SwiftJavaConfigurationShared/Configuration.swift @@ -39,6 +39,9 @@ public struct Configuration: Codable { public var outputJavaDirectory: String? public var mode: JExtractGenerationMode? + public var effectiveMode: JExtractGenerationMode { + mode ?? .default + } public var writeEmptyFiles: Bool? // FIXME: default it to false, but that plays not nice with Codable diff --git a/Sources/SwiftJavaConfigurationShared/JExtract/JExtractGenerationMode.swift b/Sources/SwiftJavaConfigurationShared/JExtract/JExtractGenerationMode.swift index 8df00cf0..1ad331da 100644 --- a/Sources/SwiftJavaConfigurationShared/JExtract/JExtractGenerationMode.swift +++ b/Sources/SwiftJavaConfigurationShared/JExtract/JExtractGenerationMode.swift @@ -19,4 +19,8 @@ public enum JExtractGenerationMode: String, Codable { /// Java Native Interface case jni + + public static var `default`: JExtractGenerationMode { + .ffm + } } diff --git a/Sources/SwiftJavaConfigurationShared/JExtract/JExtractUnsignedIntegerMode.swift b/Sources/SwiftJavaConfigurationShared/JExtract/JExtractUnsignedIntegerMode.swift index d7a94070..b53a2c6b 100644 --- a/Sources/SwiftJavaConfigurationShared/JExtract/JExtractUnsignedIntegerMode.swift +++ b/Sources/SwiftJavaConfigurationShared/JExtract/JExtractUnsignedIntegerMode.swift @@ -11,7 +11,6 @@ // SPDX-License-Identifier: Apache-2.0 // //===----------------------------------------------------------------------===// - /// Configures how Swift unsigned integers should be extracted by jextract. public enum JExtractUnsignedIntegerMode: String, Codable { /// Treat unsigned Swift integers as their signed equivalents in Java signatures, diff --git a/Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md b/Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md index e97ed03e..98dac732 100644 --- a/Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md +++ b/Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md @@ -135,10 +135,10 @@ on the Java side. | `Float` | `float` | | `Double` | `double` | -#### Unsigned numbers mode: wrap-guava +#### Unsigned numbers mode: wrapGuava You can configure `jextract` (in FFM mode) to instead import unsigned values as their unsigned type-safe representations -as offered by the Guava library: `UnsignedLong` or `UnsignedInt`. To enable this mode pass the `--unsigned-numbers wrap-guava` +as offered by the Guava library: `UnsignedLong` or `UnsignedInt`. To enable this mode pass the `--unsigned-numbers-mode wrapGuava` command line option, or set the corresponding configuration value in `swift-java.config` (TODO). This approach is type-safe, however it incurs a performance penalty for allocating a wrapper class for every @@ -162,7 +162,7 @@ you are expected to add a Guava dependency to your Java project. | `Float` | `float` | | `Double` | `double` | -> Note: The `wrap-guava` mode is currently only available in FFM mode of jextract. +> Note: The `wrapGuava` mode is currently only available in FFM mode of jextract. ### Enums diff --git a/Sources/SwiftJavaTool/Commands/JExtractCommand.swift b/Sources/SwiftJavaTool/Commands/JExtractCommand.swift index aba79983..b5942d2a 100644 --- a/Sources/SwiftJavaTool/Commands/JExtractCommand.swift +++ b/Sources/SwiftJavaTool/Commands/JExtractCommand.swift @@ -61,14 +61,14 @@ extension SwiftJava { @Flag(help: "Some build systems require an output to be present when it was 'expected', even if empty. This is used by the JExtractSwiftPlugin build plugin, but otherwise should not be necessary.") var writeEmptyFiles: Bool = false - @Option(help: "The mode of generation to use for the output files. Used with jextract mode. By default, unsigned Swift types are imported as their bit-width compatible signed Java counterparts, and annotated using the '@Unsigned' annotation. You may choose the 'wrap-guava' mode in order to import types as class wrapper types (`UnsignedInteger` et al) defined by the Google Guava library's `com.google.common.primitives' package. that ensure complete type-safety with regards to unsigned values, however they incur an allocation and performance overhead.") - var unsignedNumbers: JExtractUnsignedIntegerMode = .default + @Option(help: "The mode of generation to use for the output files. Used with jextract mode. By default, unsigned Swift types are imported as their bit-width compatible signed Java counterparts, and annotated using the '@Unsigned' annotation. You may choose the 'wrapGuava' mode in order to import types as class wrapper types (`UnsignedInteger` et al) defined by the Google Guava library's `com.google.common.primitives' package. that ensure complete type-safety with regards to unsigned values, however they incur an allocation and performance overhead.") + var unsignedNumbersMode: JExtractUnsignedIntegerMode? @Option(help: "The lowest access level of Swift declarations that should be extracted, defaults to 'public'.") - var minimumInputAccessLevel: JExtractMinimumAccessLevelMode = .default + var minimumInputAccessLevelMode: JExtractMinimumAccessLevelMode? - @Option(help: "The memory management mode to use for the generated code. By default, the user must explicitly provide `SwiftArena` to all calls that require it. By choosing `allow-automatic`, user can omit this parameter and a global GC-based arena will be used. `force-automatic` removes all explicit memory management.") - var memoryManagementMode: JExtractMemoryManagementMode = .default + @Option(help: "The memory management mode to use for the generated code. By default, the user must explicitly provide `SwiftArena` to all calls that require it. By choosing `allowGlobalAutomatic`, user can omit this parameter and a global GC-based arena will be used.") + var memoryManagementMode: JExtractMemoryManagementMode? @Option( help: """ @@ -80,7 +80,7 @@ extension SwiftJava { var dependsOn: [String] = [] @Option(help: "The mode to use for extracting asynchronous Swift functions. By default async methods are extracted as Java functions returning CompletableFuture.") - var asyncFuncMode: JExtractAsyncFuncMode = .default + var asyncFuncMode: JExtractAsyncFuncMode? } } @@ -89,21 +89,21 @@ extension SwiftJava.JExtractCommand { if let javaPackage { config.javaPackage = javaPackage } - if let mode { - config.mode = mode - } else if config.mode == nil { - config.mode = .ffm - } + configure(&config.mode, overrideWith: self.mode) config.swiftModule = self.effectiveSwiftModule config.outputJavaDirectory = outputJava config.outputSwiftDirectory = outputSwift - config.writeEmptyFiles = writeEmptyFiles - config.unsignedNumbersMode = unsignedNumbers - config.minimumInputAccessLevelMode = minimumInputAccessLevel - config.memoryManagementMode = memoryManagementMode - config.asyncFuncMode = asyncFuncMode - try checkModeCompatibility() + // @Flag does not support optional, so we check ourself if it is passed + let writeEmptyFiles = CommandLine.arguments.contains("--write-empty-files") ? true : nil + configure(&config.writeEmptyFiles, overrideWith: writeEmptyFiles) + + configure(&config.unsignedNumbersMode, overrideWith: self.unsignedNumbersMode) + configure(&config.minimumInputAccessLevelMode, overrideWith: self.minimumInputAccessLevelMode) + configure(&config.memoryManagementMode, overrideWith: self.memoryManagementMode) + configure(&config.asyncFuncMode, overrideWith: self.asyncFuncMode) + + try checkModeCompatibility(config: config) if let inputSwift = commonOptions.inputSwift { config.inputSwiftDirectory = inputSwift @@ -112,7 +112,7 @@ extension SwiftJava.JExtractCommand { config.inputSwiftDirectory = "\(FileManager.default.currentDirectoryPath)/Sources/\(swiftModule)" } - print("[debug][swift-java] Running 'swift-java jextract' in mode: " + "\(config.mode ?? .ffm)".bold) + print("[debug][swift-java] Running 'swift-java jextract' in mode: " + "\(config.effectiveMode)".bold) // Load all of the dependent configurations and associate them with Swift modules. let dependentConfigs = try loadDependentConfigs(dependsOn: self.dependsOn) @@ -122,20 +122,26 @@ extension SwiftJava.JExtractCommand { } /// Check if the configured modes are compatible, and fail if not - func checkModeCompatibility() throws { - if self.mode == .jni { - switch self.unsignedNumbers { + func checkModeCompatibility(config: Configuration) throws { + if config.effectiveMode == .jni { + switch config.effectiveUnsignedNumbersMode { case .annotate: () // OK case .wrapGuava: throw IllegalModeCombinationError("JNI mode does not support '\(JExtractUnsignedIntegerMode.wrapGuava)' Unsigned integer mode! \(Self.helpMessage)") } - } else if self.mode == .ffm { - guard self.memoryManagementMode == .explicit else { + } else if config.effectiveMode == .ffm { + guard config.effectiveMemoryManagementMode == .explicit else { throw IllegalModeCombinationError("FFM mode does not support '\(self.memoryManagementMode)' memory management mode! \(Self.helpMessage)") } } } + + func configure(_ setting: inout T?, overrideWith value: T?) { + if let value { + setting = value + } + } } struct IncompatibleModeError: Error { diff --git a/Sources/SwiftJavaTool/SwiftJavaBaseAsyncParsableCommand.swift b/Sources/SwiftJavaTool/SwiftJavaBaseAsyncParsableCommand.swift index 25b162e1..6b8c0ec6 100644 --- a/Sources/SwiftJavaTool/SwiftJavaBaseAsyncParsableCommand.swift +++ b/Sources/SwiftJavaTool/SwiftJavaBaseAsyncParsableCommand.swift @@ -167,4 +167,4 @@ extension SwiftJavaBaseAsyncParsableCommand { config.logLevel = command.logLevel return config } -} \ No newline at end of file +} From cc0ff8f6e478a05079c7206d7d4014d9c6eef776 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Tue, 4 Nov 2025 15:53:28 +0900 Subject: [PATCH 382/426] Adjust Task.immediate use so we can bring back Swift 6.1 CI until 6.2 is fixed (#417) --- .github/workflows/pull_request.yml | 4 +- Package.swift | 2 +- .../Package.swift | 2 +- Sources/JExtractSwiftLib/CodePrinter.swift | 14 ++ ...wift2JavaGenerator+NativeTranslation.swift | 24 ++-- .../Asserts/TextAssertions.swift | 22 ++-- .../JNI/JNIAsyncTests.swift | 122 ++++++++++-------- docker/Dockerfile | 2 +- 8 files changed, 110 insertions(+), 82 deletions(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 5e5b767a..70cff51c 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -140,7 +140,7 @@ jobs: strategy: fail-fast: false matrix: - swift_version: ['6.2', 'nightly'] + swift_version: ['6.1.3', '6.2', 'nightly'] os_version: ['jammy'] jdk_vendor: ['corretto'] container: @@ -182,7 +182,7 @@ jobs: strategy: fail-fast: false matrix: - swift_version: ['6.2', 'nightly'] + swift_version: ['6.1.3', '6.2', 'nightly'] os_version: ['jammy'] jdk_vendor: ['corretto'] sample_app: [ # TODO: use a reusable-workflow to generate those names diff --git a/Package.swift b/Package.swift index 09743135..7ac7d1f9 100644 --- a/Package.swift +++ b/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version: 6.2 +// swift-tools-version: 6.1 // The swift-tools-version declares the minimum version of Swift required to build this package. import CompilerPluginSupport diff --git a/Samples/SwiftJavaExtractJNISampleApp/Package.swift b/Samples/SwiftJavaExtractJNISampleApp/Package.swift index 33a35c49..6343e0db 100644 --- a/Samples/SwiftJavaExtractJNISampleApp/Package.swift +++ b/Samples/SwiftJavaExtractJNISampleApp/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version: 6.2 +// swift-tools-version: 6.1 // The swift-tools-version declares the minimum version of Swift required to build this package. import CompilerPluginSupport diff --git a/Sources/JExtractSwiftLib/CodePrinter.swift b/Sources/JExtractSwiftLib/CodePrinter.swift index c5f04d51..e6498683 100644 --- a/Sources/JExtractSwiftLib/CodePrinter.swift +++ b/Sources/JExtractSwiftLib/CodePrinter.swift @@ -70,6 +70,20 @@ public struct CodePrinter { } } + public mutating func printHashIfBlock( + _ header: Any, + function: String = #function, + file: String = #fileID, + line: UInt = #line, + body: (inout CodePrinter) throws -> () + ) rethrows { + print("#if \(header)") + indent() + try body(&self) + outdent() + print("#endif // end of \(header)", .sloc, function: function, file: file, line: line) + } + public mutating func printBraceBlock( _ header: Any, function: String = #function, diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift index 727294b1..d4ce9426 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift @@ -825,7 +825,7 @@ extension JNISwift2JavaGenerator { func printDo(printer: inout CodePrinter) { printer.print("let swiftResult$ = await \(placeholder)") - printer.print("environment = try JavaVirtualMachine.shared().environment()") + printer.print("environment = try! JavaVirtualMachine.shared().environment()") let inner = inner.render(&printer, "swiftResult$") if swiftFunctionResultType.isVoid { printer.print("environment.interface.CallBooleanMethodA(environment, globalFuture, _JNIMethodIDCache.CompletableFuture.complete, [jvalue(l: nil)])") @@ -839,7 +839,7 @@ extension JNISwift2JavaGenerator { } } - func printTask(printer: inout CodePrinter) { + func printTaskBody(printer: inout CodePrinter) { printer.printBraceBlock("defer") { printer in // Defer might on any thread, so we need to attach environment. printer.print("let deferEnvironment = try! JavaVirtualMachine.shared().environment()") @@ -867,18 +867,22 @@ extension JNISwift2JavaGenerator { } } - printer.printBraceBlock("if #available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, *)") { printer in - printer.printBraceBlock("Task.immediate") { printer in - // Immediate runs on the caller thread, so we don't need to attach the environment again. - printer.print("var environment = environment!") // this is to ensure we always use the same environment name, even though we are rebinding it. - printTask(printer: &printer) + printer.print("var task: Task? = nil") + printer.printHashIfBlock("swift(>=6.2)") { printer in + printer.printBraceBlock("if #available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, *)") { printer in + printer.printBraceBlock("task = Task.immediate") { printer in + // Immediate runs on the caller thread, so we don't need to attach the environment again. + printer.print("var environment = environment!") // this is to ensure we always use the same environment name, even though we are rebinding it. + printTaskBody(printer: &printer) + } } } - printer.printBraceBlock("else") { printer in - printer.printBraceBlock("Task") { printer in + + printer.printBraceBlock("if task == nil") { printer in + printer.printBraceBlock("task = Task") { printer in // We can be on any thread, so we need to attach the thread. printer.print("var environment = try! JavaVirtualMachine.shared().environment()") - printTask(printer: &printer) + printTaskBody(printer: &printer) } } diff --git a/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift b/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift index 001d34fa..67671548 100644 --- a/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift +++ b/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift @@ -179,7 +179,9 @@ func assertOutput( print("==== ---------------------------------------------------------------") print("Expected output:") for (n, e) in expectedLines.enumerated() { - print("\(n): \(e)".yellow(if: diffLineNumbers.map({$0 - matchingOutputOffset}).contains(n))) + let isMismatch = diffLineNumbers.map({$0 - matchingOutputOffset}).contains(n) + let marker = isMismatch ? " // <<<<<<<<<<< mismatch" : "" + print("\(n): \(e)\(marker)".yellow(if: isMismatch)) } } @@ -188,15 +190,7 @@ func assertOutput( let printFromLineNo = matchingOutputOffset for (n, g) in gotLines.enumerated() where n >= printFromLineNo { let baseLine = "\(n): \(g)" - var line = baseLine - if diffLineNumbers.contains(n) { - line += "\n" - let leadingCount = "\(n): ".count - let message = "\(String(repeating: " ", count: leadingCount))\(String(repeating: "^", count: 8)) EXPECTED MATCH OR SEARCHING FROM HERE " - line += "\(message)\(String(repeating: "^", count: max(0, line.count - message.count)))" - line = line.red - } - print(line) + print(baseLine) } print("==== ---------------------------------------------------------------\n") } @@ -248,14 +242,18 @@ func assertOutput( print("==== ---------------------------------------------------------------") print("Expected output:") for (n, e) in expectedLines.enumerated() { - print("\(e)".yellow(if: diffLineNumbers.contains(n))) + let isMismatch = diffLineNumbers.contains(n) + let marker = isMismatch ? " // <<<<<<<< error: mismatch" : "" + print("\(e)\(marker)".yellow(if: isMismatch)) } } print("==== ---------------------------------------------------------------") print("Got output:") for (n, g) in gotLines.enumerated() { - print("\(g)".red(if: diffLineNumbers.contains(n))) + let isMismatch = diffLineNumbers.contains(n) + let marker = isMismatch ? "// <<<<<<<< error: mismatch" : "" + print("\(g)\(marker)".red(if: isMismatch)) } print("==== ---------------------------------------------------------------\n") } diff --git a/Tests/JExtractSwiftTests/JNI/JNIAsyncTests.swift b/Tests/JExtractSwiftTests/JNI/JNIAsyncTests.swift index 6b26c69b..82922c7d 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIAsyncTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIAsyncTests.swift @@ -59,27 +59,30 @@ struct JNIAsyncTests { @_cdecl("Java_com_example_swift_SwiftModule__00024asyncVoid__Ljava_util_concurrent_CompletableFuture_2") func Java_com_example_swift_SwiftModule__00024asyncVoid__Ljava_util_concurrent_CompletableFuture_2(environment: UnsafeMutablePointer!, thisClass: jclass, result_future: jobject?) { let globalFuture = environment.interface.NewGlobalRef(environment, result_future) - if #available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, *) { - Task.immediate { - var environment = environment! - defer { - let deferEnvironment = try! JavaVirtualMachine.shared().environment() - environment.interface.DeleteGlobalRef(deferEnvironment, globalFuture) + var task: Task? = nil + #if swift(>=6.2) + if #available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, *) { + task = Task.immediate { + var environment = environment! + defer { + let deferEnvironment = try! JavaVirtualMachine.shared().environment() + environment.interface.DeleteGlobalRef(deferEnvironment, globalFuture) + } + let swiftResult$ = await SwiftModule.asyncVoid() + environment = try! JavaVirtualMachine.shared().environment() + environment.interface.CallBooleanMethodA(environment, globalFuture, _JNIMethodIDCache.CompletableFuture.complete, [jvalue(l: nil)]) } - let swiftResult$ = await SwiftModule.asyncVoid() - environment = try JavaVirtualMachine.shared().environment() - environment.interface.CallBooleanMethodA(environment, globalFuture, _JNIMethodIDCache.CompletableFuture.complete, [jvalue(l: nil)]) } - } - else { - Task { + #endif + if task == nil { + task = Task { var environment = try! JavaVirtualMachine.shared().environment() defer { let deferEnvironment = try! JavaVirtualMachine.shared().environment() environment.interface.DeleteGlobalRef(deferEnvironment, globalFuture) } let swiftResult$ = await SwiftModule.asyncVoid() - environment = try JavaVirtualMachine.shared().environment() + environment = try! JavaVirtualMachine.shared().environment() environment.interface.CallBooleanMethodA(environment, globalFuture, _JNIMethodIDCache.CompletableFuture.complete, [jvalue(l: nil)]) } } @@ -130,27 +133,30 @@ struct JNIAsyncTests { @_cdecl("Java_com_example_swift_SwiftModule__00024async__Ljava_util_concurrent_CompletableFuture_2") func Java_com_example_swift_SwiftModule__00024async__Ljava_util_concurrent_CompletableFuture_2(environment: UnsafeMutablePointer!, thisClass: jclass, result_future: jobject?) { let globalFuture = environment.interface.NewGlobalRef(environment, result_future) - if #available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, *) { - Task.immediate { - var environment = environment! - defer { - let deferEnvironment = try! JavaVirtualMachine.shared().environment() - environment.interface.DeleteGlobalRef(deferEnvironment, globalFuture) - } - do { - let swiftResult$ = await try SwiftModule.async() - environment = try JavaVirtualMachine.shared().environment() - environment.interface.CallBooleanMethodA(environment, globalFuture, _JNIMethodIDCache.CompletableFuture.complete, [jvalue(l: nil)]) - } - catch { - let catchEnvironment = try! JavaVirtualMachine.shared().environment() - let exception = catchEnvironment.interface.NewObjectA(catchEnvironment, _JNIMethodIDCache.Exception.class, _JNIMethodIDCache.Exception.constructWithMessage, [String(describing: error).getJValue(in: catchEnvironment)]) - catchEnvironment.interface.CallBooleanMethodA(catchEnvironment, globalFuture, _JNIMethodIDCache.CompletableFuture.completeExceptionally, [jvalue(l: exception)]) + var task: Task? = nil + #if swift(>=6.2) + if #available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, *) { + task = Task.immediate { + var environment = environment! + defer { + let deferEnvironment = try! JavaVirtualMachine.shared().environment() + environment.interface.DeleteGlobalRef(deferEnvironment, globalFuture) + } + do { + let swiftResult$ = await try SwiftModule.async() + environment = try! JavaVirtualMachine.shared().environment() + environment.interface.CallBooleanMethodA(environment, globalFuture, _JNIMethodIDCache.CompletableFuture.complete, [jvalue(l: nil)]) + } + catch { + let catchEnvironment = try! JavaVirtualMachine.shared().environment() + let exception = catchEnvironment.interface.NewObjectA(catchEnvironment, _JNIMethodIDCache.Exception.class, _JNIMethodIDCache.Exception.constructWithMessage, [String(describing: error).getJValue(in: catchEnvironment)]) + catchEnvironment.interface.CallBooleanMethodA(catchEnvironment, globalFuture, _JNIMethodIDCache.CompletableFuture.completeExceptionally, [jvalue(l: exception)]) + } } } - } - else { - Task { + #endif + if task == nil { + task = Task { var environment = try! JavaVirtualMachine.shared().environment() defer { let deferEnvironment = try! JavaVirtualMachine.shared().environment() @@ -158,7 +164,7 @@ struct JNIAsyncTests { } do { let swiftResult$ = await try SwiftModule.async() - environment = try JavaVirtualMachine.shared().environment() + environment = try! JavaVirtualMachine.shared().environment() environment.interface.CallBooleanMethodA(environment, globalFuture, _JNIMethodIDCache.CompletableFuture.complete, [jvalue(l: nil)]) } catch { @@ -215,28 +221,31 @@ struct JNIAsyncTests { @_cdecl("Java_com_example_swift_SwiftModule__00024async__JLjava_util_concurrent_CompletableFuture_2") func Java_com_example_swift_SwiftModule__00024async__JLjava_util_concurrent_CompletableFuture_2(environment: UnsafeMutablePointer!, thisClass: jclass, i: jlong, result_future: jobject?) { let globalFuture = environment.interface.NewGlobalRef(environment, result_future) + var task: Task? = nil + #if swift(>=6.2) if #available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, *) { - Task.immediate { + task = Task.immediate { var environment = environment! defer { let deferEnvironment = try! JavaVirtualMachine.shared().environment() environment.interface.DeleteGlobalRef(deferEnvironment, globalFuture) } let swiftResult$ = await SwiftModule.async(i: Int64(fromJNI: i, in: environment)) - environment = try JavaVirtualMachine.shared().environment() + environment = try! JavaVirtualMachine.shared().environment() let boxedResult$ = SwiftJavaRuntimeSupport._JNIBoxedConversions.box(swiftResult$.getJNIValue(in: environment), in: environment) environment.interface.CallBooleanMethodA(environment, globalFuture, _JNIMethodIDCache.CompletableFuture.complete, [jvalue(l: boxedResult$)]) } } - else { - Task { + #endif // end of swift(>=6.2) + if task == nil { + task = Task { var environment = try! JavaVirtualMachine.shared().environment() defer { let deferEnvironment = try! JavaVirtualMachine.shared().environment() environment.interface.DeleteGlobalRef(deferEnvironment, globalFuture) } let swiftResult$ = await SwiftModule.async(i: Int64(fromJNI: i, in: environment)) - environment = try JavaVirtualMachine.shared().environment() + environment = try! JavaVirtualMachine.shared().environment() let boxedResult$ = SwiftJavaRuntimeSupport._JNIBoxedConversions.box(swiftResult$.getJNIValue(in: environment), in: environment) environment.interface.CallBooleanMethodA(environment, globalFuture, _JNIMethodIDCache.CompletableFuture.complete, [jvalue(l: boxedResult$)]) } @@ -303,31 +312,34 @@ struct JNIAsyncTests { fatalError("c memory address was null in call to \\(#function)!") } let globalFuture = environment.interface.NewGlobalRef(environment, result_future) - if #available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, *) { - Task.immediate { - var environment = environment! - defer { - let deferEnvironment = try! JavaVirtualMachine.shared().environment() - environment.interface.DeleteGlobalRef(deferEnvironment, globalFuture) + var task: Task? = nil + #if swift(>=6.2) + if #available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, *) { + task = Task.immediate { + var environment = environment! + defer { + let deferEnvironment = try! JavaVirtualMachine.shared().environment() + environment.interface.DeleteGlobalRef(deferEnvironment, globalFuture) + } + let swiftResult$ = await SwiftModule.async(c: c$.pointee) + environment = try! JavaVirtualMachine.shared().environment() + let result$ = UnsafeMutablePointer.allocate(capacity: 1) + result$.initialize(to: swiftResult$) + let resultBits$ = Int64(Int(bitPattern: result$)) + let boxedResult$ = SwiftJavaRuntimeSupport._JNIBoxedConversions.box(resultBits$.getJNIValue(in: environment), in: environment) + environment.interface.CallBooleanMethodA(environment, globalFuture, _JNIMethodIDCache.CompletableFuture.complete, [jvalue(l: boxedResult$)]) } - let swiftResult$ = await SwiftModule.async(c: c$.pointee) - environment = try JavaVirtualMachine.shared().environment() - let result$ = UnsafeMutablePointer.allocate(capacity: 1) - result$.initialize(to: swiftResult$) - let resultBits$ = Int64(Int(bitPattern: result$)) - let boxedResult$ = SwiftJavaRuntimeSupport._JNIBoxedConversions.box(resultBits$.getJNIValue(in: environment), in: environment) - environment.interface.CallBooleanMethodA(environment, globalFuture, _JNIMethodIDCache.CompletableFuture.complete, [jvalue(l: boxedResult$)]) } - } - else { - Task { + #endif + if task == nil { + task = Task { var environment = try! JavaVirtualMachine.shared().environment() defer { let deferEnvironment = try! JavaVirtualMachine.shared().environment() environment.interface.DeleteGlobalRef(deferEnvironment, globalFuture) } let swiftResult$ = await SwiftModule.async(c: c$.pointee) - environment = try JavaVirtualMachine.shared().environment() + environment = try! JavaVirtualMachine.shared().environment() let result$ = UnsafeMutablePointer.allocate(capacity: 1) result$.initialize(to: swiftResult$) let resultBits$ = Int64(Int(bitPattern: result$)) diff --git a/docker/Dockerfile b/docker/Dockerfile index 1109dab3..ef428b87 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -21,10 +21,10 @@ ENV LANGUAGE=en_US.UTF-8 # JDK dependency RUN curl -s "https://get.sdkman.io" | bash RUN bash -c "source /root/.sdkman/bin/sdkman-init.sh && sdk install java 25.0.1-amzn" +ENV JAVA_HOME="$(sdk home java current)" RUN curl -O https://download.swift.org/swiftly/linux/swiftly-$(uname -m).tar.gz && \ tar zxf swiftly-$(uname -m).tar.gz && \ ./swiftly init --quiet-shell-followup --assume-yes && \ . "${SWIFTLY_HOME_DIR:-$HOME/.local/share/swiftly}/env.sh" && \ hash -r - From b4706f3f744de3b27cef892af580ed11419811f2 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Wed, 5 Nov 2025 11:51:16 +0900 Subject: [PATCH 383/426] Disable swift-syntax prebuilts (primarily on linux) (#422) --- .github/workflows/pull_request.yml | 8 ++++---- Samples/JavaDependencySampleApp/ci-validate.sh | 6 +++++- Samples/JavaProbablyPrime/ci-validate.sh | 5 ++++- Samples/SwiftAndJavaJarSampleLib/build.gradle | 3 ++- Samples/SwiftJavaExtractFFMSampleApp/build.gradle | 3 ++- Samples/SwiftJavaExtractFFMSampleApp/ci-validate.sh | 2 +- Samples/SwiftJavaExtractJNISampleApp/build.gradle | 3 ++- Samples/SwiftJavaExtractJNISampleApp/ci-validate.sh | 2 +- SwiftKitCore/build.gradle | 3 ++- SwiftKitFFM/build.gradle | 3 ++- 10 files changed, 25 insertions(+), 13 deletions(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 70cff51c..16151168 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -38,7 +38,7 @@ jobs: - name: Prepare CI Environment uses: ./.github/actions/prepare_env - name: Swift Build - run: swift build + run: swift build --disable-experimental-prebuilts # FIXME: until prebuilt swift-syntax isn't broken on 6.2 anymore: https://github.com/swiftlang/swift-java/issues/418 - name: Run documentation check run: ./.github/scripts/validate_docs.sh @@ -132,7 +132,7 @@ jobs: - name: Install jemalloc run: apt-get update && apt-get install -y libjemalloc-dev - name: Swift Benchmarks - run: swift package --package-path Benchmarks/ benchmark + run: swift package --package-path Benchmarks/ --disable-experimental-prebuilts benchmark # FIXME: until prebuilt swift-syntax isn't broken on 6.2 anymore: https://github.com/swiftlang/swift-java/issues/418 test-swift: name: Test (Swift) (${{ matrix.os_version }} swift:${{ matrix.swift_version }} jdk:${{matrix.jdk_vendor}}) @@ -152,9 +152,9 @@ jobs: - name: Prepare CI Environment uses: ./.github/actions/prepare_env - name: Swift Build - run: "swift build --build-tests --disable-sandbox" + run: swift build --build-tests --disable-sandbox --disable-experimental-prebuilts # FIXME: until prebuilt swift-syntax isn't broken on 6.2 anymore: https://github.com/swiftlang/swift-java/issues/418 - name: Swift Test - run: "swift test" + run: swift test --disable-experimental-prebuilts # FIXME: until prebuilt swift-syntax isn't broken on 6.2 anymore: https://github.com/swiftlang/swift-java/issues/418 test-swift-macos: name: Test (Swift) (${{ matrix.os_version }} swift:${{ matrix.swift_version }} jdk:${{matrix.jdk_vendor}}) diff --git a/Samples/JavaDependencySampleApp/ci-validate.sh b/Samples/JavaDependencySampleApp/ci-validate.sh index 2758e6aa..b6162fdc 100755 --- a/Samples/JavaDependencySampleApp/ci-validate.sh +++ b/Samples/JavaDependencySampleApp/ci-validate.sh @@ -8,7 +8,11 @@ swift run --disable-sandbox # explicitly invoke resolve without explicit path or dependency # the dependencies should be uses from the --swift-module -swift run swift-java resolve \ + +# FIXME: until prebuilt swift-syntax isn't broken on 6.2 anymore: https://github.com/swiftlang/swift-java/issues/418 +swift run \ + --disable-experimental-prebuilts \ + swift-java resolve \ Sources/JavaCommonsCSV/swift-java.config \ --swift-module JavaCommonsCSV \ --output-directory .build/plugins/outputs/javadependencysampleapp/JavaCommonsCSV/destination/SwiftJavaPlugin/ diff --git a/Samples/JavaProbablyPrime/ci-validate.sh b/Samples/JavaProbablyPrime/ci-validate.sh index 0bdd86d1..dc624996 100755 --- a/Samples/JavaProbablyPrime/ci-validate.sh +++ b/Samples/JavaProbablyPrime/ci-validate.sh @@ -3,4 +3,7 @@ set -e set -x -swift run JavaProbablyPrime 1337 \ No newline at end of file +# FIXME: until prebuilt swift-syntax isn't broken on 6.2 anymore: https://github.com/swiftlang/swift-java/issues/418 +swift run \ + --disable-experimental-prebuilts \ + JavaProbablyPrime 1337 \ No newline at end of file diff --git a/Samples/SwiftAndJavaJarSampleLib/build.gradle b/Samples/SwiftAndJavaJarSampleLib/build.gradle index 3ad59fe5..e6404adb 100644 --- a/Samples/SwiftAndJavaJarSampleLib/build.gradle +++ b/Samples/SwiftAndJavaJarSampleLib/build.gradle @@ -116,7 +116,8 @@ def jextract = tasks.register("jextract", Exec) { workingDir = layout.projectDirectory commandLine "swift" - args("build") // since Swift targets which need to be jextract-ed have the jextract build plugin, we just need to build + // FIXME: disable prebuilts until swift-syntax isn't broken on 6.2 anymore: https://github.com/swiftlang/swift-java/issues/418 + args("build", "--disable-experimental-prebuilts") // since Swift targets which need to be jextract-ed have the jextract build plugin, we just need to build // If we wanted to execute a specific subcommand, we can like this: // args("run",/* // "swift-java", "jextract", diff --git a/Samples/SwiftJavaExtractFFMSampleApp/build.gradle b/Samples/SwiftJavaExtractFFMSampleApp/build.gradle index 0200f234..dcfacdd3 100644 --- a/Samples/SwiftJavaExtractFFMSampleApp/build.gradle +++ b/Samples/SwiftJavaExtractFFMSampleApp/build.gradle @@ -101,7 +101,8 @@ def jextract = tasks.register("jextract", Exec) { workingDir = layout.projectDirectory commandLine "swift" - args("build") // since Swift targets which need to be jextract-ed have the jextract build plugin, we just need to build + // FIXME: disable prebuilts until swift-syntax isn't broken on 6.2 anymore: https://github.com/swiftlang/swift-java/issues/418 + args("build", "--disable-experimental-prebuilts") // since Swift targets which need to be jextract-ed have the jextract build plugin, we just need to build // If we wanted to execute a specific subcommand, we can like this: // args("run",/* // "swift-java", "jextract", diff --git a/Samples/SwiftJavaExtractFFMSampleApp/ci-validate.sh b/Samples/SwiftJavaExtractFFMSampleApp/ci-validate.sh index 8758bbee..ff5c32c8 100755 --- a/Samples/SwiftJavaExtractFFMSampleApp/ci-validate.sh +++ b/Samples/SwiftJavaExtractFFMSampleApp/ci-validate.sh @@ -3,7 +3,7 @@ set -x set -e -swift build # as a workaround for building swift build from within gradle having issues on CI sometimes +swift build --disable-experimental-prebuilts # FIXME: until prebuilt swift-syntax isn't broken on 6.2 anymore: https://github.com/swiftlang/swift-java/issues/418 ./gradlew run ./gradlew test \ No newline at end of file diff --git a/Samples/SwiftJavaExtractJNISampleApp/build.gradle b/Samples/SwiftJavaExtractJNISampleApp/build.gradle index b1aa8490..7f30ee42 100644 --- a/Samples/SwiftJavaExtractJNISampleApp/build.gradle +++ b/Samples/SwiftJavaExtractJNISampleApp/build.gradle @@ -102,7 +102,8 @@ def jextract = tasks.register("jextract", Exec) { workingDir = layout.projectDirectory commandLine "swift" - args("build") // since Swift targets which need to be jextract-ed have the jextract build plugin, we just need to build + // FIXME: disable prebuilts until swift-syntax isn't broken on 6.2 anymore: https://github.com/swiftlang/swift-java/issues/418 + args("build", "--disable-experimental-prebuilts") // since Swift targets which need to be jextract-ed have the jextract build plugin, we just need to build // If we wanted to execute a specific subcommand, we can like this: // args("run",/* // "swift-java", "jextract", diff --git a/Samples/SwiftJavaExtractJNISampleApp/ci-validate.sh b/Samples/SwiftJavaExtractJNISampleApp/ci-validate.sh index 8758bbee..ff5c32c8 100755 --- a/Samples/SwiftJavaExtractJNISampleApp/ci-validate.sh +++ b/Samples/SwiftJavaExtractJNISampleApp/ci-validate.sh @@ -3,7 +3,7 @@ set -x set -e -swift build # as a workaround for building swift build from within gradle having issues on CI sometimes +swift build --disable-experimental-prebuilts # FIXME: until prebuilt swift-syntax isn't broken on 6.2 anymore: https://github.com/swiftlang/swift-java/issues/418 ./gradlew run ./gradlew test \ No newline at end of file diff --git a/SwiftKitCore/build.gradle b/SwiftKitCore/build.gradle index f4376e94..bc6bd279 100644 --- a/SwiftKitCore/build.gradle +++ b/SwiftKitCore/build.gradle @@ -84,7 +84,8 @@ def compileSwift = tasks.register("compileSwift", Exec) { workingDir = rootDir commandLine "swift" - args("build", "--target", "SwiftRuntimeFunctions") + // FIXME: disable prebuilts until swift-syntax isn't broken on 6.2 anymore: https://github.com/swiftlang/swift-java/issues/418 + args("build", "--disable-experimental-prebuilts", "--target", "SwiftRuntimeFunctions") } tasks.build { dependsOn("compileSwift") diff --git a/SwiftKitFFM/build.gradle b/SwiftKitFFM/build.gradle index dcbbe8df..08a36a3e 100644 --- a/SwiftKitFFM/build.gradle +++ b/SwiftKitFFM/build.gradle @@ -86,7 +86,8 @@ def compileSwift = tasks.register("compileSwift", Exec) { workingDir = rootDir commandLine "swift" - args("build", "--target", "SwiftRuntimeFunctions") + // FIXME: disable prebuilts until swift-syntax isn't broken on 6.2 anymore: https://github.com/swiftlang/swift-java/issues/418 + args("build", "--disable-experimental-prebuilts", "--target", "SwiftRuntimeFunctions") } tasks.build { dependsOn("compileSwift") From a9f4f07a94acc8af07ba6c118072235d8ed70054 Mon Sep 17 00:00:00 2001 From: Mads Odgaard Date: Wed, 5 Nov 2025 23:08:00 +0100 Subject: [PATCH 384/426] fix docs about init and add tests (#426) --- .../Sources/MySwiftLibrary/MySwiftClass.swift | 8 ++++++++ .../Sources/MySwiftLibrary/MySwiftStruct.swift | 8 ++++++++ .../java/com/example/swift/MySwiftClassTest.java | 11 +++++++++++ .../java/com/example/swift/MySwiftStructTest.java | 13 +++++++++++++ .../Documentation.docc/SupportedFeatures.md | 2 +- 5 files changed, 41 insertions(+), 1 deletion(-) diff --git a/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftClass.swift b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftClass.swift index 4b334a5e..e6aed287 100644 --- a/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftClass.swift +++ b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftClass.swift @@ -59,6 +59,14 @@ public class MySwiftClass { self.y = 5 } + convenience public init(throwing: Bool) throws { + if throwing { + throw MySwiftError.swiftError + } else { + self.init() + } + } + deinit { p("deinit called!") } diff --git a/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftStruct.swift b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftStruct.swift index 00e2533c..ddd77132 100644 --- a/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftStruct.swift +++ b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftStruct.swift @@ -21,6 +21,14 @@ public struct MySwiftStruct { self.len = len } + public init?(doInit: Bool) { + if doInit { + self.init(cap: 10, len: 10) + } else { + return nil + } + } + public func getCapacity() -> Int64 { self.cap } diff --git a/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/MySwiftClassTest.java b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/MySwiftClassTest.java index fba8f13f..a5838629 100644 --- a/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/MySwiftClassTest.java +++ b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/MySwiftClassTest.java @@ -40,6 +40,17 @@ void init_withParameters() { } } + @Test + void init_throwing() { + try (var arena = SwiftArena.ofConfined()) { + Exception exception = assertThrows(Exception.class, () -> MySwiftClass.init(true, arena)); + assertEquals("swiftError", exception.getMessage()); + + MySwiftClass c = assertDoesNotThrow(() -> MySwiftClass.init(false, arena)); + assertNotNull(c); + } + } + @Test void sum() { try (var arena = SwiftArena.ofConfined()) { diff --git a/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/MySwiftStructTest.java b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/MySwiftStructTest.java index c2c1170b..e52e1959 100644 --- a/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/MySwiftStructTest.java +++ b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/MySwiftStructTest.java @@ -18,6 +18,8 @@ import org.swift.swiftkit.core.ConfinedSwiftMemorySession; import org.swift.swiftkit.core.SwiftArena; +import java.util.Optional; + import static org.junit.jupiter.api.Assertions.*; public class MySwiftStructTest { @@ -30,6 +32,17 @@ void init() { } } + @Test + void init_optional() { + try (var arena = SwiftArena.ofConfined()) { + assertEquals(Optional.empty(), MySwiftStruct.init(false, arena)); + + Optional optionalStruct = MySwiftStruct.init(true, arena); + assertTrue(optionalStruct.isPresent()); + assertEquals(10, optionalStruct.get().getLen()); + } + } + @Test void getAndSetLen() { try (var arena = SwiftArena.ofConfined()) { diff --git a/Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md b/Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md index 98dac732..4bbaee40 100644 --- a/Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md +++ b/Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md @@ -47,7 +47,7 @@ SwiftJava's `swift-java jextract` tool automates generating Java bindings from S | Swift Feature | FFM | JNI | |--------------------------------------------------------------------------------------|----------|-----| | Initializers: `class`, `struct` | ✅ | ✅ | -| Optional Initializers / Throwing Initializers | ❌ | ❌ | +| Optional Initializers / Throwing Initializers | ❌ | ✅ | | Deinitializers: `class`, `struct` | ✅ | ✅ | | `enum` | ❌ | ✅ | | `actor` | ❌ | ❌ | From 3ebdfbb309c327c3dae87ecf345ec4c53cd5d509 Mon Sep 17 00:00:00 2001 From: Mads Odgaard Date: Thu, 6 Nov 2025 10:45:47 +0100 Subject: [PATCH 385/426] Add CI to build JNI Sample for Android (#427) Co-authored-by: Konrad `ktoso` Malawski --- .github/workflows/pull_request.yml | 24 +++++++++++++++++++ .../SwiftJavaExtractJNISampleApp/build.gradle | 13 ++++++++-- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 16151168..a0f2eda5 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -176,6 +176,30 @@ jobs: - name: Swift Test run: "swift test" + build-swift-android: + name: Sample SwiftJavaExtractJNISampleApp (Android) (${{ matrix.os_version }} swift:${{ matrix.swift_version }} jdk:${{matrix.jdk_vendor}} android:${{matrix.sdk_triple}}) + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + swift_version: ['nightly-main'] + os_version: ['jammy'] + jdk_vendor: ['corretto'] + sdk_triple: ['x86_64-unknown-linux-android28'] + ndk_version: ['r27d'] + container: + image: ${{ (contains(matrix.swift_version, 'nightly') && 'swiftlang/swift') || 'swift' }}:${{ matrix.swift_version }}-${{ matrix.os_version }} + steps: + - uses: actions/checkout@v4 + - name: Prepare CI Environment + uses: ./.github/actions/prepare_env + - name: Install Swift SDK for Android and build + run: | + apt-get -q update && apt-get -yq install curl + cd Samples/SwiftJavaExtractJNISampleApp + curl -s --retry 3 https://raw.githubusercontent.com/swiftlang/github-workflows/refs/heads/main/.github/workflows/scripts/install-and-build-with-sdk.sh | \ + bash -s -- --android --build-command="swift build" --android-sdk-triple="${{ matrix.sdk_triple }}" --android-ndk-version="${{ matrix.ndk_version }}" ${{ matrix.swift_version }} + verify-samples: name: Sample ${{ matrix.sample_app }} (${{ matrix.os_version }} swift:${{ matrix.swift_version }} jdk:${{matrix.jdk_vendor}}) runs-on: ubuntu-latest diff --git a/Samples/SwiftJavaExtractJNISampleApp/build.gradle b/Samples/SwiftJavaExtractJNISampleApp/build.gradle index 7f30ee42..a8ce51d2 100644 --- a/Samples/SwiftJavaExtractJNISampleApp/build.gradle +++ b/Samples/SwiftJavaExtractJNISampleApp/build.gradle @@ -100,10 +100,19 @@ def jextract = tasks.register("jextract", Exec) { } } + // FIXME: disable prebuilts until swift-syntax isn't broken on 6.2 anymore: https://github.com/swiftlang/swift-java/issues/418 + def cmdArgs = ["build", "--disable-experimental-prebuilts"] + + // Check if the 'swiftSdk' project property was passed + if (project.hasProperty('swiftSdk')) { + // If it was, add the --sdk argument and its value + cmdArgs.add("--swift-sdk") + cmdArgs.add(project.property('swiftSdk').toString()) + } + workingDir = layout.projectDirectory commandLine "swift" - // FIXME: disable prebuilts until swift-syntax isn't broken on 6.2 anymore: https://github.com/swiftlang/swift-java/issues/418 - args("build", "--disable-experimental-prebuilts") // since Swift targets which need to be jextract-ed have the jextract build plugin, we just need to build + args(cmdArgs) // since Swift targets which need to be jextract-ed have the jextract build plugin, we just need to build // If we wanted to execute a specific subcommand, we can like this: // args("run",/* // "swift-java", "jextract", From 79f1f8e0f336806362bcdc6e090ff7afa968f504 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Thu, 6 Nov 2025 18:56:56 +0900 Subject: [PATCH 386/426] Enhance README with simple introduction, presentation link Updated project description and added introduction section with a reference to a WWDC presentation. --- README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 6f9a5fde..abca3b9d 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,16 @@ # Swift Java Interoperability Tools and Libraries -This repository contains two approaches to Swift/Java interoperability. +This project contains tools and libraries that facilitate **Swift & Java Interoperability**. - Swift library (`SwiftJava`) and bindings generator that allows a Swift program to make use of Java libraries by wrapping Java classes in corresponding Swift types, allowing Swift to directly call any wrapped Java API. - The `swift-java` tool which offers automated ways to import or "extract" bindings to sources or libraries in either language. The results are bindings for Swift or Java. +## Introduction + +If you'd like to check out a quick introduction to Swift & Java interoperability, you may be interested in this presentation from WWDC25: [WWDC25: Explore Swift and Java interoperability](https://www.youtube.com/watch?v=QSHO-GUGidA). + +While we work on more quickstarts and documentation, please refer to the Sample projects located in [Samples/](Samples/) that showcase the various ways you can use swift-java in your Swift or Java projects. + ## Dependencies ### Required JDK versions From cc728395a68bdc89d24250ac8f1979e1fe8b853b Mon Sep 17 00:00:00 2001 From: Mads Odgaard Date: Fri, 7 Nov 2025 06:50:54 +0100 Subject: [PATCH 387/426] [jextract] fix support for objects in async (#428) Co-authored-by: Konrad `ktoso` Malawski --- .../Sources/MySwiftLibrary/Async.swift | 4 ++ .../java/com/example/swift/AsyncTest.java | 6 ++ .../Convenience/JavaType+Extensions.swift | 9 +++ ...ISwift2JavaGenerator+JavaTranslation.swift | 6 +- ...wift2JavaGenerator+NativeTranslation.swift | 41 ++++++++------ Sources/JExtractSwiftLib/JavaParameter.swift | 9 +++ .../JNI/JNIAsyncTests.swift | 55 +++++++++++++++++++ 7 files changed, 109 insertions(+), 21 deletions(-) diff --git a/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/Async.swift b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/Async.swift index ebef1892..99f3a393 100644 --- a/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/Async.swift +++ b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/Async.swift @@ -36,3 +36,7 @@ public func asyncOptional(i: Int64) async throws -> Int64? { public func asyncThrows() async throws { throw MySwiftError.swiftError } + +public func asyncString(input: String) async -> String { + return input +} diff --git a/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/AsyncTest.java b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/AsyncTest.java index ae6e7cc7..5fe7c131 100644 --- a/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/AsyncTest.java +++ b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/AsyncTest.java @@ -74,4 +74,10 @@ void asyncOptional() { CompletableFuture future = MySwiftLibrary.asyncOptional(42); assertEquals(OptionalLong.of(42), future.join()); } + + @Test + void asyncString() { + CompletableFuture future = MySwiftLibrary.asyncString("hey"); + assertEquals("hey", future.join()); + } } \ No newline at end of file diff --git a/Sources/JExtractSwiftLib/Convenience/JavaType+Extensions.swift b/Sources/JExtractSwiftLib/Convenience/JavaType+Extensions.swift index 3b29fcd3..645e5aa4 100644 --- a/Sources/JExtractSwiftLib/Convenience/JavaType+Extensions.swift +++ b/Sources/JExtractSwiftLib/Convenience/JavaType+Extensions.swift @@ -137,4 +137,13 @@ extension JavaType { return self } } + + var requiresBoxing: Bool { + switch self { + case .boolean, .byte, .char, .short, .int, .long, .float, .double: + true + default: + false + } + } } diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift index 56174e3e..a4e5ab45 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift @@ -514,14 +514,12 @@ extension JNISwift2JavaGenerator { ) // Update native function - nativeFunctionSignature.result.javaType = .void nativeFunctionSignature.result.conversion = .asyncCompleteFuture( - nativeFunctionSignature.result.conversion, swiftFunctionResultType: originalFunctionSignature.result.type, - nativeReturnType: nativeFunctionSignature.result.javaType, - outParameters: nativeFunctionSignature.result.outParameters, + nativeFunctionSignature: nativeFunctionSignature, isThrowing: originalFunctionSignature.isThrowing ) + nativeFunctionSignature.result.javaType = .void nativeFunctionSignature.result.outParameters.append(.init(name: "result_future", type: nativeFutureType)) } } diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift index d4ce9426..13e8c676 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift @@ -570,10 +570,8 @@ extension JNISwift2JavaGenerator { indirect case unwrapOptional(NativeSwiftConversionStep, name: String, fatalErrorMessage: String) indirect case asyncCompleteFuture( - NativeSwiftConversionStep, swiftFunctionResultType: SwiftType, - nativeReturnType: JavaType, - outParameters: [JavaParameter], + nativeFunctionSignature: NativeFunctionSignature, isThrowing: Bool ) @@ -806,15 +804,22 @@ extension JNISwift2JavaGenerator { return unwrappedName case .asyncCompleteFuture( - let inner, let swiftFunctionResultType, - let nativeReturnType, - let outParameters, + let nativeFunctionSignature, let isThrowing ): + var globalRefs: [String] = ["globalFuture"] + // Global ref all indirect returns - for outParameter in outParameters { + for outParameter in nativeFunctionSignature.result.outParameters { printer.print("let \(outParameter.name) = environment.interface.NewGlobalRef(environment, \(outParameter.name))") + globalRefs.append(outParameter.name) + } + + // We also need to global ref any objects passed in + for parameter in nativeFunctionSignature.parameters.flatMap(\.parameters) where !parameter.type.isPrimitive { + printer.print("let \(parameter.name) = environment.interface.NewGlobalRef(environment, \(parameter.name))") + globalRefs.append(parameter.name) } printer.print( @@ -826,16 +831,19 @@ extension JNISwift2JavaGenerator { func printDo(printer: inout CodePrinter) { printer.print("let swiftResult$ = await \(placeholder)") printer.print("environment = try! JavaVirtualMachine.shared().environment()") - let inner = inner.render(&printer, "swiftResult$") + let inner = nativeFunctionSignature.result.conversion.render(&printer, "swiftResult$") if swiftFunctionResultType.isVoid { printer.print("environment.interface.CallBooleanMethodA(environment, globalFuture, _JNIMethodIDCache.CompletableFuture.complete, [jvalue(l: nil)])") } else { - printer.print( - """ - let boxedResult$ = SwiftJavaRuntimeSupport._JNIBoxedConversions.box(\(inner), in: environment) - environment.interface.CallBooleanMethodA(environment, globalFuture, _JNIMethodIDCache.CompletableFuture.complete, [jvalue(l: boxedResult$)]) - """ - ) + let result: String + if nativeFunctionSignature.result.javaType.requiresBoxing { + printer.print("let boxedResult$ = SwiftJavaRuntimeSupport._JNIBoxedConversions.box(\(inner), in: environment)") + result = "boxedResult$" + } else { + result = inner + } + + printer.print("environment.interface.CallBooleanMethodA(environment, globalFuture, _JNIMethodIDCache.CompletableFuture.complete, [jvalue(l: \(result))])") } } @@ -843,9 +851,8 @@ extension JNISwift2JavaGenerator { printer.printBraceBlock("defer") { printer in // Defer might on any thread, so we need to attach environment. printer.print("let deferEnvironment = try! JavaVirtualMachine.shared().environment()") - printer.print("environment.interface.DeleteGlobalRef(deferEnvironment, globalFuture)") - for outParameter in outParameters { - printer.print("environment.interface.DeleteGlobalRef(deferEnvironment, \(outParameter.name))") + for globalRef in globalRefs { + printer.print("environment.interface.DeleteGlobalRef(deferEnvironment, \(globalRef))") } } if isThrowing { diff --git a/Sources/JExtractSwiftLib/JavaParameter.swift b/Sources/JExtractSwiftLib/JavaParameter.swift index 2670e6ee..0b243b3a 100644 --- a/Sources/JExtractSwiftLib/JavaParameter.swift +++ b/Sources/JExtractSwiftLib/JavaParameter.swift @@ -35,6 +35,15 @@ struct JavaParameter { } } + var isPrimitive: Bool { + switch self { + case .concrete(let javaType): + javaType.isPrimitive + case .generic(let name, let extends): + false + } + } + var jniTypeName: String { switch self { case .concrete(let type): type.jniTypeName diff --git a/Tests/JExtractSwiftTests/JNI/JNIAsyncTests.swift b/Tests/JExtractSwiftTests/JNI/JNIAsyncTests.swift index 82922c7d..975cccc6 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIAsyncTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIAsyncTests.swift @@ -353,4 +353,59 @@ struct JNIAsyncTests { ] ) } + + @Test("Import: (String) async -> String (Java, CompletableFuture)") + func completableFuture_asyncStringToString_java() throws { + try assertOutput( + input: """ + public func async(s: String) async -> String + """, + .jni, .java, + detectChunkByInitialLines: 2, + expectedChunks: [ + """ + public static java.util.concurrent.CompletableFuture async(java.lang.String s) { + java.util.concurrent.CompletableFuture $future = new java.util.concurrent.CompletableFuture(); + SwiftModule.$async(s, $future); + return $future.thenApply((futureResult$) -> { + return futureResult$; + } + ); + } + """, + """ + private static native void $async(java.lang.String s, java.util.concurrent.CompletableFuture result_future); + """, + ] + ) + } + + @Test("Import: (String) async -> String (Swift, CompletableFuture)") + func completableFuture_asyncStringToString_swift() throws { + try assertOutput( + input: """ + public func async(s: String) async -> String + """, + .jni, .swift, + detectChunkByInitialLines: 1, + expectedChunks: [ + """ + @_cdecl("Java_com_example_swift_SwiftModule__00024async__Ljava_lang_String_2Ljava_util_concurrent_CompletableFuture_2") + func Java_com_example_swift_SwiftModule__00024async__Ljava_lang_String_2Ljava_util_concurrent_CompletableFuture_2(environment: UnsafeMutablePointer!, thisClass: jclass, s: jstring?, result_future: jobject?) { + let s = environment.interface.NewGlobalRef(environment, s) + let globalFuture = environment.interface.NewGlobalRef(environment, result_future) + ... + defer { + let deferEnvironment = try! JavaVirtualMachine.shared().environment() + environment.interface.DeleteGlobalRef(deferEnvironment, globalFuture) + environment.interface.DeleteGlobalRef(deferEnvironment, s) + } + ... + environment.interface.CallBooleanMethodA(environment, globalFuture, _JNIMethodIDCache.CompletableFuture.complete, [jvalue(l: swiftResult$.getJNIValue(in: environment))]) + ... + } + """ + ] + ) + } } From cee5e020ac29444d59ebb29afb246ac3cad6cf30 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Fri, 7 Nov 2025 14:51:28 +0900 Subject: [PATCH 388/426] Start replacing ad-hoc logging with swift-log adoption (#421) --- Package.swift | 3 +++ .../Commands/ConfigureCommand.swift | 6 ++++- .../Commands/WrapJavaCommand.swift | 7 ++++-- Sources/SwiftJavaTool/CommonOptions.swift | 25 ++++++++++--------- .../SwiftJavaBaseAsyncParsableCommand.swift | 20 ++++++++++----- 5 files changed, 40 insertions(+), 21 deletions(-) diff --git a/Package.swift b/Package.swift index 7ac7d1f9..722859ee 100644 --- a/Package.swift +++ b/Package.swift @@ -205,6 +205,7 @@ let package = Package( .package(url: "https://github.com/swiftlang/swift-syntax", from: "602.0.0"), .package(url: "https://github.com/apple/swift-argument-parser", from: "1.5.0"), .package(url: "https://github.com/apple/swift-system", from: "1.4.0"), + .package(url: "https://github.com/apple/swift-log", from: "1.2.0"), // // FIXME: swift-subprocess stopped supporting 6.0 when it moved into a package; // // we'll need to drop 6.0 as well, but currently blocked on doing so by swiftpm plugin pending design questions @@ -395,6 +396,7 @@ let package = Package( .target( name: "SwiftJavaToolLib", dependencies: [ + .product(name: "Logging", package: "swift-log"), .product(name: "SwiftBasicFormat", package: "swift-syntax"), .product(name: "SwiftSyntax", package: "swift-syntax"), .product(name: "SwiftSyntaxBuilder", package: "swift-syntax"), @@ -418,6 +420,7 @@ let package = Package( .executableTarget( name: "SwiftJavaTool", dependencies: [ + .product(name: "Logging", package: "swift-log"), .product(name: "SwiftBasicFormat", package: "swift-syntax"), .product(name: "SwiftSyntax", package: "swift-syntax"), .product(name: "SwiftSyntaxBuilder", package: "swift-syntax"), diff --git a/Sources/SwiftJavaTool/Commands/ConfigureCommand.swift b/Sources/SwiftJavaTool/Commands/ConfigureCommand.swift index 3bce6c18..9a05a286 100644 --- a/Sources/SwiftJavaTool/Commands/ConfigureCommand.swift +++ b/Sources/SwiftJavaTool/Commands/ConfigureCommand.swift @@ -12,6 +12,7 @@ // //===----------------------------------------------------------------------===// +import Logging import ArgumentParser import Foundation import SwiftJavaToolLib @@ -27,6 +28,9 @@ import SwiftJavaShared extension SwiftJava { struct ConfigureCommand: SwiftJavaBaseAsyncParsableCommand, HasCommonOptions, HasCommonJVMOptions { + + static let log: Logging.Logger = Logger(label: "swift-java:\(configuration.commandName!)") + static let configuration = CommandConfiguration( commandName: "configure", abstract: "Configure and emit a swift-java.config file based on an input dependency or jar file") @@ -63,7 +67,7 @@ extension SwiftJava { extension SwiftJava.ConfigureCommand { mutating func runSwiftJavaCommand(config: inout Configuration) async throws { let classpathEntries = self.configureCommandJVMClasspath( - searchDirs: [self.effectiveSwiftModuleURL], config: config) + searchDirs: [self.effectiveSwiftModuleURL], config: config, log: Self.log) let jvm = try self.makeJVM(classpathEntries: classpathEntries) diff --git a/Sources/SwiftJavaTool/Commands/WrapJavaCommand.swift b/Sources/SwiftJavaTool/Commands/WrapJavaCommand.swift index 69ad3ebe..43362edb 100644 --- a/Sources/SwiftJavaTool/Commands/WrapJavaCommand.swift +++ b/Sources/SwiftJavaTool/Commands/WrapJavaCommand.swift @@ -14,15 +14,18 @@ import Foundation import ArgumentParser +import Logging import SwiftJavaToolLib import SwiftJava import JavaUtilJar -import SwiftJavaToolLib import SwiftJavaConfigurationShared extension SwiftJava { struct WrapJavaCommand: SwiftJavaBaseAsyncParsableCommand, HasCommonOptions, HasCommonJVMOptions { + + static let log: Logging.Logger = .init(label: "swift-java:\(configuration.commandName!)") + static let configuration = CommandConfiguration( commandName: "wrap-java", abstract: "Wrap Java classes with corresponding Swift bindings.") @@ -74,7 +77,7 @@ extension SwiftJava.WrapJavaCommand { print("[trace][swift-java] INPUT: \(input)") var classpathEntries = self.configureCommandJVMClasspath( - searchDirs: classpathSearchDirs, config: config) + searchDirs: classpathSearchDirs, config: config, log: Self.log) // Load all of the dependent configurations and associate them with Swift modules. let dependentConfigs = try loadDependentConfigs(dependsOn: self.dependsOn).map { moduleName, config in diff --git a/Sources/SwiftJavaTool/CommonOptions.swift b/Sources/SwiftJavaTool/CommonOptions.swift index c88ecbc8..e8aee62d 100644 --- a/Sources/SwiftJavaTool/CommonOptions.swift +++ b/Sources/SwiftJavaTool/CommonOptions.swift @@ -20,6 +20,7 @@ import SwiftJava import JavaUtilJar import JavaNet import SwiftSyntax +import Logging import SwiftJavaConfigurationShared import SwiftJavaShared @@ -43,7 +44,7 @@ extension SwiftJava { var inputSwift: String? = nil @Option(name: .shortAndLong, help: "Configure the level of logs that should be printed") - var logLevel: Logger.Level = .info + var logLevel: JExtractSwiftLib.Logger.Level = .info } struct CommonJVMOptions: ParsableArguments { @@ -78,46 +79,46 @@ extension HasCommonJVMOptions { /// swift-java.classpath files as configured. /// Parameters: /// - searchDirs: search directories where we can find swift.java.classpath files to include in the configuration - func configureCommandJVMClasspath(searchDirs: [Foundation.URL], config: Configuration) -> [String] { + func configureCommandJVMClasspath(searchDirs: [Foundation.URL], config: Configuration, log: Logging.Logger) -> [String] { // Form a class path from all of our input sources: // * Command-line option --classpath let classpathOptionEntries: [String] = self.classpathEntries let classpathFromEnv = ProcessInfo.processInfo.environment["CLASSPATH"]?.split(separator: ":").map(String.init) ?? [] - print("[debug][swift-java] Base classpath from CLASSPATH environment: \(classpathFromEnv)") + log.debug("Base classpath from CLASSPATH environment: \(classpathFromEnv)") let classpathFromConfig: [String] = config.classpath?.split(separator: ":").map(String.init) ?? [] - print("[debug][swift-java] Base classpath from config: \(classpathFromConfig)") + log.debug("Base classpath from config: \(classpathFromConfig)") var classpathEntries: [String] = classpathFromConfig for searchDir in searchDirs { let classPathFilesSearchDirectory = searchDir.path - print("[debug][swift-java] Search *.swift-java.classpath in: \(classPathFilesSearchDirectory)") + log.debug("Search *.swift-java.classpath in: \(classPathFilesSearchDirectory)") let foundSwiftJavaClasspath = findSwiftJavaClasspaths(in: classPathFilesSearchDirectory) - print("[debug][swift-java] Classpath from *.swift-java.classpath files: \(foundSwiftJavaClasspath)") + log.debug("Classpath from *.swift-java.classpath files: \(foundSwiftJavaClasspath)") classpathEntries += foundSwiftJavaClasspath } if !classpathOptionEntries.isEmpty { - print("[debug][swift-java] Classpath from options: \(classpathOptionEntries)") + log.debug("Classpath from options: \(classpathOptionEntries)") classpathEntries += classpathOptionEntries } else { // * Base classpath from CLASSPATH env variable - print("[debug][swift-java] Classpath from environment: \(classpathFromEnv)") + log.debug("Classpath from environment: \(classpathFromEnv)") classpathEntries += classpathFromEnv } let extraClasspath = self.commonJVMOptions.classpath let extraClasspathEntries = extraClasspath.split(separator: ":").map(String.init) - print("[debug][swift-java] Extra classpath: \(extraClasspathEntries)") + log.debug("Extra classpath: \(extraClasspathEntries)") classpathEntries += extraClasspathEntries // Bring up the Java VM when necessary - // if logLevel >= .debug { + if log.logLevel >= .debug { let classpathString = classpathEntries.joined(separator: ":") - print("[debug][swift-java] Initialize JVM with classpath: \(classpathString)") - // } + log.debug("Initialize JVM with classpath: \(classpathString)") + } return classpathEntries } diff --git a/Sources/SwiftJavaTool/SwiftJavaBaseAsyncParsableCommand.swift b/Sources/SwiftJavaTool/SwiftJavaBaseAsyncParsableCommand.swift index 6b8c0ec6..9763b4b3 100644 --- a/Sources/SwiftJavaTool/SwiftJavaBaseAsyncParsableCommand.swift +++ b/Sources/SwiftJavaTool/SwiftJavaBaseAsyncParsableCommand.swift @@ -24,9 +24,13 @@ import SwiftSyntax import SwiftSyntaxBuilder import SwiftJavaConfigurationShared import SwiftJavaShared +import Logging protocol SwiftJavaBaseAsyncParsableCommand: AsyncParsableCommand { - var logLevel: Logger.Level { get set } + + var log: Logging.Logger { get } + + var logLevel: JExtractSwiftLib.Logger.Level { get set } /// Must be implemented with an `@OptionGroup` in Command implementations var commonOptions: SwiftJava.CommonOptions { get set } @@ -45,8 +49,8 @@ extension SwiftJavaBaseAsyncParsableCommand { extension SwiftJavaBaseAsyncParsableCommand { public mutating func run() async { - print("[info][swift-java] Run \(Self.self): \(CommandLine.arguments.joined(separator: " "))") - print("[info][swift-java] Current work directory: \(URL(fileURLWithPath: ".").path)") + self.log.info("Run \(Self.self): \(CommandLine.arguments.joined(separator: " "))") + self.log.info("Current work directory: \(URL(fileURLWithPath: ".").path)") do { var config = try readInitialConfiguration(command: self) @@ -54,12 +58,12 @@ extension SwiftJavaBaseAsyncParsableCommand { } catch { // We fail like this since throwing out of the run often ends up hiding the failure reason when it is executed as SwiftPM plugin (!) let message = "Failed with error: \(error)" - print("[error][java-swift] \(message)") + self.log.error("\(message)") fatalError(message) } // Just for debugging so it is clear which command has finished - print("[debug][swift-java] " + "Done: ".green + CommandLine.arguments.joined(separator: " ").green) + self.log.debug("\("Done: ".green) \(CommandLine.arguments.joined(separator: " ").green)") } } @@ -95,7 +99,11 @@ extension SwiftJavaBaseAsyncParsableCommand { extension SwiftJavaBaseAsyncParsableCommand { - var logLevel: Logger.Level { + var log: Logging.Logger { // FIXME: replace with stored property inside specific commands + .init(label: "swift-java") + } + + var logLevel: JExtractSwiftLib.Logger.Level { get { self.commonOptions.logLevel } From cafcc1d5c0e45bc31f73087596c1fe521eb57c94 Mon Sep 17 00:00:00 2001 From: Mads Odgaard Date: Fri, 7 Nov 2025 11:02:10 +0100 Subject: [PATCH 389/426] [jextract/jni] Add support for importing nested types (#429) --- .../Sources/MySwiftLibrary/NestedTypes.swift | 47 ++++++ .../com/example/swift/NestedTypesTest.java | 45 ++++++ Sources/JExtractSwiftLib/ImportedDecls.swift | 2 + Sources/JExtractSwiftLib/JNI/JNICaching.swift | 8 +- ...t2JavaGenerator+JavaBindingsPrinting.swift | 20 ++- ...ISwift2JavaGenerator+JavaTranslation.swift | 6 +- ...ift2JavaGenerator+SwiftThunkPrinting.swift | 6 +- .../SwiftTypes/SwiftModuleSymbolTable.swift | 2 +- .../SwiftTypes/SwiftTypeLookupContext.swift | 10 +- .../Documentation.docc/SupportedFeatures.md | 2 +- .../JNI/JNINestedTypesTests.swift | 137 ++++++++++++++++++ 11 files changed, 269 insertions(+), 16 deletions(-) create mode 100644 Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/NestedTypes.swift create mode 100644 Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/NestedTypesTest.java create mode 100644 Tests/JExtractSwiftTests/JNI/JNINestedTypesTests.swift diff --git a/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/NestedTypes.swift b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/NestedTypes.swift new file mode 100644 index 00000000..b7edefa9 --- /dev/null +++ b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/NestedTypes.swift @@ -0,0 +1,47 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import SwiftJava + +public class A { + public init() {} + + public class B { + public init() {} + + public struct C { + public init() {} + + public func g(a: A, b: B, bbc: BB.C) {} + } + } + + public class BB { + public init() {} + + public struct C { + public init() {} + } + } + + public func f(a: A, b: A.B, c: A.B.C, bb: BB, bbc: BB.C) {} +} + +public enum NestedEnum { + case one(OneStruct) + + public struct OneStruct { + public init() {} + } +} diff --git a/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/NestedTypesTest.java b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/NestedTypesTest.java new file mode 100644 index 00000000..b006ea91 --- /dev/null +++ b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/NestedTypesTest.java @@ -0,0 +1,45 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package com.example.swift; + +import org.junit.jupiter.api.Test; +import org.swift.swiftkit.core.SwiftArena; + +import static org.junit.jupiter.api.Assertions.*; + +public class NestedTypesTest { + @Test + void testClassesAndStructs() { + try (var arena = SwiftArena.ofConfined()) { + var a = A.init(arena); + var b = A.B.init(arena); + var c = A.B.C.init(arena); + var bb = A.BB.init(arena); + var abbc = A.BB.C.init(arena); + + a.f(a, b, c, bb, abbc); + c.g(a, b, abbc); + } + } + + @Test + void testStructInEnum() { + try (var arena = SwiftArena.ofConfined()) { + var obj = NestedEnum.one(NestedEnum.OneStruct.init(arena), arena); + var one = obj.getAsOne(arena); + assertTrue(one.isPresent()); + } + } +} \ No newline at end of file diff --git a/Sources/JExtractSwiftLib/ImportedDecls.swift b/Sources/JExtractSwiftLib/ImportedDecls.swift index 84cc43c0..9ba1cd6f 100644 --- a/Sources/JExtractSwiftLib/ImportedDecls.swift +++ b/Sources/JExtractSwiftLib/ImportedDecls.swift @@ -41,12 +41,14 @@ package final class ImportedNominalType: ImportedDecl { package var variables: [ImportedFunc] = [] package var cases: [ImportedEnumCase] = [] var inheritedTypes: [SwiftType] + package var parent: SwiftNominalTypeDeclaration? init(swiftNominal: SwiftNominalTypeDeclaration, lookupContext: SwiftTypeLookupContext) throws { self.swiftNominal = swiftNominal self.inheritedTypes = swiftNominal.inheritanceTypes?.compactMap { try? SwiftType($0.type, lookupContext: lookupContext) } ?? [] + self.parent = swiftNominal.parent } var swiftType: SwiftType { diff --git a/Sources/JExtractSwiftLib/JNI/JNICaching.swift b/Sources/JExtractSwiftLib/JNI/JNICaching.swift index cdb13e3f..b0521946 100644 --- a/Sources/JExtractSwiftLib/JNI/JNICaching.swift +++ b/Sources/JExtractSwiftLib/JNI/JNICaching.swift @@ -14,15 +14,15 @@ enum JNICaching { static func cacheName(for type: ImportedNominalType) -> String { - cacheName(for: type.swiftNominal.name) + cacheName(for: type.swiftNominal.qualifiedName) } static func cacheName(for type: SwiftNominalType) -> String { - cacheName(for: type.nominalTypeDecl.name) + cacheName(for: type.nominalTypeDecl.qualifiedName) } - private static func cacheName(for name: String) -> String { - "_JNI_\(name)" + private static func cacheName(for qualifiedName: String) -> String { + "_JNI_\(qualifiedName.replacingOccurrences(of: ".", with: "_"))" } static func cacheMemberName(for enumCase: ImportedEnumCase) -> String { diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift index ce6ec18e..1e59c196 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift @@ -40,7 +40,9 @@ extension JNISwift2JavaGenerator { package func writeExportedJavaSources(_ printer: inout CodePrinter) throws { let importedTypes = analysis.importedTypes.sorted(by: { (lhs, rhs) in lhs.key < rhs.key }) - for (_, ty) in importedTypes { + // Each parent type goes into its own file + // any nested types are printed inside the body as `static class` + for (_, ty) in importedTypes.filter({ _, type in type.parent == nil }) { let filename = "\(ty.swiftNominal.name).java" logger.debug("Printing contents: \(filename)") printImportedNominal(&printer, ty) @@ -145,6 +147,15 @@ extension JNISwift2JavaGenerator { """ ) + let nestedTypes = self.analysis.importedTypes.filter { _, type in + type.parent == decl.swiftNominal + } + + for nestedType in nestedTypes { + printConcreteType(&printer, nestedType.value) + printer.println() + } + printer.print( """ /** @@ -255,13 +266,18 @@ extension JNISwift2JavaGenerator { if decl.swiftNominal.isSendable { printer.print("@ThreadSafe // Sendable") } + var modifiers = ["public"] + if decl.parent != nil { + modifiers.append("static") + } + modifiers.append("final") var implements = ["JNISwiftInstance"] implements += decl.inheritedTypes .compactMap(\.asNominalTypeDeclaration) .filter { $0.kind == .protocol } .map(\.name) let implementsClause = implements.joined(separator: ", ") - printer.printBraceBlock("public final class \(decl.swiftNominal.name) implements \(implementsClause)") { printer in + printer.printBraceBlock("\(modifiers.joined(separator: " ")) class \(decl.swiftNominal.name) implements \(implementsClause)") { printer in body(&printer) } } diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift index a4e5ab45..d9a8f8d9 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift @@ -307,9 +307,7 @@ extension JNISwift2JavaGenerator { genericParameters: [SwiftGenericParameterDeclaration], genericRequirements: [SwiftGenericRequirement] ) throws -> [TranslatedParameter] { - try parameters.enumerated().map { - idx, - param in + try parameters.enumerated().map { idx, param in let parameterName = param.name ?? "arg\(idx)" return try translateParameter( swiftType: param.type, @@ -373,7 +371,7 @@ extension JNISwift2JavaGenerator { switch swiftType { case .nominal(let nominalType): - let nominalTypeName = nominalType.nominalTypeDecl.name + let nominalTypeName = nominalType.nominalTypeDecl.qualifiedName if let knownType = nominalType.nominalTypeDecl.knownTypeKind { switch knownType { diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift index c9f8af9e..91a0b0e7 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift @@ -430,7 +430,7 @@ extension JNISwift2JavaGenerator { let cName = "Java_" + self.javaPackage.replacingOccurrences(of: ".", with: "_") - + "_\(parentName.escapedJNIIdentifier)_" + + "_\(parentName.replacingOccurrences(of: ".", with: "$").escapedJNIIdentifier)_" + javaMethodName.escapedJNIIdentifier + "__" + jniSignature.escapedJNIIdentifier @@ -474,7 +474,7 @@ extension JNISwift2JavaGenerator { printCDecl( &printer, javaMethodName: "$typeMetadataAddressDowncall", - parentName: type.swiftNominal.name, + parentName: type.swiftNominal.qualifiedName, parameters: [], resultType: .long ) { printer in @@ -493,7 +493,7 @@ extension JNISwift2JavaGenerator { printCDecl( &printer, javaMethodName: "$destroy", - parentName: type.swiftNominal.name, + parentName: type.swiftNominal.qualifiedName, parameters: [ selfPointerParam ], diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftModuleSymbolTable.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftModuleSymbolTable.swift index 6328045f..2db19928 100644 --- a/Sources/JExtractSwiftLib/SwiftTypes/SwiftModuleSymbolTable.swift +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftModuleSymbolTable.swift @@ -56,4 +56,4 @@ extension SwiftModuleSymbolTable { /// Names of modules which are alternative for currently checked module. let moduleNames: Set } -} \ No newline at end of file +} diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftTypeLookupContext.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftTypeLookupContext.swift index 13f42cfc..33759a2c 100644 --- a/Sources/JExtractSwiftLib/SwiftTypes/SwiftTypeLookupContext.swift +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftTypeLookupContext.swift @@ -119,7 +119,15 @@ class SwiftTypeLookupContext { /// Create a nominal type declaration instance for the specified syntax node. private func nominalTypeDeclaration(for node: NominalTypeDeclSyntaxNode, sourceFilePath: String) throws -> SwiftNominalTypeDeclaration { - SwiftNominalTypeDeclaration( + + if let symbolTableDeclaration = self.symbolTable.lookupType( + node.name.text, + parent: try parentTypeDecl(for: node) + ) { + return symbolTableDeclaration + } + + return SwiftNominalTypeDeclaration( sourceFilePath: sourceFilePath, moduleName: self.symbolTable.moduleName, parent: try parentTypeDecl(for: node), diff --git a/Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md b/Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md index 4bbaee40..3178f60d 100644 --- a/Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md +++ b/Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md @@ -86,7 +86,7 @@ SwiftJava's `swift-java jextract` tool automates generating Java bindings from S | Subscripts: `subscript()` | ❌ | ❌ | | Equatable | ❌ | ❌ | | Pointers: `UnsafeRawPointer`, UnsafeBufferPointer (?) | 🟡 | ❌ | -| Nested types: `struct Hello { struct World {} }` | ❌ | ❌ | +| Nested types: `struct Hello { struct World {} }` | ❌ | ✅ | | Inheritance: `class Caplin: Capybara` | ❌ | ❌ | | Non-escaping `Void` closures: `func callMe(maybe: () -> ())` | ✅ | ✅ | | Non-escaping closures with primitive arguments/results: `func callMe(maybe: (Int) -> (Double))` | ✅ | ✅ | diff --git a/Tests/JExtractSwiftTests/JNI/JNINestedTypesTests.swift b/Tests/JExtractSwiftTests/JNI/JNINestedTypesTests.swift new file mode 100644 index 00000000..50a0ae26 --- /dev/null +++ b/Tests/JExtractSwiftTests/JNI/JNINestedTypesTests.swift @@ -0,0 +1,137 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import JExtractSwiftLib +import Testing + +@Suite +struct JNINestedTypesTests { + let source1 = """ + public class A { + public class B { + public func g(c: C) {} + + public struct C { + public func h(b: B) {} + } + } + } + + public func f(a: A, b: A.B, c: A.B.C) {} + """ + + @Test("Import: class and struct A.B.C (Java)") + func nestedClassesAndStructs_java() throws { + try assertOutput( + input: source1, + .jni, .java, + detectChunkByInitialLines: 1, + expectedChunks: [ + """ + public final class A implements JNISwiftInstance { + ... + public static final class B implements JNISwiftInstance { + ... + public static final class C implements JNISwiftInstance { + ... + public void h(A.B b) { + ... + } + ... + public void g(A.B.C c) { + ... + } + ... + } + """, + """ + public static void f(A a, A.B b, A.B.C c) { + ... + } + ... + """ + ] + ) + } + + @Test("Import: class and struct A.B.C (Swift)") + func nestedClassesAndStructs_swift() throws { + try assertOutput( + input: source1, + .jni, .swift, + detectChunkByInitialLines: 1, + expectedChunks: [ + """ + @_cdecl("Java_com_example_swift_A__00024destroy__J") + func Java_com_example_swift_A__00024destroy__J(environment: UnsafeMutablePointer!, thisClass: jclass, selfPointer: jlong) { + ... + } + """, + """ + @_cdecl("Java_com_example_swift_A_00024B__00024destroy__J") + func Java_com_example_swift_A_00024B__00024destroy__J(environment: UnsafeMutablePointer!, thisClass: jclass, selfPointer: jlong) { + ... + } + """, + """ + @_cdecl("Java_com_example_swift_A_00024B__00024destroy__J") + func Java_com_example_swift_A_00024B__00024destroy__J(environment: UnsafeMutablePointer!, thisClass: jclass, selfPointer: jlong) { + ... + } + """, + """ + @_cdecl("Java_com_example_swift_A_00024B_00024C__00024h__JJ") + func Java_com_example_swift_A_00024B_00024C__00024h__JJ(environment: UnsafeMutablePointer!, thisClass: jclass, b: jlong, self: jlong) { + ... + } + """ + ] + ) + } + + @Test("Import: nested in enum") + func nestedEnums_java() throws { + try assertOutput( + input: """ + public enum MyError { + case text(TextMessage) + + public struct TextMessage {} + } + + public func f(text: MyError.TextMessage) {} + """, + .jni, .java, + detectChunkByInitialLines: 1, + expectedChunks: [ + """ + public final class MyError implements JNISwiftInstance { + ... + public static final class TextMessage implements JNISwiftInstance { + ... + } + ... + public static MyError text(MyError.TextMessage arg0, SwiftArena swiftArena$) { + ... + } + """, + """ + public static void f(MyError.TextMessage text) { + ... + } + """ + ] + ) + } +} From 6419865dddef9bee0e670a1c5752342ccde0f837 Mon Sep 17 00:00:00 2001 From: Mads Odgaard Date: Tue, 11 Nov 2025 13:22:35 +0100 Subject: [PATCH 390/426] jextract: add support for arrays (#435) --- .../Sources/MySwiftLibrary/Arrays.swift | 60 ++++++ .../java/com/example/swift/ArraysTest.java | 105 ++++++++++ Sources/JExtractSwiftLib/CodePrinter.swift | 7 +- .../FFM/CDeclLowering/CRepresentation.swift | 4 +- ...Swift2JavaGenerator+FunctionLowering.swift | 9 +- ...MSwift2JavaGenerator+JavaTranslation.swift | 5 +- .../JNI/JNIJavaTypeTranslator.swift | 5 +- ...t2JavaGenerator+JavaBindingsPrinting.swift | 2 +- ...ISwift2JavaGenerator+JavaTranslation.swift | 143 +++++++++++++ ...wift2JavaGenerator+NativeTranslation.swift | 161 +++++++++++++-- .../Swift2JavaTranslator.swift | 2 + .../SwiftTypes/SwiftKnownModules.swift | 4 +- .../SwiftTypes/SwiftKnownTypeDecls.swift | 1 + .../SwiftTypes/SwiftType.swift | 17 +- .../Documentation.docc/SupportedFeatures.md | 2 +- .../JExtractSwiftTests/JNI/JNIArrayTest.swift | 188 ++++++++++++++++++ 16 files changed, 684 insertions(+), 31 deletions(-) create mode 100644 Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/Arrays.swift create mode 100644 Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/ArraysTest.java create mode 100644 Tests/JExtractSwiftTests/JNI/JNIArrayTest.swift diff --git a/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/Arrays.swift b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/Arrays.swift new file mode 100644 index 00000000..b6f050c1 --- /dev/null +++ b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/Arrays.swift @@ -0,0 +1,60 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import SwiftJava + +public func booleanArray(array: [Bool]) -> [Bool] { + return array +} + +public func byteArray(array: [UInt8]) -> [UInt8] { + return array +} + +public func byteArrayExplicit(array: Array) -> Array { + return array +} + +public func charArray(array: [UInt16]) -> [UInt16] { + return array +} + +public func shortArray(array: [Int16]) -> [Int16] { + return array +} + +public func intArray(array: [Int32]) -> [Int32] { + return array +} + +public func longArray(array: [Int64]) -> [Int64] { + return array +} + +public func floatArray(array: [Float]) -> [Float] { + return array +} + +public func doubleArray(array: [Double]) -> [Double] { + return array +} + +public func stringArray(array: [String]) -> [String] { + return array +} + +public func objectArray(array: [MySwiftClass]) -> [MySwiftClass] { + return array +} + diff --git a/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/ArraysTest.java b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/ArraysTest.java new file mode 100644 index 00000000..bf19b370 --- /dev/null +++ b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/ArraysTest.java @@ -0,0 +1,105 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package com.example.swift; + +import org.junit.jupiter.api.Test; +import org.swift.swiftkit.core.SwiftArena; + +import java.util.OptionalLong; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; + +import static org.junit.jupiter.api.Assertions.*; + +public class ArraysTest { + @Test + void booleanArray() { + boolean[] input = new boolean[] { true, false, false, true }; + assertArrayEquals(input, MySwiftLibrary.booleanArray(input)); + } + + @Test + void byteArray() { + byte[] input = new byte[] { 10, 20, 30, 40 }; + assertArrayEquals(input, MySwiftLibrary.byteArray(input)); + } + + @Test + void byteArray_empty() { + byte[] input = new byte[] {}; + assertArrayEquals(input, MySwiftLibrary.byteArray(input)); + } + + @Test + void byteArray_null() { + assertThrows(NullPointerException.class, () -> MySwiftLibrary.byteArray(null)); + } + + @Test + void byteArrayExplicit() { + byte[] input = new byte[] { 10, 20, 30, 40 }; + assertArrayEquals(input, MySwiftLibrary.byteArrayExplicit(input)); + } + + @Test + void charArray() { + char[] input = new char[] { 10, 20, 30, 40 }; + assertArrayEquals(input, MySwiftLibrary.charArray(input)); + } + + @Test + void shortArray() { + short[] input = new short[] { 10, 20, 30, 40 }; + assertArrayEquals(input, MySwiftLibrary.shortArray(input)); + } + + @Test + void intArray() { + int[] input = new int[] { 10, 20, 30, 40 }; + assertArrayEquals(input, MySwiftLibrary.intArray(input)); + } + + @Test + void longArray() { + long[] input = new long[] { 10, 20, 30, 40 }; + assertArrayEquals(input, MySwiftLibrary.longArray(input)); + } + + @Test + void stringArray() { + String[] input = new String[] { "hey", "there", "my", "friend" }; + assertArrayEquals(input, MySwiftLibrary.stringArray(input)); + } + + @Test + void floatArray() { + float[] input = new float[] { 10, 20, 30, 40 }; + assertArrayEquals(input, MySwiftLibrary.floatArray(input)); + } + + @Test + void doubleArray() { + double[] input = new double[] { 10, 20, 30, 40 }; + assertArrayEquals(input, MySwiftLibrary.doubleArray(input)); + } + + @Test + void objectArray() { + try (var arena = SwiftArena.ofConfined()) { + MySwiftClass[] input = new MySwiftClass[]{MySwiftClass.init(arena), MySwiftClass.init(arena), MySwiftClass.init(arena) }; + assertEquals(3, MySwiftLibrary.objectArray(input, arena).length); + } + } +} \ No newline at end of file diff --git a/Sources/JExtractSwiftLib/CodePrinter.swift b/Sources/JExtractSwiftLib/CodePrinter.swift index e6498683..1497a61a 100644 --- a/Sources/JExtractSwiftLib/CodePrinter.swift +++ b/Sources/JExtractSwiftLib/CodePrinter.swift @@ -86,12 +86,17 @@ public struct CodePrinter { public mutating func printBraceBlock( _ header: Any, + parameters: [String]? = nil, function: String = #function, file: String = #fileID, line: UInt = #line, body: (inout CodePrinter) throws -> () ) rethrows { - print("\(header) {") + print("\(header) {", .continue) + if let parameters { + print(" (\(parameters.joined(separator: ", "))) in", .continue) + } + println() indent() try body(&self) outdent() diff --git a/Sources/JExtractSwiftLib/FFM/CDeclLowering/CRepresentation.swift b/Sources/JExtractSwiftLib/FFM/CDeclLowering/CRepresentation.swift index 2621dd8b..3f821a1b 100644 --- a/Sources/JExtractSwiftLib/FFM/CDeclLowering/CRepresentation.swift +++ b/Sources/JExtractSwiftLib/FFM/CDeclLowering/CRepresentation.swift @@ -68,7 +68,7 @@ extension CType { case .optional(let wrapped) where wrapped.isPointer: try self.init(cdeclType: wrapped) - case .genericParameter, .metatype, .optional, .tuple, .opaque, .existential, .composite: + case .genericParameter, .metatype, .optional, .tuple, .opaque, .existential, .composite, .array: throw CDeclToCLoweringError.invalidCDeclType(cdeclType) } } @@ -127,7 +127,7 @@ extension SwiftKnownTypeDeclKind { case .void: .void case .unsafePointer, .unsafeMutablePointer, .unsafeRawBufferPointer, .unsafeMutableRawBufferPointer, .unsafeBufferPointer, .unsafeMutableBufferPointer, .string, .foundationData, .foundationDataProtocol, - .essentialsData, .essentialsDataProtocol, .optional: + .essentialsData, .essentialsDataProtocol, .optional, .array: nil } } diff --git a/Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift b/Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift index 7c8d7ab2..832aff26 100644 --- a/Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift +++ b/Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift @@ -347,6 +347,9 @@ struct CdeclLowering { case .composite: throw LoweringError.unhandledType(type) + + case .array: + throw LoweringError.unhandledType(type) } } @@ -415,7 +418,7 @@ struct CdeclLowering { } throw LoweringError.unhandledType(.optional(wrappedType)) - case .function, .metatype, .optional, .composite: + case .function, .metatype, .optional, .composite, .array: throw LoweringError.unhandledType(.optional(wrappedType)) } } @@ -516,7 +519,7 @@ struct CdeclLowering { // Custom types are not supported yet. throw LoweringError.unhandledType(type) - case .genericParameter, .function, .metatype, .optional, .tuple, .existential, .opaque, .composite: + case .genericParameter, .function, .metatype, .optional, .tuple, .existential, .opaque, .composite, .array: // TODO: Implement throw LoweringError.unhandledType(type) } @@ -670,7 +673,7 @@ struct CdeclLowering { conversion: .tupleExplode(conversions, name: outParameterName) ) - case .genericParameter, .function, .optional, .existential, .opaque, .composite: + case .genericParameter, .function, .optional, .existential, .opaque, .composite, .array: throw LoweringError.unhandledType(type) } } diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift index 5d38a0f9..72da323c 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift @@ -475,6 +475,9 @@ extension FFMSwift2JavaGenerator { case .composite: throw JavaTranslationError.unhandledType(swiftType) + + case .array(let elementType): + throw JavaTranslationError.unhandledType(swiftType) } } @@ -694,7 +697,7 @@ extension FFMSwift2JavaGenerator { // TODO: Implement. throw JavaTranslationError.unhandledType(swiftType) - case .genericParameter, .optional, .function, .existential, .opaque, .composite: + case .genericParameter, .optional, .function, .existential, .opaque, .composite, .array: throw JavaTranslationError.unhandledType(swiftType) } diff --git a/Sources/JExtractSwiftLib/JNI/JNIJavaTypeTranslator.swift b/Sources/JExtractSwiftLib/JNI/JNIJavaTypeTranslator.swift index 0d1fc675..9bd9a7d8 100644 --- a/Sources/JExtractSwiftLib/JNI/JNIJavaTypeTranslator.swift +++ b/Sources/JExtractSwiftLib/JNI/JNIJavaTypeTranslator.swift @@ -45,13 +45,14 @@ enum JNIJavaTypeTranslator { case .void: return .void case .string: return .javaLangString + case .int, .uint, // FIXME: why not supported int/uint? .unsafeRawPointer, .unsafeMutableRawPointer, .unsafePointer, .unsafeMutablePointer, .unsafeRawBufferPointer, .unsafeMutableRawBufferPointer, .unsafeBufferPointer, .unsafeMutableBufferPointer, - .optional, .foundationData, .foundationDataProtocol, .essentialsData, .essentialsDataProtocol: + .optional, .foundationData, .foundationDataProtocol, .essentialsData, .essentialsDataProtocol, .array: return nil } } -} \ No newline at end of file +} diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift index 1e59c196..07d23dc0 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift @@ -25,7 +25,7 @@ extension JNISwift2JavaGenerator { "java.util.concurrent.atomic.AtomicBoolean", // NonNull, Unsigned and friends - "org.swift.swiftkit.core.annotations.*", + "org.swift.swiftkit.core.annotations.*" ] } diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift index d9a8f8d9..9c3cdbf1 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift @@ -384,6 +384,15 @@ extension JNISwift2JavaGenerator { parameterName: parameterName ) + case .array: + guard let elementType = nominalType.genericArguments?.first else { + throw JavaTranslationError.unsupportedSwiftType(swiftType) + } + return try translateArrayParameter( + elementType: elementType, + parameterName: parameterName + ) + default: guard let javaType = JNIJavaTypeTranslator.translate(knownType: knownType, config: self.config) else { throw JavaTranslationError.unsupportedSwiftType(swiftType) @@ -461,6 +470,12 @@ extension JNISwift2JavaGenerator { throw JavaTranslationError.unsupportedSwiftType(swiftType) + case .array(let elementType): + return try translateArrayParameter( + elementType: elementType, + parameterName: parameterName + ) + case .metatype, .tuple, .composite: throw JavaTranslationError.unsupportedSwiftType(swiftType) } @@ -651,6 +666,14 @@ extension JNISwift2JavaGenerator { } return try translateOptionalResult(wrappedType: genericArgs[0], resultName: resultName) + case .array: + guard let elementType = nominalType.genericArguments?.first else { + throw JavaTranslationError.unsupportedSwiftType(swiftType) + } + return try translateArrayResult( + elementType: elementType + ) + default: guard let javaType = JNIJavaTypeTranslator.translate(knownType: knownType, config: self.config) else { throw JavaTranslationError.unsupportedSwiftType(swiftType) @@ -684,6 +707,11 @@ extension JNISwift2JavaGenerator { case .optional(let wrapped): return try translateOptionalResult(wrappedType: wrapped, resultName: resultName) + case .array(let elementType): + return try translateArrayResult( + elementType: elementType + ) + case .metatype, .tuple, .function, .existential, .opaque, .genericParameter, .composite: throw JavaTranslationError.unsupportedSwiftType(swiftType) } @@ -771,6 +799,107 @@ extension JNISwift2JavaGenerator { throw JavaTranslationError.unsupportedSwiftType(swiftType) } } + + func translateArrayParameter( + elementType: SwiftType, + parameterName: String + ) throws -> TranslatedParameter { + let parameterAnnotations: [JavaAnnotation] = getTypeAnnotations(swiftType: elementType, config: config) + + switch elementType { + case .nominal(let nominalType): + let nominalTypeName = nominalType.nominalTypeDecl.qualifiedName + + if let knownType = nominalType.nominalTypeDecl.knownTypeKind { + guard let javaType = JNIJavaTypeTranslator.translate(knownType: knownType, config: self.config) else { + throw JavaTranslationError.unsupportedSwiftType(elementType) + } + + return TranslatedParameter( + parameter: JavaParameter(name: parameterName, type: .array(javaType), annotations: parameterAnnotations), + conversion: .requireNonNull(.placeholder, message: "\(parameterName) must not be null") + ) + } + + guard !nominalType.isJavaKitWrapper else { + throw JavaTranslationError.unsupportedSwiftType(elementType) + } + + // Assume JExtract imported class + return TranslatedParameter( + parameter: JavaParameter( + name: parameterName, + type: .array(.class(package: nil, name: nominalTypeName)), + annotations: parameterAnnotations + ), + conversion: .method( + .method( + .arraysStream(.requireNonNull(.placeholder, message: "\(parameterName) must not be null")), + function: "mapToLong", + arguments: [.constant("\(nominalTypeName)::$memoryAddress")] + ), + function: "toArray", + arguments: [] + ) + ) + + default: + throw JavaTranslationError.unsupportedSwiftType(elementType) + } + } + + func translateArrayResult( + elementType: SwiftType + ) throws -> TranslatedResult { + let annotations: [JavaAnnotation] = getTypeAnnotations(swiftType: elementType, config: config) + + switch elementType { + case .nominal(let nominalType): + let nominalTypeName = nominalType.nominalTypeDecl.qualifiedName + + if let knownType = nominalType.nominalTypeDecl.knownTypeKind { + guard let javaType = JNIJavaTypeTranslator.translate(knownType: knownType, config: self.config) else { + throw JavaTranslationError.unsupportedSwiftType(elementType) + } + + return TranslatedResult( + javaType: .array(javaType), + annotations: annotations, + outParameters: [], + conversion: .placeholder + ) + } + + guard !nominalType.isJavaKitWrapper else { + throw JavaTranslationError.unsupportedSwiftType(elementType) + } + + let objectType = JavaType.class(package: nil, name: nominalTypeName) + // We assume this is a JExtract class. + return TranslatedResult( + javaType: .array(objectType), + annotations: annotations, + outParameters: [], + conversion: .method( + .method( + .arraysStream(.placeholder), + function: "mapToObj", + arguments: [ + .lambda( + args: ["pointer"], + body: .wrapMemoryAddressUnsafe(.constant("pointer"), objectType) + ) + ] + ), + function: "toArray", + arguments: [.constant("\(objectType)[]::new")] + ) + ) + + default: + throw JavaTranslationError.unsupportedSwiftType(elementType) + } + } } struct TranslatedEnumCase { @@ -976,6 +1105,13 @@ extension JNISwift2JavaGenerator { /// Prints the conversion step, ignoring the output. indirect case print(JavaNativeConversionStep) + indirect case requireNonNull(JavaNativeConversionStep, message: String) + + /// `Arrays.stream(args)` + static func arraysStream(_ argument: JavaNativeConversionStep) -> JavaNativeConversionStep { + .method(.constant("Arrays"), function: "stream", arguments: [argument]) + } + /// Returns the conversion string applied to the placeholder. func render(_ printer: inout CodePrinter, _ placeholder: String) -> String { // NOTE: 'printer' is used if the conversion wants to cause side-effects. @@ -1105,6 +1241,10 @@ extension JNISwift2JavaGenerator { let inner = inner.render(&printer, placeholder) printer.print("\(inner);") return "" + + case .requireNonNull(let inner, let message): + let inner = inner.render(&printer, placeholder) + return #"Objects.requireNonNull(\#(inner), "\#(message)")"# } } @@ -1161,6 +1301,9 @@ extension JNISwift2JavaGenerator { case .print(let inner): return inner.requiresSwiftArena + + case .requireNonNull(let inner, _): + return inner.requiresSwiftArena } } } diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift index 13e8c676..35935038 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift @@ -91,6 +91,12 @@ extension JNISwift2JavaGenerator { parameterName: parameterName ) + case .array: + guard let elementType = nominalType.genericArguments?.first else { + throw JavaTranslationError.unsupportedSwiftType(type) + } + return try translateArrayParameter(elementType: elementType, parameterName: parameterName) + default: guard let javaType = JNIJavaTypeTranslator.translate(knownType: knownType, config: self.config), javaType.implementsJavaValue else { @@ -188,6 +194,12 @@ extension JNISwift2JavaGenerator { throw JavaTranslationError.unsupportedSwiftType(type) + case .array(let elementType): + return try translateArrayParameter( + elementType: elementType, + parameterName: parameterName + ) + case .metatype, .tuple, .composite: throw JavaTranslationError.unsupportedSwiftType(type) } @@ -356,7 +368,7 @@ extension JNISwift2JavaGenerator { return NativeResult( javaType: .long, conversion: .optionalRaisingIndirectReturn( - .getJNIValue(.allocateSwiftValue(name: "_result", swiftType: swiftType)), + .getJNIValue(.allocateSwiftValue(.placeholder, name: "_result", swiftType: swiftType)), returnType: .long, discriminatorParameterName: discriminatorName, placeholderValue: .constant("0") @@ -400,7 +412,7 @@ extension JNISwift2JavaGenerator { outParameters: [] ) - case .function, .metatype, .optional, .tuple, .existential, .opaque, .genericParameter, .composite: + case .function, .metatype, .optional, .tuple, .existential, .opaque, .genericParameter, .composite, .array: throw JavaTranslationError.unsupportedSwiftType(type) } } @@ -429,7 +441,7 @@ extension JNISwift2JavaGenerator { // Custom types are not supported yet. throw JavaTranslationError.unsupportedSwiftType(type) - case .function, .metatype, .optional, .tuple, .existential, .opaque, .genericParameter, .composite: + case .function, .metatype, .optional, .tuple, .existential, .opaque, .genericParameter, .composite, .array: throw JavaTranslationError.unsupportedSwiftType(type) } } @@ -448,6 +460,12 @@ extension JNISwift2JavaGenerator { } return try translateOptionalResult(wrappedType: genericArgs[0], resultName: resultName) + case .array: + guard let elementType = nominalType.genericArguments?.first else { + throw JavaTranslationError.unsupportedSwiftType(swiftResult.type) + } + return try translateArrayResult(elementType: elementType, resultName: resultName) + default: guard let javaType = JNIJavaTypeTranslator.translate(knownType: knownType, config: self.config), javaType.implementsJavaValue else { throw JavaTranslationError.unsupportedSwiftType(swiftResult.type) @@ -467,7 +485,7 @@ extension JNISwift2JavaGenerator { return NativeResult( javaType: .long, - conversion: .getJNIValue(.allocateSwiftValue(name: resultName, swiftType: swiftResult.type)), + conversion: .getJNIValue(.allocateSwiftValue(.placeholder, name: resultName, swiftType: swiftResult.type)), outParameters: [] ) @@ -481,10 +499,108 @@ extension JNISwift2JavaGenerator { case .optional(let wrapped): return try translateOptionalResult(wrappedType: wrapped, resultName: resultName) + case .array(let elementType): + return try translateArrayResult(elementType: elementType, resultName: resultName) + case .metatype, .tuple, .function, .existential, .opaque, .genericParameter, .composite: throw JavaTranslationError.unsupportedSwiftType(swiftResult.type) } } + + func translateArrayResult( + elementType: SwiftType, + resultName: String + ) throws -> NativeResult { + switch elementType { + case .nominal(let nominalType): + if let knownType = nominalType.nominalTypeDecl.knownTypeKind { + guard let javaType = JNIJavaTypeTranslator.translate(knownType: knownType, config: self.config), + javaType.implementsJavaValue else { + throw JavaTranslationError.unsupportedSwiftType(.array(elementType)) + } + + return NativeResult( + javaType: .array(javaType), + conversion: .getJNIValue(.placeholder), + outParameters: [] + ) + } + + guard !nominalType.isJavaKitWrapper else { + throw JavaTranslationError.unsupportedSwiftType(.array(elementType)) + } + + // Assume JExtract imported class + return NativeResult( + javaType: .array(.long), + conversion: + .getJNIValue( + .method( + .placeholder, + function: "map", + arguments: [ + (nil, .closure( + args: ["object$"], + body: .allocateSwiftValue(.constant("object$"), name: "object$", swiftType: elementType) + )) + ] + ) + ), + outParameters: [] + ) + + default: + throw JavaTranslationError.unsupportedSwiftType(.array(elementType)) + } + } + + func translateArrayParameter( + elementType: SwiftType, + parameterName: String + ) throws -> NativeParameter { + switch elementType { + case .nominal(let nominalType): + if let knownType = nominalType.nominalTypeDecl.knownTypeKind { + guard let javaType = JNIJavaTypeTranslator.translate(knownType: knownType, config: self.config), + javaType.implementsJavaValue else { + throw JavaTranslationError.unsupportedSwiftType(elementType) + } + + return NativeParameter( + parameters: [ + JavaParameter(name: parameterName, type: .array(javaType)), + ], + conversion: .initFromJNI(.placeholder, swiftType: .array(elementType)) + ) + } + + guard !nominalType.isJavaKitWrapper else { + throw JavaTranslationError.unsupportedSwiftType(.array(elementType)) + } + + // Assume JExtract wrapped class + return NativeParameter( + parameters: [JavaParameter(name: parameterName, type: .array(.long))], + conversion: .method( + .initFromJNI(.placeholder, swiftType: .array(self.knownTypes.int64)), + function: "map", + arguments: [ + (nil, .closure( + args: ["pointer$"], + body: .pointee(.extractSwiftValue( + .constant("pointer$"), + swiftType: elementType, + allowNil: false, + convertLongFromJNI: false + )))) + ] + ) + ) + + default: + throw JavaTranslationError.unsupportedSwiftType(elementType) + } + } } struct NativeFunctionSignature { @@ -539,11 +655,12 @@ extension JNISwift2JavaGenerator { indirect case extractSwiftValue( NativeSwiftConversionStep, swiftType: SwiftType, - allowNil: Bool = false + allowNil: Bool = false, + convertLongFromJNI: Bool = true ) /// Allocate memory for a Swift value and outputs the pointer - case allocateSwiftValue(name: String, swiftType: SwiftType) + indirect case allocateSwiftValue(NativeSwiftConversionStep, name: String, swiftType: SwiftType) /// The thing to which the pointer typed, which is the `pointee` property /// of the `Unsafe(Mutable)Pointer` types in Swift. @@ -575,6 +692,9 @@ extension JNISwift2JavaGenerator { isThrowing: Bool ) + /// `{ (args) -> return body }` + indirect case closure(args: [String] = [], body: NativeSwiftConversionStep) + /// Returns the conversion string applied to the placeholder. func render(_ printer: inout CodePrinter, _ placeholder: String) -> String { // NOTE: 'printer' is used if the conversion wants to cause side-effects. @@ -630,18 +750,18 @@ extension JNISwift2JavaGenerator { ) return existentialName - case .extractSwiftValue(let inner, let swiftType, let allowNil): + case .extractSwiftValue(let inner, let swiftType, let allowNil, let convertLongFromJNI): let inner = inner.render(&printer, placeholder) let pointerName = "\(inner)$" if !allowNil { printer.print(#"assert(\#(inner) != 0, "\#(inner) memory address was null")"#) } - printer.print( - """ - let \(inner)Bits$ = Int(Int64(fromJNI: \(inner), in: environment)) - let \(pointerName) = UnsafeMutablePointer<\(swiftType)>(bitPattern: \(inner)Bits$) - """ - ) + if convertLongFromJNI { + printer.print("let \(inner)Bits$ = Int(Int64(fromJNI: \(inner), in: environment))") + } else { + printer.print("let \(inner)Bits$ = Int(\(inner))") + } + printer.print("let \(pointerName) = UnsafeMutablePointer<\(swiftType)>(bitPattern: \(inner)Bits$)") if !allowNil { printer.print( """ @@ -653,13 +773,14 @@ extension JNISwift2JavaGenerator { } return pointerName - case .allocateSwiftValue(let name, let swiftType): + case .allocateSwiftValue(let inner, let name, let swiftType): + let inner = inner.render(&printer, placeholder) let pointerName = "\(name)$" let bitsName = "\(name)Bits$" printer.print( """ let \(pointerName) = UnsafeMutablePointer<\(swiftType)>.allocate(capacity: 1) - \(pointerName).initialize(to: \(placeholder)) + \(pointerName).initialize(to: \(inner)) let \(bitsName) = Int64(Int(bitPattern: \(pointerName))) """ ) @@ -894,6 +1015,16 @@ extension JNISwift2JavaGenerator { } return "" + + case .closure(let args, let body): + var printer = CodePrinter() + printer.printBraceBlock("", parameters: args) { printer in + let body = body.render(&printer, placeholder) + if !body.isEmpty { + printer.print("return \(body)") + } + } + return printer.finalize() } } } diff --git a/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift b/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift index 7de792c0..60b99a63 100644 --- a/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift +++ b/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift @@ -142,6 +142,8 @@ extension Swift2JavaTranslator { return types.contains(where: check) case .genericParameter: return false + case .array(let ty): + return check(ty) } } diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownModules.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownModules.swift index 7acb1199..1be8071c 100644 --- a/Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownModules.swift +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownModules.swift @@ -94,6 +94,8 @@ private let swiftSourceFile: SourceFileSyntax = """ public struct Optional {} + public struct Array {} + // FIXME: Support 'typealias Void = ()' public struct Void {} @@ -117,4 +119,4 @@ private var foundationSourceFile: SourceFileSyntax { // On platforms other than Darwin, imports such as FoundationEssentials, FoundationNetworking, etc. are used, // so this file should be created by combining the files of the aforementioned modules. foundationEssentialsSourceFile -} \ No newline at end of file +} diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownTypeDecls.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownTypeDecls.swift index 809f2aa1..4a0cb9e8 100644 --- a/Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownTypeDecls.swift +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownTypeDecls.swift @@ -40,6 +40,7 @@ enum SwiftKnownTypeDeclKind: String, Hashable { case optional = "Swift.Optional" case void = "Swift.Void" case string = "Swift.String" + case array = "Swift.Array" // Foundation case foundationDataProtocol = "Foundation.DataProtocol" diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftType.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftType.swift index 3840b3e1..b2f8d6ea 100644 --- a/Sources/JExtractSwiftLib/SwiftTypes/SwiftType.swift +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftType.swift @@ -40,6 +40,9 @@ enum SwiftType: Equatable { /// `type1` & `type2` indirect case composite([SwiftType]) + /// `[type]` + indirect case array(SwiftType) + static var void: Self { return .tuple([]) } @@ -48,7 +51,7 @@ enum SwiftType: Equatable { switch self { case .nominal(let nominal): nominal case .tuple(let elements): elements.count == 1 ? elements[0].asNominalType : nil - case .genericParameter, .function, .metatype, .optional, .existential, .opaque, .composite: nil + case .genericParameter, .function, .metatype, .optional, .existential, .opaque, .composite, .array: nil } } @@ -91,7 +94,7 @@ enum SwiftType: Equatable { return nominal.nominalTypeDecl.isReferenceType case .metatype, .function: return true - case .genericParameter, .optional, .tuple, .existential, .opaque, .composite: + case .genericParameter, .optional, .tuple, .existential, .opaque, .composite, .array: return false } } @@ -127,7 +130,7 @@ extension SwiftType: CustomStringConvertible { private var postfixRequiresParentheses: Bool { switch self { case .function, .existential, .opaque, .composite: true - case .genericParameter, .metatype, .nominal, .optional, .tuple: false + case .genericParameter, .metatype, .nominal, .optional, .tuple, .array: false } } @@ -152,6 +155,8 @@ extension SwiftType: CustomStringConvertible { return "some \(constraintType)" case .composite(let types): return types.map(\.description).joined(separator: " & ") + case .array(let type): + return "[\(type)]" } } } @@ -213,7 +218,7 @@ extension SwiftNominalType { extension SwiftType { init(_ type: TypeSyntax, lookupContext: SwiftTypeLookupContext) throws { switch type.as(TypeSyntaxEnum.self) { - case .arrayType, .classRestrictionType, + case .classRestrictionType, .dictionaryType, .missingType, .namedOpaqueReturnType, .packElementType, .packExpansionType, .suppressedType, .inlineArrayType: throw TypeTranslationError.unimplementedType(type) @@ -323,6 +328,10 @@ extension SwiftType { } self = .composite(types) + + case .arrayType(let arrayType): + let elementType = try SwiftType(arrayType.element, lookupContext: lookupContext) + self = .array(elementType) } } diff --git a/Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md b/Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md index 3178f60d..7e8c66d3 100644 --- a/Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md +++ b/Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md @@ -58,7 +58,7 @@ SwiftJava's `swift-java jextract` tool automates generating Java bindings from S | Stored properties: `var`, `let` (with `willSet`, `didSet`) | ✅ | ✅ | | Computed properties: `var` (incl. `throws`) | ✅ / TODO | ✅ | | Async functions `func async` and properties: `var { get async {} }` | ❌ | ✅ | -| Arrays: `[UInt8]`, `[T]` | ❌ | ❌ | +| Arrays: `[UInt8]`, `[MyType]`, `Array` etc | ❌ | ✅ | | Dictionaries: `[String: Int]`, `[K:V]` | ❌ | ❌ | | Generic parameters in functions: `func f(x: T)` | ❌ | ✅ | | Generic return values in functions: `func f() -> T` | ❌ | ❌ | diff --git a/Tests/JExtractSwiftTests/JNI/JNIArrayTest.swift b/Tests/JExtractSwiftTests/JNI/JNIArrayTest.swift new file mode 100644 index 00000000..ebe3f807 --- /dev/null +++ b/Tests/JExtractSwiftTests/JNI/JNIArrayTest.swift @@ -0,0 +1,188 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import JExtractSwiftLib +import Testing + +@Suite +struct JNIArrayTest { + + @Test("Import: (Array) -> Array (Java)") + func uint8Array_explicitType_java() throws { + try assertOutput( + input: "public func f(array: Array) -> Array {}", + .jni, .java, + detectChunkByInitialLines: 1, + expectedChunks: [ + """ + public static byte[] f(@Unsigned byte[] array) { + return SwiftModule.$f(Objects.requireNonNull(array, "array must not be null")); + } + """, + """ + private static native byte[] $f(byte[] array); + """, + ] + ) + } + + @Test("Import: (Array) -> Array (Swift)") + func uint8Array_explicitType_swift() throws { + try assertOutput( + input: "public func f(array: Array) -> Array {}", + .jni, .swift, + detectChunkByInitialLines: 1, + expectedChunks: [ + """ + @_cdecl("Java_com_example_swift_SwiftModule__00024f___3B") + func Java_com_example_swift_SwiftModule__00024f___3B(environment: UnsafeMutablePointer!, thisClass: jclass, array: jbyteArray?) -> jbyteArray? { + return SwiftModule.f(array: [UInt8](fromJNI: array, in: environment)).getJNIValue(in: environment) + } + """ + ] + ) + } + + @Test("Import: ([UInt8]) -> [UInt8] (Java)") + func uint8Array_syntaxSugar_java() throws { + try assertOutput( + input: "public func f(array: Array) -> Array {}", + .jni, .java, + detectChunkByInitialLines: 1, + expectedChunks: [ + """ + public static byte[] f(@Unsigned byte[] array) { + return SwiftModule.$f(Objects.requireNonNull(array, "array must not be null")); + } + """, + """ + private static native byte[] $f(byte[] array); + """, + ] + ) + } + + @Test("Import: ([UInt8]) -> [UInt8] (Swift)") + func uint8Array_syntaxSugar_swift() throws { + try assertOutput( + input: "public func f(array: [UInt8]) -> [UInt8] {}", + .jni, .swift, + detectChunkByInitialLines: 1, + expectedChunks: [ + """ + @_cdecl("Java_com_example_swift_SwiftModule__00024f___3B") + func Java_com_example_swift_SwiftModule__00024f___3B(environment: UnsafeMutablePointer!, thisClass: jclass, array: jbyteArray?) -> jbyteArray? { + return SwiftModule.f(array: [UInt8](fromJNI: array, in: environment)).getJNIValue(in: environment) + } + """ + ] + ) + } + + @Test("Import: ([Int64]) -> [Int64] (Java)") + func int64Array_syntaxSugar_java() throws { + try assertOutput( + input: "public func f(array: [Int64]) -> [Int64] {}", + .jni, .java, + detectChunkByInitialLines: 1, + expectedChunks: [ + """ + public static long[] f(long[] array) { + return SwiftModule.$f(Objects.requireNonNull(array, "array must not be null")); + } + """, + """ + private static native long[] $f(long[] array); + """, + ] + ) + } + + @Test("Import: ([Int64]) -> [Int64] (Swift)") + func int64Array_syntaxSugar_swift() throws { + try assertOutput( + input: "public func f(array: [Int64]) -> [Int64] {}", + .jni, .swift, + detectChunkByInitialLines: 1, + expectedChunks: [ + """ + @_cdecl("Java_com_example_swift_SwiftModule__00024f___3J") + func Java_com_example_swift_SwiftModule__00024f___3J(environment: UnsafeMutablePointer!, thisClass: jclass, array: jlongArray?) -> jlongArray? { + return SwiftModule.f(array: [Int64](fromJNI: array, in: environment)).getJNIValue(in: environment) + } + """ + ] + ) + } + + @Test("Import: ([MySwiftClass]) -> [MySwiftClass] (Java)") + func swiftClassArray_syntaxSugar_java() throws { + try assertOutput( + input: """ + public class MySwiftClass {} + public func f(array: [MySwiftClass]) -> [MySwiftClass] {} + """, + .jni, .java, + detectChunkByInitialLines: 1, + expectedChunks: [ + """ + public static MySwiftClass[] f(MySwiftClass[] array, SwiftArena swiftArena$) { + return Arrays.stream(SwiftModule.$f(Arrays.stream(Objects.requireNonNull(array, "array must not be null")).mapToLong(MySwiftClass::$memoryAddress).toArray())).mapToObj((pointer) -> { + return MySwiftClass.wrapMemoryAddressUnsafe(pointer, swiftArena$); + } + ).toArray(MySwiftClass[]::new); + } + """, + """ + private static native long[] $f(long[] array); + """, + ] + ) + } + + @Test("Import: ([MySwiftClass]) -> [MySwiftClass] (Swift)") + func swiftClassArray_syntaxSugar_swift() throws { + try assertOutput( + input: """ + public class MySwiftClass {} + public func f(array: [MySwiftClass]) -> [MySwiftClass] {} + """, + .jni, .swift, + detectChunkByInitialLines: 1, + expectedChunks: [ + """ + @_cdecl("Java_com_example_swift_SwiftModule__00024f___3J") + func Java_com_example_swift_SwiftModule__00024f___3J(environment: UnsafeMutablePointer!, thisClass: jclass, array: jlongArray?) -> jlongArray? { + return SwiftModule.f(array: [Int64](fromJNI: array, in: environment).map( { (pointer$) in + assert(pointer$ != 0, "pointer$ memory address was null") + let pointer$Bits$ = Int(pointer$) + let pointer$$ = UnsafeMutablePointer(bitPattern: pointer$Bits$) + guard let pointer$$ else { + fatalError("pointer$ memory address was null in call to \\(#function)!") + } + return pointer$$.pointee + } + )).map( { (object$) in + let object$$ = UnsafeMutablePointer.allocate(capacity: 1) + object$$.initialize(to: object$) + let object$Bits$ = Int64(Int(bitPattern: object$$)) + return object$Bits$ + } + ).getJNIValue(in: environment) + } + """ + ] + ) + } +} From e907ab050e4cac6d22bd6c72a1449b3a1f55a106 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Wed, 12 Nov 2025 12:56:36 +0900 Subject: [PATCH 391/426] Delete WIP.md (#438) --- WIP.md | 25 ------------------------- 1 file changed, 25 deletions(-) delete mode 100644 WIP.md diff --git a/WIP.md b/WIP.md deleted file mode 100644 index 88671233..00000000 --- a/WIP.md +++ /dev/null @@ -1,25 +0,0 @@ -## Work In Progress - -This package is a work in progress, and many details are subject to change. - -Here is a long yet still very incomplete list of things we would like to do or -improve: - -- Expressivity gaps: - - [ ] Automatically turn get/set method pairs into Swift properties? - - [ ] Implement a global registry that lets us find the Swift type corresponding to a canonical Java class name (e.g., `java.net.URL` -> `JavaKitNetwork.URL`) - - [ ] Introduce overloads of `is` and `as` on the Swift projections so that conversion to any implemented interface or extended superclass returns non-optional. - - [ ] Figure out how to express the equivalent of `super.foo()` that calls the superclass's method from the subclass method. - - [ ] Recognize Java's enum classes and map them into Swift well - - [ ] Translate Java constants into Swift constants - - [ ] Support nested classes - - [ ] Figure out how to subclass a Java class from Swift -- Tooling - - [ ] Generate Swift projections for more common Java types into JavaKit libraries to make it easier to get started - - [ ] Teach `Java2Swift` when to create extensions of already-translated types that pick up any members that couldn't be translated because of missing types. See, for example, how `JavaKitReflection` adds extensions to `JavaClass` based on types like `Method` and `Parameter` -- Performance: - - [ ] Cache method/field IDs when we can - - [ ] Investigate noncopyable types to remove excess copies - - [ ] Investigate "unbridged" variants of String, Array, etc. - - [ ] Investigate the new [Foreign Function & Memory API](https://bugs.openjdk.org/browse/JDK-8312523) (aka Project Panama) for exposing Swift APIs to Java. - From 46699587ec25374ec6f0431beb6ea29dfa8d9758 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Wed, 12 Nov 2025 14:17:09 +0900 Subject: [PATCH 392/426] jextract/jni: use deferEnvironment instead of environment interface (#437) --- ...wift2JavaGenerator+NativeTranslation.swift | 2 +- .../JNI/JNIAsyncTests.swift | 20 +++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift index 35935038..1994dce0 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift @@ -973,7 +973,7 @@ extension JNISwift2JavaGenerator { // Defer might on any thread, so we need to attach environment. printer.print("let deferEnvironment = try! JavaVirtualMachine.shared().environment()") for globalRef in globalRefs { - printer.print("environment.interface.DeleteGlobalRef(deferEnvironment, \(globalRef))") + printer.print("deferEnvironment.interface.DeleteGlobalRef(deferEnvironment, \(globalRef))") } } if isThrowing { diff --git a/Tests/JExtractSwiftTests/JNI/JNIAsyncTests.swift b/Tests/JExtractSwiftTests/JNI/JNIAsyncTests.swift index 975cccc6..1930e601 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIAsyncTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIAsyncTests.swift @@ -66,7 +66,7 @@ struct JNIAsyncTests { var environment = environment! defer { let deferEnvironment = try! JavaVirtualMachine.shared().environment() - environment.interface.DeleteGlobalRef(deferEnvironment, globalFuture) + deferEnvironment.interface.DeleteGlobalRef(deferEnvironment, globalFuture) } let swiftResult$ = await SwiftModule.asyncVoid() environment = try! JavaVirtualMachine.shared().environment() @@ -79,7 +79,7 @@ struct JNIAsyncTests { var environment = try! JavaVirtualMachine.shared().environment() defer { let deferEnvironment = try! JavaVirtualMachine.shared().environment() - environment.interface.DeleteGlobalRef(deferEnvironment, globalFuture) + deferEnvironment.interface.DeleteGlobalRef(deferEnvironment, globalFuture) } let swiftResult$ = await SwiftModule.asyncVoid() environment = try! JavaVirtualMachine.shared().environment() @@ -140,7 +140,7 @@ struct JNIAsyncTests { var environment = environment! defer { let deferEnvironment = try! JavaVirtualMachine.shared().environment() - environment.interface.DeleteGlobalRef(deferEnvironment, globalFuture) + deferEnvironment.interface.DeleteGlobalRef(deferEnvironment, globalFuture) } do { let swiftResult$ = await try SwiftModule.async() @@ -160,7 +160,7 @@ struct JNIAsyncTests { var environment = try! JavaVirtualMachine.shared().environment() defer { let deferEnvironment = try! JavaVirtualMachine.shared().environment() - environment.interface.DeleteGlobalRef(deferEnvironment, globalFuture) + deferEnvironment.interface.DeleteGlobalRef(deferEnvironment, globalFuture) } do { let swiftResult$ = await try SwiftModule.async() @@ -228,7 +228,7 @@ struct JNIAsyncTests { var environment = environment! defer { let deferEnvironment = try! JavaVirtualMachine.shared().environment() - environment.interface.DeleteGlobalRef(deferEnvironment, globalFuture) + deferEnvironment.interface.DeleteGlobalRef(deferEnvironment, globalFuture) } let swiftResult$ = await SwiftModule.async(i: Int64(fromJNI: i, in: environment)) environment = try! JavaVirtualMachine.shared().environment() @@ -242,7 +242,7 @@ struct JNIAsyncTests { var environment = try! JavaVirtualMachine.shared().environment() defer { let deferEnvironment = try! JavaVirtualMachine.shared().environment() - environment.interface.DeleteGlobalRef(deferEnvironment, globalFuture) + deferEnvironment.interface.DeleteGlobalRef(deferEnvironment, globalFuture) } let swiftResult$ = await SwiftModule.async(i: Int64(fromJNI: i, in: environment)) environment = try! JavaVirtualMachine.shared().environment() @@ -319,7 +319,7 @@ struct JNIAsyncTests { var environment = environment! defer { let deferEnvironment = try! JavaVirtualMachine.shared().environment() - environment.interface.DeleteGlobalRef(deferEnvironment, globalFuture) + deferEnvironment.interface.DeleteGlobalRef(deferEnvironment, globalFuture) } let swiftResult$ = await SwiftModule.async(c: c$.pointee) environment = try! JavaVirtualMachine.shared().environment() @@ -336,7 +336,7 @@ struct JNIAsyncTests { var environment = try! JavaVirtualMachine.shared().environment() defer { let deferEnvironment = try! JavaVirtualMachine.shared().environment() - environment.interface.DeleteGlobalRef(deferEnvironment, globalFuture) + deferEnvironment.interface.DeleteGlobalRef(deferEnvironment, globalFuture) } let swiftResult$ = await SwiftModule.async(c: c$.pointee) environment = try! JavaVirtualMachine.shared().environment() @@ -397,8 +397,8 @@ struct JNIAsyncTests { ... defer { let deferEnvironment = try! JavaVirtualMachine.shared().environment() - environment.interface.DeleteGlobalRef(deferEnvironment, globalFuture) - environment.interface.DeleteGlobalRef(deferEnvironment, s) + deferEnvironment.interface.DeleteGlobalRef(deferEnvironment, globalFuture) + deferEnvironment.interface.DeleteGlobalRef(deferEnvironment, s) } ... environment.interface.CallBooleanMethodA(environment, globalFuture, _JNIMethodIDCache.CompletableFuture.complete, [jvalue(l: swiftResult$.getJNIValue(in: environment))]) From f010c8e33d528085057bb8e82eb53136df30effd Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Wed, 12 Nov 2025 19:32:42 +0900 Subject: [PATCH 393/426] wrap-java revamp and add generic methods, types, and supertypes support (#397) --- Package.swift | 4 +- Plugins/SwiftJavaPlugin/SwiftJavaPlugin.swift | 31 ++ .../Sources/JavaCommonsCSV/swift-java.config | 4 +- .../JavaDependencySampleApp/ci-validate.sh | 4 +- .../Sources/MySwiftLibrary/NestedTypes.swift | 2 +- .../com/example/swift/HelloJava2SwiftJNI.java | 2 - .../JavaLangReflect/Method+Utilities.swift | 26 +- .../TypeVariable+Extensions.swift | 63 ++++ .../generated/Executable.swift | 3 - .../generated/ParameterizedType.swift | 21 ++ .../JavaLangReflect/generated/Type.swift | 9 + .../generated/TypeVariable.swift | 4 +- .../JavaStdlib/JavaNet/URL+Extensions.swift | 34 ++ .../JavaNet/URLClassLoader+Workaround.swift | 22 ++ Sources/SwiftJava/AnyJavaObject.swift | 6 +- .../JavaVirtualMachine.swift | 2 +- .../{JavaKitVM => JVM}/LockedState.swift | 0 .../ThreadLocalStorage.swift | 0 .../JavaClass+CustomStringConvertible.swift | 21 ++ Sources/SwiftJava/JavaObjectHolder.swift | 4 +- .../String+Extensions.swift | 18 +- .../SwiftJava/SwiftJavaConversionError.swift | 22 ++ .../SwiftJava/generated/CharSequence.swift | 3 + .../SwiftJava/generated/JavaCharacter.swift | 328 +++++++++--------- Sources/SwiftJava/generated/JavaClass.swift | 34 +- .../SwiftJava/generated/JavaClassLoader.swift | 8 +- Sources/SwiftJava/generated/JavaEnum.swift | 11 + Sources/SwiftJava/generated/JavaInteger.swift | 29 +- Sources/SwiftJava/generated/JavaLong.swift | 18 +- .../SwiftJava/generated/JavaOptional.swift | 2 +- .../generated/JavaReflectArray.swift | 71 ++++ .../JavaReflectParameterizedType.swift | 17 + .../SwiftJava/generated/JavaReflectType.swift | 8 + Sources/SwiftJava/swift-java.config | 2 + .../Configuration.swift | 8 +- .../Commands/ConfigureCommand.swift | 56 ++- .../Commands/JExtractCommand.swift | 10 +- .../Commands/ResolveCommand.swift | 22 +- .../Commands/WrapJavaCommand.swift | 52 ++- Sources/SwiftJavaTool/CommonOptions.swift | 21 +- Sources/SwiftJavaTool/ExcludedJDKTypes.swift | 42 +++ .../SwiftJavaTool/Java/JavaClassLoader.swift | 1 + .../JavaClassTranslator.swift | 309 +++++++++-------- .../JavaGenericsSupport.swift | 89 +++++ .../SwiftJavaToolLib/JavaHomeSupport.swift | 92 +++++ .../JavaParameterizedType.swift | 38 ++ .../JavaTranslator+Configuration.swift | 10 +- .../JavaTranslator+Validation.swift | 53 ++- Sources/SwiftJavaToolLib/JavaTranslator.swift | 114 ++++-- .../SwiftJavaToolLib/JavaType+Equality.swift | 135 +++++++ .../FFMNestedTypesTests.swift | 56 +++ .../JNI/JNINestedTypesTests.swift | 2 +- .../JNI/JNIUnsignedNumberTests.swift | 1 - .../CompileJavaWrapTools.swift | 174 ++++++++++ .../Java2SwiftTests.swift | 278 ++++++++------- .../JavaTranslatorTests.swift | 58 ++++ .../JavaTranslatorValidationTests.swift | 13 +- .../SwiftJavaToolLibTests/TempFileTools.swift | 34 ++ .../SwiftJavaToolLibTests/WrapJavaTests.swift | 273 +++++++++++++++ 59 files changed, 2150 insertions(+), 624 deletions(-) create mode 100644 Sources/JavaStdlib/JavaLangReflect/TypeVariable+Extensions.swift create mode 100644 Sources/JavaStdlib/JavaNet/URL+Extensions.swift create mode 100644 Sources/JavaStdlib/JavaNet/URLClassLoader+Workaround.swift rename Sources/SwiftJava/{JavaKitVM => JVM}/JavaVirtualMachine.swift (99%) rename Sources/SwiftJava/{JavaKitVM => JVM}/LockedState.swift (100%) rename Sources/SwiftJava/{JavaKitVM => JVM}/ThreadLocalStorage.swift (100%) create mode 100644 Sources/SwiftJava/JavaClass+CustomStringConvertible.swift rename Sources/{SwiftJavaTool => SwiftJava}/String+Extensions.swift (82%) create mode 100644 Sources/SwiftJava/SwiftJavaConversionError.swift create mode 100644 Sources/SwiftJava/generated/JavaEnum.swift create mode 100644 Sources/SwiftJava/generated/JavaReflectArray.swift create mode 100644 Sources/SwiftJava/generated/JavaReflectParameterizedType.swift create mode 100644 Sources/SwiftJava/generated/JavaReflectType.swift create mode 100644 Sources/SwiftJavaTool/ExcludedJDKTypes.swift create mode 100644 Sources/SwiftJavaToolLib/JavaGenericsSupport.swift create mode 100644 Sources/SwiftJavaToolLib/JavaHomeSupport.swift create mode 100644 Sources/SwiftJavaToolLib/JavaParameterizedType.swift create mode 100644 Sources/SwiftJavaToolLib/JavaType+Equality.swift create mode 100644 Tests/JExtractSwiftTests/FFMNestedTypesTests.swift create mode 100644 Tests/SwiftJavaToolLibTests/CompileJavaWrapTools.swift create mode 100644 Tests/SwiftJavaToolLibTests/JavaTranslatorTests.swift create mode 100644 Tests/SwiftJavaToolLibTests/TempFileTools.swift create mode 100644 Tests/SwiftJavaToolLibTests/WrapJavaTests.swift diff --git a/Package.swift b/Package.swift index 722859ee..7d872795 100644 --- a/Package.swift +++ b/Package.swift @@ -14,6 +14,9 @@ func findJavaHome() -> String { print("JAVA_HOME = \(home)") return home } + if let opts = ProcessInfo.processInfo.environment["SWIFT_JAVA_JAVA_OPTS"] { + print("SWIFT_JAVA_JAVA_OPTS = \(opts)") + } // This is a workaround for envs (some IDEs) which have trouble with // picking up env variables during the build process @@ -420,7 +423,6 @@ let package = Package( .executableTarget( name: "SwiftJavaTool", dependencies: [ - .product(name: "Logging", package: "swift-log"), .product(name: "SwiftBasicFormat", package: "swift-syntax"), .product(name: "SwiftSyntax", package: "swift-syntax"), .product(name: "SwiftSyntaxBuilder", package: "swift-syntax"), diff --git a/Plugins/SwiftJavaPlugin/SwiftJavaPlugin.swift b/Plugins/SwiftJavaPlugin/SwiftJavaPlugin.swift index 57641eff..7908932d 100644 --- a/Plugins/SwiftJavaPlugin/SwiftJavaPlugin.swift +++ b/Plugins/SwiftJavaPlugin/SwiftJavaPlugin.swift @@ -165,6 +165,11 @@ struct SwiftJavaBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin { log("No dependencies to fetch for target \(sourceModule.name)") } + // Add all the core Java stdlib modules as --depends-on + let javaStdlibModules = getExtractedJavaStdlibModules() + log("Include Java standard library SwiftJava modules: \(javaStdlibModules)") + arguments += javaStdlibModules.flatMap { ["--depends-on", $0] } + if !outputSwiftFiles.isEmpty { arguments += [ configFile.path(percentEncoded: false) ] @@ -236,3 +241,29 @@ extension SwiftJavaBuildToolPlugin { outputDirectory(context: context, generated: generated).appending(path: filename) } } + +func getExtractedJavaStdlibModules() -> [String] { + let fileManager = FileManager.default + let sourcesPath = URL(fileURLWithPath: #filePath) + .deletingLastPathComponent() + .deletingLastPathComponent() + .appendingPathComponent("Sources") + .appendingPathComponent("JavaStdlib") + + guard let stdlibDirContents = try? fileManager.contentsOfDirectory( + at: sourcesPath, + includingPropertiesForKeys: [.isDirectoryKey], + options: [.skipsHiddenFiles] + ) else { + return [] + } + + return stdlibDirContents.compactMap { url in + guard let resourceValues = try? url.resourceValues(forKeys: [.isDirectoryKey]), + let isDirectory = resourceValues.isDirectory, + isDirectory else { + return nil + } + return url.lastPathComponent + }.sorted() +} \ No newline at end of file diff --git a/Samples/JavaDependencySampleApp/Sources/JavaCommonsCSV/swift-java.config b/Samples/JavaDependencySampleApp/Sources/JavaCommonsCSV/swift-java.config index 3b685159..dc38efd9 100644 --- a/Samples/JavaDependencySampleApp/Sources/JavaCommonsCSV/swift-java.config +++ b/Samples/JavaDependencySampleApp/Sources/JavaCommonsCSV/swift-java.config @@ -1,11 +1,13 @@ { "classes" : { "org.apache.commons.io.FilenameUtils" : "FilenameUtils", - "org.apache.commons.io.IOCase" : "IOCase", "org.apache.commons.csv.CSVFormat" : "CSVFormat", "org.apache.commons.csv.CSVParser" : "CSVParser", "org.apache.commons.csv.CSVRecord" : "CSVRecord" }, + "filterExclude" : [ + "org.apache.commons.csv.CSVFormat$Predefined", + ], "dependencies" : [ "org.apache.commons:commons-csv:1.12.0" ] diff --git a/Samples/JavaDependencySampleApp/ci-validate.sh b/Samples/JavaDependencySampleApp/ci-validate.sh index b6162fdc..feeb8767 100755 --- a/Samples/JavaDependencySampleApp/ci-validate.sh +++ b/Samples/JavaDependencySampleApp/ci-validate.sh @@ -4,7 +4,9 @@ set -e set -x # invoke resolve as part of a build run -swift run --disable-sandbox +swift build \ + --disable-experimental-prebuilts \ + --disable-sandbox # explicitly invoke resolve without explicit path or dependency # the dependencies should be uses from the --swift-module diff --git a/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/NestedTypes.swift b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/NestedTypes.swift index b7edefa9..fb2b4924 100644 --- a/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/NestedTypes.swift +++ b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/NestedTypes.swift @@ -44,4 +44,4 @@ public enum NestedEnum { public struct OneStruct { public init() {} } -} +} \ No newline at end of file diff --git a/Samples/SwiftJavaExtractJNISampleApp/src/main/java/com/example/swift/HelloJava2SwiftJNI.java b/Samples/SwiftJavaExtractJNISampleApp/src/main/java/com/example/swift/HelloJava2SwiftJNI.java index 3109f64e..407ebe7c 100644 --- a/Samples/SwiftJavaExtractJNISampleApp/src/main/java/com/example/swift/HelloJava2SwiftJNI.java +++ b/Samples/SwiftJavaExtractJNISampleApp/src/main/java/com/example/swift/HelloJava2SwiftJNI.java @@ -16,8 +16,6 @@ // Import swift-extract generated sources -// Import javakit/swiftkit support libraries - import org.swift.swiftkit.core.SwiftArena; import org.swift.swiftkit.core.SwiftLibraries; diff --git a/Sources/JavaStdlib/JavaLangReflect/Method+Utilities.swift b/Sources/JavaStdlib/JavaLangReflect/Method+Utilities.swift index 71ee864c..ecc11b50 100644 --- a/Sources/JavaStdlib/JavaLangReflect/Method+Utilities.swift +++ b/Sources/JavaStdlib/JavaLangReflect/Method+Utilities.swift @@ -13,23 +13,41 @@ //===----------------------------------------------------------------------===// extension Method { + /// Whether this is a 'public' method. public var isPublic: Bool { - return (getModifiers() & 1) != 0 + return (getModifiers() & 0x00000001) != 0 + } + + /// Whether this is a 'private' method. + public var isPrivate: Bool { + return (getModifiers() & 0x00000002) != 0 } /// Whether this is a 'protected' method. public var isProtected: Bool { - return (getModifiers() & 4) != 0 + return (getModifiers() & 0x00000004) != 0 + } + + /// Whether this is a 'package' method. + /// + /// The "default" access level in Java is 'package', it is signified by lack of a different access modifier. + public var isPackage: Bool { + return !isPublic && !isPrivate && !isProtected } /// Whether this is a 'static' method. public var isStatic: Bool { - return (getModifiers() & 0x08) != 0 + return (getModifiers() & 0x00000008) != 0 } /// Whether this is a 'native' method. public var isNative: Bool { - return (getModifiers() & 256) != 0 + return (getModifiers() & 0x00000100) != 0 + } + + /// Whether this is a 'final' method. + public var isFinal: Bool { + return (getModifiers() & 0x00000010) != 0 } } diff --git a/Sources/JavaStdlib/JavaLangReflect/TypeVariable+Extensions.swift b/Sources/JavaStdlib/JavaLangReflect/TypeVariable+Extensions.swift new file mode 100644 index 00000000..157ae353 --- /dev/null +++ b/Sources/JavaStdlib/JavaLangReflect/TypeVariable+Extensions.swift @@ -0,0 +1,63 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import CSwiftJavaJNI +import SwiftJava + +// FIXME: all interfaces should ahve these https://github.com/swiftlang/swift-java/issues/430 +extension TypeVariable { + + @JavaMethod + public func toString() -> String + + @JavaMethod + public func getClass() -> JavaClass! + + @JavaMethod + public func equals(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func hashCode() -> Int32 + +} + +// FIXME: All Java objects are Hashable, we should handle that accordingly. +extension TypeVariable: Hashable { + + public func hash(into hasher: inout Hasher) { + guard let pojo = self.as(JavaObject.self) else { + return + } + + hasher.combine(pojo.hashCode()) + } + + public static func == (lhs: TypeVariable, rhs: TypeVariable) -> Bool { + guard let lhpojo: JavaObject = lhs.as(JavaObject.self) else { + return false + } + guard let rhpojo: JavaObject = rhs.as(JavaObject.self) else { + return false + } + + return lhpojo.equals(rhpojo) + } + +} + +extension TypeVariable { + public var description: String { + toString() + } +} \ No newline at end of file diff --git a/Sources/JavaStdlib/JavaLangReflect/generated/Executable.swift b/Sources/JavaStdlib/JavaLangReflect/generated/Executable.swift index 3a6df8ea..af9931d3 100644 --- a/Sources/JavaStdlib/JavaLangReflect/generated/Executable.swift +++ b/Sources/JavaStdlib/JavaLangReflect/generated/Executable.swift @@ -11,9 +11,6 @@ open class Executable: AccessibleObject { @JavaMethod open func getModifiers() -> Int32 - @JavaMethod - open func getTypeParameters() -> [TypeVariable?] - @JavaMethod open func getParameterTypes() -> [JavaClass?] diff --git a/Sources/JavaStdlib/JavaLangReflect/generated/ParameterizedType.swift b/Sources/JavaStdlib/JavaLangReflect/generated/ParameterizedType.swift index 5e29ee05..984c2b16 100644 --- a/Sources/JavaStdlib/JavaLangReflect/generated/ParameterizedType.swift +++ b/Sources/JavaStdlib/JavaLangReflect/generated/ParameterizedType.swift @@ -16,3 +16,24 @@ public struct ParameterizedType { @JavaMethod public func getTypeName() -> String } + +extension ParameterizedType { + + @JavaMethod + public func toString() -> String + + @JavaMethod + public func getClass() -> JavaClass! + + @JavaMethod + public func equals(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func hashCode() -> Int32 +} + +extension ParameterizedType: CustomStringConvertible { + public var description: String { + toString() + } +} \ No newline at end of file diff --git a/Sources/JavaStdlib/JavaLangReflect/generated/Type.swift b/Sources/JavaStdlib/JavaLangReflect/generated/Type.swift index ff52b41a..2e85c384 100644 --- a/Sources/JavaStdlib/JavaLangReflect/generated/Type.swift +++ b/Sources/JavaStdlib/JavaLangReflect/generated/Type.swift @@ -6,4 +6,13 @@ import CSwiftJavaJNI public struct Type { @JavaMethod public func getTypeName() -> String + + @JavaMethod + public func toString() -> String +} + +extension Type: CustomStringConvertible { + public var description: String { + "JavaLangReflect.Type(\(self.toString()))" + } } diff --git a/Sources/JavaStdlib/JavaLangReflect/generated/TypeVariable.swift b/Sources/JavaStdlib/JavaLangReflect/generated/TypeVariable.swift index 736fcfde..7bf8f7ba 100644 --- a/Sources/JavaStdlib/JavaLangReflect/generated/TypeVariable.swift +++ b/Sources/JavaStdlib/JavaLangReflect/generated/TypeVariable.swift @@ -3,10 +3,10 @@ import SwiftJava import CSwiftJavaJNI @JavaInterface("java.lang.reflect.TypeVariable", extends: Type.self) -public struct TypeVariable { +public struct TypeVariable: CustomStringConvertible { @JavaMethod public func getGenericDeclaration() -> GenericDeclaration! - + @JavaMethod public func getAnnotatedBounds() -> [AnnotatedType?] diff --git a/Sources/JavaStdlib/JavaNet/URL+Extensions.swift b/Sources/JavaStdlib/JavaNet/URL+Extensions.swift new file mode 100644 index 00000000..2b220d1c --- /dev/null +++ b/Sources/JavaStdlib/JavaNet/URL+Extensions.swift @@ -0,0 +1,34 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import SwiftJava +import CSwiftJavaJNI + +import Foundation +public typealias SwiftJavaFoundationURL = Foundation.URL + +extension SwiftJavaFoundationURL { + public static func fromJava(_ url: URL) throws -> SwiftJavaFoundationURL { + guard let converted = SwiftJavaFoundationURL(string: try url.toURI().toString()) else { + throw SwiftJavaConversionError("Failed to convert \(URL.self) to \(SwiftJavaFoundationURL.self)") + } + return converted + } +} + +extension URL { + public static func fromSwift(_ url: SwiftJavaFoundationURL) throws -> URL { + return try URL(url.absoluteString) + } +} \ No newline at end of file diff --git a/Sources/JavaStdlib/JavaNet/URLClassLoader+Workaround.swift b/Sources/JavaStdlib/JavaNet/URLClassLoader+Workaround.swift new file mode 100644 index 00000000..4c55f6af --- /dev/null +++ b/Sources/JavaStdlib/JavaNet/URLClassLoader+Workaround.swift @@ -0,0 +1,22 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import CSwiftJavaJNI +import SwiftJava + +// FIXME: workaround until importing properly would make UCL inherit from CL https://github.com/swiftlang/swift-java/issues/423 +extension URLClassLoader /* workaround for missing inherits from ClassLoader */ { + @JavaMethod + public func loadClass(_ name: String) throws -> JavaClass? +} diff --git a/Sources/SwiftJava/AnyJavaObject.swift b/Sources/SwiftJava/AnyJavaObject.swift index e514d3e6..bf749820 100644 --- a/Sources/SwiftJava/AnyJavaObject.swift +++ b/Sources/SwiftJava/AnyJavaObject.swift @@ -52,7 +52,7 @@ public protocol AnyJavaObject { /// Protocol that allows Swift types to specify a custom Java class loader on /// initialization. This is useful for platforms (e.g. Android) where the default /// class loader does not make all application classes visible. -public protocol CustomJavaClassLoader: AnyJavaObject { +public protocol AnyJavaObjectWithCustomClassLoader: AnyJavaObject { static func getJavaClassLoader(in environment: JNIEnvironment) throws -> JavaClassLoader! } @@ -118,8 +118,8 @@ extension AnyJavaObject { in environment: JNIEnvironment, _ body: (jclass) throws -> Result ) throws -> Result { - if let customJavaClassLoader = self as? CustomJavaClassLoader.Type, - let customClassLoader = try customJavaClassLoader.getJavaClassLoader(in: environment) { + if let AnyJavaObjectWithCustomClassLoader = self as? AnyJavaObjectWithCustomClassLoader.Type, + let customClassLoader = try AnyJavaObjectWithCustomClassLoader.getJavaClassLoader(in: environment) { try _withJNIClassFromCustomClassLoader(customClassLoader, in: environment, body) } else { try _withJNIClassFromDefaultClassLoader(in: environment, body) diff --git a/Sources/SwiftJava/JavaKitVM/JavaVirtualMachine.swift b/Sources/SwiftJava/JVM/JavaVirtualMachine.swift similarity index 99% rename from Sources/SwiftJava/JavaKitVM/JavaVirtualMachine.swift rename to Sources/SwiftJava/JVM/JavaVirtualMachine.swift index bb574c8a..1c7936a3 100644 --- a/Sources/SwiftJava/JavaKitVM/JavaVirtualMachine.swift +++ b/Sources/SwiftJava/JVM/JavaVirtualMachine.swift @@ -350,4 +350,4 @@ extension JavaVirtualMachine { enum JavaKitError: Error { case classpathEntryNotFound(entry: String, classpath: [String]) } -} +} \ No newline at end of file diff --git a/Sources/SwiftJava/JavaKitVM/LockedState.swift b/Sources/SwiftJava/JVM/LockedState.swift similarity index 100% rename from Sources/SwiftJava/JavaKitVM/LockedState.swift rename to Sources/SwiftJava/JVM/LockedState.swift diff --git a/Sources/SwiftJava/JavaKitVM/ThreadLocalStorage.swift b/Sources/SwiftJava/JVM/ThreadLocalStorage.swift similarity index 100% rename from Sources/SwiftJava/JavaKitVM/ThreadLocalStorage.swift rename to Sources/SwiftJava/JVM/ThreadLocalStorage.swift diff --git a/Sources/SwiftJava/JavaClass+CustomStringConvertible.swift b/Sources/SwiftJava/JavaClass+CustomStringConvertible.swift new file mode 100644 index 00000000..e7eb2510 --- /dev/null +++ b/Sources/SwiftJava/JavaClass+CustomStringConvertible.swift @@ -0,0 +1,21 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import CSwiftJavaJNI + +extension JavaClass: CustomStringConvertible { + public var description: String { + toString() + } +} \ No newline at end of file diff --git a/Sources/SwiftJava/JavaObjectHolder.swift b/Sources/SwiftJava/JavaObjectHolder.swift index 319a09e8..5930da59 100644 --- a/Sources/SwiftJava/JavaObjectHolder.swift +++ b/Sources/SwiftJava/JavaObjectHolder.swift @@ -17,8 +17,8 @@ import CSwiftJavaJNI /// Stores a reference to a Java object, managing it as a global reference so /// that the Java virtual machine will not move or deallocate the object /// while this instance is live. -public class JavaObjectHolder { - public private(set) var object: jobject? +public final class JavaObjectHolder { + public private(set) var object: jobject? // TODO: thread-safety public let environment: JNIEnvironment /// Take a reference to a Java object and promote it to a global reference diff --git a/Sources/SwiftJavaTool/String+Extensions.swift b/Sources/SwiftJava/String+Extensions.swift similarity index 82% rename from Sources/SwiftJavaTool/String+Extensions.swift rename to Sources/SwiftJava/String+Extensions.swift index 304e217d..94fb1928 100644 --- a/Sources/SwiftJavaTool/String+Extensions.swift +++ b/Sources/SwiftJava/String+Extensions.swift @@ -13,17 +13,15 @@ //===----------------------------------------------------------------------===// import Foundation -import ArgumentParser -import SwiftJavaToolLib -import SwiftJava -import JavaUtilJar -import SwiftJavaToolLib -import SwiftJavaConfigurationShared +// import SwiftJavaToolLib +// import SwiftJava +// import JavaUtilJar +// import SwiftJavaConfigurationShared extension String { /// For a String that's of the form java.util.Vector, return the "Vector" /// part. - var defaultSwiftNameForJavaClass: String { + package var defaultSwiftNameForJavaClass: String { if let dotLoc = lastIndex(of: ".") { let afterDot = index(after: dotLoc) return String(self[afterDot...]).javaClassNameToCanonicalName.adjustedSwiftTypeName @@ -36,12 +34,12 @@ extension String { extension String { /// Replace all of the $'s for nested names with "." to turn a Java class /// name into a Java canonical class name, - var javaClassNameToCanonicalName: String { + package var javaClassNameToCanonicalName: String { return replacing("$", with: ".") } /// Whether this is the name of an anonymous class. - var isLocalJavaClass: Bool { + package var isLocalJavaClass: Bool { for segment in split(separator: "$") { if let firstChar = segment.first, firstChar.isNumber { return true @@ -52,7 +50,7 @@ extension String { } /// Adjust type name for "bad" type names that don't work well in Swift. - var adjustedSwiftTypeName: String { + package var adjustedSwiftTypeName: String { switch self { case "Type": return "JavaType" default: return self diff --git a/Sources/SwiftJava/SwiftJavaConversionError.swift b/Sources/SwiftJava/SwiftJavaConversionError.swift new file mode 100644 index 00000000..5b29741c --- /dev/null +++ b/Sources/SwiftJava/SwiftJavaConversionError.swift @@ -0,0 +1,22 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +/// Used to indicate Swift/Java conversion failures. +public struct SwiftJavaConversionError: Error { + public let message: String + + public init(_ message: String) { + self.message = message + } +} \ No newline at end of file diff --git a/Sources/SwiftJava/generated/CharSequence.swift b/Sources/SwiftJava/generated/CharSequence.swift index eadc509e..ee5dca36 100644 --- a/Sources/SwiftJava/generated/CharSequence.swift +++ b/Sources/SwiftJava/generated/CharSequence.swift @@ -9,6 +9,9 @@ public struct CharSequence { @JavaMethod public func toString() -> String + @JavaMethod + public func getChars(_ arg0: Int32, _ arg1: Int32, _ arg2: [UInt16], _ arg3: Int32) + @JavaMethod public func charAt(_ arg0: Int32) -> UInt16 diff --git a/Sources/SwiftJava/generated/JavaCharacter.swift b/Sources/SwiftJava/generated/JavaCharacter.swift index 406b45ee..f79742a3 100644 --- a/Sources/SwiftJava/generated/JavaCharacter.swift +++ b/Sources/SwiftJava/generated/JavaCharacter.swift @@ -1557,985 +1557,985 @@ extension JavaCharacter { if let COMMON = classObj.COMMON { self.init(javaHolder: COMMON.javaHolder) } else { - fatalError("Enum value COMMON was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value COMMON was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .LATIN: if let LATIN = classObj.LATIN { self.init(javaHolder: LATIN.javaHolder) } else { - fatalError("Enum value LATIN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value LATIN was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .GREEK: if let GREEK = classObj.GREEK { self.init(javaHolder: GREEK.javaHolder) } else { - fatalError("Enum value GREEK was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value GREEK was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .CYRILLIC: if let CYRILLIC = classObj.CYRILLIC { self.init(javaHolder: CYRILLIC.javaHolder) } else { - fatalError("Enum value CYRILLIC was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value CYRILLIC was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .ARMENIAN: if let ARMENIAN = classObj.ARMENIAN { self.init(javaHolder: ARMENIAN.javaHolder) } else { - fatalError("Enum value ARMENIAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value ARMENIAN was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .HEBREW: if let HEBREW = classObj.HEBREW { self.init(javaHolder: HEBREW.javaHolder) } else { - fatalError("Enum value HEBREW was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value HEBREW was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .ARABIC: if let ARABIC = classObj.ARABIC { self.init(javaHolder: ARABIC.javaHolder) } else { - fatalError("Enum value ARABIC was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value ARABIC was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .SYRIAC: if let SYRIAC = classObj.SYRIAC { self.init(javaHolder: SYRIAC.javaHolder) } else { - fatalError("Enum value SYRIAC was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value SYRIAC was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .THAANA: if let THAANA = classObj.THAANA { self.init(javaHolder: THAANA.javaHolder) } else { - fatalError("Enum value THAANA was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value THAANA was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .DEVANAGARI: if let DEVANAGARI = classObj.DEVANAGARI { self.init(javaHolder: DEVANAGARI.javaHolder) } else { - fatalError("Enum value DEVANAGARI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value DEVANAGARI was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .BENGALI: if let BENGALI = classObj.BENGALI { self.init(javaHolder: BENGALI.javaHolder) } else { - fatalError("Enum value BENGALI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value BENGALI was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .GURMUKHI: if let GURMUKHI = classObj.GURMUKHI { self.init(javaHolder: GURMUKHI.javaHolder) } else { - fatalError("Enum value GURMUKHI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value GURMUKHI was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .GUJARATI: if let GUJARATI = classObj.GUJARATI { self.init(javaHolder: GUJARATI.javaHolder) } else { - fatalError("Enum value GUJARATI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value GUJARATI was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .ORIYA: if let ORIYA = classObj.ORIYA { self.init(javaHolder: ORIYA.javaHolder) } else { - fatalError("Enum value ORIYA was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value ORIYA was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .TAMIL: if let TAMIL = classObj.TAMIL { self.init(javaHolder: TAMIL.javaHolder) } else { - fatalError("Enum value TAMIL was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value TAMIL was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .TELUGU: if let TELUGU = classObj.TELUGU { self.init(javaHolder: TELUGU.javaHolder) } else { - fatalError("Enum value TELUGU was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value TELUGU was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .KANNADA: if let KANNADA = classObj.KANNADA { self.init(javaHolder: KANNADA.javaHolder) } else { - fatalError("Enum value KANNADA was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value KANNADA was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .MALAYALAM: if let MALAYALAM = classObj.MALAYALAM { self.init(javaHolder: MALAYALAM.javaHolder) } else { - fatalError("Enum value MALAYALAM was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value MALAYALAM was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .SINHALA: if let SINHALA = classObj.SINHALA { self.init(javaHolder: SINHALA.javaHolder) } else { - fatalError("Enum value SINHALA was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value SINHALA was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .THAI: if let THAI = classObj.THAI { self.init(javaHolder: THAI.javaHolder) } else { - fatalError("Enum value THAI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value THAI was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .LAO: if let LAO = classObj.LAO { self.init(javaHolder: LAO.javaHolder) } else { - fatalError("Enum value LAO was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value LAO was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .TIBETAN: if let TIBETAN = classObj.TIBETAN { self.init(javaHolder: TIBETAN.javaHolder) } else { - fatalError("Enum value TIBETAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value TIBETAN was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .MYANMAR: if let MYANMAR = classObj.MYANMAR { self.init(javaHolder: MYANMAR.javaHolder) } else { - fatalError("Enum value MYANMAR was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value MYANMAR was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .GEORGIAN: if let GEORGIAN = classObj.GEORGIAN { self.init(javaHolder: GEORGIAN.javaHolder) } else { - fatalError("Enum value GEORGIAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value GEORGIAN was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .HANGUL: if let HANGUL = classObj.HANGUL { self.init(javaHolder: HANGUL.javaHolder) } else { - fatalError("Enum value HANGUL was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value HANGUL was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .ETHIOPIC: if let ETHIOPIC = classObj.ETHIOPIC { self.init(javaHolder: ETHIOPIC.javaHolder) } else { - fatalError("Enum value ETHIOPIC was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value ETHIOPIC was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .CHEROKEE: if let CHEROKEE = classObj.CHEROKEE { self.init(javaHolder: CHEROKEE.javaHolder) } else { - fatalError("Enum value CHEROKEE was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value CHEROKEE was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .CANADIAN_ABORIGINAL: if let CANADIAN_ABORIGINAL = classObj.CANADIAN_ABORIGINAL { self.init(javaHolder: CANADIAN_ABORIGINAL.javaHolder) } else { - fatalError("Enum value CANADIAN_ABORIGINAL was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value CANADIAN_ABORIGINAL was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .OGHAM: if let OGHAM = classObj.OGHAM { self.init(javaHolder: OGHAM.javaHolder) } else { - fatalError("Enum value OGHAM was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value OGHAM was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .RUNIC: if let RUNIC = classObj.RUNIC { self.init(javaHolder: RUNIC.javaHolder) } else { - fatalError("Enum value RUNIC was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value RUNIC was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .KHMER: if let KHMER = classObj.KHMER { self.init(javaHolder: KHMER.javaHolder) } else { - fatalError("Enum value KHMER was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value KHMER was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .MONGOLIAN: if let MONGOLIAN = classObj.MONGOLIAN { self.init(javaHolder: MONGOLIAN.javaHolder) } else { - fatalError("Enum value MONGOLIAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value MONGOLIAN was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .HIRAGANA: if let HIRAGANA = classObj.HIRAGANA { self.init(javaHolder: HIRAGANA.javaHolder) } else { - fatalError("Enum value HIRAGANA was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value HIRAGANA was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .KATAKANA: if let KATAKANA = classObj.KATAKANA { self.init(javaHolder: KATAKANA.javaHolder) } else { - fatalError("Enum value KATAKANA was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value KATAKANA was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .BOPOMOFO: if let BOPOMOFO = classObj.BOPOMOFO { self.init(javaHolder: BOPOMOFO.javaHolder) } else { - fatalError("Enum value BOPOMOFO was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value BOPOMOFO was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .HAN: if let HAN = classObj.HAN { self.init(javaHolder: HAN.javaHolder) } else { - fatalError("Enum value HAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value HAN was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .YI: if let YI = classObj.YI { self.init(javaHolder: YI.javaHolder) } else { - fatalError("Enum value YI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value YI was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .OLD_ITALIC: if let OLD_ITALIC = classObj.OLD_ITALIC { self.init(javaHolder: OLD_ITALIC.javaHolder) } else { - fatalError("Enum value OLD_ITALIC was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value OLD_ITALIC was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .GOTHIC: if let GOTHIC = classObj.GOTHIC { self.init(javaHolder: GOTHIC.javaHolder) } else { - fatalError("Enum value GOTHIC was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value GOTHIC was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .DESERET: if let DESERET = classObj.DESERET { self.init(javaHolder: DESERET.javaHolder) } else { - fatalError("Enum value DESERET was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value DESERET was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .INHERITED: if let INHERITED = classObj.INHERITED { self.init(javaHolder: INHERITED.javaHolder) } else { - fatalError("Enum value INHERITED was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value INHERITED was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .TAGALOG: if let TAGALOG = classObj.TAGALOG { self.init(javaHolder: TAGALOG.javaHolder) } else { - fatalError("Enum value TAGALOG was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value TAGALOG was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .HANUNOO: if let HANUNOO = classObj.HANUNOO { self.init(javaHolder: HANUNOO.javaHolder) } else { - fatalError("Enum value HANUNOO was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value HANUNOO was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .BUHID: if let BUHID = classObj.BUHID { self.init(javaHolder: BUHID.javaHolder) } else { - fatalError("Enum value BUHID was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value BUHID was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .TAGBANWA: if let TAGBANWA = classObj.TAGBANWA { self.init(javaHolder: TAGBANWA.javaHolder) } else { - fatalError("Enum value TAGBANWA was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value TAGBANWA was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .LIMBU: if let LIMBU = classObj.LIMBU { self.init(javaHolder: LIMBU.javaHolder) } else { - fatalError("Enum value LIMBU was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value LIMBU was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .TAI_LE: if let TAI_LE = classObj.TAI_LE { self.init(javaHolder: TAI_LE.javaHolder) } else { - fatalError("Enum value TAI_LE was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value TAI_LE was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .LINEAR_B: if let LINEAR_B = classObj.LINEAR_B { self.init(javaHolder: LINEAR_B.javaHolder) } else { - fatalError("Enum value LINEAR_B was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value LINEAR_B was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .UGARITIC: if let UGARITIC = classObj.UGARITIC { self.init(javaHolder: UGARITIC.javaHolder) } else { - fatalError("Enum value UGARITIC was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value UGARITIC was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .SHAVIAN: if let SHAVIAN = classObj.SHAVIAN { self.init(javaHolder: SHAVIAN.javaHolder) } else { - fatalError("Enum value SHAVIAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value SHAVIAN was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .OSMANYA: if let OSMANYA = classObj.OSMANYA { self.init(javaHolder: OSMANYA.javaHolder) } else { - fatalError("Enum value OSMANYA was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value OSMANYA was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .CYPRIOT: if let CYPRIOT = classObj.CYPRIOT { self.init(javaHolder: CYPRIOT.javaHolder) } else { - fatalError("Enum value CYPRIOT was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value CYPRIOT was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .BRAILLE: if let BRAILLE = classObj.BRAILLE { self.init(javaHolder: BRAILLE.javaHolder) } else { - fatalError("Enum value BRAILLE was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value BRAILLE was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .BUGINESE: if let BUGINESE = classObj.BUGINESE { self.init(javaHolder: BUGINESE.javaHolder) } else { - fatalError("Enum value BUGINESE was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value BUGINESE was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .COPTIC: if let COPTIC = classObj.COPTIC { self.init(javaHolder: COPTIC.javaHolder) } else { - fatalError("Enum value COPTIC was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value COPTIC was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .NEW_TAI_LUE: if let NEW_TAI_LUE = classObj.NEW_TAI_LUE { self.init(javaHolder: NEW_TAI_LUE.javaHolder) } else { - fatalError("Enum value NEW_TAI_LUE was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value NEW_TAI_LUE was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .GLAGOLITIC: if let GLAGOLITIC = classObj.GLAGOLITIC { self.init(javaHolder: GLAGOLITIC.javaHolder) } else { - fatalError("Enum value GLAGOLITIC was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value GLAGOLITIC was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .TIFINAGH: if let TIFINAGH = classObj.TIFINAGH { self.init(javaHolder: TIFINAGH.javaHolder) } else { - fatalError("Enum value TIFINAGH was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value TIFINAGH was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .SYLOTI_NAGRI: if let SYLOTI_NAGRI = classObj.SYLOTI_NAGRI { self.init(javaHolder: SYLOTI_NAGRI.javaHolder) } else { - fatalError("Enum value SYLOTI_NAGRI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value SYLOTI_NAGRI was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .OLD_PERSIAN: if let OLD_PERSIAN = classObj.OLD_PERSIAN { self.init(javaHolder: OLD_PERSIAN.javaHolder) } else { - fatalError("Enum value OLD_PERSIAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value OLD_PERSIAN was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .KHAROSHTHI: if let KHAROSHTHI = classObj.KHAROSHTHI { self.init(javaHolder: KHAROSHTHI.javaHolder) } else { - fatalError("Enum value KHAROSHTHI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value KHAROSHTHI was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .BALINESE: if let BALINESE = classObj.BALINESE { self.init(javaHolder: BALINESE.javaHolder) } else { - fatalError("Enum value BALINESE was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value BALINESE was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .CUNEIFORM: if let CUNEIFORM = classObj.CUNEIFORM { self.init(javaHolder: CUNEIFORM.javaHolder) } else { - fatalError("Enum value CUNEIFORM was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value CUNEIFORM was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .PHOENICIAN: if let PHOENICIAN = classObj.PHOENICIAN { self.init(javaHolder: PHOENICIAN.javaHolder) } else { - fatalError("Enum value PHOENICIAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value PHOENICIAN was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .PHAGS_PA: if let PHAGS_PA = classObj.PHAGS_PA { self.init(javaHolder: PHAGS_PA.javaHolder) } else { - fatalError("Enum value PHAGS_PA was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value PHAGS_PA was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .NKO: if let NKO = classObj.NKO { self.init(javaHolder: NKO.javaHolder) } else { - fatalError("Enum value NKO was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value NKO was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .SUNDANESE: if let SUNDANESE = classObj.SUNDANESE { self.init(javaHolder: SUNDANESE.javaHolder) } else { - fatalError("Enum value SUNDANESE was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value SUNDANESE was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .BATAK: if let BATAK = classObj.BATAK { self.init(javaHolder: BATAK.javaHolder) } else { - fatalError("Enum value BATAK was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value BATAK was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .LEPCHA: if let LEPCHA = classObj.LEPCHA { self.init(javaHolder: LEPCHA.javaHolder) } else { - fatalError("Enum value LEPCHA was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value LEPCHA was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .OL_CHIKI: if let OL_CHIKI = classObj.OL_CHIKI { self.init(javaHolder: OL_CHIKI.javaHolder) } else { - fatalError("Enum value OL_CHIKI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value OL_CHIKI was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .VAI: if let VAI = classObj.VAI { self.init(javaHolder: VAI.javaHolder) } else { - fatalError("Enum value VAI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value VAI was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .SAURASHTRA: if let SAURASHTRA = classObj.SAURASHTRA { self.init(javaHolder: SAURASHTRA.javaHolder) } else { - fatalError("Enum value SAURASHTRA was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value SAURASHTRA was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .KAYAH_LI: if let KAYAH_LI = classObj.KAYAH_LI { self.init(javaHolder: KAYAH_LI.javaHolder) } else { - fatalError("Enum value KAYAH_LI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value KAYAH_LI was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .REJANG: if let REJANG = classObj.REJANG { self.init(javaHolder: REJANG.javaHolder) } else { - fatalError("Enum value REJANG was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value REJANG was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .LYCIAN: if let LYCIAN = classObj.LYCIAN { self.init(javaHolder: LYCIAN.javaHolder) } else { - fatalError("Enum value LYCIAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value LYCIAN was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .CARIAN: if let CARIAN = classObj.CARIAN { self.init(javaHolder: CARIAN.javaHolder) } else { - fatalError("Enum value CARIAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value CARIAN was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .LYDIAN: if let LYDIAN = classObj.LYDIAN { self.init(javaHolder: LYDIAN.javaHolder) } else { - fatalError("Enum value LYDIAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value LYDIAN was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .CHAM: if let CHAM = classObj.CHAM { self.init(javaHolder: CHAM.javaHolder) } else { - fatalError("Enum value CHAM was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value CHAM was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .TAI_THAM: if let TAI_THAM = classObj.TAI_THAM { self.init(javaHolder: TAI_THAM.javaHolder) } else { - fatalError("Enum value TAI_THAM was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value TAI_THAM was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .TAI_VIET: if let TAI_VIET = classObj.TAI_VIET { self.init(javaHolder: TAI_VIET.javaHolder) } else { - fatalError("Enum value TAI_VIET was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value TAI_VIET was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .AVESTAN: if let AVESTAN = classObj.AVESTAN { self.init(javaHolder: AVESTAN.javaHolder) } else { - fatalError("Enum value AVESTAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value AVESTAN was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .EGYPTIAN_HIEROGLYPHS: if let EGYPTIAN_HIEROGLYPHS = classObj.EGYPTIAN_HIEROGLYPHS { self.init(javaHolder: EGYPTIAN_HIEROGLYPHS.javaHolder) } else { - fatalError("Enum value EGYPTIAN_HIEROGLYPHS was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value EGYPTIAN_HIEROGLYPHS was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .SAMARITAN: if let SAMARITAN = classObj.SAMARITAN { self.init(javaHolder: SAMARITAN.javaHolder) } else { - fatalError("Enum value SAMARITAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value SAMARITAN was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .MANDAIC: if let MANDAIC = classObj.MANDAIC { self.init(javaHolder: MANDAIC.javaHolder) } else { - fatalError("Enum value MANDAIC was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value MANDAIC was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .LISU: if let LISU = classObj.LISU { self.init(javaHolder: LISU.javaHolder) } else { - fatalError("Enum value LISU was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value LISU was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .BAMUM: if let BAMUM = classObj.BAMUM { self.init(javaHolder: BAMUM.javaHolder) } else { - fatalError("Enum value BAMUM was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value BAMUM was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .JAVANESE: if let JAVANESE = classObj.JAVANESE { self.init(javaHolder: JAVANESE.javaHolder) } else { - fatalError("Enum value JAVANESE was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value JAVANESE was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .MEETEI_MAYEK: if let MEETEI_MAYEK = classObj.MEETEI_MAYEK { self.init(javaHolder: MEETEI_MAYEK.javaHolder) } else { - fatalError("Enum value MEETEI_MAYEK was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value MEETEI_MAYEK was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .IMPERIAL_ARAMAIC: if let IMPERIAL_ARAMAIC = classObj.IMPERIAL_ARAMAIC { self.init(javaHolder: IMPERIAL_ARAMAIC.javaHolder) } else { - fatalError("Enum value IMPERIAL_ARAMAIC was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value IMPERIAL_ARAMAIC was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .OLD_SOUTH_ARABIAN: if let OLD_SOUTH_ARABIAN = classObj.OLD_SOUTH_ARABIAN { self.init(javaHolder: OLD_SOUTH_ARABIAN.javaHolder) } else { - fatalError("Enum value OLD_SOUTH_ARABIAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value OLD_SOUTH_ARABIAN was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .INSCRIPTIONAL_PARTHIAN: if let INSCRIPTIONAL_PARTHIAN = classObj.INSCRIPTIONAL_PARTHIAN { self.init(javaHolder: INSCRIPTIONAL_PARTHIAN.javaHolder) } else { - fatalError("Enum value INSCRIPTIONAL_PARTHIAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value INSCRIPTIONAL_PARTHIAN was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .INSCRIPTIONAL_PAHLAVI: if let INSCRIPTIONAL_PAHLAVI = classObj.INSCRIPTIONAL_PAHLAVI { self.init(javaHolder: INSCRIPTIONAL_PAHLAVI.javaHolder) } else { - fatalError("Enum value INSCRIPTIONAL_PAHLAVI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value INSCRIPTIONAL_PAHLAVI was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .OLD_TURKIC: if let OLD_TURKIC = classObj.OLD_TURKIC { self.init(javaHolder: OLD_TURKIC.javaHolder) } else { - fatalError("Enum value OLD_TURKIC was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value OLD_TURKIC was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .BRAHMI: if let BRAHMI = classObj.BRAHMI { self.init(javaHolder: BRAHMI.javaHolder) } else { - fatalError("Enum value BRAHMI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value BRAHMI was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .KAITHI: if let KAITHI = classObj.KAITHI { self.init(javaHolder: KAITHI.javaHolder) } else { - fatalError("Enum value KAITHI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value KAITHI was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .MEROITIC_HIEROGLYPHS: if let MEROITIC_HIEROGLYPHS = classObj.MEROITIC_HIEROGLYPHS { self.init(javaHolder: MEROITIC_HIEROGLYPHS.javaHolder) } else { - fatalError("Enum value MEROITIC_HIEROGLYPHS was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value MEROITIC_HIEROGLYPHS was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .MEROITIC_CURSIVE: if let MEROITIC_CURSIVE = classObj.MEROITIC_CURSIVE { self.init(javaHolder: MEROITIC_CURSIVE.javaHolder) } else { - fatalError("Enum value MEROITIC_CURSIVE was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value MEROITIC_CURSIVE was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .SORA_SOMPENG: if let SORA_SOMPENG = classObj.SORA_SOMPENG { self.init(javaHolder: SORA_SOMPENG.javaHolder) } else { - fatalError("Enum value SORA_SOMPENG was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value SORA_SOMPENG was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .CHAKMA: if let CHAKMA = classObj.CHAKMA { self.init(javaHolder: CHAKMA.javaHolder) } else { - fatalError("Enum value CHAKMA was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value CHAKMA was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .SHARADA: if let SHARADA = classObj.SHARADA { self.init(javaHolder: SHARADA.javaHolder) } else { - fatalError("Enum value SHARADA was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value SHARADA was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .TAKRI: if let TAKRI = classObj.TAKRI { self.init(javaHolder: TAKRI.javaHolder) } else { - fatalError("Enum value TAKRI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value TAKRI was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .MIAO: if let MIAO = classObj.MIAO { self.init(javaHolder: MIAO.javaHolder) } else { - fatalError("Enum value MIAO was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value MIAO was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .CAUCASIAN_ALBANIAN: if let CAUCASIAN_ALBANIAN = classObj.CAUCASIAN_ALBANIAN { self.init(javaHolder: CAUCASIAN_ALBANIAN.javaHolder) } else { - fatalError("Enum value CAUCASIAN_ALBANIAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value CAUCASIAN_ALBANIAN was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .BASSA_VAH: if let BASSA_VAH = classObj.BASSA_VAH { self.init(javaHolder: BASSA_VAH.javaHolder) } else { - fatalError("Enum value BASSA_VAH was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value BASSA_VAH was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .DUPLOYAN: if let DUPLOYAN = classObj.DUPLOYAN { self.init(javaHolder: DUPLOYAN.javaHolder) } else { - fatalError("Enum value DUPLOYAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value DUPLOYAN was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .ELBASAN: if let ELBASAN = classObj.ELBASAN { self.init(javaHolder: ELBASAN.javaHolder) } else { - fatalError("Enum value ELBASAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value ELBASAN was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .GRANTHA: if let GRANTHA = classObj.GRANTHA { self.init(javaHolder: GRANTHA.javaHolder) } else { - fatalError("Enum value GRANTHA was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value GRANTHA was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .PAHAWH_HMONG: if let PAHAWH_HMONG = classObj.PAHAWH_HMONG { self.init(javaHolder: PAHAWH_HMONG.javaHolder) } else { - fatalError("Enum value PAHAWH_HMONG was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value PAHAWH_HMONG was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .KHOJKI: if let KHOJKI = classObj.KHOJKI { self.init(javaHolder: KHOJKI.javaHolder) } else { - fatalError("Enum value KHOJKI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value KHOJKI was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .LINEAR_A: if let LINEAR_A = classObj.LINEAR_A { self.init(javaHolder: LINEAR_A.javaHolder) } else { - fatalError("Enum value LINEAR_A was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value LINEAR_A was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .MAHAJANI: if let MAHAJANI = classObj.MAHAJANI { self.init(javaHolder: MAHAJANI.javaHolder) } else { - fatalError("Enum value MAHAJANI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value MAHAJANI was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .MANICHAEAN: if let MANICHAEAN = classObj.MANICHAEAN { self.init(javaHolder: MANICHAEAN.javaHolder) } else { - fatalError("Enum value MANICHAEAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value MANICHAEAN was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .MENDE_KIKAKUI: if let MENDE_KIKAKUI = classObj.MENDE_KIKAKUI { self.init(javaHolder: MENDE_KIKAKUI.javaHolder) } else { - fatalError("Enum value MENDE_KIKAKUI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value MENDE_KIKAKUI was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .MODI: if let MODI = classObj.MODI { self.init(javaHolder: MODI.javaHolder) } else { - fatalError("Enum value MODI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value MODI was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .MRO: if let MRO = classObj.MRO { self.init(javaHolder: MRO.javaHolder) } else { - fatalError("Enum value MRO was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value MRO was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .OLD_NORTH_ARABIAN: if let OLD_NORTH_ARABIAN = classObj.OLD_NORTH_ARABIAN { self.init(javaHolder: OLD_NORTH_ARABIAN.javaHolder) } else { - fatalError("Enum value OLD_NORTH_ARABIAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value OLD_NORTH_ARABIAN was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .NABATAEAN: if let NABATAEAN = classObj.NABATAEAN { self.init(javaHolder: NABATAEAN.javaHolder) } else { - fatalError("Enum value NABATAEAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value NABATAEAN was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .PALMYRENE: if let PALMYRENE = classObj.PALMYRENE { self.init(javaHolder: PALMYRENE.javaHolder) } else { - fatalError("Enum value PALMYRENE was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value PALMYRENE was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .PAU_CIN_HAU: if let PAU_CIN_HAU = classObj.PAU_CIN_HAU { self.init(javaHolder: PAU_CIN_HAU.javaHolder) } else { - fatalError("Enum value PAU_CIN_HAU was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value PAU_CIN_HAU was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .OLD_PERMIC: if let OLD_PERMIC = classObj.OLD_PERMIC { self.init(javaHolder: OLD_PERMIC.javaHolder) } else { - fatalError("Enum value OLD_PERMIC was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value OLD_PERMIC was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .PSALTER_PAHLAVI: if let PSALTER_PAHLAVI = classObj.PSALTER_PAHLAVI { self.init(javaHolder: PSALTER_PAHLAVI.javaHolder) } else { - fatalError("Enum value PSALTER_PAHLAVI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value PSALTER_PAHLAVI was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .SIDDHAM: if let SIDDHAM = classObj.SIDDHAM { self.init(javaHolder: SIDDHAM.javaHolder) } else { - fatalError("Enum value SIDDHAM was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value SIDDHAM was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .KHUDAWADI: if let KHUDAWADI = classObj.KHUDAWADI { self.init(javaHolder: KHUDAWADI.javaHolder) } else { - fatalError("Enum value KHUDAWADI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value KHUDAWADI was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .TIRHUTA: if let TIRHUTA = classObj.TIRHUTA { self.init(javaHolder: TIRHUTA.javaHolder) } else { - fatalError("Enum value TIRHUTA was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value TIRHUTA was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .WARANG_CITI: if let WARANG_CITI = classObj.WARANG_CITI { self.init(javaHolder: WARANG_CITI.javaHolder) } else { - fatalError("Enum value WARANG_CITI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value WARANG_CITI was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .AHOM: if let AHOM = classObj.AHOM { self.init(javaHolder: AHOM.javaHolder) } else { - fatalError("Enum value AHOM was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value AHOM was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .ANATOLIAN_HIEROGLYPHS: if let ANATOLIAN_HIEROGLYPHS = classObj.ANATOLIAN_HIEROGLYPHS { self.init(javaHolder: ANATOLIAN_HIEROGLYPHS.javaHolder) } else { - fatalError("Enum value ANATOLIAN_HIEROGLYPHS was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value ANATOLIAN_HIEROGLYPHS was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .HATRAN: if let HATRAN = classObj.HATRAN { self.init(javaHolder: HATRAN.javaHolder) } else { - fatalError("Enum value HATRAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value HATRAN was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .MULTANI: if let MULTANI = classObj.MULTANI { self.init(javaHolder: MULTANI.javaHolder) } else { - fatalError("Enum value MULTANI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value MULTANI was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .OLD_HUNGARIAN: if let OLD_HUNGARIAN = classObj.OLD_HUNGARIAN { self.init(javaHolder: OLD_HUNGARIAN.javaHolder) } else { - fatalError("Enum value OLD_HUNGARIAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value OLD_HUNGARIAN was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .SIGNWRITING: if let SIGNWRITING = classObj.SIGNWRITING { self.init(javaHolder: SIGNWRITING.javaHolder) } else { - fatalError("Enum value SIGNWRITING was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value SIGNWRITING was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .ADLAM: if let ADLAM = classObj.ADLAM { self.init(javaHolder: ADLAM.javaHolder) } else { - fatalError("Enum value ADLAM was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value ADLAM was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .BHAIKSUKI: if let BHAIKSUKI = classObj.BHAIKSUKI { self.init(javaHolder: BHAIKSUKI.javaHolder) } else { - fatalError("Enum value BHAIKSUKI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value BHAIKSUKI was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .MARCHEN: if let MARCHEN = classObj.MARCHEN { self.init(javaHolder: MARCHEN.javaHolder) } else { - fatalError("Enum value MARCHEN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value MARCHEN was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .NEWA: if let NEWA = classObj.NEWA { self.init(javaHolder: NEWA.javaHolder) } else { - fatalError("Enum value NEWA was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value NEWA was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .OSAGE: if let OSAGE = classObj.OSAGE { self.init(javaHolder: OSAGE.javaHolder) } else { - fatalError("Enum value OSAGE was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value OSAGE was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .TANGUT: if let TANGUT = classObj.TANGUT { self.init(javaHolder: TANGUT.javaHolder) } else { - fatalError("Enum value TANGUT was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value TANGUT was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .MASARAM_GONDI: if let MASARAM_GONDI = classObj.MASARAM_GONDI { self.init(javaHolder: MASARAM_GONDI.javaHolder) } else { - fatalError("Enum value MASARAM_GONDI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value MASARAM_GONDI was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .NUSHU: if let NUSHU = classObj.NUSHU { self.init(javaHolder: NUSHU.javaHolder) } else { - fatalError("Enum value NUSHU was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value NUSHU was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .SOYOMBO: if let SOYOMBO = classObj.SOYOMBO { self.init(javaHolder: SOYOMBO.javaHolder) } else { - fatalError("Enum value SOYOMBO was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value SOYOMBO was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .ZANABAZAR_SQUARE: if let ZANABAZAR_SQUARE = classObj.ZANABAZAR_SQUARE { self.init(javaHolder: ZANABAZAR_SQUARE.javaHolder) } else { - fatalError("Enum value ZANABAZAR_SQUARE was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value ZANABAZAR_SQUARE was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .HANIFI_ROHINGYA: if let HANIFI_ROHINGYA = classObj.HANIFI_ROHINGYA { self.init(javaHolder: HANIFI_ROHINGYA.javaHolder) } else { - fatalError("Enum value HANIFI_ROHINGYA was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value HANIFI_ROHINGYA was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .OLD_SOGDIAN: if let OLD_SOGDIAN = classObj.OLD_SOGDIAN { self.init(javaHolder: OLD_SOGDIAN.javaHolder) } else { - fatalError("Enum value OLD_SOGDIAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value OLD_SOGDIAN was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .SOGDIAN: if let SOGDIAN = classObj.SOGDIAN { self.init(javaHolder: SOGDIAN.javaHolder) } else { - fatalError("Enum value SOGDIAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value SOGDIAN was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .DOGRA: if let DOGRA = classObj.DOGRA { self.init(javaHolder: DOGRA.javaHolder) } else { - fatalError("Enum value DOGRA was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value DOGRA was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .GUNJALA_GONDI: if let GUNJALA_GONDI = classObj.GUNJALA_GONDI { self.init(javaHolder: GUNJALA_GONDI.javaHolder) } else { - fatalError("Enum value GUNJALA_GONDI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value GUNJALA_GONDI was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .MAKASAR: if let MAKASAR = classObj.MAKASAR { self.init(javaHolder: MAKASAR.javaHolder) } else { - fatalError("Enum value MAKASAR was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value MAKASAR was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .MEDEFAIDRIN: if let MEDEFAIDRIN = classObj.MEDEFAIDRIN { self.init(javaHolder: MEDEFAIDRIN.javaHolder) } else { - fatalError("Enum value MEDEFAIDRIN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value MEDEFAIDRIN was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .ELYMAIC: if let ELYMAIC = classObj.ELYMAIC { self.init(javaHolder: ELYMAIC.javaHolder) } else { - fatalError("Enum value ELYMAIC was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value ELYMAIC was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .NANDINAGARI: if let NANDINAGARI = classObj.NANDINAGARI { self.init(javaHolder: NANDINAGARI.javaHolder) } else { - fatalError("Enum value NANDINAGARI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value NANDINAGARI was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .NYIAKENG_PUACHUE_HMONG: if let NYIAKENG_PUACHUE_HMONG = classObj.NYIAKENG_PUACHUE_HMONG { self.init(javaHolder: NYIAKENG_PUACHUE_HMONG.javaHolder) } else { - fatalError("Enum value NYIAKENG_PUACHUE_HMONG was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value NYIAKENG_PUACHUE_HMONG was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .WANCHO: if let WANCHO = classObj.WANCHO { self.init(javaHolder: WANCHO.javaHolder) } else { - fatalError("Enum value WANCHO was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value WANCHO was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .YEZIDI: if let YEZIDI = classObj.YEZIDI { self.init(javaHolder: YEZIDI.javaHolder) } else { - fatalError("Enum value YEZIDI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value YEZIDI was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .CHORASMIAN: if let CHORASMIAN = classObj.CHORASMIAN { self.init(javaHolder: CHORASMIAN.javaHolder) } else { - fatalError("Enum value CHORASMIAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value CHORASMIAN was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .DIVES_AKURU: if let DIVES_AKURU = classObj.DIVES_AKURU { self.init(javaHolder: DIVES_AKURU.javaHolder) } else { - fatalError("Enum value DIVES_AKURU was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value DIVES_AKURU was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .KHITAN_SMALL_SCRIPT: if let KHITAN_SMALL_SCRIPT = classObj.KHITAN_SMALL_SCRIPT { self.init(javaHolder: KHITAN_SMALL_SCRIPT.javaHolder) } else { - fatalError("Enum value KHITAN_SMALL_SCRIPT was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value KHITAN_SMALL_SCRIPT was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .VITHKUQI: if let VITHKUQI = classObj.VITHKUQI { self.init(javaHolder: VITHKUQI.javaHolder) } else { - fatalError("Enum value VITHKUQI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value VITHKUQI was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .OLD_UYGHUR: if let OLD_UYGHUR = classObj.OLD_UYGHUR { self.init(javaHolder: OLD_UYGHUR.javaHolder) } else { - fatalError("Enum value OLD_UYGHUR was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value OLD_UYGHUR was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .CYPRO_MINOAN: if let CYPRO_MINOAN = classObj.CYPRO_MINOAN { self.init(javaHolder: CYPRO_MINOAN.javaHolder) } else { - fatalError("Enum value CYPRO_MINOAN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value CYPRO_MINOAN was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .TANGSA: if let TANGSA = classObj.TANGSA { self.init(javaHolder: TANGSA.javaHolder) } else { - fatalError("Enum value TANGSA was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value TANGSA was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .TOTO: if let TOTO = classObj.TOTO { self.init(javaHolder: TOTO.javaHolder) } else { - fatalError("Enum value TOTO was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value TOTO was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .KAWI: if let KAWI = classObj.KAWI { self.init(javaHolder: KAWI.javaHolder) } else { - fatalError("Enum value KAWI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value KAWI was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .NAG_MUNDARI: if let NAG_MUNDARI = classObj.NAG_MUNDARI { self.init(javaHolder: NAG_MUNDARI.javaHolder) } else { - fatalError("Enum value NAG_MUNDARI was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value NAG_MUNDARI was unexpectedly nil, please re-run swift-java on the most updated Java class") } case .UNKNOWN: if let UNKNOWN = classObj.UNKNOWN { self.init(javaHolder: UNKNOWN.javaHolder) } else { - fatalError("Enum value UNKNOWN was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value UNKNOWN was unexpectedly nil, please re-run swift-java on the most updated Java class") } } } diff --git a/Sources/SwiftJava/generated/JavaClass.swift b/Sources/SwiftJava/generated/JavaClass.swift index 0f1af1cd..a1147e3c 100644 --- a/Sources/SwiftJava/generated/JavaClass.swift +++ b/Sources/SwiftJava/generated/JavaClass.swift @@ -1,7 +1,7 @@ // Auto-generated by Java-to-Swift wrapper generator. import CSwiftJavaJNI -@JavaClass("java.lang.Class") +@JavaClass("java.lang.Class", implements: JavaReflectType.self) open class JavaClass: JavaObject { @JavaMethod open func getName() -> String @@ -52,13 +52,16 @@ open class JavaClass: JavaObject { open func isRecord() -> Bool @JavaMethod - open func getClassLoader() -> JavaClassLoader! + open func isSealed() -> Bool @JavaMethod - open func newInstance() throws -> JavaObject! + open func getInterfaces() -> [JavaClass?] @JavaMethod - open func getInterfaces() -> [JavaClass?] + open func getClassLoader() -> JavaClassLoader! + + @JavaMethod + open func newInstance() throws -> T! @JavaMethod open func isMemberClass() -> Bool @@ -70,7 +73,7 @@ open class JavaClass: JavaObject { open func isAnonymousClass() -> Bool @JavaMethod - open func getEnclosingClass() throws -> JavaClass! + open func getEnclosingClass() -> JavaClass! @JavaMethod open func arrayType() -> JavaClass! @@ -81,6 +84,9 @@ open class JavaClass: JavaObject { @JavaMethod open func getCanonicalName() -> String + @JavaMethod + open func getDeclaredClasses() -> [JavaClass?] + @JavaMethod open func getPackageName() -> String @@ -102,11 +108,17 @@ open class JavaClass: JavaObject { @JavaMethod open func isSynthetic() -> Bool + @JavaMethod + open func getGenericSuperclass() -> JavaReflectType! + + @JavaMethod + open func getGenericInterfaces() -> [JavaReflectType?] + @JavaMethod open func getSigners() -> [JavaObject?] @JavaMethod - open func getDeclaringClass() throws -> JavaClass! + open func getDeclaringClass() -> JavaClass! @JavaMethod open func getTypeName() -> String @@ -114,9 +126,6 @@ open class JavaClass: JavaObject { @JavaMethod open func getClasses() -> [JavaClass?] - @JavaMethod - open func getDeclaredClasses() throws -> [JavaClass?] - @JavaMethod open func getEnumConstants() -> [JavaObject?] @@ -128,16 +137,13 @@ open class JavaClass: JavaObject { @JavaMethod open func getNestMembers() -> [JavaClass?] - - @JavaMethod - open func isSealed() -> Bool } extension JavaClass { @JavaStaticMethod - public func forName(_ arg0: String, _ arg1: Bool, _ arg2: JavaClassLoader?) throws -> JavaClass! where ObjectType == JavaClass + public func forName(_ arg0: String) throws -> JavaClass! where ObjectType == JavaClass @JavaStaticMethod - public func forName(_ arg0: String) throws -> JavaClass! where ObjectType == JavaClass + public func forName(_ arg0: String, _ arg1: Bool, _ arg2: JavaClassLoader?) throws -> JavaClass! where ObjectType == JavaClass @JavaStaticMethod public func forPrimitiveName(_ arg0: String) -> JavaClass! where ObjectType == JavaClass diff --git a/Sources/SwiftJava/generated/JavaClassLoader.swift b/Sources/SwiftJava/generated/JavaClassLoader.swift index 349cba8d..0cd64aa1 100644 --- a/Sources/SwiftJava/generated/JavaClassLoader.swift +++ b/Sources/SwiftJava/generated/JavaClassLoader.swift @@ -7,10 +7,10 @@ open class JavaClassLoader: JavaObject { open func getName() -> String @JavaMethod - open func loadClass(_ arg0: String, _ arg1: Bool) throws -> JavaClass! + open func loadClass(_ arg0: String) throws -> JavaClass! @JavaMethod - open func loadClass(_ arg0: String) throws -> JavaClass! + open func loadClass(_ arg0: String, _ arg1: Bool) throws -> JavaClass! @JavaMethod open func setSigners(_ arg0: JavaClass?, _ arg1: [JavaObject?]) @@ -22,10 +22,10 @@ open class JavaClassLoader: JavaObject { open func findLoadedClass(_ arg0: String) -> JavaClass! @JavaMethod - open func findClass(_ arg0: String) throws -> JavaClass! + open func findClass(_ arg0: String, _ arg1: String) -> JavaClass! @JavaMethod - open func findClass(_ arg0: String, _ arg1: String) -> JavaClass! + open func findClass(_ arg0: String) throws -> JavaClass! @JavaMethod open func resolveClass(_ arg0: JavaClass?) diff --git a/Sources/SwiftJava/generated/JavaEnum.swift b/Sources/SwiftJava/generated/JavaEnum.swift new file mode 100644 index 00000000..2b8e102c --- /dev/null +++ b/Sources/SwiftJava/generated/JavaEnum.swift @@ -0,0 +1,11 @@ +// // Auto-generated by Java-to-Swift wrapper generator. +// import CSwiftJavaJNI + +// @JavaClass("java.lang.Enum") +// open class JavaEnum: JavaObject { +// @JavaMethod +// public func name() -> String + +// @JavaMethod +// public func ordinal() -> Int32 +// } diff --git a/Sources/SwiftJava/generated/JavaInteger.swift b/Sources/SwiftJava/generated/JavaInteger.swift index 94800037..df57ba66 100644 --- a/Sources/SwiftJava/generated/JavaInteger.swift +++ b/Sources/SwiftJava/generated/JavaInteger.swift @@ -3,7 +3,6 @@ import CSwiftJavaJNI @JavaClass("java.lang.Integer") open class JavaInteger: JavaNumber { - @JavaMethod @_nonoverride public convenience init(_ arg0: Int32, environment: JNIEnvironment? = nil) @@ -121,10 +120,10 @@ extension JavaClass { public func valueOf(_ arg0: String) throws -> JavaInteger! @JavaStaticMethod - public func valueOf(_ arg0: String, _ arg1: Int32) throws -> JavaInteger! + public func valueOf(_ arg0: Int32) -> JavaInteger! @JavaStaticMethod - public func valueOf(_ arg0: Int32) -> JavaInteger! + public func valueOf(_ arg0: String, _ arg1: Int32) throws -> JavaInteger! @JavaStaticMethod public func toHexString(_ arg0: Int32) -> String @@ -133,31 +132,37 @@ extension JavaClass { public func decode(_ arg0: String) throws -> JavaInteger! @JavaStaticMethod - public func parseInt(_ arg0: String) throws -> Int32 + public func parseInt(_ arg0: CharSequence?, _ arg1: Int32, _ arg2: Int32, _ arg3: Int32) throws -> Int32 @JavaStaticMethod public func parseInt(_ arg0: String, _ arg1: Int32) throws -> Int32 @JavaStaticMethod - public func toUnsignedLong(_ arg0: Int32) -> Int64 + public func parseInt(_ arg0: String) throws -> Int32 @JavaStaticMethod - public func sum(_ arg0: Int32, _ arg1: Int32) -> Int32 + public func highestOneBit(_ arg0: Int32) -> Int32 @JavaStaticMethod - public func toUnsignedString(_ arg0: Int32, _ arg1: Int32) -> String + public func toUnsignedLong(_ arg0: Int32) -> Int64 + + @JavaStaticMethod + public func sum(_ arg0: Int32, _ arg1: Int32) -> Int32 @JavaStaticMethod public func toUnsignedString(_ arg0: Int32) -> String @JavaStaticMethod - public func parseUnsignedInt(_ arg0: String) throws -> Int32 + public func toUnsignedString(_ arg0: Int32, _ arg1: Int32) -> String @JavaStaticMethod public func parseUnsignedInt(_ arg0: String, _ arg1: Int32) throws -> Int32 @JavaStaticMethod - public func getInteger(_ arg0: String, _ arg1: JavaInteger?) -> JavaInteger! + public func parseUnsignedInt(_ arg0: String) throws -> Int32 + + @JavaStaticMethod + public func parseUnsignedInt(_ arg0: CharSequence?, _ arg1: Int32, _ arg2: Int32, _ arg3: Int32) throws -> Int32 @JavaStaticMethod public func getInteger(_ arg0: String, _ arg1: Int32) -> JavaInteger! @@ -166,13 +171,13 @@ extension JavaClass { public func getInteger(_ arg0: String) -> JavaInteger! @JavaStaticMethod - public func toOctalString(_ arg0: Int32) -> String + public func getInteger(_ arg0: String, _ arg1: JavaInteger?) -> JavaInteger! @JavaStaticMethod - public func toBinaryString(_ arg0: Int32) -> String + public func toOctalString(_ arg0: Int32) -> String @JavaStaticMethod - public func highestOneBit(_ arg0: Int32) -> Int32 + public func toBinaryString(_ arg0: Int32) -> String @JavaStaticMethod public func lowestOneBit(_ arg0: Int32) -> Int32 diff --git a/Sources/SwiftJava/generated/JavaLong.swift b/Sources/SwiftJava/generated/JavaLong.swift index a986e9ef..7ea8fc09 100644 --- a/Sources/SwiftJava/generated/JavaLong.swift +++ b/Sources/SwiftJava/generated/JavaLong.swift @@ -126,10 +126,10 @@ extension JavaClass { public func compare(_ arg0: Int64, _ arg1: Int64) -> Int32 @JavaStaticMethod - public func valueOf(_ arg0: String) throws -> JavaLong! + public func valueOf(_ arg0: Int64) -> JavaLong! @JavaStaticMethod - public func valueOf(_ arg0: Int64) -> JavaLong! + public func valueOf(_ arg0: String) throws -> JavaLong! @JavaStaticMethod public func valueOf(_ arg0: String, _ arg1: Int32) throws -> JavaLong! @@ -140,6 +140,9 @@ extension JavaClass { @JavaStaticMethod public func decode(_ arg0: String) throws -> JavaLong! + @JavaStaticMethod + public func highestOneBit(_ arg0: Int64) -> Int64 + @JavaStaticMethod public func sum(_ arg0: Int64, _ arg1: Int64) -> Int64 @@ -155,9 +158,6 @@ extension JavaClass { @JavaStaticMethod public func toBinaryString(_ arg0: Int64) -> String - @JavaStaticMethod - public func highestOneBit(_ arg0: Int64) -> Int64 - @JavaStaticMethod public func lowestOneBit(_ arg0: Int64) -> Int64 @@ -168,20 +168,20 @@ extension JavaClass { public func rotateRight(_ arg0: Int64, _ arg1: Int32) -> Int64 @JavaStaticMethod - public func parseLong(_ arg0: CharSequence?, _ arg1: Int32, _ arg2: Int32, _ arg3: Int32) throws -> Int64 + public func parseLong(_ arg0: String) throws -> Int64 @JavaStaticMethod public func parseLong(_ arg0: String, _ arg1: Int32) throws -> Int64 @JavaStaticMethod - public func parseLong(_ arg0: String) throws -> Int64 + public func parseLong(_ arg0: CharSequence?, _ arg1: Int32, _ arg2: Int32, _ arg3: Int32) throws -> Int64 @JavaStaticMethod - public func parseUnsignedLong(_ arg0: CharSequence?, _ arg1: Int32, _ arg2: Int32, _ arg3: Int32) throws -> Int64 + public func parseUnsignedLong(_ arg0: String) throws -> Int64 @JavaStaticMethod public func parseUnsignedLong(_ arg0: String, _ arg1: Int32) throws -> Int64 @JavaStaticMethod - public func parseUnsignedLong(_ arg0: String) throws -> Int64 + public func parseUnsignedLong(_ arg0: CharSequence?, _ arg1: Int32, _ arg2: Int32, _ arg3: Int32) throws -> Int64 } diff --git a/Sources/SwiftJava/generated/JavaOptional.swift b/Sources/SwiftJava/generated/JavaOptional.swift index 08cc764a..5f10005f 100644 --- a/Sources/SwiftJava/generated/JavaOptional.swift +++ b/Sources/SwiftJava/generated/JavaOptional.swift @@ -4,7 +4,7 @@ import CSwiftJavaJNI @JavaClass("java.util.Optional") open class JavaOptional: JavaObject { @JavaMethod - open func get() -> JavaObject! + open func get() -> JavaObject! // FIXME: Currently we do generate -> T https://github.com/swiftlang/swift-java/issues/439 @JavaMethod open override func equals(_ arg0: JavaObject?) -> Bool diff --git a/Sources/SwiftJava/generated/JavaReflectArray.swift b/Sources/SwiftJava/generated/JavaReflectArray.swift new file mode 100644 index 00000000..4cae1202 --- /dev/null +++ b/Sources/SwiftJava/generated/JavaReflectArray.swift @@ -0,0 +1,71 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import CSwiftJavaJNI + +@JavaClass("java.lang.reflect.Array") +open class JavaReflectArray: JavaObject { + +} +extension JavaClass { + @JavaStaticMethod + public func get(_ arg0: JavaObject?, _ arg1: Int32) throws -> JavaObject! + + @JavaStaticMethod + public func getLength(_ arg0: JavaObject?) throws -> Int32 + + @JavaStaticMethod + public func getBoolean(_ arg0: JavaObject?, _ arg1: Int32) throws -> Bool + + @JavaStaticMethod + public func getByte(_ arg0: JavaObject?, _ arg1: Int32) throws -> Int8 + + @JavaStaticMethod + public func getShort(_ arg0: JavaObject?, _ arg1: Int32) throws -> Int16 + + @JavaStaticMethod + public func getChar(_ arg0: JavaObject?, _ arg1: Int32) throws -> UInt16 + + @JavaStaticMethod + public func getInt(_ arg0: JavaObject?, _ arg1: Int32) throws -> Int32 + + @JavaStaticMethod + public func getLong(_ arg0: JavaObject?, _ arg1: Int32) throws -> Int64 + + @JavaStaticMethod + public func getFloat(_ arg0: JavaObject?, _ arg1: Int32) throws -> Float + + @JavaStaticMethod + public func getDouble(_ arg0: JavaObject?, _ arg1: Int32) throws -> Double + + @JavaStaticMethod + public func newInstance(_ arg0: JavaClass?, _ arg1: Int32) throws -> JavaObject! + + @JavaStaticMethod + public func newInstance(_ arg0: JavaClass?, _ arg1: [Int32]) throws -> JavaObject! + + @JavaStaticMethod + public func set(_ arg0: JavaObject?, _ arg1: Int32, _ arg2: JavaObject?) throws + + @JavaStaticMethod + public func setBoolean(_ arg0: JavaObject?, _ arg1: Int32, _ arg2: Bool) throws + + @JavaStaticMethod + public func setByte(_ arg0: JavaObject?, _ arg1: Int32, _ arg2: Int8) throws + + @JavaStaticMethod + public func setChar(_ arg0: JavaObject?, _ arg1: Int32, _ arg2: UInt16) throws + + @JavaStaticMethod + public func setShort(_ arg0: JavaObject?, _ arg1: Int32, _ arg2: Int16) throws + + @JavaStaticMethod + public func setInt(_ arg0: JavaObject?, _ arg1: Int32, _ arg2: Int32) throws + + @JavaStaticMethod + public func setLong(_ arg0: JavaObject?, _ arg1: Int32, _ arg2: Int64) throws + + @JavaStaticMethod + public func setFloat(_ arg0: JavaObject?, _ arg1: Int32, _ arg2: Float) throws + + @JavaStaticMethod + public func setDouble(_ arg0: JavaObject?, _ arg1: Int32, _ arg2: Double) throws +} diff --git a/Sources/SwiftJava/generated/JavaReflectParameterizedType.swift b/Sources/SwiftJava/generated/JavaReflectParameterizedType.swift new file mode 100644 index 00000000..a0801644 --- /dev/null +++ b/Sources/SwiftJava/generated/JavaReflectParameterizedType.swift @@ -0,0 +1,17 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import CSwiftJavaJNI + +@JavaInterface("java.lang.reflect.ParameterizedType", extends: JavaReflectType.self) +public struct JavaReflectParameterizedType { + @JavaMethod + public func getOwnerType() -> JavaReflectType! + + @JavaMethod + public func getRawType() -> JavaReflectType! + + @JavaMethod + public func getActualTypeArguments() -> [JavaReflectType?] + + @JavaMethod + public func getTypeName() -> String +} diff --git a/Sources/SwiftJava/generated/JavaReflectType.swift b/Sources/SwiftJava/generated/JavaReflectType.swift new file mode 100644 index 00000000..fdf3b572 --- /dev/null +++ b/Sources/SwiftJava/generated/JavaReflectType.swift @@ -0,0 +1,8 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import CSwiftJavaJNI + +@JavaInterface("java.lang.reflect.Type") +public struct JavaReflectType { + @JavaMethod + public func getTypeName() -> String +} diff --git a/Sources/SwiftJava/swift-java.config b/Sources/SwiftJava/swift-java.config index b45671a7..d07ff162 100644 --- a/Sources/SwiftJava/swift-java.config +++ b/Sources/SwiftJava/swift-java.config @@ -5,6 +5,8 @@ "java.lang.Byte" : "JavaByte", "java.lang.Character" : "JavaCharacter", "java.lang.Class" : "JavaClass", + "java.lang.reflect.Type" : "JavaReflectType", + "java.lang.reflect.ParameterizedType" : "JavaReflectParameterizedType", "java.lang.ClassLoader" : "JavaClassLoader", "java.lang.Double" : "JavaDouble", "java.lang.Error" : "JavaError", diff --git a/Sources/SwiftJavaConfigurationShared/Configuration.swift b/Sources/SwiftJavaConfigurationShared/Configuration.swift index c9d0cedf..0fb5494f 100644 --- a/Sources/SwiftJavaConfigurationShared/Configuration.swift +++ b/Sources/SwiftJavaConfigurationShared/Configuration.swift @@ -65,7 +65,7 @@ public struct Configuration: Codable { asyncFuncMode ?? .default } - // ==== java 2 swift --------------------------------------------------------- + // ==== wrap-java --------------------------------------------------------- /// The Java class path that should be passed along to the swift-java tool. public var classpath: String? = nil @@ -85,6 +85,12 @@ public struct Configuration: Codable { // Generate class files suitable for the specified Java SE release. public var targetCompatibility: JavaVersion? + /// Filter input Java types by their package prefix if set. + public var filterInclude: [String]? + + /// Exclude input Java types by their package prefix or exact match. + public var filterExclude: [String]? + // ==== dependencies --------------------------------------------------------- // Java dependencies we need to fetch for this target. diff --git a/Sources/SwiftJavaTool/Commands/ConfigureCommand.swift b/Sources/SwiftJavaTool/Commands/ConfigureCommand.swift index 9a05a286..837d5e2f 100644 --- a/Sources/SwiftJavaTool/Commands/ConfigureCommand.swift +++ b/Sources/SwiftJavaTool/Commands/ConfigureCommand.swift @@ -72,7 +72,7 @@ extension SwiftJava.ConfigureCommand { let jvm = try self.makeJVM(classpathEntries: classpathEntries) - try emitConfiguration(classpath: self.commonJVMOptions.classpath, environment: jvm.environment()) + try emitConfiguration(classpathEntries: classpathEntries, environment: jvm.environment()) } /// Get base configuration, depending on if we are to 'amend' or 'overwrite' the existing configuration. @@ -97,32 +97,41 @@ extension SwiftJava.ConfigureCommand { // TODO: make this perhaps "emit type mappings" mutating func emitConfiguration( - classpath: [String], + classpathEntries: [String], environment: JNIEnvironment ) throws { - if let filterJavaPackage = self.commonJVMOptions.filterJavaPackage { - print("[java-swift][debug] Generate Java->Swift type mappings. Active filter: \(filterJavaPackage)") + var log = Self.log + log.logLevel = .init(rawValue: self.logLevel.rawValue)! + + log.info("Run: emit configuration...") + var (amendExistingConfig, configuration) = try getBaseConfigurationForWrite() + + if !self.commonOptions.filterInclude.isEmpty { + log.debug("Generate Java->Swift type mappings. Active include filters: \(self.commonOptions.filterInclude)") + } else if let filters = configuration.filterInclude, !filters.isEmpty { + // take the package filter from the configuration file + self.commonOptions.filterInclude = filters + } else { + log.debug("Generate Java->Swift type mappings. No package include filter applied.") } - print("[java-swift][debug] Classpath: \(classpath)") + log.debug("Classpath: \(classpathEntries)") - if classpath.isEmpty { - print("[java-swift][warning] Classpath is empty!") + if classpathEntries.isEmpty { + log.warning("Classpath is empty!") } // Get a fresh or existing configuration we'll amend - var (amendExistingConfig, configuration) = try getBaseConfigurationForWrite() if amendExistingConfig { - print("[swift-java] Amend existing swift-java.config file...") + log.info("Amend existing swift-java.config file...") } - configuration.classpath = classpath.joined(separator: ":") // TODO: is this correct? + configuration.classpath = classpathEntries.joined(separator: ":") // TODO: is this correct? // Import types from all the classpath entries; // Note that we use the package level filtering, so users have some control over what gets imported. - let classpathEntries = classpath.split(separator: ":").map(String.init) for entry in classpathEntries { guard fileOrDirectoryExists(at: entry) else { // We only log specific jars missing, as paths may be empty directories that won't hurt not existing. - print("[debug][swift-java] Classpath entry does not exist: \(entry)") + log.debug("Classpath entry does not exist: \(entry)") continue } @@ -135,9 +144,9 @@ extension SwiftJava.ConfigureCommand { environment: environment ) } else if FileManager.default.fileExists(atPath: entry) { - print("[warning][swift-java] Currently unable handle directory classpath entries for config generation! Skipping: \(entry)") + log.warning("Currently unable handle directory classpath entries for config generation! Skipping: \(entry)") } else { - print("[warning][swift-java] Classpath entry does not exist, skipping: \(entry)") + log.warning("Classpath entry does not exist, skipping: \(entry)") } } @@ -158,6 +167,8 @@ extension SwiftJava.ConfigureCommand { forJar jarFile: JarFile, environment: JNIEnvironment ) throws { + let log = Self.log + for entry in jarFile.entries()! { // We only look at class files in the Jar file. guard entry.getName().hasSuffix(".class") else { @@ -183,9 +194,8 @@ extension SwiftJava.ConfigureCommand { let javaCanonicalName = String(entry.getName().replacing("/", with: ".") .dropLast(".class".count)) - if let filterJavaPackage = self.commonJVMOptions.filterJavaPackage, - !javaCanonicalName.hasPrefix(filterJavaPackage) { - // Skip classes which don't match our expected prefix + guard SwiftJava.shouldImport(javaCanonicalName: javaCanonicalName, commonOptions: self.commonOptions) else { + log.info("Skip importing class: \(javaCanonicalName) due to include/exclude filters") continue } @@ -195,7 +205,17 @@ extension SwiftJava.ConfigureCommand { continue } - configuration.classes?[javaCanonicalName] = + if configuration.classes == nil { + configuration.classes = [:] + } + + if let configuredSwiftName = configuration.classes![javaCanonicalName] { + log.info("Java type '\(javaCanonicalName)' already configured as '\(configuredSwiftName)' Swift type.") + } else { + log.info("Configure Java type '\(javaCanonicalName)' as '\(javaCanonicalName.defaultSwiftNameForJavaClass.bold)' Swift type.") + } + + configuration.classes![javaCanonicalName] = javaCanonicalName.defaultSwiftNameForJavaClass } } diff --git a/Sources/SwiftJavaTool/Commands/JExtractCommand.swift b/Sources/SwiftJavaTool/Commands/JExtractCommand.swift index b5942d2a..b5c3a7bb 100644 --- a/Sources/SwiftJavaTool/Commands/JExtractCommand.swift +++ b/Sources/SwiftJavaTool/Commands/JExtractCommand.swift @@ -86,9 +86,7 @@ extension SwiftJava { extension SwiftJava.JExtractCommand { func runSwiftJavaCommand(config: inout Configuration) async throws { - if let javaPackage { - config.javaPackage = javaPackage - } + configure(&config.javaPackage, overrideWith: self.javaPackage) configure(&config.mode, overrideWith: self.mode) config.swiftModule = self.effectiveSwiftModule config.outputJavaDirectory = outputJava @@ -136,12 +134,6 @@ extension SwiftJava.JExtractCommand { } } } - - func configure(_ setting: inout T?, overrideWith value: T?) { - if let value { - setting = value - } - } } struct IncompatibleModeError: Error { diff --git a/Sources/SwiftJavaTool/Commands/ResolveCommand.swift b/Sources/SwiftJavaTool/Commands/ResolveCommand.swift index 58c64690..7cc4c477 100644 --- a/Sources/SwiftJavaTool/Commands/ResolveCommand.swift +++ b/Sources/SwiftJavaTool/Commands/ResolveCommand.swift @@ -104,7 +104,10 @@ extension SwiftJava.ResolveCommand { let deps = dependencies.map { $0.descriptionGradleStyle } print("[debug][swift-java] Resolve and fetch dependencies for: \(deps)") - let dependenciesClasspath = await resolveDependencies(dependencies: dependencies) + let workDir = URL(fileURLWithPath: FileManager.default.currentDirectoryPath) + .appendingPathComponent(".build") + + let dependenciesClasspath = await resolveDependencies(workDir: workDir, dependencies: dependencies) let classpathEntries = dependenciesClasspath.split(separator: ":") print("[info][swift-java] Resolved classpath for \(deps.count) dependencies of '\(swiftModule)', classpath entries: \(classpathEntries.count), ", terminator: "") @@ -122,10 +125,15 @@ extension SwiftJava.ResolveCommand { /// /// - Parameter dependencies: maven-style dependencies to resolve /// - Returns: Colon-separated classpath - func resolveDependencies(dependencies: [JavaDependencyDescriptor]) async -> String { - let workDir = URL(fileURLWithPath: FileManager.default.currentDirectoryPath) - .appendingPathComponent(".build") - let resolverDir = try! createTemporaryDirectory(in: workDir) + func resolveDependencies(workDir: URL, dependencies: [JavaDependencyDescriptor]) async -> String { + print("Create directory: \(workDir.absoluteString)") + + let resolverDir: URL + do { + resolverDir = try createTemporaryDirectory(in: workDir) + } catch { + fatalError("Unable to create temp directory at: \(workDir.absoluteString)! \(error)") + } defer { try? FileManager.default.removeItem(at: resolverDir) } @@ -162,7 +170,9 @@ extension SwiftJava.ResolveCommand { } else { let suggestDisablingSandbox = "It may be that the Sandbox has prevented dependency fetching, please re-run with '--disable-sandbox'." fatalError("Gradle output had no SWIFT_JAVA_CLASSPATH! \(suggestDisablingSandbox). \n" + - "Output was:<<<\(outString)>>>; Err was:<<<\(errString ?? "")>>>") + "Command was: \(CommandLine.arguments.joined(separator: " ").bold)\n" + + "Output was: <<<\(outString)>>>;\n" + + "Err was: <<<\(errString)>>>") } return String(classpathOutput.dropFirst(SwiftJavaClasspathPrefix.count)) diff --git a/Sources/SwiftJavaTool/Commands/WrapJavaCommand.swift b/Sources/SwiftJavaTool/Commands/WrapJavaCommand.swift index 43362edb..ae985e77 100644 --- a/Sources/SwiftJavaTool/Commands/WrapJavaCommand.swift +++ b/Sources/SwiftJavaTool/Commands/WrapJavaCommand.swift @@ -66,6 +66,9 @@ extension SwiftJava { extension SwiftJava.WrapJavaCommand { mutating func runSwiftJavaCommand(config: inout Configuration) async throws { + configure(&config.filterInclude, append: self.commonOptions.filterInclude) + configure(&config.filterExclude, append: self.commonOptions.filterExclude) + // Get base classpath configuration for this target and configuration var classpathSearchDirs = [self.effectiveSwiftModuleURL] if let cacheDir = self.cacheDirectory { @@ -113,16 +116,19 @@ extension SwiftJava.WrapJavaCommand { extension SwiftJava.WrapJavaCommand { mutating func generateWrappers( config: Configuration, - // classpathEntries: [String], dependentConfigs: [(String, Configuration)], environment: JNIEnvironment ) throws { let translator = JavaTranslator( + config: config, swiftModuleName: effectiveSwiftModule, environment: environment, translateAsClass: true ) + log.info("Active include filters: \(config.filterInclude ?? [])") + log.info("Active exclude filters: \(config.filterExclude ?? [])") + // Keep track of all of the Java classes that will have // Swift-native implementations. translator.swiftNativeImplementations = Set(swiftNativeImplementation) @@ -139,12 +145,30 @@ extension SwiftJava.WrapJavaCommand { translator.addConfiguration(config, forSwiftModule: effectiveSwiftModule) // Load all of the explicitly-requested classes. - let classLoader = try JavaClass(environment: environment) + let classLoader = try! JavaClass(environment: environment) .getSystemClassLoader()! var javaClasses: [JavaClass] = [] - for (javaClassName, _) in config.classes ?? [:] { + eachClass: for (javaClassName, _) in config.classes ?? [:] { + + // If we have an inclusive filter, import only types from it + for include in config.filterInclude ?? [] { + guard javaClassName.starts(with: include) else { + log.info("Skip Java type: \(javaClassName) (does not match filter)") + continue + } + } + // If we have an exclude filter, check for it as well + for exclude in config.filterExclude ?? [] { + if javaClassName.starts(with: exclude) { + log.info("Skip Java type: \(javaClassName) (does match exclude filter: \(exclude))") + continue eachClass + } + } + + log.info("Wrapping java type: \(javaClassName)") + guard let javaClass = try classLoader.loadClass(javaClassName) else { - print("warning: could not find Java class '\(javaClassName)'") + log.warning("Could not load Java class '\(javaClassName)', skipping.") continue } @@ -178,8 +202,23 @@ extension SwiftJava.WrapJavaCommand { return nil } + // If we have an inclusive filter, import only types from it + for include in config.filterInclude ?? [] { + guard javaClassName.starts(with: include) else { + log.info("Skip Java type: \(javaClassName) (does not match filter)") + return nil + } + } + // If we have an exclude filter, check for it as well + for exclude in config.filterExclude ?? [] { + if javaClassName.starts(with: exclude) { + log.info("Skip Java type: \(javaClassName) (does match exclude filter: \(exclude))") + return nil + } + } + // If this class has been explicitly mentioned, we're done. - if translator.translatedClasses[javaClassName] != nil { + guard translator.translatedClasses[javaClassName] == nil else { return nil } @@ -187,9 +226,8 @@ extension SwiftJava.WrapJavaCommand { let swiftUnqualifiedName = javaClassName.javaClassNameToCanonicalName .defaultSwiftNameForJavaClass - let swiftName = "\(currentSwiftName).\(swiftUnqualifiedName)" - translator.translatedClasses[javaClassName] = (swiftName, nil) + translator.translatedClasses[javaClassName] = SwiftTypeName(module: nil, name: swiftName) return nestedClass } diff --git a/Sources/SwiftJavaTool/CommonOptions.swift b/Sources/SwiftJavaTool/CommonOptions.swift index e8aee62d..ebdfdbea 100644 --- a/Sources/SwiftJavaTool/CommonOptions.swift +++ b/Sources/SwiftJavaTool/CommonOptions.swift @@ -30,6 +30,18 @@ protocol HasCommonOptions { var commonOptions: SwiftJava.CommonOptions { get set } } extension HasCommonOptions { + func configure(_ setting: inout T?, overrideWith value: T?) { + if let value { + setting = value + } + } + + func configure(_ setting: inout [T]?, append value: [T]?) { + if let value { + setting?.append(contentsOf: value) + } + } + var outputDirectory: String? { self.commonOptions.outputDirectory } @@ -45,6 +57,12 @@ extension SwiftJava { @Option(name: .shortAndLong, help: "Configure the level of logs that should be printed") var logLevel: JExtractSwiftLib.Logger.Level = .info + + @Option(name: .long, help: "While scanning a classpath, inspect ONLY types included in these packages") + var filterInclude: [String] = [] + + @Option(name: .long, help: "While scanning a classpath, skip types which match the filter prefix") + var filterExclude: [String] = [] } struct CommonJVMOptions: ParsableArguments { @@ -53,9 +71,6 @@ extension SwiftJava { help: "Class search path of directories and zip/jar files from which Java classes can be loaded." ) var classpath: [String] = [] - - @Option(name: .shortAndLong, help: "While scanning a classpath, inspect only types included in this package") - var filterJavaPackage: String? = nil } } diff --git a/Sources/SwiftJavaTool/ExcludedJDKTypes.swift b/Sources/SwiftJavaTool/ExcludedJDKTypes.swift new file mode 100644 index 00000000..1d24022f --- /dev/null +++ b/Sources/SwiftJavaTool/ExcludedJDKTypes.swift @@ -0,0 +1,42 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +extension SwiftJava { + /// Some types we cannot handle importing, so we hardcode skipping them. + public static let ExcludedJDKTypes: Set = [ + "java.lang.Enum", + "java.lang.Enum$EnumDesc", + ] + + static func shouldImport(javaCanonicalName: String, commonOptions: SwiftJava.CommonOptions) -> Bool { + if SwiftJava.ExcludedJDKTypes.contains(javaCanonicalName) { + return false + } + + for include in commonOptions.filterInclude { + guard javaCanonicalName.hasPrefix(include) else { + // Skip classes which don't match our expected prefix + return false + } + } + + for exclude in commonOptions.filterExclude { + if javaCanonicalName.hasPrefix(exclude) { + return false + } + } + + return true + } +} \ No newline at end of file diff --git a/Sources/SwiftJavaTool/Java/JavaClassLoader.swift b/Sources/SwiftJavaTool/Java/JavaClassLoader.swift index d465a206..27650885 100644 --- a/Sources/SwiftJavaTool/Java/JavaClassLoader.swift +++ b/Sources/SwiftJavaTool/Java/JavaClassLoader.swift @@ -17,6 +17,7 @@ import SwiftJavaShared import CSwiftJavaJNI import SwiftJava +// FIXME: do we need this here or can we rely on the generated one? @JavaClass("java.lang.ClassLoader") public struct ClassLoader { @JavaMethod diff --git a/Sources/SwiftJavaToolLib/JavaClassTranslator.swift b/Sources/SwiftJavaToolLib/JavaClassTranslator.swift index a7c4d76f..795639e5 100644 --- a/Sources/SwiftJavaToolLib/JavaClassTranslator.swift +++ b/Sources/SwiftJavaToolLib/JavaClassTranslator.swift @@ -15,6 +15,8 @@ import SwiftJava import JavaLangReflect import SwiftSyntax +import SwiftJavaConfigurationShared +import Logging /// Utility type that translates a single Java class into its corresponding /// Swift type and any additional helper types or functions. @@ -23,6 +25,10 @@ struct JavaClassTranslator { /// needed for translation. let translator: JavaTranslator + var log: Logger { + translator.log + } + /// The Java class (or interface) being translated. let javaClass: JavaClass @@ -47,7 +53,7 @@ struct JavaClassTranslator { let effectiveJavaSuperclass: JavaClass? /// The Swift name of the superclass. - let swiftSuperclass: String? + let swiftSuperclass: SwiftJavaParameterizedType? /// The Swift names of the interfaces that this class implements. let swiftInterfaces: [String] @@ -98,16 +104,16 @@ struct JavaClassTranslator { } /// The generic parameter clause for the Swift version of the Java class. - var genericParameterClause: String { + var genericParameters: [String] { if javaTypeParameters.isEmpty { - return "" + return [] } let genericParameters = javaTypeParameters.map { param in "\(param.getName()): AnyJavaObject" } - return "<\(genericParameters.joined(separator: ", "))>" + return genericParameters } /// Prepare translation for the given Java class (or interface). @@ -126,23 +132,38 @@ struct JavaClassTranslator { self.javaTypeParameters = javaClass.getTypeParameters().compactMap { $0 } self.nestedClasses = translator.nestedClasses[fullName] ?? [] - // Superclass. + // Superclass, incl parameter types (if any) if !javaClass.isInterface() { var javaSuperclass = javaClass.getSuperclass() - var swiftSuperclass: String? = nil + var javaGenericSuperclass: JavaReflectType? = javaClass.getGenericSuperclass() + var swiftSuperclassName: String? = nil + var swiftSuperclassTypeArgs: [String] = [] while let javaSuperclassNonOpt = javaSuperclass { do { - swiftSuperclass = try translator.getSwiftTypeName(javaSuperclassNonOpt, preferValueTypes: false).swiftName + swiftSuperclassName = try translator.getSwiftTypeName(javaSuperclassNonOpt, preferValueTypes: false).swiftName + if let javaGenericSuperclass = javaGenericSuperclass?.as(JavaReflectParameterizedType.self) { + for typeArg in javaGenericSuperclass.getActualTypeArguments() { + let javaTypeArgName = typeArg?.getTypeName() ?? "" + if let swiftTypeArgName = self.translator.translatedClasses[javaTypeArgName] { + swiftSuperclassTypeArgs.append(swiftTypeArgName.qualifiedName) + } else { + swiftSuperclassTypeArgs.append("/* MISSING MAPPING FOR */ \(javaTypeArgName)") + } + } + } break } catch { translator.logUntranslated("Unable to translate '\(fullName)' superclass: \(error)") } javaSuperclass = javaSuperclassNonOpt.getSuperclass() + javaGenericSuperclass = javaClass.getGenericSuperclass() } self.effectiveJavaSuperclass = javaSuperclass - self.swiftSuperclass = swiftSuperclass + self.swiftSuperclass = SwiftJavaParameterizedType( + name: swiftSuperclassName, + typeArguments: swiftSuperclassTypeArgs) } else { self.effectiveJavaSuperclass = nil self.swiftSuperclass = nil @@ -192,8 +213,9 @@ struct JavaClassTranslator { for method in methods { guard let method else { continue } - // Only look at public and protected methods here. - guard method.isPublic || method.isProtected else { continue } + guard shouldExtract(method: method) else { + continue + } // Skip any methods that are expected to be implemented in Swift. We will // visit them in the second pass, over the *declared* methods, because @@ -226,6 +248,20 @@ struct JavaClassTranslator { /// MARK: Collection of Java class members. extension JavaClassTranslator { + + /// Determines whether a method should be extracted for translation. + /// Only look at public and protected methods here. + private func shouldExtract(method: Method) -> Bool { + switch self.translator.config.effectiveMinimumInputAccessLevelMode { + case .internal: + return method.isPublic || method.isProtected || method.isPackage + case .package: + return method.isPublic || method.isProtected || method.isPackage + case .public: + return method.isPublic || method.isProtected + } + } + /// Add a field to the appropriate lists(s) for later translation. private mutating func addField(_ field: Field) { // Static fields go into a separate list. @@ -325,13 +361,25 @@ extension JavaClassTranslator { // Compute the "extends" clause for the superclass (of the struct // formulation) or the inheritance clause (for the class // formulation). - let extends: String + let extendsClause: String let inheritanceClause: String if translateAsClass { - extends = "" - inheritanceClause = swiftSuperclass.map { ": \($0)" } ?? "" + extendsClause = "" + inheritanceClause = + if let swiftSuperclass, swiftSuperclass.typeArguments.isEmpty { + ": \(swiftSuperclass.name)" + } else if let swiftSuperclass { + ": \(swiftSuperclass.name)<\(swiftSuperclass.typeArguments.joined(separator: ", "))>" + } else { + "" + } } else { - extends = swiftSuperclass.map { ", extends: \($0).self" } ?? "" + extendsClause = + if let swiftSuperclass { + ", extends: \(swiftSuperclass.render()).self" + } else { + "" + } inheritanceClause = "" } @@ -344,12 +392,19 @@ extension JavaClassTranslator { interfacesStr = ", \(prefix): \(swiftInterfaces.map { "\($0).self" }.joined(separator: ", "))" } + let genericParameterClause = + if genericParameters.isEmpty { + "" + } else { + "<\(genericParameters.joined(separator: ", "))>" + } + // Emit the struct declaration describing the java class. let classOrInterface: String = isInterface ? "JavaInterface" : "JavaClass"; let introducer = translateAsClass ? "open class" : "public struct" var classDecl: DeclSyntax = """ - @\(raw: classOrInterface)(\(literal: javaClass.getName())\(raw: extends)\(raw: interfacesStr)) + @\(raw: classOrInterface)(\(literal: javaClass.getName())\(raw: extendsClause)\(raw: interfacesStr)) \(raw: introducer) \(raw: swiftInnermostTypeName)\(raw: genericParameterClause)\(raw: inheritanceClause) { \(raw: members.map { $0.description }.joined(separator: "\n\n")) } @@ -396,7 +451,7 @@ extension JavaClassTranslator { } let genericArgumentClause = "<\(genericParameterNames.joined(separator: ", "))>" - staticMemberWhereClause = " where ObjectType == \(swiftTypeName)\(genericArgumentClause)" + staticMemberWhereClause = " where ObjectType == \(swiftTypeName)\(genericArgumentClause)" // FIXME: move the 'where ...' part into the render bit } else { staticMemberWhereClause = "" } @@ -418,7 +473,7 @@ extension JavaClassTranslator { do { return try renderMethod( method, implementedInSwift: /*FIXME:*/false, - genericParameterClause: genericParameterClause, + genericParameters: genericParameters, whereClause: staticMemberWhereClause ) } catch { @@ -435,7 +490,7 @@ extension JavaClassTranslator { // Specify the specialization arguments when needed. let extSpecialization: String - if genericParameterClause.isEmpty { + if genericParameters.isEmpty { extSpecialization = "<\(swiftTypeName)>" } else { extSpecialization = "" @@ -523,31 +578,76 @@ extension JavaClassTranslator { let accessModifier = javaConstructor.isPublic ? "public " : "" let convenienceModifier = translateAsClass ? "convenience " : "" let nonoverrideAttribute = translateAsClass ? "@_nonoverride " : "" + + // FIXME: handle generics in constructors return """ @JavaMethod \(raw: nonoverrideAttribute)\(raw: accessModifier)\(raw: convenienceModifier)init(\(raw: parametersStr))\(raw: throwsStr) """ } + func genericParameterIsUsedInSignature(_ typeParam: TypeVariable, in method: Method) -> Bool { + // --- Return type + // Is the return type exactly the type param + // FIXME: make this equals based? + if method.getGenericReturnType().getTypeName() == typeParam.getTypeName() { + return true + } + + if let parameterizedReturnType = method.getGenericReturnType().as(ParameterizedType.self) { + for actualTypeParam in parameterizedReturnType.getActualTypeArguments() { + guard let actualTypeParam else { continue } + if actualTypeParam.isEqualTo(typeParam.as(Type.self)) { + return true + } + } + } + + return false + } + /// Translates the given Java method into a Swift declaration. package func renderMethod( _ javaMethod: Method, implementedInSwift: Bool, - genericParameterClause: String = "", + genericParameters: [String] = [], whereClause: String = "" ) throws -> DeclSyntax { - // Map the parameters. - let parameters = try translateJavaParameters(javaMethod.getParameters()) + // Map the generic params on the method. + var allGenericParameters = genericParameters + let typeParameters = javaMethod.getTypeParameters() + if typeParameters.contains(where: {$0 != nil }) { + allGenericParameters += typeParameters.compactMap { typeParam in + guard let typeParam else { return nil } + guard genericParameterIsUsedInSignature(typeParam, in: javaMethod) else { + return nil + } + return "\(typeParam.getTypeName()): AnyJavaObject" + } + } + let genericParameterClauseStr = + if allGenericParameters.isEmpty { + "" + } else { + "<\(allGenericParameters.joined(separator: ", "))>" + } + // Map the parameters. + let parameters = try translateJavaParameters(javaMethod) let parametersStr = parameters.map { $0.description }.joined(separator: ", ") // Map the result type. let resultTypeStr: String - let resultType = try translator.getSwiftTypeNameAsString( - javaMethod.getGenericReturnType()!, - preferValueTypes: true, + let resultType = try translator.getSwiftReturnTypeNameAsString( + method: javaMethod, + preferValueTypes: true, outerOptional: .implicitlyUnwrappedOptional ) + // let resultType = try translator.getSwiftTypeNameAsString( + // javaMethod.getGenericReturnType()!, + // preferValueTypes: true, + // outerOptional: .implicitlyUnwrappedOptional + // ) // FIXME: cleanup the checking here if resultType != "Void" && resultType != "Swift.Void" { @@ -556,6 +656,7 @@ extension JavaClassTranslator { resultTypeStr = "" } + // --- Handle other effects let throwsStr = javaMethod.throwsCheckedException ? "throws" : "" let swiftMethodName = javaMethod.getName().escapedSwiftName let methodAttribute: AttributeSyntax = implementedInSwift @@ -581,23 +682,24 @@ extension JavaClassTranslator { let resultOptional: String = resultType.optionalWrappedType() ?? resultType let baseBody: ExprSyntax = "\(raw: javaMethod.throwsCheckedException ? "try " : "")\(raw: swiftMethodName)(\(raw: parameters.map(\.passedArg).joined(separator: ", ")))" - let body: ExprSyntax = if let optionalType = resultType.optionalWrappedType() { - "Optional(javaOptional: \(baseBody))" - } else { - baseBody - } + let body: ExprSyntax = + if resultType.optionalWrappedType() != nil { + "Optional(javaOptional: \(baseBody))" + } else { + baseBody + } return """ - \(methodAttribute)\(raw: accessModifier)\(raw: overrideOpt)func \(raw: swiftMethodName)\(raw: genericParameterClause)(\(raw: parametersStr))\(raw: throwsStr)\(raw: resultTypeStr)\(raw: whereClause) + \(methodAttribute)\(raw: accessModifier)\(raw: overrideOpt)func \(raw: swiftMethodName)\(raw: genericParameterClauseStr)(\(raw: parametersStr))\(raw: throwsStr)\(raw: resultTypeStr)\(raw: whereClause) - \(raw: accessModifier)\(raw: overrideOpt)func \(raw: swiftMethodName)Optional\(raw: genericParameterClause)(\(raw: parameters.map(\.clause.description).joined(separator: ", ")))\(raw: throwsStr) -> \(raw: resultOptional)\(raw: whereClause) { + \(raw: accessModifier)\(raw: overrideOpt)func \(raw: swiftMethodName)Optional\(raw: genericParameterClauseStr)(\(raw: parameters.map(\.clause.description).joined(separator: ", ")))\(raw: throwsStr) -> \(raw: resultOptional)\(raw: whereClause) { \(body) } """ } else { return """ - \(methodAttribute)\(raw: accessModifier)\(raw: overrideOpt)func \(raw: swiftMethodName)\(raw: genericParameterClause)(\(raw: parametersStr))\(raw: throwsStr)\(raw: resultTypeStr)\(raw: whereClause) + \(methodAttribute)\(raw: accessModifier)\(raw: overrideOpt)func \(raw: swiftMethodName)\(raw: genericParameterClauseStr)(\(raw: parametersStr))\(raw: throwsStr)\(raw: resultTypeStr)\(raw: whereClause) """ } } @@ -688,7 +790,7 @@ extension JavaClassTranslator { ? "self.init(javaHolder: \($0.getName()).javaHolder)" : "self = \($0.getName())") } else { - fatalError("Enum value \($0.getName()) was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value \($0.getName()) was unexpectedly nil, please re-run swift-java on the most updated Java class") } """ }.joined(separator: "\n")) @@ -700,7 +802,30 @@ extension JavaClassTranslator { } // Translate a Java parameter list into Swift parameters. - private func translateJavaParameters(_ parameters: [Parameter?]) throws -> [FunctionParameterSyntax] { + private func translateJavaParameters( + _ javaMethod: JavaLangReflect.Method + ) throws -> [FunctionParameterSyntax] { + let parameters: [Parameter?] = javaMethod.getParameters() + + return try parameters.compactMap { javaParameter in + guard let javaParameter else { return nil } + + let typeName = try translator.getSwiftTypeNameAsString( + method: javaMethod, + javaParameter.getParameterizedType()!, + preferValueTypes: true, + outerOptional: .optional + ) + let paramName = javaParameter.getName() + return "_ \(raw: paramName): \(raw: typeName)" + } + } + + // Translate a Java parameter list into Swift parameters. + @available(*, deprecated, message: "Prefer the method based version") // FIXME: constructors are not well handled + private func translateJavaParameters( + _ parameters: [Parameter?] + ) throws -> [FunctionParameterSyntax] { return try parameters.compactMap { javaParameter in guard let javaParameter else { return nil } @@ -778,9 +903,7 @@ extension JavaClassTranslator { continue } - // Ignore non-public, non-protected methods because they would not - // have been render into the Swift superclass. - if !overriddenMethod.isPublic && !overriddenMethod.isProtected { + guard shouldExtract(method: overriddenMethod) else { continue } @@ -791,6 +914,7 @@ extension JavaClassTranslator { return true } } catch { + // FIXME: logging } } @@ -815,114 +939,3 @@ extension [Type?] { } } -extension Type { - /// Adjust the given type to use its bounds, mirroring what we do in - /// mapping Java types into Swift. - func adjustToJavaBounds(adjusted: inout Bool) -> Type { - if let typeVariable = self.as(TypeVariable.self), - typeVariable.getBounds().count == 1, - let bound = typeVariable.getBounds()[0] { - adjusted = true - return bound - } - - if let wildcardType = self.as(WildcardType.self), - wildcardType.getUpperBounds().count == 1, - let bound = wildcardType.getUpperBounds()[0] { - adjusted = true - return bound - } - - return self - } - - /// Determine whether this type is equivalent to or a subtype of the other - /// type. - func isEqualTo(_ other: Type) -> Bool { - // First, adjust types to their bounds, if we need to. - var anyAdjusted: Bool = false - let adjustedSelf = self.adjustToJavaBounds(adjusted: &anyAdjusted) - let adjustedOther = other.adjustToJavaBounds(adjusted: &anyAdjusted) - if anyAdjusted { - return adjustedSelf.isEqualTo(adjustedOther) - } - - // If both are classes, check for equivalence. - if let selfClass = self.as(JavaClass.self), - let otherClass = other.as(JavaClass.self) { - return selfClass.equals(otherClass.as(JavaObject.self)) - } - - // If both are arrays, check that their component types are equivalent. - if let selfArray = self.as(GenericArrayType.self), - let otherArray = other.as(GenericArrayType.self) { - return selfArray.getGenericComponentType().isEqualTo(otherArray.getGenericComponentType()) - } - - // If both are parameterized types, check their raw type and type - // arguments for equivalence. - if let selfParameterizedType = self.as(ParameterizedType.self), - let otherParameterizedType = other.as(ParameterizedType.self) { - if !selfParameterizedType.getRawType().isEqualTo(otherParameterizedType.getRawType()) { - return false - } - - return selfParameterizedType.getActualTypeArguments() - .allTypesEqual(otherParameterizedType.getActualTypeArguments()) - } - - // If both are type variables, compare their bounds. - // FIXME: This is a hack. - if let selfTypeVariable = self.as(TypeVariable.self), - let otherTypeVariable = other.as(TypeVariable.self) { - return selfTypeVariable.getBounds().allTypesEqual(otherTypeVariable.getBounds()) - } - - // If both are wildcards, compare their upper and lower bounds. - if let selfWildcard = self.as(WildcardType.self), - let otherWildcard = other.as(WildcardType.self) { - return selfWildcard.getUpperBounds().allTypesEqual(otherWildcard.getUpperBounds()) - && selfWildcard.getLowerBounds().allTypesEqual(otherWildcard.getLowerBounds()) - } - - return false - } - - /// Determine whether this type is equivalent to or a subtype of the - /// other type. - func isEqualToOrSubtypeOf(_ other: Type) -> Bool { - // First, adjust types to their bounds, if we need to. - var anyAdjusted: Bool = false - let adjustedSelf = self.adjustToJavaBounds(adjusted: &anyAdjusted) - let adjustedOther = other.adjustToJavaBounds(adjusted: &anyAdjusted) - if anyAdjusted { - return adjustedSelf.isEqualToOrSubtypeOf(adjustedOther) - } - - if isEqualTo(other) { - return true - } - - // If both are classes, check for subclassing. - if let selfClass = self.as(JavaClass.self), - let otherClass = other.as(JavaClass.self) { - // If either is a Java array, then this cannot be a subtype relationship - // in Swift. - if selfClass.isArray() || otherClass.isArray() { - return false - } - - return selfClass.isSubclass(of: otherClass) - } - - // Anything object-like is a subclass of java.lang.Object - if let otherClass = other.as(JavaClass.self), - otherClass.getName() == "java.lang.Object" { - if self.is(GenericArrayType.self) || self.is(ParameterizedType.self) || - self.is(WildcardType.self) || self.is(TypeVariable.self) { - return true - } - } - return false - } -} diff --git a/Sources/SwiftJavaToolLib/JavaGenericsSupport.swift b/Sources/SwiftJavaToolLib/JavaGenericsSupport.swift new file mode 100644 index 00000000..7c781962 --- /dev/null +++ b/Sources/SwiftJavaToolLib/JavaGenericsSupport.swift @@ -0,0 +1,89 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import JavaLangReflect +import JavaTypes +import SwiftBasicFormat +import SwiftJava +import SwiftJavaConfigurationShared +import SwiftSyntax +import SwiftSyntaxBuilder + +struct GenericJavaTypeOriginInfo { + enum GenericSource { + /// The source of the generic + case `class`([Type]) + case method + } + + var source: GenericSource + var type: Type +} + +/// if the type (that is used by the Method) is generic, return if the use originates from the method, or a surrounding class. +func getGenericJavaTypeOriginInfo(_ type: Type?, from method: Method) -> [GenericJavaTypeOriginInfo] { + guard let type else { + return [] + } + + guard isGenericJavaType(type) else { + return [] // it's not a generic type, no "origin" of the use to detect + } + + var methodTypeVars = method.getTypeParameters() + + // TODO: also handle nested classes here... + var classTypeVars = method.getDeclaringClass().getTypeParameters() + + var usedTypeVars: [TypeVariable] = [] + + return [] +} + +func isGenericJavaType(_ type: Type?) -> Bool { + guard let type else { + return false + } + + // Check if it's a type variable (e.g., T, E, etc.) + if type.as(TypeVariable.self) != nil { + return true + } + + // Check if it's a parameterized type (e.g., List, Map) + if let paramType = type.as(ParameterizedType.self) { + let typeArgs: [Type?] = paramType.getActualTypeArguments() + + // Check if any of the type arguments are generic + for typeArg in typeArgs { + guard let typeArg else { continue } + if isGenericJavaType(typeArg) { + return true + } + } + } + + // Check if it's a generic array type (e.g., T[], List[]) + if let arrayType = type.as(GenericArrayType.self) { + let componentType = arrayType.getGenericComponentType() + return isGenericJavaType(componentType) + } + + // Check if it's a wildcard type (e.g., ? extends Number, ? super String) + if type.as(WildcardType.self) != nil { + return true + } + + return false +} diff --git a/Sources/SwiftJavaToolLib/JavaHomeSupport.swift b/Sources/SwiftJavaToolLib/JavaHomeSupport.swift new file mode 100644 index 00000000..cd18f7a8 --- /dev/null +++ b/Sources/SwiftJavaToolLib/JavaHomeSupport.swift @@ -0,0 +1,92 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import Foundation + +/// Detected JAVA_HOME for this process. +package let javaHome: String = findJavaHome() + +// Note: the JAVA_HOME environment variable must be set to point to where +// Java is installed, e.g., +// Library/Java/JavaVirtualMachines/openjdk-21.jdk/Contents/Home. +public func findJavaHome() -> String { + if let home = ProcessInfo.processInfo.environment["JAVA_HOME"] { + return home + } + + // This is a workaround for envs (some IDEs) which have trouble with + // picking up env variables during the build process + let path = "\(FileManager.default.homeDirectoryForCurrentUser.path()).java_home" + if let home = try? String(contentsOfFile: path, encoding: .utf8) { + if let lastChar = home.last, lastChar.isNewline { + return String(home.dropLast()) + } + + return home + } + + if let home = getJavaHomeFromLibexecJavaHome(), + !home.isEmpty + { + return home + } + + if ProcessInfo.processInfo.environment["SPI_PROCESSING"] == "1" + && ProcessInfo.processInfo.environment["SPI_BUILD"] == nil + { + // Just ignore that we're missing a JAVA_HOME when building in Swift Package Index during general processing where no Java is needed. However, do _not_ suppress the error during SPI's compatibility build stage where Java is required. + return "" + } + fatalError("Please set the JAVA_HOME environment variable to point to where Java is installed.") +} + +/// On MacOS we can use the java_home tool as a fallback if we can't find JAVA_HOME environment variable. +public func getJavaHomeFromLibexecJavaHome() -> String? { + let task = Process() + task.executableURL = URL(fileURLWithPath: "/usr/libexec/java_home") + + // Check if the executable exists before trying to run it + guard FileManager.default.fileExists(atPath: task.executableURL!.path) else { + print("/usr/libexec/java_home does not exist") + return nil + } + + let pipe = Pipe() + task.standardOutput = pipe + task.standardError = pipe // Redirect standard error to the same pipe for simplicity + + do { + try task.run() + task.waitUntilExit() + + let data = pipe.fileHandleForReading.readDataToEndOfFile() + let output = String(data: data, encoding: .utf8)?.trimmingCharacters( + in: .whitespacesAndNewlines) + + if task.terminationStatus == 0 { + return output + } else { + print("java_home terminated with status: \(task.terminationStatus)") + // Optionally, log the error output for debugging + if let errorOutput = String( + data: pipe.fileHandleForReading.readDataToEndOfFile(), encoding: .utf8) { + print("Error output: \(errorOutput)") + } + return nil + } + } catch { + print("Error running java_home: \(error)") + return nil + } +} diff --git a/Sources/SwiftJavaToolLib/JavaParameterizedType.swift b/Sources/SwiftJavaToolLib/JavaParameterizedType.swift new file mode 100644 index 00000000..a1b2c6b6 --- /dev/null +++ b/Sources/SwiftJavaToolLib/JavaParameterizedType.swift @@ -0,0 +1,38 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +// E.g. `Another` +struct SwiftJavaParameterizedType { + let name: String + let typeArguments: [String] + + init?(name: String?, typeArguments: [String]) { + guard let name else { + return nil + } + + self.name = name + self.typeArguments = typeArguments + } + + func render() -> String { + if typeArguments.isEmpty { + name + } else { + "\(name)<\(typeArguments.joined(separator: ", "))>" + } + } + + +} diff --git a/Sources/SwiftJavaToolLib/JavaTranslator+Configuration.swift b/Sources/SwiftJavaToolLib/JavaTranslator+Configuration.swift index 4fc9feb0..655c6765 100644 --- a/Sources/SwiftJavaToolLib/JavaTranslator+Configuration.swift +++ b/Sources/SwiftJavaToolLib/JavaTranslator+Configuration.swift @@ -16,11 +16,6 @@ import Foundation import SwiftJavaConfigurationShared extension JavaTranslator { -// /// Read a configuration file from the given URL. -// package static func readConfiguration(from url: URL) throws -> Configuration { -// let contents = try Data(contentsOf: url) -// return try JSONDecoder().decode(Configuration.self, from: contents) -// } /// Load the configuration file with the given name to populate the known set of /// translated Java classes. @@ -30,10 +25,7 @@ extension JavaTranslator { } for (javaClassName, swiftName) in classes { - translatedClasses[javaClassName] = ( - swiftType: swiftName, - swiftModule: swiftModule - ) + translatedClasses[javaClassName] = SwiftTypeName(module: swiftModule, name: swiftName) } } } diff --git a/Sources/SwiftJavaToolLib/JavaTranslator+Validation.swift b/Sources/SwiftJavaToolLib/JavaTranslator+Validation.swift index 9d4d00ca..3a6468d5 100644 --- a/Sources/SwiftJavaToolLib/JavaTranslator+Validation.swift +++ b/Sources/SwiftJavaToolLib/JavaTranslator+Validation.swift @@ -12,24 +12,45 @@ // //===----------------------------------------------------------------------===// -package extension JavaTranslator { - struct SwiftTypeName: Hashable { - let swiftType: String - let swiftModule: String? +public typealias JavaFullyQualifiedTypeName = String - package init(swiftType: String, swiftModule: String?) { - self.swiftType = swiftType - self.swiftModule = swiftModule +package struct SwiftTypeName: Hashable, CustomStringConvertible { + package let swiftModule: String? + package let swiftType: String + + package init(module: String?, name: String) { + self.swiftModule = module + self.swiftType = name + } + + package var qualifiedName: String { + if let swiftModule { + "\(swiftModule).\(swiftType)" + } else { + "\(swiftType)" + } + } + + package var description: String { + if let swiftModule { + "`\(swiftModule)/\(swiftType)`" + } else { + "`\(swiftType)`" } } +} + +package extension JavaTranslator { struct SwiftToJavaMapping: Equatable { let swiftType: SwiftTypeName - let javaTypes: [String] + let javaTypes: [JavaFullyQualifiedTypeName] - package init(swiftType: SwiftTypeName, javaTypes: [String]) { + package init(swiftType: SwiftTypeName, javaTypes: [JavaFullyQualifiedTypeName]) { self.swiftType = swiftType self.javaTypes = javaTypes + precondition(!javaTypes.contains("com.google.protobuf.AbstractMessage$Builder"), + "\(swiftType) mapped as \(javaTypes)\n\(CommandLine.arguments.joined(separator: " "))") // XXX } } @@ -48,15 +69,23 @@ package extension JavaTranslator { private func mappingDescription(mapping: SwiftToJavaMapping) -> String { let javaTypes = mapping.javaTypes.map { "'\($0)'" }.joined(separator: ", ") - return "Swift Type: '\(mapping.swiftType.swiftModule ?? "")'.'\(mapping.swiftType.swiftType)', Java Types: \(javaTypes)" + return "Swift module: '\(mapping.swiftType.swiftModule ?? "")', type: '\(mapping.swiftType.swiftType)', Java Types: \(javaTypes)" } } func validateClassConfiguration() throws(ValidationError) { + // for a in translatedClasses { + // print("MAPPING = \(a.key) -> \(a.value.swiftModule?.escapedSwiftName ?? "").\(a.value.swiftType.escapedSwiftName)") + // } + // Group all classes by swift name - let groupedDictionary: [SwiftTypeName: [(String, (String, String?))]] = Dictionary(grouping: translatedClasses, by: { SwiftTypeName(swiftType: $0.value.swiftType, swiftModule: $0.value.swiftModule) }) + let groupedDictionary: [SwiftTypeName: [(JavaFullyQualifiedTypeName, SwiftTypeName)]] = Dictionary(grouping: translatedClasses, by: { + // SwiftTypeName(swiftType: $0.value.swiftType, swiftModule: $0.value.swiftModule) + $0.value + }) // Find all that are mapped to multiple names - let multipleClassesMappedToSameName: [SwiftTypeName: [(String, (String, String?))]] = groupedDictionary.filter { (key: SwiftTypeName, value: [(String, (String, String?))]) in + let multipleClassesMappedToSameName: [SwiftTypeName: [(JavaFullyQualifiedTypeName, SwiftTypeName)]] = groupedDictionary.filter { + (key: SwiftTypeName, value: [(JavaFullyQualifiedTypeName, SwiftTypeName)]) in value.count > 1 } diff --git a/Sources/SwiftJavaToolLib/JavaTranslator.swift b/Sources/SwiftJavaToolLib/JavaTranslator.swift index 7cb8a7ee..71e01179 100644 --- a/Sources/SwiftJavaToolLib/JavaTranslator.swift +++ b/Sources/SwiftJavaToolLib/JavaTranslator.swift @@ -19,10 +19,16 @@ import SwiftBasicFormat import SwiftSyntax import SwiftJavaConfigurationShared import SwiftSyntaxBuilder +import Foundation +import Logging /// Utility that translates Java classes into Swift source code to access /// those Java classes. package class JavaTranslator { + let config: Configuration + + let log: Logger + /// The name of the Swift module that we are translating into. let swiftModuleName: String @@ -35,7 +41,10 @@ package class JavaTranslator { /// A mapping from the name of each known Java class to the corresponding /// Swift type name and its Swift module. - package var translatedClasses: [String: (swiftType: String, swiftModule: String?)] = [:] + package var translatedClasses: [JavaFullyQualifiedTypeName: SwiftTypeName] = [ + "java.lang.Object": SwiftTypeName(module: "SwiftJava", name: "JavaObject"), + "byte[]": SwiftTypeName(module: nil, name: "[UInt8]") + ] /// A mapping from the name of each known Java class with the Swift value type /// (and its module) to which it is mapped. @@ -44,8 +53,8 @@ package class JavaTranslator { /// `translatedClasses` should map to a representation of the Java class (i.e., /// an AnyJavaObject-conforming type) whereas the entry here should map to /// a value type. - package let translatedToValueTypes: [String: (swiftType: String, swiftModule: String) ] = [ - "java.lang.String": ("String", "SwiftJava"), + package let translatedToValueTypes: [JavaFullyQualifiedTypeName: SwiftTypeName] = [ + "java.lang.String": SwiftTypeName(module: "SwiftJava", name: "String"), ] /// The set of Swift modules that need to be imported to make the generated @@ -64,15 +73,21 @@ package class JavaTranslator { package var nestedClasses: [String: [JavaClass]] = [:] package init( + config: Configuration, swiftModuleName: String, environment: JNIEnvironment, translateAsClass: Bool = false, format: BasicFormat = JavaTranslator.defaultFormat ) { + self.config = config self.swiftModuleName = swiftModuleName self.environment = environment self.translateAsClass = translateAsClass self.format = format + + var l = Logger(label: "swift-java") + l.logLevel = .init(rawValue: (config.logLevel ?? .info).rawValue)! + self.log = l } /// Clear out any per-file state when we want to start a new file. @@ -112,8 +127,28 @@ extension JavaTranslator { // MARK: Type translation extension JavaTranslator { + + func getSwiftReturnTypeNameAsString( + method: JavaLangReflect.Method, + preferValueTypes: Bool, + outerOptional: OptionalKind + ) throws -> String { + // let returnType = method.getReturnType() + let genericReturnType = method.getGenericReturnType() + + // Special handle the case when the return type is the generic type of the method: ` T foo()` + + // if isGenericJavaType(genericReturnType) { + // print("[swift] generic method! \(method.getDeclaringClass().getName()).\(method.getName())") + // getGenericJavaTypeOriginInfo(genericReturnType, from: method) + // } + + return try getSwiftTypeNameAsString(method: method, genericReturnType!, preferValueTypes: preferValueTypes, outerOptional: outerOptional) + } + /// Turn a Java type into a string. func getSwiftTypeNameAsString( + method: JavaLangReflect.Method? = nil, _ javaType: Type, preferValueTypes: Bool, outerOptional: OptionalKind @@ -123,11 +158,7 @@ extension JavaTranslator { typeVariable.getBounds().count == 1, let bound = typeVariable.getBounds()[0] { - return try getSwiftTypeNameAsString( - bound, - preferValueTypes: preferValueTypes, - outerOptional: outerOptional - ) + return outerOptional.adjustTypeName(typeVariable.getName()) } // Replace wildcards with their upper bound. @@ -164,30 +195,42 @@ extension JavaTranslator { // Handle parameterized types by recursing on the raw type and the type // arguments. - if let parameterizedType = javaType.as(ParameterizedType.self), - let rawJavaType = parameterizedType.getRawType() - { - var rawSwiftType = try getSwiftTypeNameAsString( - rawJavaType, - preferValueTypes: false, - outerOptional: outerOptional - ) + if let parameterizedType = javaType.as(ParameterizedType.self) { + if let rawJavaType = parameterizedType.getRawType() { + var rawSwiftType = try getSwiftTypeNameAsString( + rawJavaType, + preferValueTypes: false, + outerOptional: outerOptional + ) - let optionalSuffix: String - if let lastChar = rawSwiftType.last, lastChar == "?" || lastChar == "!" { - optionalSuffix = "\(lastChar)" - rawSwiftType.removeLast() - } else { - optionalSuffix = "" - } + let optionalSuffix: String + if let lastChar = rawSwiftType.last, lastChar == "?" || lastChar == "!" { + optionalSuffix = "\(lastChar)" + rawSwiftType.removeLast() + } else { + optionalSuffix = "" + } - let typeArguments = try parameterizedType.getActualTypeArguments().compactMap { typeArg in - try typeArg.map { typeArg in - try getSwiftTypeNameAsString(typeArg, preferValueTypes: false, outerOptional: .nonoptional) + let typeArguments: [String] = try parameterizedType.getActualTypeArguments().compactMap { typeArg in + guard let typeArg else { return nil } + + let mappedSwiftName = try getSwiftTypeNameAsString(method: method, typeArg, preferValueTypes: false, outerOptional: .nonoptional) + + // FIXME: improve the get instead... + if mappedSwiftName == nil || mappedSwiftName == "JavaObject" { + // Try to salvage it, is it perhaps a type parameter? + if let method { + if method.getTypeParameters().contains(where: { $0?.getTypeName() == typeArg.getTypeName() }) { + return typeArg.getTypeName() + } + } + } + + return mappedSwiftName } - } - return "\(rawSwiftType)<\(typeArguments.joined(separator: ", "))>\(optionalSuffix)" + return "\(rawSwiftType)<\(typeArguments.joined(separator: ", "))>\(optionalSuffix)" + } } // Handle direct references to Java classes. @@ -196,10 +239,12 @@ extension JavaTranslator { } let (swiftName, isOptional) = try getSwiftTypeName(javaClass, preferValueTypes: preferValueTypes) - var resultString = swiftName - if isOptional { - resultString = outerOptional.adjustTypeName(resultString) - } + let resultString = + if isOptional { + outerOptional.adjustTypeName(swiftName) + } else { + swiftName + } return resultString } @@ -233,7 +278,10 @@ extension JavaTranslator { if preferValueTypes, let translatedValueType = translatedToValueTypes[name] { // Note that we need to import this Swift module. if translatedValueType.swiftModule != swiftModuleName { - importedSwiftModules.insert(translatedValueType.swiftModule) + guard let module = translatedValueType.swiftModule else { + preconditionFailure("Translated value type must have Swift module, but was nil! Type: \(translatedValueType)") + } + importedSwiftModules.insert(module) } return translatedValueType.swiftType diff --git a/Sources/SwiftJavaToolLib/JavaType+Equality.swift b/Sources/SwiftJavaToolLib/JavaType+Equality.swift new file mode 100644 index 00000000..b3d4a37a --- /dev/null +++ b/Sources/SwiftJavaToolLib/JavaType+Equality.swift @@ -0,0 +1,135 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import SwiftJava +import JavaLangReflect +import SwiftSyntax +import SwiftJavaConfigurationShared +import Logging + +extension Type { + /// Adjust the given type to use its bounds, mirroring what we do in + /// mapping Java types into Swift. + func adjustToJavaBounds(adjusted: inout Bool) -> Type { + if let typeVariable = self.as(TypeVariable.self), + typeVariable.getBounds().count == 1, + let bound = typeVariable.getBounds()[0] { + adjusted = true + return bound + } + + if let wildcardType = self.as(WildcardType.self), + wildcardType.getUpperBounds().count == 1, + let bound = wildcardType.getUpperBounds()[0] { + adjusted = true + return bound + } + + return self + } + + /// Determine whether this type is equivalent to or a subtype of the other + /// type. + func isEqualTo(_ other: Type, file: String = #file, line: Int = #line, function: String = #function) -> Bool { + if self.javaHolder.object == other.javaHolder.object { + return true + } + + // First, adjust types to their bounds, if we need to. + var anyAdjusted: Bool = false + let adjustedSelf = self.adjustToJavaBounds(adjusted: &anyAdjusted) + let adjustedOther = other.adjustToJavaBounds(adjusted: &anyAdjusted) + if anyAdjusted { + return adjustedSelf.isEqualTo(adjustedOther) + } + + // If both are classes, check for equivalence. + if let selfClass = self.as(JavaClass.self), + let otherClass = other.as(JavaClass.self) { + return selfClass.equals(otherClass.as(JavaObject.self)) + } + + // If both are arrays, check that their component types are equivalent. + if let selfArray = self.as(GenericArrayType.self), + let otherArray = other.as(GenericArrayType.self) { + return selfArray.getGenericComponentType().isEqualTo(otherArray.getGenericComponentType()) + } + + // If both are parameterized types, check their raw type and type + // arguments for equivalence. + if let selfParameterizedType = self.as(ParameterizedType.self), + let otherParameterizedType = other.as(ParameterizedType.self) { + if !selfParameterizedType.getRawType().isEqualTo(otherParameterizedType.getRawType()) { + return false + } + + return selfParameterizedType.getActualTypeArguments() + .allTypesEqual(otherParameterizedType.getActualTypeArguments()) + } + + // If both are type variables, compare their bounds. + // FIXME: This is a hack. + if let selfTypeVariable = self.as(TypeVariable.self), + let otherTypeVariable = other.as(TypeVariable.self) { + return selfTypeVariable.getBounds().allTypesEqual(otherTypeVariable.getBounds()) + } + + // If both are wildcards, compare their upper and lower bounds. + if let selfWildcard = self.as(WildcardType.self), + let otherWildcard = other.as(WildcardType.self) { + return selfWildcard.getUpperBounds().allTypesEqual(otherWildcard.getUpperBounds()) + && selfWildcard.getLowerBounds().allTypesEqual(otherWildcard.getLowerBounds()) + } + + return false + } + + /// Determine whether this type is equivalent to or a subtype of the + /// other type. + func isEqualToOrSubtypeOf(_ other: Type) -> Bool { + // First, adjust types to their bounds, if we need to. + var anyAdjusted: Bool = false + let adjustedSelf = self.adjustToJavaBounds(adjusted: &anyAdjusted) + let adjustedOther = other.adjustToJavaBounds(adjusted: &anyAdjusted) + if anyAdjusted { + return adjustedSelf.isEqualToOrSubtypeOf(adjustedOther) + } + + if isEqualTo(other) { + return true + } + + // If both are classes, check for subclassing. + if let selfClass = self.as(JavaClass.self), + let otherClass = other.as(JavaClass.self) { + // If either is a Java array, then this cannot be a subtype relationship + // in Swift. + if selfClass.isArray() || otherClass.isArray() { + return false + } + + return selfClass.isSubclass(of: otherClass) + } + + // Anything object-like is a subclass of java.lang.Object + if let otherClass = other.as(JavaClass.self), + otherClass.getName() == "java.lang.Object" { + if self.is(GenericArrayType.self) || self.is(ParameterizedType.self) || + self.is(WildcardType.self) || self.is(TypeVariable.self) { + return true + } + } + return false + } +} diff --git a/Tests/JExtractSwiftTests/FFMNestedTypesTests.swift b/Tests/JExtractSwiftTests/FFMNestedTypesTests.swift new file mode 100644 index 00000000..5bb422ea --- /dev/null +++ b/Tests/JExtractSwiftTests/FFMNestedTypesTests.swift @@ -0,0 +1,56 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import JExtractSwiftLib +import SwiftJavaConfigurationShared +import Testing + +final class FFMNestedTypesTests { + let class_interfaceFile = + """ + public enum MyNamespace { } + + extension MyNamespace { + public struct MyNestedStruct { + public func test() {} + } + } + """ + + @Test("Import: Nested type in extension MyNamespace { struct MyName {} }") + func test_nested_in_extension() throws { + var config = Configuration() + config.swiftModule = "__FakeModule" + let st = Swift2JavaTranslator(config: config) + st.log.logLevel = .error + + try st.analyze(path: "Fake.swift", text: class_interfaceFile) + + let generator = FFMSwift2JavaGenerator( + config: config, + translator: st, + javaPackage: "com.example.swift", + swiftOutputDirectory: "/fake", + javaOutputDirectory: "/fake" + ) + + guard let ty = st.importedTypes["MyNamespace.MyNestedStruct"] else { + fatalError("Didn't import nested type!") + } + + + + } + +} \ No newline at end of file diff --git a/Tests/JExtractSwiftTests/JNI/JNINestedTypesTests.swift b/Tests/JExtractSwiftTests/JNI/JNINestedTypesTests.swift index 50a0ae26..67d966e3 100644 --- a/Tests/JExtractSwiftTests/JNI/JNINestedTypesTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNINestedTypesTests.swift @@ -134,4 +134,4 @@ struct JNINestedTypesTests { ] ) } -} +} \ No newline at end of file diff --git a/Tests/JExtractSwiftTests/JNI/JNIUnsignedNumberTests.swift b/Tests/JExtractSwiftTests/JNI/JNIUnsignedNumberTests.swift index 61a94062..0833b21f 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIUnsignedNumberTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIUnsignedNumberTests.swift @@ -47,7 +47,6 @@ final class JNIUnsignedNumberTests { func jni_unsignedInt_annotate() throws { var config = Configuration() config.unsignedNumbersMode = .annotate - config.logLevel = .trace try assertOutput( input: "public func unsignedInt(_ arg: UInt32)", diff --git a/Tests/SwiftJavaToolLibTests/CompileJavaWrapTools.swift b/Tests/SwiftJavaToolLibTests/CompileJavaWrapTools.swift new file mode 100644 index 00000000..68702b62 --- /dev/null +++ b/Tests/SwiftJavaToolLibTests/CompileJavaWrapTools.swift @@ -0,0 +1,174 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +@_spi(Testing) import SwiftJava +import SwiftJavaToolLib +import JavaUtilJar +import JavaNet +import SwiftJavaShared +import SwiftJavaConfigurationShared +import _Subprocess +import XCTest // NOTE: Workaround for https://github.com/swiftlang/swift-java/issues/43 +import Foundation + +fileprivate func createTemporaryDirectory(in directory: Foundation.URL) throws -> Foundation.URL { + let uuid = UUID().uuidString + let resolverDirectoryURL = directory.appendingPathComponent("swift-java-testing-\(uuid)") + + try FileManager.default.createDirectory(at: resolverDirectoryURL, withIntermediateDirectories: true, attributes: nil) + + return resolverDirectoryURL +} + +/// Returns the directory that should be added to the classpath of the JVM to analyze the sources. +func compileJava(_ sourceText: String) async throws -> Foundation.URL { + let sourceFile = try TempFile.create(suffix: "java", sourceText) + + let classesDirectory = try createTemporaryDirectory(in: FileManager.default.temporaryDirectory) + + let javacProcess = try await _Subprocess.run( + .path(.init("\(javaHome)" + "/bin/javac")), + arguments: [ + "-d", classesDirectory.path, // output directory for .class files + sourceFile.path + ], + output: .string(limit: Int.max, encoding: UTF8.self), + error: .string(limit: Int.max, encoding: UTF8.self) + ) + + // Check if compilation was successful + guard javacProcess.terminationStatus.isSuccess else { + let outString = javacProcess.standardOutput ?? "" + let errString = javacProcess.standardError ?? "" + fatalError("javac '\(sourceFile)' failed (\(javacProcess.terminationStatus));\n" + + "OUT: \(outString)\n" + + "ERROR: \(errString)") + } + + print("Compiled java sources to: \(classesDirectory)") + return classesDirectory +} + +func withJavaTranslator( + javaClassNames: [String], + classpath: [Foundation.URL], + body: (JavaTranslator) throws -> (), + function: String = #function, + file: StaticString = #filePath, + line: UInt = #line +) throws { + print("New withJavaTranslator, for classpath: \(classpath)") + let jvm = try JavaVirtualMachine.shared( + classpath: classpath.map(\.path), + replace: true + ) + + var config = Configuration() + config.minimumInputAccessLevelMode = .package + + let environment = try jvm.environment() + let translator = JavaTranslator( + config: config, + swiftModuleName: "SwiftModule", + environment: environment, + translateAsClass: true) + + try body(translator) +} + +/// Translate a Java class and assert that the translated output contains +/// each of the expected "chunks" of text. +func assertWrapJavaOutput( + javaClassNames: [String], + classpath: [Foundation.URL], + assert assertBody: (JavaTranslator) throws -> Void = { _ in }, + expectedChunks: [String], + function: String = #function, + file: StaticString = #filePath, + line: UInt = #line +) throws { + let jvm = try JavaVirtualMachine.shared( + //classpath: classpath.map(\.path), + replace: false + ) + // Do NOT destroy the jvm here, because the JavaClasses will need to deinit, + // and do so while the env is still valid... + + var config = Configuration() + config.minimumInputAccessLevelMode = .package + + let environment = try jvm.environment() + let translator = JavaTranslator( + config: config, + swiftModuleName: "SwiftModule", + environment: environment, + translateAsClass: true) + + let classpathJavaURLs = classpath.map({ try! URL.init("\($0)/") }) // we MUST have a trailing slash for JVM to consider it a search directory + let classLoader = URLClassLoader(classpathJavaURLs, environment: environment) + + // FIXME: deduplicate this + translator.startNewFile() + + var swiftCompleteOutputText = "" + + var javaClasses: [JavaClass] = [] + for javaClassName in javaClassNames { + guard let javaClass = try! classLoader.loadClass(javaClassName) else { + fatalError("Could not load Java class '\(javaClassName)' in test \(function) @ \(file):\(line)!") + } + javaClasses.append(javaClass) + + // FIXME: deduplicate this with SwiftJava.WrapJavaCommand.runCommand !!! + // TODO: especially because nested classes + // WrapJavaCommand(). + + let swiftUnqualifiedName = javaClassName.javaClassNameToCanonicalName + .defaultSwiftNameForJavaClass + translator.translatedClasses[javaClassName] = + .init(module: nil, name: swiftUnqualifiedName) + + try translator.validateClassConfiguration() + + let swiftClassDecls = try translator.translateClass(javaClass) + let importDecls = translator.getImportDecls() + + let swiftFileText = + """ + // --------------------------------------------------------------------------- + // Auto-generated by Java-to-Swift wrapper generator. + \(importDecls.map { $0.description }.joined()) + \(swiftClassDecls.map { $0.description }.joined(separator: "\n")) + \n + """ + swiftCompleteOutputText += swiftFileText + } + + // Run any additional user defined assertions: + try assertBody(translator) + + for expectedChunk in expectedChunks { + // We make the matching in-sensitive to whitespace: + let checkAgainstText = swiftCompleteOutputText.replacing(" ", with: "") + let checkAgainstExpectedChunk = expectedChunk.replacing(" ", with: "") + +let failureMessage = "Expected chunk: \n" + + "\(expectedChunk.yellow)" + + "\n" + + "not found in:\n" + + "\(swiftCompleteOutputText)" + XCTAssertTrue(checkAgainstText.contains(checkAgainstExpectedChunk), + "\(failureMessage)") + } +} \ No newline at end of file diff --git a/Tests/SwiftJavaToolLibTests/Java2SwiftTests.swift b/Tests/SwiftJavaToolLibTests/Java2SwiftTests.swift index f251766a..e302fdc5 100644 --- a/Tests/SwiftJavaToolLibTests/Java2SwiftTests.swift +++ b/Tests/SwiftJavaToolLibTests/Java2SwiftTests.swift @@ -14,6 +14,7 @@ @_spi(Testing) import SwiftJava +import SwiftJavaConfigurationShared import SwiftJavaToolLib import XCTest // NOTE: Workaround for https://github.com/swiftlang/swift-java/issues/43 @@ -48,12 +49,12 @@ class Java2SwiftTests: XCTestCase { public struct MyJavaObject { """, """ - @JavaMethod - public func toString() -> String + @JavaMethod + public func toString() -> String """, """ - @JavaMethod - public func wait() throws + @JavaMethod + public func wait() throws """ ] ) @@ -64,7 +65,7 @@ class Java2SwiftTests: XCTestCase { JavaClass.self, swiftTypeName: "MyJavaClass", translatedClasses: [ - "java.lang.Object": ("JavaObject", nil), + "java.lang.Object": SwiftTypeName(module: nil, name: "JavaObject"), ], expectedChunks: [ "import SwiftJava", @@ -73,8 +74,8 @@ class Java2SwiftTests: XCTestCase { public struct MyJavaClass { """, """ - @JavaStaticMethod - public func forName(_ arg0: String) throws -> MyJavaClass! where ObjectType == MyJavaClass + @JavaStaticMethod + public func forName(_ arg0: String) throws -> MyJavaClass! where ObjectType == MyJavaClass """, ] ) @@ -100,12 +101,12 @@ class Java2SwiftTests: XCTestCase { if let APRIL = classObj.APRIL { self = APRIL } else { - fatalError("Enum value APRIL was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value APRIL was unexpectedly nil, please re-run swift-java on the most updated Java class") } """, """ - @JavaStaticField(isFinal: true) - public var APRIL: Month! + @JavaStaticField(isFinal: true) + public var APRIL: Month! """ ]) } @@ -115,19 +116,19 @@ class Java2SwiftTests: XCTestCase { MyArrayList.self, swiftTypeName: "JavaArrayList", translatedClasses: [ - "java.lang.Object": ("JavaObject", nil), - "java.lang.reflect.Array": ("JavaArray", nil), - "java.util.List": ("JavaList", nil), - "java.util.function.IntFunction": ("MyJavaIntFunction", nil), + "java.lang.Object": SwiftTypeName(module: nil, name: "JavaObject"), + "java.lang.reflect.Array": SwiftTypeName(module: nil, name: "JavaArray"), + "java.util.List": SwiftTypeName(module: nil, name: "JavaList"), + "java.util.function.IntFunction": SwiftTypeName(module: nil, name: "MyJavaIntFunction"), ], expectedChunks: [ """ - @JavaMethod - public func subList(_ arg0: Int32, _ arg1: Int32) -> JavaList! + @JavaMethod + public func subList(_ arg0: Int32, _ arg1: Int32) -> JavaList! """, """ - @JavaMethod - public func toArray(_ arg0: MyJavaIntFunction?) -> [JavaObject?] + @JavaMethod + public func toArray(_ arg0: MyJavaIntFunction?) -> [T?] """ ] ) @@ -138,13 +139,13 @@ class Java2SwiftTests: XCTestCase { MyLinkedList.self, swiftTypeName: "JavaLinkedList", translatedClasses: [ - "java.lang.Object": ("JavaObject", nil), - "java.util.List": ("JavaList", nil), + "java.lang.Object": SwiftTypeName(module: nil, name: "JavaObject"), + "java.util.List": SwiftTypeName(module: nil, name: "JavaList"), ], expectedChunks: [ """ - @JavaMethod - public func subList(_ arg0: Int32, _ arg1: Int32) -> JavaList! + @JavaMethod + public func subList(_ arg0: Int32, _ arg1: Int32) -> JavaList! """ ] ) @@ -155,9 +156,9 @@ class Java2SwiftTests: XCTestCase { ProcessBuilder.self, swiftTypeName: "ProcessBuilder", translatedClasses: [ - "java.lang.ProcessBuilder": ("ProcessBuilder", nil), - "java.lang.ProcessBuilder$Redirect": ("ProcessBuilder.Redirect", nil), - "java.lang.ProcessBuilder$Redirect$Type": ("ProcessBuilder.Redirect.Type", nil), + "java.lang.ProcessBuilder": SwiftTypeName(module: nil, name: "ProcessBuilder"), + "java.lang.ProcessBuilder$Redirect": SwiftTypeName(module: nil, name: "ProcessBuilder.Redirect"), + "java.lang.ProcessBuilder$Redirect$Type": SwiftTypeName(module: nil, name: "ProcessBuilder.Redirect.Type"), ], nestedClasses: [ "java.lang.ProcessBuilder": [JavaClass().as(JavaClass.self)!], @@ -166,8 +167,8 @@ class Java2SwiftTests: XCTestCase { expectedChunks: [ "import SwiftJava", """ - @JavaMethod - public func redirectInput() -> ProcessBuilder.Redirect! + @JavaMethod + public func redirectInput() -> ProcessBuilder.Redirect! """, """ extension ProcessBuilder { @@ -183,8 +184,8 @@ class Java2SwiftTests: XCTestCase { public struct Type { """, """ - @JavaMethod - public func type() -> ProcessBuilder.Redirect.`Type`! + @JavaMethod + public func type() -> ProcessBuilder.Redirect.`Type`! """, ] ) @@ -195,9 +196,9 @@ class Java2SwiftTests: XCTestCase { ProcessBuilder.self, swiftTypeName: "ProcessBuilder", translatedClasses: [ - "java.lang.ProcessBuilder": ("ProcessBuilder", nil), - "java.lang.ProcessBuilder$Redirect": ("ProcessBuilder.PBRedirect", nil), - "java.lang.ProcessBuilder$Redirect$Type": ("ProcessBuilder.PBRedirect.JavaType", nil), + "java.lang.ProcessBuilder": SwiftTypeName(module: nil, name: "ProcessBuilder"), + "java.lang.ProcessBuilder$Redirect": SwiftTypeName(module: nil, name: "ProcessBuilder.PBRedirect"), + "java.lang.ProcessBuilder$Redirect$Type": SwiftTypeName(module: nil, name: "ProcessBuilder.PBRedirect.JavaType"), ], nestedClasses: [ "java.lang.ProcessBuilder": [JavaClass().as(JavaClass.self)!], @@ -206,8 +207,8 @@ class Java2SwiftTests: XCTestCase { expectedChunks: [ "import SwiftJava", """ - @JavaMethod - public func redirectInput() -> ProcessBuilder.PBRedirect! + @JavaMethod + public func redirectInput() -> ProcessBuilder.PBRedirect! """, """ extension ProcessBuilder { @@ -223,8 +224,8 @@ class Java2SwiftTests: XCTestCase { public struct JavaType { """, """ - @JavaMethod - public func type() -> ProcessBuilder.PBRedirect.JavaType! + @JavaMethod + public func type() -> ProcessBuilder.PBRedirect.JavaType! """ ] ) @@ -248,9 +249,9 @@ class Java2SwiftTests: XCTestCase { MyObjects.self, swiftTypeName: "MyJavaObjects", translatedClasses: [ - "java.lang.Object" : ("JavaObject", "SwiftJava"), - "java.util.function.Supplier" : ("MySupplier", "JavaUtilFunction"), - "java.lang.String" : ("JavaString", "SwiftJava"), + "java.lang.Object" : SwiftTypeName(module: "SwiftJava", name: "JavaObject"), + "java.util.function.Supplier" : SwiftTypeName(module: "JavaUtilFunction", name: "MySupplier"), + "java.lang.String" : SwiftTypeName(module: "SwiftJava", name: "JavaString"), ], expectedChunks: [ """ @@ -261,8 +262,8 @@ class Java2SwiftTests: XCTestCase { public struct MyJavaObjects { """, """ - @JavaStaticMethod - public func requireNonNull(_ arg0: JavaObject?, _ arg1: MySupplier?) -> JavaObject! + @JavaStaticMethod + public func requireNonNull(_ arg0: T?, _ arg1: MySupplier?) -> T """, ] ) @@ -280,20 +281,20 @@ class Java2SwiftTests: XCTestCase { open class JavaObject { """, """ - @JavaMethod - @_nonoverride public convenience init(environment: JNIEnvironment? = nil) + @JavaMethod + @_nonoverride public convenience init(environment: JNIEnvironment? = nil) """, """ - @JavaMethod - open func toString() -> String + @JavaMethod + open func toString() -> String """, """ - @JavaMethod - open func wait() throws + @JavaMethod + open func wait() throws """, """ - @JavaMethod - open func clone() throws -> JavaObject! + @JavaMethod + open func clone() throws -> JavaObject! """, ] ) @@ -305,7 +306,7 @@ class Java2SwiftTests: XCTestCase { swiftTypeName: "JavaString", asClass: true, translatedClasses: [ - "java.lang.Object" : ("JavaObject", "SwiftJava"), + "java.lang.Object" : SwiftTypeName(module: "SwiftJava", name: "JavaObject"), ], expectedChunks: [ "import SwiftJava", @@ -314,24 +315,24 @@ class Java2SwiftTests: XCTestCase { open class JavaString: JavaObject { """, """ - @JavaMethod - @_nonoverride public convenience init(environment: JNIEnvironment? = nil) + @JavaMethod + @_nonoverride public convenience init(environment: JNIEnvironment? = nil) """, """ - @JavaMethod - open override func toString() -> String + @JavaMethod + open override func toString() -> String """, """ - @JavaMethod - open override func equals(_ arg0: JavaObject?) -> Bool + @JavaMethod + open override func equals(_ arg0: JavaObject?) -> Bool """, """ - @JavaMethod - open func intern() -> String + @JavaMethod + open func intern() -> String """, """ - @JavaStaticMethod - public func valueOf(_ arg0: Int64) -> String + @JavaStaticMethod + public func valueOf(_ arg0: Int64) -> String """, ] ) @@ -361,12 +362,12 @@ class Java2SwiftTests: XCTestCase { if let APRIL = classObj.APRIL { self.init(javaHolder: APRIL.javaHolder) } else { - fatalError("Enum value APRIL was unexpectedly nil, please re-run Java2Swift on the most updated Java class") + fatalError("Enum value APRIL was unexpectedly nil, please re-run swift-java on the most updated Java class") } """, """ - @JavaStaticField(isFinal: true) - public var APRIL: Month! + @JavaStaticField(isFinal: true) + public var APRIL: Month! """ ]) } @@ -380,9 +381,9 @@ class Java2SwiftTests: XCTestCase { swiftTypeName: "URLClassLoader", asClass: true, translatedClasses: [ - "java.lang.Object" : ("JavaObject", "SwiftJava"), - "java.lang.ClassLoader" : ("ClassLoader", "SwiftJava"), - "java.net.URL" : ("URL", "JavaNet"), + "java.lang.Object" : SwiftTypeName(module: "SwiftJava", name: "JavaObject"), + "java.lang.ClassLoader" : SwiftTypeName(module: "SwiftJava", name: "ClassLoader"), + "java.net.URL" : SwiftTypeName(module: "JavaNet", name: "URL"), ], expectedChunks: [ "import SwiftJava", @@ -391,12 +392,12 @@ class Java2SwiftTests: XCTestCase { open class URLClassLoader: ClassLoader { """, """ - @JavaMethod - open func close() throws + @JavaMethod + open func close() throws """, """ - @JavaMethod - open override func findResource(_ arg0: String) -> URL! + @JavaMethod + open override func findResource(_ arg0: String) -> URL! """, ] ) @@ -411,8 +412,8 @@ class Java2SwiftTests: XCTestCase { swiftTypeName: "URLClassLoader", asClass: true, translatedClasses: [ - "java.lang.Object" : ("JavaObject", "SwiftJava"), - "java.net.URL" : ("URL", "JavaNet"), + "java.lang.Object": SwiftTypeName(module: "SwiftJava", name: "JavaObject"), + "java.net.URL": SwiftTypeName(module: "JavaNet", name: "URL"), ], expectedChunks: [ "import SwiftJava", @@ -421,12 +422,12 @@ class Java2SwiftTests: XCTestCase { open class URLClassLoader: JavaObject { """, """ - @JavaMethod - open func close() throws + @JavaMethod + open func close() throws """, """ - @JavaMethod - open func findResource(_ arg0: String) -> URL! + @JavaMethod + open func findResource(_ arg0: String) -> URL! """, ] ) @@ -440,9 +441,9 @@ class Java2SwiftTests: XCTestCase { swiftTypeName: "JavaByte", asClass: true, translatedClasses: [ - "java.lang.Object" : ("JavaObject", "SwiftJava"), - "java.lang.Number" : ("JavaNumber", "SwiftJava"), - "java.lang.Byte" : ("JavaByte", "SwiftJava"), + "java.lang.Object": SwiftTypeName(module: "SwiftJava", name: "JavaObject"), + "java.lang.Number": SwiftTypeName(module: "SwiftJava", name: "JavaNumber"), + "java.lang.Byte": SwiftTypeName(module: "SwiftJava", name: "JavaByte"), ], expectedChunks: [ "import SwiftJava", @@ -451,8 +452,8 @@ class Java2SwiftTests: XCTestCase { open class JavaByte: JavaNumber { """, """ - @JavaMethod - open override func equals(_ arg0: JavaObject?) -> Bool + @JavaMethod + open override func equals(_ arg0: JavaObject?) -> Bool """, ] ) @@ -464,8 +465,8 @@ class Java2SwiftTests: XCTestCase { swiftTypeName: "MyJavaIntFunction", asClass: true, translatedClasses: [ - "java.lang.Object" : ("JavaObject", "SwiftJava"), - "java.util.function.IntFunction": ("MyJavaIntFunction", nil), + "java.lang.Object" : SwiftTypeName(module: "SwiftJava", name: "JavaObject"), + "java.util.function.IntFunction": SwiftTypeName(module: nil, name: "MyJavaIntFunction"), ], expectedChunks: [ "import SwiftJava", @@ -474,8 +475,8 @@ class Java2SwiftTests: XCTestCase { public struct MyJavaIntFunction { """, """ - @JavaMethod - public func apply(_ arg0: Int32) -> JavaObject! + @JavaMethod + public func apply(_ arg0: Int32) -> R! """, ] ) @@ -487,11 +488,11 @@ class Java2SwiftTests: XCTestCase { swiftTypeName: "Method", asClass: true, translatedClasses: [ - "java.lang.Object" : ("JavaObject", "SwiftJava"), - "java.lang.Class" : ("JavaClass", "SwiftJava"), - "java.lang.reflect.Executable": ("Executable", "JavaLangReflect"), - "java.lang.reflect.Method": ("Method", "JavaLangReflect"), - "java.lang.reflect.TypeVariable" : ("TypeVariable", "JavaLangReflect"), + "java.lang.Object" : SwiftTypeName(module: "SwiftJava", name: "JavaObject"), + "java.lang.Class" : SwiftTypeName(module: "SwiftJava", name: "JavaClass"), + "java.lang.reflect.Executable": SwiftTypeName(module: "JavaLangReflect", name: "Executable"), + "java.lang.reflect.Method": SwiftTypeName(module: "JavaLangReflect", name: "Method"), + "java.lang.reflect.TypeVariable" : SwiftTypeName(module: "JavaLangReflect", name: "TypeVariable"), ], expectedChunks: [ "import JavaLangReflect", @@ -500,16 +501,16 @@ class Java2SwiftTests: XCTestCase { open class Method: Executable { """, """ - @JavaMethod - open func getTypeParameters() -> [TypeVariable?] + @JavaMethod + open func getTypeParameters() -> [TypeVariable?] """, """ - @JavaMethod - open override func getParameterTypes() -> [JavaClass?] + @JavaMethod + open override func getParameterTypes() -> [JavaClass?] """, """ - @JavaMethod - open override func getDeclaringClass() -> JavaClass! + @JavaMethod + open override func getDeclaringClass() -> JavaClass! """, ] ) @@ -521,11 +522,11 @@ class Java2SwiftTests: XCTestCase { swiftTypeName: "Constructor", asClass: true, translatedClasses: [ - "java.lang.Object" : ("JavaObject", "SwiftJava"), - "java.lang.Class" : ("JavaClass", "SwiftJava"), - "java.lang.reflect.Executable": ("Executable", "JavaLangReflect"), - "java.lang.reflect.Method": ("Method", "JavaLangReflect"), - "java.lang.reflect.TypeVariable" : ("TypeVariable", "JavaLangReflect"), + "java.lang.Object" : SwiftTypeName(module: "SwiftJava", name: "JavaObject"), + "java.lang.Class" : SwiftTypeName(module: "SwiftJava", name: "JavaClass"), + "java.lang.reflect.Executable": SwiftTypeName(module: "JavaLangReflect", name: "Executable"), + "java.lang.reflect.Method": SwiftTypeName(module: "JavaLangReflect", name: "Method"), + "java.lang.reflect.TypeVariable" : SwiftTypeName(module: "JavaLangReflect", name: "TypeVariable"), ], expectedChunks: [ "import JavaLangReflect", @@ -534,16 +535,16 @@ class Java2SwiftTests: XCTestCase { open class Constructor: Executable { """, """ - @JavaMethod - open func getTypeParameters() -> [TypeVariable>?] + @JavaMethod + open func getTypeParameters() -> [TypeVariable>?] """, """ - @JavaMethod - open override func getParameterTypes() -> [JavaClass?] + @JavaMethod + open override func getParameterTypes() -> [JavaClass?] """, """ - @JavaMethod - open override func getDeclaringClass() -> JavaClass! + @JavaMethod + open override func getDeclaringClass() -> JavaClass! """, ] ) @@ -555,10 +556,10 @@ class Java2SwiftTests: XCTestCase { swiftTypeName: "NIOByteBuffer", asClass: true, translatedClasses: [ - "java.lang.Object" : ("JavaObject", "SwiftJava"), - "java.lang.Class" : ("JavaClass", "SwiftJava"), - "java.nio.Buffer": ("NIOBuffer", "JavaNio"), - "java.nio.ByteBuffer": ("NIOByteBuffer", "JavaNio"), + "java.lang.Object": SwiftTypeName(module: "SwiftJava", name: "JavaObject"), + "java.lang.Class": SwiftTypeName(module: "SwiftJava", name: "JavaClass"), + "java.nio.Buffer": SwiftTypeName(module: "JavaNio", name: "NIOBuffer"), + "java.nio.ByteBuffer": SwiftTypeName(module: "JavaNio", name: "NIOByteBuffer"), ], expectedChunks: [ "import JavaNio", @@ -580,61 +581,58 @@ class Java2SwiftTests: XCTestCase { } @JavaClass("java.lang.ClassLoader") -public struct ClassLoader { } +fileprivate struct ClassLoader { } @JavaClass("java.security.SecureClassLoader") -public struct SecureClassLoader { } +fileprivate struct SecureClassLoader { } @JavaClass("java.net.URLClassLoader") -public struct URLClassLoader { } - +fileprivate struct URLClassLoader { } @JavaClass("java.util.ArrayList") -public struct MyArrayList { +fileprivate struct MyArrayList { } @JavaClass("java.util.LinkedList") -public struct MyLinkedList { +fileprivate struct MyLinkedList { } @JavaClass("java.lang.String") -public struct MyJavaString { +fileprivate struct MyJavaString { } @JavaClass("java.util.Objects") -public struct MyObjects { } +fileprivate struct MyObjects { } @JavaInterface("java.util.function.Supplier") -public struct MySupplier { } +fileprivate struct MySupplier { } @JavaInterface("java.util.function.IntFunction") -public struct MyJavaIntFunction { +fileprivate struct MyJavaIntFunction { } @JavaClass("java.lang.reflect.Method", extends: Executable.self) -public struct Method { +fileprivate struct Method { } @JavaClass("java.lang.reflect.Constructor", extends: Executable.self) -public struct Constructor { +fileprivate struct Constructor { } @JavaClass("java.lang.reflect.Executable") -public struct Executable { +fileprivate struct Executable { } @JavaInterface("java.lang.reflect.TypeVariable") -public struct TypeVariable { +fileprivate struct TypeVariable { } @JavaClass("java.nio.Buffer") -open class NIOBuffer: JavaObject { - +fileprivate class NIOBuffer: JavaObject { } @JavaClass("java.nio.ByteBuffer") -open class NIOByteBuffer: NIOBuffer { - +fileprivate class NIOByteBuffer: NIOBuffer { } /// Translate a Java class and assert that the translated output contains @@ -643,9 +641,8 @@ func assertTranslatedClass( _ javaType: JavaClassType.Type, swiftTypeName: String, asClass: Bool = false, - translatedClasses: [ - String: (swiftType: String, swiftModule: String?) - ] = [:], + config: Configuration = Configuration(), + translatedClasses: [String: SwiftTypeName] = [:], nestedClasses: [String: [JavaClass]] = [:], expectedChunks: [String], file: StaticString = #filePath, @@ -653,13 +650,14 @@ func assertTranslatedClass( ) throws { let environment = try jvm.environment() let translator = JavaTranslator( + config: config, swiftModuleName: "SwiftModule", environment: environment, translateAsClass: asClass ) translator.translatedClasses = translatedClasses - translator.translatedClasses[javaType.fullJavaClassName] = (swiftTypeName, nil) + translator.translatedClasses[javaType.fullJavaClassName] = SwiftTypeName(module: nil, name: swiftTypeName) translator.nestedClasses = nestedClasses translator.startNewFile() @@ -677,12 +675,22 @@ func assertTranslatedClass( \(translatedDecls.map { $0.description }.joined(separator: "\n")) """ + func normalizeWhitespace(_ text: String) -> String { + return text.components(separatedBy: .newlines) + .map { $0.trimmingCharacters(in: .whitespaces) } + .joined(separator: "\n") + } + + let normalizedSwiftFileText = normalizeWhitespace(swiftFileText) + for expectedChunk in expectedChunks { - if swiftFileText.contains(expectedChunk) { + let normalizedExpectedChunk = normalizeWhitespace(expectedChunk) + + if normalizedSwiftFileText.contains(normalizedExpectedChunk) { continue } - XCTFail("Expected chunk '\(expectedChunk)' not found in '\(swiftFileText)'", file: file, line: line) + XCTFail("Expected chunk:\n---\n\(expectedChunk.yellow)\n---\nnot found in:\n===\n\(swiftFileText)\n===", file: file, line: line) } } } diff --git a/Tests/SwiftJavaToolLibTests/JavaTranslatorTests.swift b/Tests/SwiftJavaToolLibTests/JavaTranslatorTests.swift new file mode 100644 index 00000000..9983813d --- /dev/null +++ b/Tests/SwiftJavaToolLibTests/JavaTranslatorTests.swift @@ -0,0 +1,58 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import JavaUtilJar +@_spi(Testing) import SwiftJava +import SwiftJavaConfigurationShared +import SwiftJavaShared +import SwiftJavaToolLib +import XCTest // NOTE: Workaround for https://github.com/swiftlang/swift-java/issues/43 +import _Subprocess + +class JavaTranslatorTests: XCTestCase { + + func translateGenericMethodParameters() async throws { + let classpathURL = try await compileJava( + """ + package com.example; + + class Item { + final T value; + Item(T item) { + this.value = item; + } + } + class Pair { } + + class ExampleSimpleClass { + Pair getPair( + String name, + Item key, + Item value + ) { return null; } + } + """) + + try withJavaTranslator( + javaClassNames: [ + "com.example.Item", + "com.example.Pair", + "com.example.ExampleSimpleClass", + ], + classpath: [classpathURL], + ) { translator in + + } + } +} diff --git a/Tests/SwiftJavaToolLibTests/JavaTranslatorValidationTests.swift b/Tests/SwiftJavaToolLibTests/JavaTranslatorValidationTests.swift index 220f1c61..558add20 100644 --- a/Tests/SwiftJavaToolLibTests/JavaTranslatorValidationTests.swift +++ b/Tests/SwiftJavaToolLibTests/JavaTranslatorValidationTests.swift @@ -14,15 +14,16 @@ import SwiftJavaToolLib import XCTest +import SwiftJavaConfigurationShared final class JavaTranslatorValidationTests: XCTestCase { func testValidationError() throws { - let translator = try JavaTranslator(swiftModuleName: "SwiftModule", environment: jvm.environment()) + let translator = try JavaTranslator(config: Configuration(), swiftModuleName: "SwiftModule", environment: jvm.environment()) translator.translatedClasses = [ - "TestClass": ("Class1", "Module1"), - "TestClass2": ("Class1", "Module2"), - "TestClass3": ("Class1", "Module1"), - "TestClass4": ("Class1", nil) + "TestClass": SwiftTypeName(module: "Module1", name: "Class1"), + "TestClass2": SwiftTypeName(module: "Module2", name: "Class1"), + "TestClass3": SwiftTypeName(module: "Module1", name: "Class1"), + "TestClass4": SwiftTypeName(module: nil, name: "Class1") ] XCTAssertThrowsError(try translator.validateClassConfiguration()) { error in @@ -31,7 +32,7 @@ final class JavaTranslatorValidationTests: XCTestCase { switch validationError { case .multipleClassesMappedToSameName(let swiftToJavaMapping): XCTAssertEqual(swiftToJavaMapping, [ - JavaTranslator.SwiftToJavaMapping(swiftType: .init(swiftType: "Class1", swiftModule: "Module1"), + JavaTranslator.SwiftToJavaMapping(swiftType: .init(module: "Module1", name: "Class1"), javaTypes: ["TestClass", "TestClass3"]) ]) } diff --git a/Tests/SwiftJavaToolLibTests/TempFileTools.swift b/Tests/SwiftJavaToolLibTests/TempFileTools.swift new file mode 100644 index 00000000..5b133108 --- /dev/null +++ b/Tests/SwiftJavaToolLibTests/TempFileTools.swift @@ -0,0 +1,34 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024-2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import Foundation + +/// Example demonstrating how to create a temporary file using Swift Foundation APIs +public class TempFile { + + public static func create( + suffix: String, + _ contents: String = "", + in tempDirectory: URL = FileManager.default.temporaryDirectory) throws -> URL { + let tempFileName = "tmp_\(UUID().uuidString).\(suffix)" + let tempFileURL = tempDirectory.appendingPathComponent(tempFileName) + + try contents.write(to: tempFileURL, atomically: true, encoding: .utf8) + + return tempFileURL + } + public static func delete(at fileURL: URL) throws { + try FileManager.default.removeItem(at: fileURL) + } +} \ No newline at end of file diff --git a/Tests/SwiftJavaToolLibTests/WrapJavaTests.swift b/Tests/SwiftJavaToolLibTests/WrapJavaTests.swift new file mode 100644 index 00000000..1c3d10d2 --- /dev/null +++ b/Tests/SwiftJavaToolLibTests/WrapJavaTests.swift @@ -0,0 +1,273 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +@_spi(Testing) import SwiftJava +import SwiftJavaToolLib +import JavaUtilJar +import SwiftJavaShared +import JavaNet +import SwiftJavaConfigurationShared +import _Subprocess +import XCTest // NOTE: Workaround for https://github.com/swiftlang/swift-java/issues/43 + +final class WrapJavaTests: XCTestCase { + + func testWrapJavaFromCompiledJavaSource() async throws { + let classpathURL = try await compileJava( + """ + package com.example; + + class ExampleSimpleClass {} + """) + + try assertWrapJavaOutput( + javaClassNames: [ + "com.example.ExampleSimpleClass" + ], + classpath: [classpathURL], + expectedChunks: [ + """ + import CSwiftJavaJNI + import SwiftJava + """, + """ + @JavaClass("com.example.ExampleSimpleClass") + open class ExampleSimpleClass: JavaObject { + """ + ] + ) + } + + // @Test + func testWrapJavaGenericMethod_singleGeneric() async throws { + let classpathURL = try await compileJava( + """ + package com.example; + + class Item { + final T value; + Item(T item) { + this.value = item; + } + } + class Pair { } + + class ExampleSimpleClass { + KeyType getGeneric(Item key) { return null; } + } + """) + + try assertWrapJavaOutput( + javaClassNames: [ + "com.example.Item", + "com.example.Pair", + "com.example.ExampleSimpleClass" + ], + classpath: [classpathURL], + expectedChunks: [ + """ + import CSwiftJavaJNI + import SwiftJava + """, + """ + @JavaClass("com.example.Pair") + open class Pair: JavaObject { + """, + """ + @JavaClass("com.example.ExampleSimpleClass") + open class ExampleSimpleClass: JavaObject { + """, + """ + @JavaMethod + open func getGeneric(_ arg0: Item?) -> KeyType + """, + ] + ) + } + + // This is just a warning in Java, but a hard error in Swift, so we must 'prune' generic params + func testWrapJavaGenericMethod_pruneNotUsedGenericParam() async throws { + let classpathURL = try await compileJava( + """ + package com.example; + + class Item { + final T value; + Item(T item) { + this.value = item; + } + } + class Pair { } + + final class ExampleSimpleClass { + // use in return type + KeyType getGeneric() { + return null; + } + } + """) + + try assertWrapJavaOutput( + javaClassNames: [ + "com.example.Item", + "com.example.Pair", + "com.example.ExampleSimpleClass" + ], + classpath: [classpathURL], + expectedChunks: [ + """ + @JavaMethod + open func getGeneric() -> KeyType + """, + ] + ) + } + + func testWrapJavaGenericMethod_multipleGenerics() async throws { + let classpathURL = try await compileJava( + """ + package com.example; + + class Item { + final T value; + Item(T item) { + this.value = item; + } + } + class Pair { } + + class ExampleSimpleClass { + Pair getPair(String name, Item key, Item value) { return null; } + } + """) + + try assertWrapJavaOutput( + javaClassNames: [ + "com.example.Item", + "com.example.Pair", + "com.example.ExampleSimpleClass" + ], + classpath: [classpathURL], + expectedChunks: [ + """ + import CSwiftJavaJNI + import SwiftJava + """, + """ + @JavaClass("com.example.Item") + open class Item: JavaObject { + """, + """ + @JavaClass("com.example.Pair") + open class Pair: JavaObject { + """, + """ + @JavaClass("com.example.ExampleSimpleClass") + open class ExampleSimpleClass: JavaObject { + """, + """ + @JavaMethod + open func getPair(_ arg0: String, _ arg1: Item?, _ arg2: Item?) -> Pair! + """, + ] + ) + } + + func test_Java2Swift_returnType_generic() async throws { + let classpathURL = try await compileJava( + """ + package com.example; + + final class List {} + final class Map {} + + class GenericClass { + public T getClassGeneric() { return null; } + + public M getMethodGeneric() { return null; } + + public Map getMixedGeneric() { return null; } + + public String getNonGeneric() { return null; } + + public List getParameterizedClassGeneric() { return null; } + + public List getWildcard() { return null; } + + public T[] getGenericArray() { return null; } + } + """) + + try assertWrapJavaOutput( + javaClassNames: [ + "com.example.GenericClass", + ], + classpath: [classpathURL], + expectedChunks: [ + """ + @JavaMethod + open func getClassGeneric() -> T + """, + """ + @JavaMethod + open func getNonGeneric() -> String + """, + ] + ) + } + + func testGenericSuperclass() async throws { + return // FIXME: we need this + + let classpathURL = try await compileJava( + """ + package com.example; + + class ByteArray {} + class CompressingStore extends AbstractStore {} + abstract class AbstractStore {} // implements Store {} + // interface Store {} + + """) + + try assertWrapJavaOutput( + javaClassNames: [ + "com.example.ByteArray", + // TODO: what if we visit in other order, does the wrap-java handle it + // "com.example.Store", + "com.example.AbstractStore", + "com.example.CompressingStore", + ], + classpath: [classpathURL], + expectedChunks: [ + """ + import CSwiftJavaJNI + import SwiftJava + """, + """ + @JavaClass("com.example.ByteArray") + open class ByteArray: JavaObject { + """, + // """ + // @JavaInterface("com.example.Store") + // public struct Store { + // """, + """ + @JavaClass("com.example.CompressingStore") + open class CompressingStore: AbstractStore { + """ + ] + ) + } +} From 542090ecfd36dd4dc31334c58d902eb327c40203 Mon Sep 17 00:00:00 2001 From: Konrad Malawski Date: Wed, 12 Nov 2025 20:56:33 +0900 Subject: [PATCH 394/426] Improve Optional handling, and generic get() -> T --- Samples/JavaKitSampleApp/Package.swift | 11 ++++ .../example/swift/ThreadSafeHelperClass.java | 16 +++++- .../JavaKitOptionalTests.swift | 56 +++++++++++++++++++ Samples/JavaKitSampleApp/ci-validate.sh | 4 +- Sources/SwiftJava/AnyJavaObject.swift | 6 +- .../SwiftJava/JavaObject+Inheritance.swift | 18 +++--- Sources/SwiftJava/JavaString+Extensions.swift | 34 +++++++++++ Sources/SwiftJava/Macros.swift | 4 +- Sources/SwiftJava/Optional+JavaOptional.swift | 14 +++++ Sources/SwiftJava/String+Extensions.swift | 4 -- .../SwiftJava/generated/JavaOptional.swift | 4 +- Sources/SwiftJavaMacros/JavaMethodMacro.swift | 52 +++++++++++++++-- .../JavaClassMacroTests.swift | 34 +++++++++++ 13 files changed, 232 insertions(+), 25 deletions(-) create mode 100644 Samples/JavaKitSampleApp/Tests/JavaKitExampleTests/JavaKitOptionalTests.swift create mode 100644 Sources/SwiftJava/JavaString+Extensions.swift diff --git a/Samples/JavaKitSampleApp/Package.swift b/Samples/JavaKitSampleApp/Package.swift index 881b8d0b..082d61ac 100644 --- a/Samples/JavaKitSampleApp/Package.swift +++ b/Samples/JavaKitSampleApp/Package.swift @@ -78,5 +78,16 @@ let package = Package( .plugin(name: "SwiftJavaPlugin", package: "swift-java"), ] ), + + .testTarget( + name: "JavaKitExampleTests", + dependencies: [ + "JavaKitExample" + ], + swiftSettings: [ + .swiftLanguageMode(.v5), + .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]) + ] + ), ] ) diff --git a/Samples/JavaKitSampleApp/Sources/JavaKitExample/com/example/swift/ThreadSafeHelperClass.java b/Samples/JavaKitSampleApp/Sources/JavaKitExample/com/example/swift/ThreadSafeHelperClass.java index 3b7793f0..38fe1a74 100644 --- a/Samples/JavaKitSampleApp/Sources/JavaKitExample/com/example/swift/ThreadSafeHelperClass.java +++ b/Samples/JavaKitSampleApp/Sources/JavaKitExample/com/example/swift/ThreadSafeHelperClass.java @@ -23,7 +23,7 @@ public class ThreadSafeHelperClass { public ThreadSafeHelperClass() { } - public Optional text = Optional.of(""); + public Optional text = Optional.of("cool string"); public final OptionalDouble val = OptionalDouble.of(2); @@ -31,6 +31,20 @@ public String getValue(Optional name) { return name.orElse(""); } + + public String getOrElse(Optional name) { + return name.orElse("or else value"); + } + + public Optional getNil() { + return Optional.empty(); + } + + // @NonNull + // public Optional getNil() { + // return Optional.empty(); + // } + public Optional getText() { return text; } diff --git a/Samples/JavaKitSampleApp/Tests/JavaKitExampleTests/JavaKitOptionalTests.swift b/Samples/JavaKitSampleApp/Tests/JavaKitExampleTests/JavaKitOptionalTests.swift new file mode 100644 index 00000000..9ed14cd0 --- /dev/null +++ b/Samples/JavaKitSampleApp/Tests/JavaKitExampleTests/JavaKitOptionalTests.swift @@ -0,0 +1,56 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import JavaKitExample + +import SwiftJava +import JavaUtilFunction +import Testing + +@Suite +struct ManglingTests { + + @Test + func methodMangling() throws { + let jvm = try! JavaVirtualMachine.shared( + classpath: [ + ".build/plugins/outputs/javakitsampleapp/JavaKitExample/destination/JavaCompilerPlugin/Java" + ] + ) + let env = try! jvm.environment() + + let helper = ThreadSafeHelperClass(environment: env) + + let text: JavaString? = helper.textOptional + #expect(#"Optional("cool string")"# == String(describing: Optional("cool string"))) + #expect(#"Optional("cool string")"# == String(describing: text)) + + // let defaultValue: String? = helper.getOrElse(JavaOptional.empty()) + // #expect(#"Optional("or else value")"# == String(describing: defaultValue)) + + let noneValue: JavaOptional = helper.getNil()! + #expect(noneValue.isPresent() == false) + #expect("\(noneValue)" == "SwiftJava.JavaOptional") + + let textFunc: JavaString? = helper.getTextOptional() + #expect(#"Optional("cool string")"# == String(describing: textFunc)) + + let doubleOpt: Double? = helper.valOptional + #expect(#"Optional(2.0)"# == String(describing: doubleOpt)) + + let longOpt: Int64? = helper.fromOptional(21 as Int32?) + #expect(#"Optional(21)"# == String(describing: longOpt)) + } + +} \ No newline at end of file diff --git a/Samples/JavaKitSampleApp/ci-validate.sh b/Samples/JavaKitSampleApp/ci-validate.sh index f453a00b..297f5c88 100755 --- a/Samples/JavaKitSampleApp/ci-validate.sh +++ b/Samples/JavaKitSampleApp/ci-validate.sh @@ -3,7 +3,9 @@ set -e set -x -swift build +swift build \ + --disable-experimental-prebuilts # FIXME: until prebuilt swift-syntax isn't broken on 6.2 anymore: https://github.com/swiftlang/swift-java/issues/418 + "$JAVA_HOME/bin/java" \ -cp .build/plugins/outputs/javakitsampleapp/JavaKitExample/destination/JavaCompilerPlugin/Java \ -Djava.library.path=.build/debug \ diff --git a/Sources/SwiftJava/AnyJavaObject.swift b/Sources/SwiftJava/AnyJavaObject.swift index bf749820..fe77bdbd 100644 --- a/Sources/SwiftJava/AnyJavaObject.swift +++ b/Sources/SwiftJava/AnyJavaObject.swift @@ -59,7 +59,11 @@ public protocol AnyJavaObjectWithCustomClassLoader: AnyJavaObject { extension AnyJavaObject { /// Retrieve the underlying Java object. public var javaThis: jobject { - javaHolder.object! + javaHolder.object! // FIXME: this is a bad idea, can be null + } + + public var javaThisOptional: jobject? { + javaHolder.object } /// Retrieve the environment in which this Java object resides. diff --git a/Sources/SwiftJava/JavaObject+Inheritance.swift b/Sources/SwiftJava/JavaObject+Inheritance.swift index f306b9c6..0ddd7944 100644 --- a/Sources/SwiftJava/JavaObject+Inheritance.swift +++ b/Sources/SwiftJava/JavaObject+Inheritance.swift @@ -22,16 +22,16 @@ extension AnyJavaObject { private func isInstanceOf( _ otherClass: OtherClass.Type ) -> jclass? { - try? otherClass.withJNIClass(in: javaEnvironment) { otherJavaClass in - if javaEnvironment.interface.IsInstanceOf( - javaEnvironment, - javaThis, - otherJavaClass - ) == 0 { - return nil - } + guard let this: jobject = javaThisOptional else { + return nil + } + + return try? otherClass.withJNIClass(in: javaEnvironment) { otherJavaClass in + if javaEnvironment.interface.IsInstanceOf(javaEnvironment, this, otherJavaClass) == 0 { + return nil + } - return otherJavaClass + return otherJavaClass } } diff --git a/Sources/SwiftJava/JavaString+Extensions.swift b/Sources/SwiftJava/JavaString+Extensions.swift new file mode 100644 index 00000000..1836777d --- /dev/null +++ b/Sources/SwiftJava/JavaString+Extensions.swift @@ -0,0 +1,34 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import CSwiftJavaJNI +import JavaTypes + +extension JavaString: CustomStringConvertible, CustomDebugStringConvertible { + public var description: String { + return toString() + } + public var debugDescription: String { + return "\"" + toString() + "\"" + } +} + +extension Optional where Wrapped == JavaString { + public var description: String { + switch self { + case .some(let value): "Optional(\(value.toString())" + case .none: "nil" + } + } +} \ No newline at end of file diff --git a/Sources/SwiftJava/Macros.swift b/Sources/SwiftJava/Macros.swift index 8e1bb86c..bda70f14 100644 --- a/Sources/SwiftJava/Macros.swift +++ b/Sources/SwiftJava/Macros.swift @@ -124,7 +124,9 @@ public macro JavaStaticField(_ javaFieldName: String? = nil, isFinal: Bool = fal /// /// corresponds to the Java constructor `HelloSwift(String name)`. @attached(body) -public macro JavaMethod() = #externalMacro(module: "SwiftJavaMacros", type: "JavaMethodMacro") +public macro JavaMethod( + genericResult: String? = nil +) = #externalMacro(module: "SwiftJavaMacros", type: "JavaMethodMacro") /// Attached macro that turns a Swift method on JavaClass into one that wraps /// a Java static method on the underlying Java class object. diff --git a/Sources/SwiftJava/Optional+JavaOptional.swift b/Sources/SwiftJava/Optional+JavaOptional.swift index c9becd58..8e3924fb 100644 --- a/Sources/SwiftJava/Optional+JavaOptional.swift +++ b/Sources/SwiftJava/Optional+JavaOptional.swift @@ -79,3 +79,17 @@ public extension Optional where Wrapped == Int64 { } } } + +extension JavaOptional { + public func empty(environment: JNIEnvironment? = nil) -> JavaOptional! { + guard let env = try? environment ?? JavaVirtualMachine.shared().environment() else { + return nil + } + + guard let opt = try? JavaClass>(environment: env).empty() else { + return nil + } + + return opt.as(JavaOptional.self) + } +} diff --git a/Sources/SwiftJava/String+Extensions.swift b/Sources/SwiftJava/String+Extensions.swift index 94fb1928..b45f60bf 100644 --- a/Sources/SwiftJava/String+Extensions.swift +++ b/Sources/SwiftJava/String+Extensions.swift @@ -13,10 +13,6 @@ //===----------------------------------------------------------------------===// import Foundation -// import SwiftJavaToolLib -// import SwiftJava -// import JavaUtilJar -// import SwiftJavaConfigurationShared extension String { /// For a String that's of the form java.util.Vector, return the "Vector" diff --git a/Sources/SwiftJava/generated/JavaOptional.swift b/Sources/SwiftJava/generated/JavaOptional.swift index 5f10005f..3ea01070 100644 --- a/Sources/SwiftJava/generated/JavaOptional.swift +++ b/Sources/SwiftJava/generated/JavaOptional.swift @@ -3,8 +3,8 @@ import CSwiftJavaJNI @JavaClass("java.util.Optional") open class JavaOptional: JavaObject { - @JavaMethod - open func get() -> JavaObject! // FIXME: Currently we do generate -> T https://github.com/swiftlang/swift-java/issues/439 + @JavaMethod(genericResult: "T") + open func get() -> T! @JavaMethod open override func equals(_ arg0: JavaObject?) -> Bool diff --git a/Sources/SwiftJavaMacros/JavaMethodMacro.swift b/Sources/SwiftJavaMacros/JavaMethodMacro.swift index db8a3b36..d265bd5f 100644 --- a/Sources/SwiftJavaMacros/JavaMethodMacro.swift +++ b/Sources/SwiftJavaMacros/JavaMethodMacro.swift @@ -47,18 +47,41 @@ extension JavaMethodMacro: BodyMacro { } guard let funcDecl = declaration.as(FunctionDeclSyntax.self) else { - fatalError("not a function") + fatalError("not a function: \(declaration)") } let isStatic = node.attributeName.trimmedDescription == "JavaStaticMethod" let funcName = funcDecl.name.text let params = funcDecl.signature.parameterClause.parameters - let resultType: String = - funcDecl.signature.returnClause.map { result in - ", resultType: \(result.type.typeReferenceString).self" - } ?? "" let paramNames = params.map { param in param.parameterName?.text ?? "" }.joined(separator: ", ") + let genericResultType: String? = + if case let .argumentList(arguments) = node.arguments, + let firstElement = arguments.first, + let stringLiteral = firstElement.expression + .as(StringLiteralExprSyntax.self), + stringLiteral.segments.count == 1, + case let .stringSegment(wrapperName)? = stringLiteral.segments.first { + "\(wrapperName)" + } else { + nil + } + + // Determine the result type + let resultType: String = + if let returnClause = funcDecl.signature.returnClause { + if let genericResultType { + // we need to type-erase the signature, because on JVM level generics are erased and we'd otherwise + // form a signature with the "concrete" type, which would not match the real byte-code level signature + // of the method we're trying to call -- which would result in a MethodNotFound exception. + ", resultType: /*type-erased:\(genericResultType)*/JavaObject?.self" + } else { + ", resultType: \(returnClause.type.typeReferenceString).self" + } + } else { + "" + } + let parametersAsArgs: String if paramNames.isEmpty { parametersAsArgs = "" @@ -70,8 +93,25 @@ extension JavaMethodMacro: BodyMacro { funcDecl.signature.effectSpecifiers?.throwsClause != nil ? "try" : "try!" + let resultSyntax: CodeBlockItemSyntax = + "\(raw: tryKeyword) dynamicJava\(raw: isStatic ? "Static" : "")MethodCall(methodName: \(literal: funcName)\(raw: parametersAsArgs)\(raw: resultType))" + + if let genericResultType { + return [ + """ + /* convert erased return value to \(raw: genericResultType) */ + if let result$ = \(resultSyntax) { + return \(raw: genericResultType)(javaThis: result$.javaThis, environment: try! JavaVirtualMachine.shared().environment()) + } else { + return nil + } + """ + ] + } + + // no return type conversions return [ - "return \(raw: tryKeyword) dynamicJava\(raw: isStatic ? "Static" : "")MethodCall(methodName: \(literal: funcName)\(raw: parametersAsArgs)\(raw: resultType))" + "return \(resultSyntax)" ] } diff --git a/Tests/SwiftJavaMacrosTests/JavaClassMacroTests.swift b/Tests/SwiftJavaMacrosTests/JavaClassMacroTests.swift index 7eead3d2..759e0cb8 100644 --- a/Tests/SwiftJavaMacrosTests/JavaClassMacroTests.swift +++ b/Tests/SwiftJavaMacrosTests/JavaClassMacroTests.swift @@ -296,5 +296,39 @@ class JavaKitMacroTests: XCTestCase { macros: Self.javaKitMacros ) } + + func testJavaOptionalGenericGet() throws { + assertMacroExpansion(""" + @JavaClass("java.lang.Optional") + open class JavaOptional: JavaObject { + @JavaMethod(genericResult: "T") + open func get() -> T! + } + """, + expandedSource: """ + + open class JavaOptional: JavaObject { + open func get() -> T! { + /* convert erased return value to T */ + if let result$ = try! dynamicJavaMethodCall(methodName: "get", resultType: /*type-erased:T*/ JavaObject?.self) { + return T(javaThis: result$.javaThis, environment: try! JavaVirtualMachine.shared().environment()) + } else { + return nil + } + } + + /// The full Java class name for this Swift type. + open override class var fullJavaClassName: String { + "java.lang.Optional" + } + + public required init(javaHolder: JavaObjectHolder) { + super.init(javaHolder: javaHolder) + } + } + """, + macros: Self.javaKitMacros + ) + } } From 705563d8fb9ace63aa8deed454903ba2c6241de0 Mon Sep 17 00:00:00 2001 From: Konrad Malawski Date: Thu, 13 Nov 2025 12:18:09 +0900 Subject: [PATCH 395/426] wrap-java: generate genericResult info in @JavaMethods --- Sources/SwiftJava/Macros.swift | 16 ++++++++ .../JavaClassTranslator.swift | 37 +++++++++++++++---- .../SwiftJavaToolLibTests/WrapJavaTests.swift | 33 ++++++++++++++++- 3 files changed, 77 insertions(+), 9 deletions(-) diff --git a/Sources/SwiftJava/Macros.swift b/Sources/SwiftJava/Macros.swift index bda70f14..cc6891bb 100644 --- a/Sources/SwiftJava/Macros.swift +++ b/Sources/SwiftJava/Macros.swift @@ -123,6 +123,22 @@ public macro JavaStaticField(_ javaFieldName: String? = nil, isFinal: Bool = fal /// ``` /// /// corresponds to the Java constructor `HelloSwift(String name)`. +/// +/// ### Generics and type-erasure +/// Swift and Java differ in how they represent generics at runtime. +/// In Java, generics are type-erased and the JVM representation of generic types is erased to `java.lang.Object`. +/// Swift on the other hand, reifies types which means a `Test` in practice will be a specific type with +/// the generic substituted `Test`. This means that at runtime, calling a generic @JavaMethod needs to know +/// which of the parameters (or result type) must be subjected to type-erasure as we form the call into the Java function. +/// +/// In order to mark a generic return type you must indicate it to the @JavaMethod macro like this: +/// ```swift +/// // Java: class Test { public get(); } +/// @JavaMethod(genericResult: "T!") +/// func get() -> T! +/// ``` +/// This allows the macro to form a call into the get() method, which at runtime, will have an `java.lang.Object` +/// returning method signature, and then, convert the result to the expected `T` type on the Swift side. @attached(body) public macro JavaMethod( genericResult: String? = nil diff --git a/Sources/SwiftJavaToolLib/JavaClassTranslator.swift b/Sources/SwiftJavaToolLib/JavaClassTranslator.swift index 795639e5..9ca2a4ab 100644 --- a/Sources/SwiftJavaToolLib/JavaClassTranslator.swift +++ b/Sources/SwiftJavaToolLib/JavaClassTranslator.swift @@ -643,11 +643,8 @@ extension JavaClassTranslator { preferValueTypes: true, outerOptional: .implicitlyUnwrappedOptional ) - // let resultType = try translator.getSwiftTypeNameAsString( - // javaMethod.getGenericReturnType()!, - // preferValueTypes: true, - // outerOptional: .implicitlyUnwrappedOptional - // ) + let typeEraseGenericResultType: Bool = + isGenericJavaType(javaMethod.getGenericReturnType()) // FIXME: cleanup the checking here if resultType != "Void" && resultType != "Swift.Void" { @@ -659,9 +656,33 @@ extension JavaClassTranslator { // --- Handle other effects let throwsStr = javaMethod.throwsCheckedException ? "throws" : "" let swiftMethodName = javaMethod.getName().escapedSwiftName - let methodAttribute: AttributeSyntax = implementedInSwift - ? "" - : javaMethod.isStatic ? "@JavaStaticMethod\n" : "@JavaMethod\n"; + + // Compute the '@...JavaMethod(...)' details + let methodAttribute: AttributeSyntax + if implementedInSwift { + methodAttribute = "" + } else { + var methodAttributeStr = + if javaMethod.isStatic { + "@JavaStaticMethod" + } else { + "@JavaMethod" + } + // Do we need to record any generic information, in order to enable type-erasure for the upcalls? + var parameters: [String] = [] + if typeEraseGenericResultType { + parameters.append("genericResult: \"\(resultType)\"") + } + // TODO: generic parameters? + if !parameters.isEmpty { + methodAttributeStr += "(" + methodAttributeStr.append(parameters.joined(separator: ", ")) + methodAttributeStr += ")" + } + methodAttributeStr += "\n" + methodAttribute = "\(raw: methodAttributeStr)" + } + let accessModifier = implementedInSwift ? "" : (javaMethod.isStatic || !translateAsClass) ? "public " : "open " diff --git a/Tests/SwiftJavaToolLibTests/WrapJavaTests.swift b/Tests/SwiftJavaToolLibTests/WrapJavaTests.swift index 1c3d10d2..765a446e 100644 --- a/Tests/SwiftJavaToolLibTests/WrapJavaTests.swift +++ b/Tests/SwiftJavaToolLibTests/WrapJavaTests.swift @@ -227,7 +227,7 @@ final class WrapJavaTests: XCTestCase { ) } - func testGenericSuperclass() async throws { + func testWrapJavaGenericSuperclass() async throws { return // FIXME: we need this let classpathURL = try await compileJava( @@ -270,4 +270,35 @@ final class WrapJavaTests: XCTestCase { ] ) } + + func testWrapJavaGenericMethodTypeErasure_returnType() async throws { + let classpathURL = try await compileJava( + """ + package com.example; + + final class Kappa { + public T get() { return null; } + } + """) + + try assertWrapJavaOutput( + javaClassNames: [ + "com.example.Kappa", + ], + classpath: [classpathURL], + expectedChunks: [ + """ + import CSwiftJavaJNI + import SwiftJava + """, + """ + @JavaClass("com.example.Kappa") + open class Kappa: JavaObject { + @JavaMethod(genericResult: "T!") + open func get() -> T! + } + """ + ] + ) + } } From 42cda8cbadc93d57f9a1f819ab32f20de08d28b5 Mon Sep 17 00:00:00 2001 From: Konrad Malawski Date: Thu, 13 Nov 2025 21:06:27 +0900 Subject: [PATCH 396/426] properly handle Optional::ofNullable, de-dupe generic params; use SortedSet --- Package.swift | 2 + Sources/SwiftJava/Macros.swift | 6 +- Sources/SwiftJava/generated/JavaLong.swift | 6 +- .../generated/JavaOptionalDouble.swift | 4 +- .../JavaClassTranslator.swift | 46 ++++++++----- Sources/SwiftJavaToolLib/JavaTranslator.swift | 11 ++-- .../WrapJavaTests/BasicWrapJavaTests.swift | 52 +++++++++++++++ .../GenericsWrapJavaTests.swift} | 66 ++++++++++--------- 8 files changed, 135 insertions(+), 58 deletions(-) create mode 100644 Tests/SwiftJavaToolLibTests/WrapJavaTests/BasicWrapJavaTests.swift rename Tests/SwiftJavaToolLibTests/{WrapJavaTests.swift => WrapJavaTests/GenericsWrapJavaTests.swift} (91%) diff --git a/Package.swift b/Package.swift index 7d872795..b4c20208 100644 --- a/Package.swift +++ b/Package.swift @@ -209,6 +209,7 @@ let package = Package( .package(url: "https://github.com/apple/swift-argument-parser", from: "1.5.0"), .package(url: "https://github.com/apple/swift-system", from: "1.4.0"), .package(url: "https://github.com/apple/swift-log", from: "1.2.0"), + .package(url: "https://github.com/apple/swift-collections", .upToNextMinor(from: "1.3.0")), // primarily for ordered collections // // FIXME: swift-subprocess stopped supporting 6.0 when it moved into a package; // // we'll need to drop 6.0 as well, but currently blocked on doing so by swiftpm plugin pending design questions @@ -400,6 +401,7 @@ let package = Package( name: "SwiftJavaToolLib", dependencies: [ .product(name: "Logging", package: "swift-log"), + .product(name: "OrderedCollections", package: "swift-collections"), .product(name: "SwiftBasicFormat", package: "swift-syntax"), .product(name: "SwiftSyntax", package: "swift-syntax"), .product(name: "SwiftSyntaxBuilder", package: "swift-syntax"), diff --git a/Sources/SwiftJava/Macros.swift b/Sources/SwiftJava/Macros.swift index cc6891bb..f11c2fd3 100644 --- a/Sources/SwiftJava/Macros.swift +++ b/Sources/SwiftJava/Macros.swift @@ -150,11 +150,13 @@ public macro JavaMethod( /// The macro must be used within a specific JavaClass instance. /// /// ```swift -/// @JavaMethod +/// @JavaStaticMethod /// func sayHelloBack(_ i: Int32) -> Double /// ``` @attached(body) -public macro JavaStaticMethod() = #externalMacro(module: "SwiftJavaMacros", type: "JavaMethodMacro") +public macro JavaStaticMethod( + genericResult: String? = nil +) = #externalMacro(module: "SwiftJavaMacros", type: "JavaMethodMacro") /// Macro that marks extensions to specify that all of the @JavaMethod /// methods are implementations of Java methods spelled as `native`. diff --git a/Sources/SwiftJava/generated/JavaLong.swift b/Sources/SwiftJava/generated/JavaLong.swift index 7ea8fc09..4e993d65 100644 --- a/Sources/SwiftJava/generated/JavaLong.swift +++ b/Sources/SwiftJava/generated/JavaLong.swift @@ -140,9 +140,6 @@ extension JavaClass { @JavaStaticMethod public func decode(_ arg0: String) throws -> JavaLong! - @JavaStaticMethod - public func highestOneBit(_ arg0: Int64) -> Int64 - @JavaStaticMethod public func sum(_ arg0: Int64, _ arg1: Int64) -> Int64 @@ -158,6 +155,9 @@ extension JavaClass { @JavaStaticMethod public func toBinaryString(_ arg0: Int64) -> String + @JavaStaticMethod + public func highestOneBit(_ arg0: Int64) -> Int64 + @JavaStaticMethod public func lowestOneBit(_ arg0: Int64) -> Int64 diff --git a/Sources/SwiftJava/generated/JavaOptionalDouble.swift b/Sources/SwiftJava/generated/JavaOptionalDouble.swift index 0d0e2eae..58aa9441 100644 --- a/Sources/SwiftJava/generated/JavaOptionalDouble.swift +++ b/Sources/SwiftJava/generated/JavaOptionalDouble.swift @@ -16,10 +16,10 @@ open class JavaOptionalDouble: JavaObject { open func isEmpty() -> Bool @JavaMethod - open func isPresent() -> Bool + open func orElse(_ arg0: Double) -> Double @JavaMethod - open func orElse(_ arg0: Double) -> Double + open func isPresent() -> Bool @JavaMethod open func orElseThrow() -> Double diff --git a/Sources/SwiftJavaToolLib/JavaClassTranslator.swift b/Sources/SwiftJavaToolLib/JavaClassTranslator.swift index 9ca2a4ab..ab66004c 100644 --- a/Sources/SwiftJavaToolLib/JavaClassTranslator.swift +++ b/Sources/SwiftJavaToolLib/JavaClassTranslator.swift @@ -15,6 +15,7 @@ import SwiftJava import JavaLangReflect import SwiftSyntax +import OrderedCollections import SwiftJavaConfigurationShared import Logging @@ -606,25 +607,35 @@ extension JavaClassTranslator { return false } - /// Translates the given Java method into a Swift declaration. - package func renderMethod( - _ javaMethod: Method, - implementedInSwift: Bool, - genericParameters: [String] = [], - whereClause: String = "" - ) throws -> DeclSyntax { - // Map the generic params on the method. - var allGenericParameters = genericParameters + // TODO: make it more precise with the "origin" of the generic parameter (outer class etc) + func collectMethodGenericParameters( + genericParameters: [String], + method javaMethod: Method + ) -> OrderedSet { + var allGenericParameters = OrderedSet(genericParameters) let typeParameters = javaMethod.getTypeParameters() if typeParameters.contains(where: {$0 != nil }) { - allGenericParameters += typeParameters.compactMap { typeParam in + allGenericParameters.appending(contentsOf: typeParameters.compactMap { typeParam in guard let typeParam else { return nil } guard genericParameterIsUsedInSignature(typeParam, in: javaMethod) else { return nil } return "\(typeParam.getTypeName()): AnyJavaObject" - } + }) } + + return allGenericParameters + } + + /// Translates the given Java method into a Swift declaration. + package func renderMethod( + _ javaMethod: Method, + implementedInSwift: Bool, + genericParameters: [String] = [], + whereClause: String = "" + ) throws -> DeclSyntax { + // Map the generic params on the method. + let allGenericParameters = collectMethodGenericParameters(genericParameters: genericParameters, method: javaMethod) let genericParameterClauseStr = if allGenericParameters.isEmpty { "" @@ -657,7 +668,7 @@ extension JavaClassTranslator { let throwsStr = javaMethod.throwsCheckedException ? "throws" : "" let swiftMethodName = javaMethod.getName().escapedSwiftName - // Compute the '@...JavaMethod(...)' details + // Compute the parameters for '@...JavaMethod(...)' let methodAttribute: AttributeSyntax if implementedInSwift { methodAttribute = "" @@ -674,6 +685,7 @@ extension JavaClassTranslator { parameters.append("genericResult: \"\(resultType)\"") } // TODO: generic parameters? + if !parameters.isEmpty { methodAttributeStr += "(" methodAttributeStr.append(parameters.joined(separator: ", ")) @@ -690,6 +702,7 @@ extension JavaClassTranslator { ? "override " : "" + // FIXME: refactor this so we don't have to duplicate the method signatures if resultType.optionalWrappedType() != nil || parameters.contains(where: { $0.type.trimmedDescription.optionalWrappedType() != nil }) { let parameters = parameters.map { param -> (clause: FunctionParameterSyntax, passedArg: String) in let name = param.secondName!.trimmedDescription @@ -711,7 +724,8 @@ extension JavaClassTranslator { } - return """ + return + """ \(methodAttribute)\(raw: accessModifier)\(raw: overrideOpt)func \(raw: swiftMethodName)\(raw: genericParameterClauseStr)(\(raw: parametersStr))\(raw: throwsStr)\(raw: resultTypeStr)\(raw: whereClause) \(raw: accessModifier)\(raw: overrideOpt)func \(raw: swiftMethodName)Optional\(raw: genericParameterClauseStr)(\(raw: parameters.map(\.clause.description).joined(separator: ", ")))\(raw: throwsStr) -> \(raw: resultOptional)\(raw: whereClause) { @@ -719,7 +733,8 @@ extension JavaClassTranslator { } """ } else { - return """ + return + """ \(methodAttribute)\(raw: accessModifier)\(raw: overrideOpt)func \(raw: swiftMethodName)\(raw: genericParameterClauseStr)(\(raw: parametersStr))\(raw: throwsStr)\(raw: resultTypeStr)\(raw: whereClause) """ } @@ -900,6 +915,7 @@ struct MethodCollector { } // MARK: Utility functions + extension JavaClassTranslator { /// Determine whether this method is an override of another Java /// method. @@ -935,7 +951,7 @@ extension JavaClassTranslator { return true } } catch { - // FIXME: logging + log.warning("Failed to determine if method '\(method)' is an override, error: \(error)") } } diff --git a/Sources/SwiftJavaToolLib/JavaTranslator.swift b/Sources/SwiftJavaToolLib/JavaTranslator.swift index 71e01179..3fcd9a6d 100644 --- a/Sources/SwiftJavaToolLib/JavaTranslator.swift +++ b/Sources/SwiftJavaToolLib/JavaTranslator.swift @@ -138,12 +138,11 @@ extension JavaTranslator { // Special handle the case when the return type is the generic type of the method: ` T foo()` - // if isGenericJavaType(genericReturnType) { - // print("[swift] generic method! \(method.getDeclaringClass().getName()).\(method.getName())") - // getGenericJavaTypeOriginInfo(genericReturnType, from: method) - // } - - return try getSwiftTypeNameAsString(method: method, genericReturnType!, preferValueTypes: preferValueTypes, outerOptional: outerOptional) + return try getSwiftTypeNameAsString( + method: method, + genericReturnType!, + preferValueTypes: preferValueTypes, + outerOptional: outerOptional) } /// Turn a Java type into a string. diff --git a/Tests/SwiftJavaToolLibTests/WrapJavaTests/BasicWrapJavaTests.swift b/Tests/SwiftJavaToolLibTests/WrapJavaTests/BasicWrapJavaTests.swift new file mode 100644 index 00000000..d4596c90 --- /dev/null +++ b/Tests/SwiftJavaToolLibTests/WrapJavaTests/BasicWrapJavaTests.swift @@ -0,0 +1,52 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +@_spi(Testing) import SwiftJava +import SwiftJavaToolLib +import JavaUtilJar +import SwiftJavaShared +import JavaNet +import SwiftJavaConfigurationShared +import _Subprocess +import XCTest // NOTE: Workaround for https://github.com/swiftlang/swift-java/issues/43 + +final class BasicWrapJavaTests: XCTestCase { + + func testWrapJavaFromCompiledJavaSource() async throws { + let classpathURL = try await compileJava( + """ + package com.example; + + class ExampleSimpleClass {} + """) + + try assertWrapJavaOutput( + javaClassNames: [ + "com.example.ExampleSimpleClass" + ], + classpath: [classpathURL], + expectedChunks: [ + """ + import CSwiftJavaJNI + import SwiftJava + """, + """ + @JavaClass("com.example.ExampleSimpleClass") + open class ExampleSimpleClass: JavaObject { + """ + ] + ) + } + +} \ No newline at end of file diff --git a/Tests/SwiftJavaToolLibTests/WrapJavaTests.swift b/Tests/SwiftJavaToolLibTests/WrapJavaTests/GenericsWrapJavaTests.swift similarity index 91% rename from Tests/SwiftJavaToolLibTests/WrapJavaTests.swift rename to Tests/SwiftJavaToolLibTests/WrapJavaTests/GenericsWrapJavaTests.swift index 765a446e..c20b0d62 100644 --- a/Tests/SwiftJavaToolLibTests/WrapJavaTests.swift +++ b/Tests/SwiftJavaToolLibTests/WrapJavaTests/GenericsWrapJavaTests.swift @@ -21,35 +21,8 @@ import SwiftJavaConfigurationShared import _Subprocess import XCTest // NOTE: Workaround for https://github.com/swiftlang/swift-java/issues/43 -final class WrapJavaTests: XCTestCase { +final class GenericsWrapJavaTests: XCTestCase { - func testWrapJavaFromCompiledJavaSource() async throws { - let classpathURL = try await compileJava( - """ - package com.example; - - class ExampleSimpleClass {} - """) - - try assertWrapJavaOutput( - javaClassNames: [ - "com.example.ExampleSimpleClass" - ], - classpath: [classpathURL], - expectedChunks: [ - """ - import CSwiftJavaJNI - import SwiftJava - """, - """ - @JavaClass("com.example.ExampleSimpleClass") - open class ExampleSimpleClass: JavaObject { - """ - ] - ) - } - - // @Test func testWrapJavaGenericMethod_singleGeneric() async throws { let classpathURL = try await compileJava( """ @@ -271,7 +244,7 @@ final class WrapJavaTests: XCTestCase { ) } - func testWrapJavaGenericMethodTypeErasure_returnType() async throws { + func test_wrapJava_genericMethodTypeErasure_returnType() async throws { let classpathURL = try await compileJava( """ package com.example; @@ -301,4 +274,37 @@ final class WrapJavaTests: XCTestCase { ] ) } -} + + func test_wrapJava_genericMethodTypeErasure_ofNullableOptional() async throws { + let classpathURL = try await compileJava( + """ + package com.example; + + final class Optional { + public static Optional ofNullable(T value) { return null; } + } + """) + + try assertWrapJavaOutput( + javaClassNames: [ + "com.example.Optional" + ], + classpath: [classpathURL], + expectedChunks: [ + """ + @JavaClass("com.example.Optional") + open class Optional: JavaObject { + + } + """, + """ + extension JavaClass { + @JavaStaticMethod(genericResult: "Optional!") + public func ofNullable(_ arg0: T?) -> Optional! where ObjectType == Optional + } + """ + ] + ) + } + +} \ No newline at end of file From 29f088adfcc5dbeea89d89c08b35f7e27d1d35dd Mon Sep 17 00:00:00 2001 From: Konrad Malawski Date: Thu, 13 Nov 2025 22:54:15 +0900 Subject: [PATCH 397/426] further improvements in handling type erased return types --- .../JavaClassTranslator.swift | 29 ++++++----- .../JavaGenericsSupport.swift | 22 ++++++++ Sources/SwiftJavaToolLib/JavaTranslator.swift | 1 - .../Java2SwiftTests.swift | 4 +- .../WrapJavaTests/GenericsWrapJavaTests.swift | 51 +++++++++++++++---- 5 files changed, 80 insertions(+), 27 deletions(-) diff --git a/Sources/SwiftJavaToolLib/JavaClassTranslator.swift b/Sources/SwiftJavaToolLib/JavaClassTranslator.swift index ab66004c..01c747c3 100644 --- a/Sources/SwiftJavaToolLib/JavaClassTranslator.swift +++ b/Sources/SwiftJavaToolLib/JavaClassTranslator.swift @@ -610,18 +610,19 @@ extension JavaClassTranslator { // TODO: make it more precise with the "origin" of the generic parameter (outer class etc) func collectMethodGenericParameters( genericParameters: [String], - method javaMethod: Method + method: Method ) -> OrderedSet { var allGenericParameters = OrderedSet(genericParameters) - let typeParameters = javaMethod.getTypeParameters() - if typeParameters.contains(where: {$0 != nil }) { - allGenericParameters.appending(contentsOf: typeParameters.compactMap { typeParam in - guard let typeParam else { return nil } - guard genericParameterIsUsedInSignature(typeParam, in: javaMethod) else { - return nil - } - return "\(typeParam.getTypeName()): AnyJavaObject" - }) + + let typeParameters = method.getTypeParameters() + for typeParameter in typeParameters { + guard let typeParameter else { continue } + + guard genericParameterIsUsedInSignature(typeParameter, in: method) else { + continue + } + + allGenericParameters.append("\(typeParameter.getTypeName()): AnyJavaObject") } return allGenericParameters @@ -654,8 +655,8 @@ extension JavaClassTranslator { preferValueTypes: true, outerOptional: .implicitlyUnwrappedOptional ) - let typeEraseGenericResultType: Bool = - isGenericJavaType(javaMethod.getGenericReturnType()) + let hasTypeEraseGenericResultType: Bool = + isTypeErased(javaMethod.getGenericReturnType()) // FIXME: cleanup the checking here if resultType != "Void" && resultType != "Swift.Void" { @@ -681,7 +682,7 @@ extension JavaClassTranslator { } // Do we need to record any generic information, in order to enable type-erasure for the upcalls? var parameters: [String] = [] - if typeEraseGenericResultType { + if hasTypeEraseGenericResultType { parameters.append("genericResult: \"\(resultType)\"") } // TODO: generic parameters? @@ -951,7 +952,7 @@ extension JavaClassTranslator { return true } } catch { - log.warning("Failed to determine if method '\(method)' is an override, error: \(error)") + log.debug("Failed to determine if method '\(method)' is an override, error: \(error)") } } diff --git a/Sources/SwiftJavaToolLib/JavaGenericsSupport.swift b/Sources/SwiftJavaToolLib/JavaGenericsSupport.swift index 7c781962..1d847276 100644 --- a/Sources/SwiftJavaToolLib/JavaGenericsSupport.swift +++ b/Sources/SwiftJavaToolLib/JavaGenericsSupport.swift @@ -87,3 +87,25 @@ func isGenericJavaType(_ type: Type?) -> Bool { return false } + +/// Check if a type is type-erased att runtime. +/// +/// E.g. in a method returning a generic `T` the T is type erased and must +/// be represented as a `java.lang.Object` instead. +func isTypeErased(_ type: Type?) -> Bool { + guard let type else { + return false + } + + // Check if it's a type variable (e.g., T, E, etc.) + if type.as(TypeVariable.self) != nil { + return true + } + + // Check if it's a wildcard type (e.g., ? extends Number, ? super String) + if type.as(WildcardType.self) != nil { + return true + } + + return false +} diff --git a/Sources/SwiftJavaToolLib/JavaTranslator.swift b/Sources/SwiftJavaToolLib/JavaTranslator.swift index 3fcd9a6d..1c71afda 100644 --- a/Sources/SwiftJavaToolLib/JavaTranslator.swift +++ b/Sources/SwiftJavaToolLib/JavaTranslator.swift @@ -133,7 +133,6 @@ extension JavaTranslator { preferValueTypes: Bool, outerOptional: OptionalKind ) throws -> String { - // let returnType = method.getReturnType() let genericReturnType = method.getGenericReturnType() // Special handle the case when the return type is the generic type of the method: ` T foo()` diff --git a/Tests/SwiftJavaToolLibTests/Java2SwiftTests.swift b/Tests/SwiftJavaToolLibTests/Java2SwiftTests.swift index e302fdc5..f2bf868c 100644 --- a/Tests/SwiftJavaToolLibTests/Java2SwiftTests.swift +++ b/Tests/SwiftJavaToolLibTests/Java2SwiftTests.swift @@ -262,7 +262,7 @@ class Java2SwiftTests: XCTestCase { public struct MyJavaObjects { """, """ - @JavaStaticMethod + @JavaStaticMethod(genericResult: "T!") public func requireNonNull(_ arg0: T?, _ arg1: MySupplier?) -> T """, ] @@ -475,7 +475,7 @@ class Java2SwiftTests: XCTestCase { public struct MyJavaIntFunction { """, """ - @JavaMethod + @JavaMethod(genericResult: "R!") public func apply(_ arg0: Int32) -> R! """, ] diff --git a/Tests/SwiftJavaToolLibTests/WrapJavaTests/GenericsWrapJavaTests.swift b/Tests/SwiftJavaToolLibTests/WrapJavaTests/GenericsWrapJavaTests.swift index c20b0d62..fa8f05b6 100644 --- a/Tests/SwiftJavaToolLibTests/WrapJavaTests/GenericsWrapJavaTests.swift +++ b/Tests/SwiftJavaToolLibTests/WrapJavaTests/GenericsWrapJavaTests.swift @@ -62,8 +62,8 @@ final class GenericsWrapJavaTests: XCTestCase { open class ExampleSimpleClass: JavaObject { """, """ - @JavaMethod - open func getGeneric(_ arg0: Item?) -> KeyType + @JavaMethod(genericResult: "KeyType!") + open func getGeneric(_ arg0: Item?) -> KeyType! """, ] ) @@ -100,8 +100,8 @@ final class GenericsWrapJavaTests: XCTestCase { classpath: [classpathURL], expectedChunks: [ """ - @JavaMethod - open func getGeneric() -> KeyType + @JavaMethod(genericResult: "KeyType!") + open func getGeneric() -> KeyType! """, ] ) @@ -162,8 +162,10 @@ final class GenericsWrapJavaTests: XCTestCase { """ package com.example; + // Mini decls in order to avoid warnings about some funcs we're not yet importing cleanly final class List {} final class Map {} + final class Number {} class GenericClass { public T getClassGeneric() { return null; } @@ -184,18 +186,41 @@ final class GenericsWrapJavaTests: XCTestCase { try assertWrapJavaOutput( javaClassNames: [ + "com.example.Map", + "com.example.List", + "com.example.Number", "com.example.GenericClass", ], classpath: [classpathURL], expectedChunks: [ + """ + @JavaMethod(genericResult: "T!") + open func getClassGeneric() -> T! + """, + """ + @JavaMethod(genericResult: "M!") + open func getMethodGeneric() -> M! + """, """ @JavaMethod - open func getClassGeneric() -> T + open func getMixedGeneric() -> Map! """, """ @JavaMethod open func getNonGeneric() -> String """, + """ + @JavaMethod + open func getParameterizedClassGeneric() -> List! + """, + """ + @JavaMethod + open func getWildcard() -> List! + """, + """ + @JavaMethod + open func getGenericArray() -> [T?] + """, ] ) } @@ -275,13 +300,15 @@ final class GenericsWrapJavaTests: XCTestCase { ) } - func test_wrapJava_genericMethodTypeErasure_ofNullableOptional() async throws { + func test_wrapJava_genericMethodTypeErasure_ofNullableOptional_staticMethods() async throws { let classpathURL = try await compileJava( """ package com.example; final class Optional { public static Optional ofNullable(T value) { return null; } + + public static T nonNull(T value) { return null; } } """) @@ -294,14 +321,18 @@ final class GenericsWrapJavaTests: XCTestCase { """ @JavaClass("com.example.Optional") open class Optional: JavaObject { - - } """, """ extension JavaClass { - @JavaStaticMethod(genericResult: "Optional!") - public func ofNullable(_ arg0: T?) -> Optional! where ObjectType == Optional + """, + """ + @JavaStaticMethod + public func ofNullable(_ arg0: T?) -> Optional! where ObjectType == Optional } + """, + """ + @JavaStaticMethod(genericResult: "T!") + public func nonNull(_ arg0: T?) -> T! where ObjectType == Optional """ ] ) From 78311ba2bd32871571de65361747c061ef1f8a83 Mon Sep 17 00:00:00 2001 From: Konrad Malawski Date: Thu, 13 Nov 2025 23:08:38 +0900 Subject: [PATCH 398/426] rename genericResult: param to typeErasedResult: --- Sources/SwiftJava/Macros.swift | 6 +-- .../SwiftJava/generated/JavaOptional.swift | 2 +- Sources/SwiftJavaMacros/JavaMethodMacro.swift | 10 ++++- .../JavaClassTranslator.swift | 2 +- .../JavaClassMacroTests.swift | 2 +- .../Java2SwiftTests.swift | 4 +- .../WrapJavaTests/GenericsWrapJavaTests.swift | 44 ++++++++++++++++--- 7 files changed, 55 insertions(+), 15 deletions(-) diff --git a/Sources/SwiftJava/Macros.swift b/Sources/SwiftJava/Macros.swift index f11c2fd3..eb9c4374 100644 --- a/Sources/SwiftJava/Macros.swift +++ b/Sources/SwiftJava/Macros.swift @@ -134,14 +134,14 @@ public macro JavaStaticField(_ javaFieldName: String? = nil, isFinal: Bool = fal /// In order to mark a generic return type you must indicate it to the @JavaMethod macro like this: /// ```swift /// // Java: class Test { public get(); } -/// @JavaMethod(genericResult: "T!") +/// @JavaMethod(typeErasedResult: "T!") /// func get() -> T! /// ``` /// This allows the macro to form a call into the get() method, which at runtime, will have an `java.lang.Object` /// returning method signature, and then, convert the result to the expected `T` type on the Swift side. @attached(body) public macro JavaMethod( - genericResult: String? = nil + typeErasedResult: String? = nil ) = #externalMacro(module: "SwiftJavaMacros", type: "JavaMethodMacro") /// Attached macro that turns a Swift method on JavaClass into one that wraps @@ -155,7 +155,7 @@ public macro JavaMethod( /// ``` @attached(body) public macro JavaStaticMethod( - genericResult: String? = nil + typeErasedResult: String? = nil ) = #externalMacro(module: "SwiftJavaMacros", type: "JavaMethodMacro") /// Macro that marks extensions to specify that all of the @JavaMethod diff --git a/Sources/SwiftJava/generated/JavaOptional.swift b/Sources/SwiftJava/generated/JavaOptional.swift index 3ea01070..f3b7adca 100644 --- a/Sources/SwiftJava/generated/JavaOptional.swift +++ b/Sources/SwiftJava/generated/JavaOptional.swift @@ -3,7 +3,7 @@ import CSwiftJavaJNI @JavaClass("java.util.Optional") open class JavaOptional: JavaObject { - @JavaMethod(genericResult: "T") + @JavaMethod(typeErasedResult: "T") open func get() -> T! @JavaMethod diff --git a/Sources/SwiftJavaMacros/JavaMethodMacro.swift b/Sources/SwiftJavaMacros/JavaMethodMacro.swift index d265bd5f..f992ee76 100644 --- a/Sources/SwiftJavaMacros/JavaMethodMacro.swift +++ b/Sources/SwiftJavaMacros/JavaMethodMacro.swift @@ -62,7 +62,15 @@ extension JavaMethodMacro: BodyMacro { .as(StringLiteralExprSyntax.self), stringLiteral.segments.count == 1, case let .stringSegment(wrapperName)? = stringLiteral.segments.first { - "\(wrapperName)" + // TODO: Improve this unwrapping a bit; + // Trim the trailing ! and ? from the type for purposes + // of initializing the type wrapper in the method body + if "\(wrapperName)".hasSuffix("!") || + "\(wrapperName)".hasSuffix("?") { + String("\(wrapperName)".dropLast()) + } else { + "\(wrapperName)" + } } else { nil } diff --git a/Sources/SwiftJavaToolLib/JavaClassTranslator.swift b/Sources/SwiftJavaToolLib/JavaClassTranslator.swift index 01c747c3..0f7aa45d 100644 --- a/Sources/SwiftJavaToolLib/JavaClassTranslator.swift +++ b/Sources/SwiftJavaToolLib/JavaClassTranslator.swift @@ -683,7 +683,7 @@ extension JavaClassTranslator { // Do we need to record any generic information, in order to enable type-erasure for the upcalls? var parameters: [String] = [] if hasTypeEraseGenericResultType { - parameters.append("genericResult: \"\(resultType)\"") + parameters.append("typeErasedResult: \"\(resultType)\"") } // TODO: generic parameters? diff --git a/Tests/SwiftJavaMacrosTests/JavaClassMacroTests.swift b/Tests/SwiftJavaMacrosTests/JavaClassMacroTests.swift index 759e0cb8..5cbeae16 100644 --- a/Tests/SwiftJavaMacrosTests/JavaClassMacroTests.swift +++ b/Tests/SwiftJavaMacrosTests/JavaClassMacroTests.swift @@ -301,7 +301,7 @@ class JavaKitMacroTests: XCTestCase { assertMacroExpansion(""" @JavaClass("java.lang.Optional") open class JavaOptional: JavaObject { - @JavaMethod(genericResult: "T") + @JavaMethod(typeErasedResult: "T") open func get() -> T! } """, diff --git a/Tests/SwiftJavaToolLibTests/Java2SwiftTests.swift b/Tests/SwiftJavaToolLibTests/Java2SwiftTests.swift index f2bf868c..a3b33ba7 100644 --- a/Tests/SwiftJavaToolLibTests/Java2SwiftTests.swift +++ b/Tests/SwiftJavaToolLibTests/Java2SwiftTests.swift @@ -262,7 +262,7 @@ class Java2SwiftTests: XCTestCase { public struct MyJavaObjects { """, """ - @JavaStaticMethod(genericResult: "T!") + @JavaStaticMethod(typeErasedResult: "T!") public func requireNonNull(_ arg0: T?, _ arg1: MySupplier?) -> T """, ] @@ -475,7 +475,7 @@ class Java2SwiftTests: XCTestCase { public struct MyJavaIntFunction { """, """ - @JavaMethod(genericResult: "R!") + @JavaMethod(typeErasedResult: "R!") public func apply(_ arg0: Int32) -> R! """, ] diff --git a/Tests/SwiftJavaToolLibTests/WrapJavaTests/GenericsWrapJavaTests.swift b/Tests/SwiftJavaToolLibTests/WrapJavaTests/GenericsWrapJavaTests.swift index fa8f05b6..cba7b38f 100644 --- a/Tests/SwiftJavaToolLibTests/WrapJavaTests/GenericsWrapJavaTests.swift +++ b/Tests/SwiftJavaToolLibTests/WrapJavaTests/GenericsWrapJavaTests.swift @@ -62,7 +62,7 @@ final class GenericsWrapJavaTests: XCTestCase { open class ExampleSimpleClass: JavaObject { """, """ - @JavaMethod(genericResult: "KeyType!") + @JavaMethod(typeErasedResult: "KeyType!") open func getGeneric(_ arg0: Item?) -> KeyType! """, ] @@ -100,7 +100,7 @@ final class GenericsWrapJavaTests: XCTestCase { classpath: [classpathURL], expectedChunks: [ """ - @JavaMethod(genericResult: "KeyType!") + @JavaMethod(typeErasedResult: "KeyType!") open func getGeneric() -> KeyType! """, ] @@ -194,11 +194,11 @@ final class GenericsWrapJavaTests: XCTestCase { classpath: [classpathURL], expectedChunks: [ """ - @JavaMethod(genericResult: "T!") + @JavaMethod(typeErasedResult: "T!") open func getClassGeneric() -> T! """, """ - @JavaMethod(genericResult: "M!") + @JavaMethod(typeErasedResult: "M!") open func getMethodGeneric() -> M! """, """ @@ -292,7 +292,7 @@ final class GenericsWrapJavaTests: XCTestCase { """ @JavaClass("com.example.Kappa") open class Kappa: JavaObject { - @JavaMethod(genericResult: "T!") + @JavaMethod(typeErasedResult: "T!") open func get() -> T! } """ @@ -331,11 +331,43 @@ final class GenericsWrapJavaTests: XCTestCase { } """, """ - @JavaStaticMethod(genericResult: "T!") + @JavaStaticMethod(typeErasedResult: "T!") public func nonNull(_ arg0: T?) -> T! where ObjectType == Optional """ ] ) } + + // TODO: this should be improved some more, we need to generated a `: Map` on the Swift side + func test_wrapJava_genericMethodTypeErasure_genericExtendsMap() async throws { + let classpathURL = try await compileJava( + """ + package com.example; + + final class Map {} + + final class Something { + public > M putIn(M map) { return null; } + } + """) + + try assertWrapJavaOutput( + javaClassNames: [ + "com.example.Map", + "com.example.Something", + ], + classpath: [classpathURL], + expectedChunks: [ + """ + @JavaClass("com.example.Something") + open class Something: JavaObject { + """, + """ + @JavaMethod(typeErasedResult: "M!") + open func putIn(_ arg0: M?) -> M! + """, + ] + ) + } } \ No newline at end of file From bed0e03fb89ae3ddaefa5f81a5b5bf7b7ef43e8d Mon Sep 17 00:00:00 2001 From: Konrad Malawski Date: Fri, 14 Nov 2025 12:22:19 +0900 Subject: [PATCH 399/426] Allow // comments in swift-java.config "JSON with comments" --- .../Configuration.swift | 24 +++++++++++++- .../SwiftJavaConfigurationTests.swift | 33 +++++++++++++++++++ 2 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 Tests/SwiftJavaConfigurationSharedTests/SwiftJavaConfigurationTests.swift diff --git a/Sources/SwiftJavaConfigurationShared/Configuration.swift b/Sources/SwiftJavaConfigurationShared/Configuration.swift index 0fb5494f..a840a7cf 100644 --- a/Sources/SwiftJavaConfigurationShared/Configuration.swift +++ b/Sources/SwiftJavaConfigurationShared/Configuration.swift @@ -157,15 +157,37 @@ public func readConfiguration(sourceDir: String, file: String = #fileID, line: U return try readConfiguration(configPath: configPath, file: file, line: line) } +/// Read a swift-java.config file at the specified path. +/// +/// Configuration is expected to be "JSON-with-comments". +/// Specifically "//" comments are allowed and will be trimmed before passing the rest of the config into a standard JSON parser. public func readConfiguration(configPath: URL, file: String = #fileID, line: UInt = #line) throws -> Configuration? { guard let configData = try? Data(contentsOf: configPath) else { return nil } + guard let configString = String(data: configData, encoding: .utf8) else { + return nil + } + + return try readConfiguration(string: configString, configPath: configPath) +} + +public func readConfiguration(string: String, configPath: URL?, file: String = #fileID, line: UInt = #line) throws -> Configuration? { + let cleanedConfigString = string + .split(separator: "\n") + .filter { line in + !line.trimmingCharacters(in: .whitespaces).starts(with: "//") + }.joined(separator: "\n") + + guard let configData = cleanedConfigString.data(using: .utf8) else { + return nil + } + do { return try JSONDecoder().decode(Configuration.self, from: configData) } catch { - throw ConfigurationError(message: "Failed to parse SwiftJava configuration at '\(configPath.absoluteURL)'! \(#fileID):\(#line)", error: error, + throw ConfigurationError(message: "Failed to parse SwiftJava configuration at '\(configPath.map({ $0.absoluteURL.description }) ?? "")'! \(#fileID):\(#line)", error: error, file: file, line: line) } } diff --git a/Tests/SwiftJavaConfigurationSharedTests/SwiftJavaConfigurationTests.swift b/Tests/SwiftJavaConfigurationSharedTests/SwiftJavaConfigurationTests.swift new file mode 100644 index 00000000..c9466986 --- /dev/null +++ b/Tests/SwiftJavaConfigurationSharedTests/SwiftJavaConfigurationTests.swift @@ -0,0 +1,33 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024-2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import SwiftJavaConfigurationShared +import Testing + +@Suite +struct SwiftJavaConfigurationTests { + + @Test + func parseJSONWithComments() throws { + let config = try readConfiguration(string: + """ + // some comments + { + // anywhere is ok + "classpath": "" + } + """, configPath: nil) + } +} + From 99ae03082fcdb604e3946edd2305d3ae52cedce4 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Fri, 14 Nov 2025 12:44:29 +0900 Subject: [PATCH 400/426] Remove hardcoded precondition about protobuf --- Sources/SwiftJavaToolLib/JavaTranslator+Validation.swift | 2 -- 1 file changed, 2 deletions(-) diff --git a/Sources/SwiftJavaToolLib/JavaTranslator+Validation.swift b/Sources/SwiftJavaToolLib/JavaTranslator+Validation.swift index 3a6468d5..f56d26c5 100644 --- a/Sources/SwiftJavaToolLib/JavaTranslator+Validation.swift +++ b/Sources/SwiftJavaToolLib/JavaTranslator+Validation.swift @@ -49,8 +49,6 @@ package extension JavaTranslator { package init(swiftType: SwiftTypeName, javaTypes: [JavaFullyQualifiedTypeName]) { self.swiftType = swiftType self.javaTypes = javaTypes - precondition(!javaTypes.contains("com.google.protobuf.AbstractMessage$Builder"), - "\(swiftType) mapped as \(javaTypes)\n\(CommandLine.arguments.joined(separator: " "))") // XXX } } From eb84283516c89a39c5c2c4290852f113e3b4de8d Mon Sep 17 00:00:00 2001 From: Konrad Malawski Date: Fri, 14 Nov 2025 19:20:56 +0900 Subject: [PATCH 401/426] Allow JSON5 in JSONDecoder I hadn't realized JSONDecoder has gained JSON5 support, so we don't need to do the manual // stripping and can just enable 5 mode when decoding JSON :-) --- Plugins/JavaCompilerPlugin/JavaCompilerPlugin.swift | 4 +++- .../SwiftJavaConfigurationShared/Configuration.swift | 12 ++++-------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/Plugins/JavaCompilerPlugin/JavaCompilerPlugin.swift b/Plugins/JavaCompilerPlugin/JavaCompilerPlugin.swift index f90150fd..93c358df 100644 --- a/Plugins/JavaCompilerPlugin/JavaCompilerPlugin.swift +++ b/Plugins/JavaCompilerPlugin/JavaCompilerPlugin.swift @@ -38,7 +38,9 @@ struct JavaCompilerBuildToolPlugin: BuildToolPlugin { let config: Configuration? if let configData = try? Data(contentsOf: configFile) { - config = try? JSONDecoder().decode(Configuration.self, from: configData) + let decoder = JSONDecoder() + decoder.allowsJSON5 = true + config = try? decoder.decode(Configuration.self, from: configData) } else { config = nil } diff --git a/Sources/SwiftJavaConfigurationShared/Configuration.swift b/Sources/SwiftJavaConfigurationShared/Configuration.swift index a840a7cf..493ee4bc 100644 --- a/Sources/SwiftJavaConfigurationShared/Configuration.swift +++ b/Sources/SwiftJavaConfigurationShared/Configuration.swift @@ -174,18 +174,14 @@ public func readConfiguration(configPath: URL, file: String = #fileID, line: UIn } public func readConfiguration(string: String, configPath: URL?, file: String = #fileID, line: UInt = #line) throws -> Configuration? { - let cleanedConfigString = string - .split(separator: "\n") - .filter { line in - !line.trimmingCharacters(in: .whitespaces).starts(with: "//") - }.joined(separator: "\n") - - guard let configData = cleanedConfigString.data(using: .utf8) else { + guard let configData = string.data(using: .utf8) else { return nil } do { - return try JSONDecoder().decode(Configuration.self, from: configData) + let decoder = JSONDecoder() + decoder.allowsJSON5 = true + return try decoder.decode(Configuration.self, from: configData) } catch { throw ConfigurationError(message: "Failed to parse SwiftJava configuration at '\(configPath.map({ $0.absoluteURL.description }) ?? "")'! \(#fileID):\(#line)", error: error, file: file, line: line) From 7a314a639d7375c002e3d04e713bd505d4ca8697 Mon Sep 17 00:00:00 2001 From: Konrad Malawski Date: Fri, 14 Nov 2025 19:38:56 +0900 Subject: [PATCH 402/426] add docs about swift-java.config --- .../Documentation.docc/SwiftJavaCommandLineTool.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Sources/SwiftJavaDocumentation/Documentation.docc/SwiftJavaCommandLineTool.md b/Sources/SwiftJavaDocumentation/Documentation.docc/SwiftJavaCommandLineTool.md index 32a82eb4..e600651b 100644 --- a/Sources/SwiftJavaDocumentation/Documentation.docc/SwiftJavaCommandLineTool.md +++ b/Sources/SwiftJavaDocumentation/Documentation.docc/SwiftJavaCommandLineTool.md @@ -254,3 +254,14 @@ public final class SomeModule ... { public static void globalFunction() { ... } } ``` + +### The swift-java.config file + +Many of the tools–as well as SwiftPM plugin's–behaviors can be configured using the `swift-java.config` file. + +You can refer to the ``SwiftJavaSharedConfiguration/Configuration`` struct to learn about the supported options. + +Configuration from the config files may be overriden or augmented by explicit command line parameters, +please refer to the options documentation for details on their behavior. + +> Note: **Comments in configuration**: The configuration is a JSON 5 file, which among other things allows `//` and `/* */` comments, so feel free to add line comments explaining rationale for some of the settings in youf configuration. \ No newline at end of file From 64066bfbebd379476dc3d8956e1fde307d6c58da Mon Sep 17 00:00:00 2001 From: Konrad Malawski Date: Mon, 17 Nov 2025 11:00:51 +0900 Subject: [PATCH 403/426] scripts: improve validate_docs to not add the dependency if already there --- .github/scripts/validate_docs.sh | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/scripts/validate_docs.sh b/.github/scripts/validate_docs.sh index 8ee777b0..5e553943 100755 --- a/.github/scripts/validate_docs.sh +++ b/.github/scripts/validate_docs.sh @@ -3,11 +3,17 @@ set -e set -x -cat <> Package.swift +DEPENDENCY='.package(url: "https://github.com/swiftlang/swift-docc-plugin", from: "1.0.0")' + +if grep -q "$DEPENDENCY" Package.swift; then + echo "Package.swift already contains 'swift-docc-plugin" +else + cat <> Package.swift package.dependencies.append( - .package(url: "https://github.com/swiftlang/swift-docc-plugin", from: "1.0.0") + $DEPENDENCY ) EOF +fi swift package --disable-sandbox plugin generate-documentation --target "SwiftJavaDocumentation" --warnings-as-errors --analyze From 61fa6ab10e1c7b960b4d230a28d69cd565a24f78 Mon Sep 17 00:00:00 2001 From: Konrad Malawski Date: Mon, 17 Nov 2025 11:20:39 +0900 Subject: [PATCH 404/426] resolve docs issue --- .../Documentation.docc/SwiftJavaCommandLineTool.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/SwiftJavaDocumentation/Documentation.docc/SwiftJavaCommandLineTool.md b/Sources/SwiftJavaDocumentation/Documentation.docc/SwiftJavaCommandLineTool.md index e600651b..82371383 100644 --- a/Sources/SwiftJavaDocumentation/Documentation.docc/SwiftJavaCommandLineTool.md +++ b/Sources/SwiftJavaDocumentation/Documentation.docc/SwiftJavaCommandLineTool.md @@ -259,7 +259,7 @@ public final class SomeModule ... { Many of the tools–as well as SwiftPM plugin's–behaviors can be configured using the `swift-java.config` file. -You can refer to the ``SwiftJavaSharedConfiguration/Configuration`` struct to learn about the supported options. +You can refer to the `SwiftJavaConfigurationShared/Configuration` struct to learn about the supported options. Configuration from the config files may be overriden or augmented by explicit command line parameters, please refer to the options documentation for details on their behavior. From a9add7fe8017e84fde278b58e0866f8ce6d53fd4 Mon Sep 17 00:00:00 2001 From: Konrad Malawski Date: Fri, 14 Nov 2025 15:15:17 +0900 Subject: [PATCH 405/426] wrap-java: correct importing nested types We cannot just blindly visit all getClasses() because this includes types form super classes as well. This is useful in general, but in this context we specifically want types which are nested in this exact declaration, not its parens. --- Sources/SwiftJava/String+Extensions.swift | 3 +- .../Commands/WrapJavaCommand.swift | 27 +++++++++---- .../JavaTranslator+Validation.swift | 12 ++---- .../WrapJavaTests/BasicWrapJavaTests.swift | 39 +++++++++++++++++++ 4 files changed, 64 insertions(+), 17 deletions(-) diff --git a/Sources/SwiftJava/String+Extensions.swift b/Sources/SwiftJava/String+Extensions.swift index b45f60bf..0af0de10 100644 --- a/Sources/SwiftJava/String+Extensions.swift +++ b/Sources/SwiftJava/String+Extensions.swift @@ -15,8 +15,7 @@ import Foundation extension String { - /// For a String that's of the form java.util.Vector, return the "Vector" - /// part. + /// For a String that's of the form java.util.Vector, return the "Vector" part. package var defaultSwiftNameForJavaClass: String { if let dotLoc = lastIndex(of: ".") { let afterDot = index(after: dotLoc) diff --git a/Sources/SwiftJavaTool/Commands/WrapJavaCommand.swift b/Sources/SwiftJavaTool/Commands/WrapJavaCommand.swift index ae985e77..0af1e75b 100644 --- a/Sources/SwiftJavaTool/Commands/WrapJavaCommand.swift +++ b/Sources/SwiftJavaTool/Commands/WrapJavaCommand.swift @@ -180,21 +180,24 @@ extension SwiftJava.WrapJavaCommand { // of classes to be translated if they were already specified. var allClassesToVisit = javaClasses var currentClassIndex: Int = 0 - while currentClassIndex < allClassesToVisit.count { + outerClassLoop: while currentClassIndex < allClassesToVisit.count { defer { currentClassIndex += 1 } - // The current class we're in. + // The current top-level class we're in. let currentClass = allClassesToVisit[currentClassIndex] + let currentClassName = currentClass.getName() guard let currentSwiftName = translator.translatedClasses[currentClass.getName()]?.swiftType else { continue } - // Find all of the nested classes that weren't explicitly translated - // already. - let nestedClasses: [JavaClass] = currentClass.getClasses().compactMap { nestedClass in - guard let nestedClass else { return nil } + // Find all of the nested classes that weren't explicitly translated already. + let nestedAndSuperclassNestedClasses = currentClass.getClasses() // watch out, this includes nested types from superclasses + let nestedClasses: [JavaClass] = nestedAndSuperclassNestedClasses.compactMap { nestedClass in + guard let nestedClass else { + return nil + } // If this is a local class, we're done. let javaClassName = nestedClass.getName() @@ -202,6 +205,14 @@ extension SwiftJava.WrapJavaCommand { return nil } + // We only want to visit and import types which are explicitly inside this decl, + // and NOT any of the types contained in the super classes. That would violate our "current class" + // nesting, because those are *actually* nested in the other class, not "the current one" (i.e. in a super class). + guard javaClassName.hasPrefix(currentClassName) else { + log.trace("Skip super-class nested class '\(javaClassName)', is not member of \(currentClassName). Will be visited independently.") + return nil + } + // If we have an inclusive filter, import only types from it for include in config.filterInclude ?? [] { guard javaClassName.starts(with: include) else { @@ -227,7 +238,9 @@ extension SwiftJava.WrapJavaCommand { .defaultSwiftNameForJavaClass let swiftName = "\(currentSwiftName).\(swiftUnqualifiedName)" - translator.translatedClasses[javaClassName] = SwiftTypeName(module: nil, name: swiftName) + let translatedSwiftName = SwiftTypeName(module: nil, name: swiftName) + translator.translatedClasses[javaClassName] = translatedSwiftName + log.debug("Record translated Java class '\(javaClassName)' -> \(translatedSwiftName)") return nestedClass } diff --git a/Sources/SwiftJavaToolLib/JavaTranslator+Validation.swift b/Sources/SwiftJavaToolLib/JavaTranslator+Validation.swift index f56d26c5..8071c36a 100644 --- a/Sources/SwiftJavaToolLib/JavaTranslator+Validation.swift +++ b/Sources/SwiftJavaToolLib/JavaTranslator+Validation.swift @@ -58,10 +58,10 @@ package extension JavaTranslator { package var description: String { switch self { case .multipleClassesMappedToSameName(let swiftToJavaMapping): - """ - The following Java classes were mapped to the same Swift type name: - \(swiftToJavaMapping.map(mappingDescription(mapping:)).joined(separator: "\n")) - """ + """ + The following Java classes were mapped to the same Swift type name: + \(swiftToJavaMapping.map(mappingDescription(mapping:)).joined(separator: "\n")) + """ } } @@ -72,10 +72,6 @@ package extension JavaTranslator { } } func validateClassConfiguration() throws(ValidationError) { - // for a in translatedClasses { - // print("MAPPING = \(a.key) -> \(a.value.swiftModule?.escapedSwiftName ?? "").\(a.value.swiftType.escapedSwiftName)") - // } - // Group all classes by swift name let groupedDictionary: [SwiftTypeName: [(JavaFullyQualifiedTypeName, SwiftTypeName)]] = Dictionary(grouping: translatedClasses, by: { // SwiftTypeName(swiftType: $0.value.swiftType, swiftModule: $0.value.swiftModule) diff --git a/Tests/SwiftJavaToolLibTests/WrapJavaTests/BasicWrapJavaTests.swift b/Tests/SwiftJavaToolLibTests/WrapJavaTests/BasicWrapJavaTests.swift index d4596c90..74ed3ce2 100644 --- a/Tests/SwiftJavaToolLibTests/WrapJavaTests/BasicWrapJavaTests.swift +++ b/Tests/SwiftJavaToolLibTests/WrapJavaTests/BasicWrapJavaTests.swift @@ -49,4 +49,43 @@ final class BasicWrapJavaTests: XCTestCase { ) } + func test_wrapJava_doNotDupeImportNestedClassesFromSuperclassAutomatically() async throws { + let classpathURL = try await compileJava( + """ + package com.example; + + class SuperClass { + class SuperNested {} + } + + class ExampleSimpleClass { + class SimpleNested {} + } + """) + + try assertWrapJavaOutput( + javaClassNames: [ + "com.example.SuperClass", + "com.example.SuperClass$SuperNested", + "com.example.ExampleSimpleClass", + ], + classpath: [classpathURL], + expectedChunks: [ + """ + @JavaClass("com.example.SuperClass") + open class SuperClass: JavaObject { + """, + // FIXME: the mapping configuration could be used to nest this properly but today we don't automatically? + """ + @JavaClass("com.example.SuperClass$SuperNested") + open class SuperNested: JavaObject { + """, + """ + @JavaClass("com.example.SuperClass") + open class SuperClass: JavaObject { + """, + ] + ) + } + } \ No newline at end of file From 5f7ac58f57c59b1cea36c321744519cb2ad9772d Mon Sep 17 00:00:00 2001 From: Konrad Malawski Date: Mon, 17 Nov 2025 13:38:59 +0900 Subject: [PATCH 406/426] Fix how we handle appending to empty config Also cleanup handling filtering in wrap-java a bit --- Sources/JavaStdlib/JavaIO/swift-java.config | 2 +- .../Commands/ConfigureCommand.swift | 10 ++-- .../Commands/WrapJavaCommand.swift | 55 +++++++++---------- Sources/SwiftJavaTool/CommonOptions.swift | 6 +- 4 files changed, 38 insertions(+), 35 deletions(-) diff --git a/Sources/JavaStdlib/JavaIO/swift-java.config b/Sources/JavaStdlib/JavaIO/swift-java.config index 7b40b2da..571e0216 100644 --- a/Sources/JavaStdlib/JavaIO/swift-java.config +++ b/Sources/JavaStdlib/JavaIO/swift-java.config @@ -10,10 +10,10 @@ "java.lang.Readable" : "Readable", "java.io.Writer" : "Writer", "java.io.File" : "File", + "java.io.Closeable" : "Closeable", "java.nio.file.Path" : "Path", "java.io.FileDescriptor" : "FileDescriptor", "java.nio.charset.Charset" : "Charset", - "java.io.Closeable" : "Closeable", "java.io.Flushable" : "Flushable", "java.io.Flushable" : "ByteBuffer", "java.nio.file.WatchService" : "WatchService", diff --git a/Sources/SwiftJavaTool/Commands/ConfigureCommand.swift b/Sources/SwiftJavaTool/Commands/ConfigureCommand.swift index 837d5e2f..455cb962 100644 --- a/Sources/SwiftJavaTool/Commands/ConfigureCommand.swift +++ b/Sources/SwiftJavaTool/Commands/ConfigureCommand.swift @@ -104,11 +104,11 @@ extension SwiftJava.ConfigureCommand { log.logLevel = .init(rawValue: self.logLevel.rawValue)! log.info("Run: emit configuration...") - var (amendExistingConfig, configuration) = try getBaseConfigurationForWrite() + var (amendExistingConfig, config) = try getBaseConfigurationForWrite() if !self.commonOptions.filterInclude.isEmpty { log.debug("Generate Java->Swift type mappings. Active include filters: \(self.commonOptions.filterInclude)") - } else if let filters = configuration.filterInclude, !filters.isEmpty { + } else if let filters = config.filterInclude, !filters.isEmpty { // take the package filter from the configuration file self.commonOptions.filterInclude = filters } else { @@ -124,7 +124,7 @@ extension SwiftJava.ConfigureCommand { if amendExistingConfig { log.info("Amend existing swift-java.config file...") } - configuration.classpath = classpathEntries.joined(separator: ":") // TODO: is this correct? + config.classpath = classpathEntries.joined(separator: ":") // TODO: is this correct? // Import types from all the classpath entries; // Note that we use the package level filtering, so users have some control over what gets imported. @@ -139,7 +139,7 @@ extension SwiftJava.ConfigureCommand { if entry.hasSuffix(".jar") { let jarFile = try JarFile(entry, false, environment: environment) try addJavaToSwiftMappings( - to: &configuration, + to: &config, forJar: jarFile, environment: environment ) @@ -151,7 +151,7 @@ extension SwiftJava.ConfigureCommand { } // Encode the configuration. - let contents = try configuration.renderJSON() + let contents = try config.renderJSON() // Write the file. try writeContents( diff --git a/Sources/SwiftJavaTool/Commands/WrapJavaCommand.swift b/Sources/SwiftJavaTool/Commands/WrapJavaCommand.swift index 0af1e75b..0e70ad00 100644 --- a/Sources/SwiftJavaTool/Commands/WrapJavaCommand.swift +++ b/Sources/SwiftJavaTool/Commands/WrapJavaCommand.swift @@ -66,6 +66,7 @@ extension SwiftJava { extension SwiftJava.WrapJavaCommand { mutating func runSwiftJavaCommand(config: inout Configuration) async throws { + print("self.commonOptions.filterInclude = \(self.commonOptions.filterInclude)") configure(&config.filterInclude, append: self.commonOptions.filterInclude) configure(&config.filterExclude, append: self.commonOptions.filterExclude) @@ -114,6 +115,7 @@ extension SwiftJava.WrapJavaCommand { } extension SwiftJava.WrapJavaCommand { + mutating func generateWrappers( config: Configuration, dependentConfigs: [(String, Configuration)], @@ -148,21 +150,9 @@ extension SwiftJava.WrapJavaCommand { let classLoader = try! JavaClass(environment: environment) .getSystemClassLoader()! var javaClasses: [JavaClass] = [] - eachClass: for (javaClassName, _) in config.classes ?? [:] { - - // If we have an inclusive filter, import only types from it - for include in config.filterInclude ?? [] { - guard javaClassName.starts(with: include) else { - log.info("Skip Java type: \(javaClassName) (does not match filter)") - continue - } - } - // If we have an exclude filter, check for it as well - for exclude in config.filterExclude ?? [] { - if javaClassName.starts(with: exclude) { - log.info("Skip Java type: \(javaClassName) (does match exclude filter: \(exclude))") - continue eachClass - } + for (javaClassName, _) in config.classes ?? [:] { + guard shouldImportJavaClass(javaClassName, config: config) else { + continue } log.info("Wrapping java type: \(javaClassName)") @@ -213,19 +203,8 @@ extension SwiftJava.WrapJavaCommand { return nil } - // If we have an inclusive filter, import only types from it - for include in config.filterInclude ?? [] { - guard javaClassName.starts(with: include) else { - log.info("Skip Java type: \(javaClassName) (does not match filter)") - return nil - } - } - // If we have an exclude filter, check for it as well - for exclude in config.filterExclude ?? [] { - if javaClassName.starts(with: exclude) { - log.info("Skip Java type: \(javaClassName) (does match exclude filter: \(exclude))") - return nil - } + guard shouldImportJavaClass(javaClassName, config: config) else { + return nil } // If this class has been explicitly mentioned, we're done. @@ -285,4 +264,24 @@ extension SwiftJava.WrapJavaCommand { ) } } + + private func shouldImportJavaClass(_ javaClassName: String, config: Configuration) -> Bool { + // If we have an inclusive filter, import only types from it + for include in config.filterInclude ?? [] { + guard javaClassName.starts(with: include) else { + log.info("Skip Java type: \(javaClassName) (does not match include filter: \(include))") + return false + } + } + // If we have an exclude filter, check for it as well + for exclude in config.filterExclude ?? [] { + if javaClassName.starts(with: exclude) { + log.info("Skip Java type: \(javaClassName) (does match exclude filter: \(exclude))") + return false + } + } + + // The class matches import filters, if any, and was not excluded. + return true + } } diff --git a/Sources/SwiftJavaTool/CommonOptions.swift b/Sources/SwiftJavaTool/CommonOptions.swift index ebdfdbea..c313202b 100644 --- a/Sources/SwiftJavaTool/CommonOptions.swift +++ b/Sources/SwiftJavaTool/CommonOptions.swift @@ -38,7 +38,11 @@ extension HasCommonOptions { func configure(_ setting: inout [T]?, append value: [T]?) { if let value { - setting?.append(contentsOf: value) + if setting == nil { + setting = value + } else { + setting?.append(contentsOf: value) + } } } From c8023b7bc38140d911e15edb4026bcfc61e69af3 Mon Sep 17 00:00:00 2001 From: Konrad Malawski Date: Mon, 17 Nov 2025 16:39:35 +0900 Subject: [PATCH 407/426] fix mistake in how filtering applied to wrap java --- .../SwiftJavaTool/Commands/WrapJavaCommand.swift | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/Sources/SwiftJavaTool/Commands/WrapJavaCommand.swift b/Sources/SwiftJavaTool/Commands/WrapJavaCommand.swift index 0e70ad00..51315102 100644 --- a/Sources/SwiftJavaTool/Commands/WrapJavaCommand.swift +++ b/Sources/SwiftJavaTool/Commands/WrapJavaCommand.swift @@ -267,9 +267,19 @@ extension SwiftJava.WrapJavaCommand { private func shouldImportJavaClass(_ javaClassName: String, config: Configuration) -> Bool { // If we have an inclusive filter, import only types from it - for include in config.filterInclude ?? [] { - guard javaClassName.starts(with: include) else { - log.info("Skip Java type: \(javaClassName) (does not match include filter: \(include))") + if let includes = config.filterInclude, !includes.isEmpty { + let anyIncludeFilterMatched = includes.contains { include in + if javaClassName.starts(with: include) { + // TODO: lower to trace level + log.info("Skip Java type: \(javaClassName) (does not match any include filter)") + return true + } + + return false + } + + guard anyIncludeFilterMatched else { + log.info("Skip Java type: \(javaClassName) (does not match any include filter)") return false } } From 0f65d46e02e328c165cc48f8aef4d0a8604781e8 Mon Sep 17 00:00:00 2001 From: Konrad Malawski Date: Thu, 20 Nov 2025 16:50:26 +0900 Subject: [PATCH 408/426] config: log-level should encode as string --- .../SwiftTypeInSubDirectory.swift | 0 .../Sources/MySwiftLibrary/swift-java.config | 3 +- .../swift/SwiftTypeInSubDirectoryTest.java | 71 +++++++++++++++++++ .../Sources/MySwiftLibrary/swift-java.config | 2 +- .../Configuration.swift | 17 +++-- 5 files changed, 87 insertions(+), 6 deletions(-) create mode 100644 Samples/SwiftJavaExtractFFMSampleApp/Sources/MySwiftLibrary/LibrarySubDirectory/SwiftTypeInSubDirectory.swift create mode 100644 Samples/SwiftJavaExtractFFMSampleApp/src/test/java/com/example/swift/SwiftTypeInSubDirectoryTest.java diff --git a/Samples/SwiftJavaExtractFFMSampleApp/Sources/MySwiftLibrary/LibrarySubDirectory/SwiftTypeInSubDirectory.swift b/Samples/SwiftJavaExtractFFMSampleApp/Sources/MySwiftLibrary/LibrarySubDirectory/SwiftTypeInSubDirectory.swift new file mode 100644 index 00000000..e69de29b diff --git a/Samples/SwiftJavaExtractFFMSampleApp/Sources/MySwiftLibrary/swift-java.config b/Samples/SwiftJavaExtractFFMSampleApp/Sources/MySwiftLibrary/swift-java.config index 6e5bc2af..3a76a8d8 100644 --- a/Samples/SwiftJavaExtractFFMSampleApp/Sources/MySwiftLibrary/swift-java.config +++ b/Samples/SwiftJavaExtractFFMSampleApp/Sources/MySwiftLibrary/swift-java.config @@ -1,3 +1,4 @@ { - "javaPackage": "com.example.swift" + "javaPackage": "com.example.swift", + "logLevel": "trace" } diff --git a/Samples/SwiftJavaExtractFFMSampleApp/src/test/java/com/example/swift/SwiftTypeInSubDirectoryTest.java b/Samples/SwiftJavaExtractFFMSampleApp/src/test/java/com/example/swift/SwiftTypeInSubDirectoryTest.java new file mode 100644 index 00000000..1f0464eb --- /dev/null +++ b/Samples/SwiftJavaExtractFFMSampleApp/src/test/java/com/example/swift/SwiftTypeInSubDirectoryTest.java @@ -0,0 +1,71 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package com.example.swift; + +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.swift.swiftkit.core.SwiftLibraries; +import org.swift.swiftkit.ffm.AllocatingSwiftArena; + +import java.io.File; +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.*; + +public class MySwiftClassTest { + + void checkPaths(Throwable throwable) { + var paths = SwiftLibraries.getJavaLibraryPath().split(":"); + for (var path : paths) { + Stream.of(new File(path).listFiles()) + .filter(file -> !file.isDirectory()) + .forEach((file) -> { + System.out.println(" - " + file.getPath()); + }); + } + + throw new RuntimeException(throwable); + } + + @Test + void test_MySwiftClass_voidMethod() { + try(var arena = AllocatingSwiftArena.ofConfined()) { + MySwiftClass o = MySwiftClass.init(12, 42, arena); + o.voidMethod(); + } catch (Throwable throwable) { + checkPaths(throwable); + } + } + + @Test + void test_MySwiftClass_makeIntMethod() { + try(var arena = AllocatingSwiftArena.ofConfined()) { + MySwiftClass o = MySwiftClass.init(12, 42, arena); + var got = o.makeIntMethod(); + assertEquals(12, got); + } + } + + @Test + @Disabled // TODO: Need var mangled names in interfaces + void test_MySwiftClass_property_len() { + try(var arena = AllocatingSwiftArena.ofConfined()) { + MySwiftClass o = MySwiftClass.init(12, 42, arena); + var got = o.getLen(); + assertEquals(12, got); + } + } + +} diff --git a/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/swift-java.config b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/swift-java.config index be44c2fd..3d6a1201 100644 --- a/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/swift-java.config +++ b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/swift-java.config @@ -1,5 +1,5 @@ { "javaPackage": "com.example.swift", "mode": "jni", - "logLevel": ["debug"] + "logLevel": "debug" } diff --git a/Sources/SwiftJavaConfigurationShared/Configuration.swift b/Sources/SwiftJavaConfigurationShared/Configuration.swift index 493ee4bc..661cf963 100644 --- a/Sources/SwiftJavaConfigurationShared/Configuration.swift +++ b/Sources/SwiftJavaConfigurationShared/Configuration.swift @@ -183,7 +183,10 @@ public func readConfiguration(string: String, configPath: URL?, file: String = # decoder.allowsJSON5 = true return try decoder.decode(Configuration.self, from: configData) } catch { - throw ConfigurationError(message: "Failed to parse SwiftJava configuration at '\(configPath.map({ $0.absoluteURL.description }) ?? "")'! \(#fileID):\(#line)", error: error, + throw ConfigurationError( + message: "Failed to parse SwiftJava configuration at '\(configPath.map({ $0.absoluteURL.description }) ?? "")'! \(#fileID):\(#line)", + error: error, + text: string, file: file, line: line) } } @@ -276,19 +279,21 @@ extension Configuration { public struct ConfigurationError: Error { let message: String let error: any Error + let text: String? let file: String let line: UInt - init(message: String, error: any Error, file: String = #fileID, line: UInt = #line) { + init(message: String, error: any Error, text: String?, file: String = #fileID, line: UInt = #line) { self.message = message self.error = error + self.text = text self.file = file self.line = line } } -public enum LogLevel: String, Codable, Hashable { +public enum LogLevel: String, ExpressibleByStringLiteral, Codable, Hashable { case trace = "trace" case debug = "debug" case info = "info" @@ -296,11 +301,15 @@ public enum LogLevel: String, Codable, Hashable { case warning = "warning" case error = "error" case critical = "critical" + + public init(stringLiteral value: String) { + self = LogLevel(rawValue: value) ?? .info + } } extension LogLevel { public init(from decoder: any Decoder) throws { - var container = try decoder.unkeyedContainer() + var container = try decoder.singleValueContainer() let string = try container.decode(String.self) switch string { case "trace": self = .trace From 6728fc6d7f475ffde38a01214dfddd07ec744c14 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Thu, 20 Nov 2025 16:53:29 +0900 Subject: [PATCH 409/426] Delete Samples/SwiftJavaExtractFFMSampleApp/Sources/MySwiftLibrary/LibrarySubDirectory/SwiftTypeInSubDirectory.swift --- .../LibrarySubDirectory/SwiftTypeInSubDirectory.swift | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 Samples/SwiftJavaExtractFFMSampleApp/Sources/MySwiftLibrary/LibrarySubDirectory/SwiftTypeInSubDirectory.swift diff --git a/Samples/SwiftJavaExtractFFMSampleApp/Sources/MySwiftLibrary/LibrarySubDirectory/SwiftTypeInSubDirectory.swift b/Samples/SwiftJavaExtractFFMSampleApp/Sources/MySwiftLibrary/LibrarySubDirectory/SwiftTypeInSubDirectory.swift deleted file mode 100644 index e69de29b..00000000 From 6a75aeb726e87da413b97682be2c966d8eaaabbe Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Thu, 20 Nov 2025 19:33:47 +0900 Subject: [PATCH 410/426] Delete Samples/SwiftJavaExtractFFMSampleApp/src/test/java/com/example/swift/SwiftTypeInSubDirectoryTest.java --- .../swift/SwiftTypeInSubDirectoryTest.java | 71 ------------------- 1 file changed, 71 deletions(-) delete mode 100644 Samples/SwiftJavaExtractFFMSampleApp/src/test/java/com/example/swift/SwiftTypeInSubDirectoryTest.java diff --git a/Samples/SwiftJavaExtractFFMSampleApp/src/test/java/com/example/swift/SwiftTypeInSubDirectoryTest.java b/Samples/SwiftJavaExtractFFMSampleApp/src/test/java/com/example/swift/SwiftTypeInSubDirectoryTest.java deleted file mode 100644 index 1f0464eb..00000000 --- a/Samples/SwiftJavaExtractFFMSampleApp/src/test/java/com/example/swift/SwiftTypeInSubDirectoryTest.java +++ /dev/null @@ -1,71 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of Swift.org project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -package com.example.swift; - -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import org.swift.swiftkit.core.SwiftLibraries; -import org.swift.swiftkit.ffm.AllocatingSwiftArena; - -import java.io.File; -import java.util.stream.Stream; - -import static org.junit.jupiter.api.Assertions.*; - -public class MySwiftClassTest { - - void checkPaths(Throwable throwable) { - var paths = SwiftLibraries.getJavaLibraryPath().split(":"); - for (var path : paths) { - Stream.of(new File(path).listFiles()) - .filter(file -> !file.isDirectory()) - .forEach((file) -> { - System.out.println(" - " + file.getPath()); - }); - } - - throw new RuntimeException(throwable); - } - - @Test - void test_MySwiftClass_voidMethod() { - try(var arena = AllocatingSwiftArena.ofConfined()) { - MySwiftClass o = MySwiftClass.init(12, 42, arena); - o.voidMethod(); - } catch (Throwable throwable) { - checkPaths(throwable); - } - } - - @Test - void test_MySwiftClass_makeIntMethod() { - try(var arena = AllocatingSwiftArena.ofConfined()) { - MySwiftClass o = MySwiftClass.init(12, 42, arena); - var got = o.makeIntMethod(); - assertEquals(12, got); - } - } - - @Test - @Disabled // TODO: Need var mangled names in interfaces - void test_MySwiftClass_property_len() { - try(var arena = AllocatingSwiftArena.ofConfined()) { - MySwiftClass o = MySwiftClass.init(12, 42, arena); - var got = o.getLen(); - assertEquals(12, got); - } - } - -} From 3fa3d449ec60bb524c34ed461973319ea7b10074 Mon Sep 17 00:00:00 2001 From: Mads Odgaard Date: Mon, 1 Dec 2025 08:24:05 +0100 Subject: [PATCH 411/426] Fix `allowGlobalAutomatic` mode for interfaces (#466) --- ...t2JavaGenerator+JavaBindingsPrinting.swift | 13 +++++++- .../MemoryManagementModeTests.swift | 30 +++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift index 07d23dc0..1e18cbe8 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift @@ -424,7 +424,11 @@ extension JNISwift2JavaGenerator { ) } - private func printJavaBindingWrapperMethod(_ printer: inout CodePrinter, _ decl: ImportedFunc, signaturesOnly: Bool) { + private func printJavaBindingWrapperMethod( + _ printer: inout CodePrinter, + _ decl: ImportedFunc, + signaturesOnly: Bool + ) { guard let translatedDecl = translatedDecl(for: decl) else { fatalError("Decl was not translated, \(decl)") } @@ -470,6 +474,13 @@ extension JNISwift2JavaGenerator { if let importedFunc { printDeclDocumentation(&printer, importedFunc) } + var modifiers = modifiers + + // If we are a protocol, we emit this as default method + if importedFunc?.parentType?.asNominalTypeDeclaration?.kind == .protocol { + modifiers.insert("default", at: 1) + } + printer.printBraceBlock("\(annotationsStr)\(modifiers.joined(separator: " ")) \(resultType) \(translatedDecl.name)(\(parametersStr))\(throwsClause)") { printer in let globalArenaName = "SwiftMemoryManagement.GLOBAL_SWIFT_JAVA_ARENA" let arguments = translatedDecl.translatedFunctionSignature.parameters.map(\.parameter.name) + [globalArenaName] diff --git a/Tests/JExtractSwiftTests/MemoryManagementModeTests.swift b/Tests/JExtractSwiftTests/MemoryManagementModeTests.swift index 6017c987..2228aad8 100644 --- a/Tests/JExtractSwiftTests/MemoryManagementModeTests.swift +++ b/Tests/JExtractSwiftTests/MemoryManagementModeTests.swift @@ -74,4 +74,34 @@ struct MemoryManagementModeTests { ] ) } + + @Test + func allowGlobalAutomatic_protocol() throws { + var config = Configuration() + config.memoryManagementMode = .allowGlobalAutomatic + + try assertOutput( + input: + """ + public class MyClass {} + + public protocol MyProtocol { + public func f() -> MyClass + } + """, + config: config, + .jni, .java, + detectChunkByInitialLines: 1, + expectedChunks: [ + """ + public default MyClass f() { + return f(SwiftMemoryManagement.GLOBAL_SWIFT_JAVA_ARENA); + } + """, + """ + public MyClass f(SwiftArena swiftArena$); + """ + ] + ) + } } From 6eb4705a483a1455563bf2d4f098c7c2e5e5cdf2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Bukowiecki?= Date: Mon, 1 Dec 2025 08:24:38 +0100 Subject: [PATCH 412/426] Improve readme section of Java installation from SDKMan . (#461) Co-authored-by: pelekon <13712101+pelekon@users.noreply.github.com> --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index abca3b9d..7494366e 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,12 @@ Alternatively, you can use a JDK manager like [sdkman](https://sdkman.io/install $ export JAVA_HOME="$(sdk home java current)" ``` +E.g sdkman install command: + +```bash +sdk install java 25.0.1-amzn +``` + ## Self-publish supporting Java libraries Swift-java relies on supporting libraries that are under active development and not yet published to Maven Central. To use the project, you'll need to self-publish these libraries locally so your Java project can depend on them. From 8d6365c29072f339849e8e06a2dbd10a65b96d51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Bukowiecki?= Date: Mon, 1 Dec 2025 08:26:30 +0100 Subject: [PATCH 413/426] jextract (ffm, jni): Subscripts support (#459) Co-authored-by: pelekon <13712101+pelekon@users.noreply.github.com> --- .../MySwiftLibrary/MySwiftStruct.swift | 22 ++ .../swift/swiftkitffm/MySwiftStructTest.java | 22 ++ .../MySwiftLibrary/MySwiftStruct.swift | 22 ++ .../com/example/swift/MySwiftStructTest.java | 22 ++ ...Swift2JavaGenerator+FunctionLowering.swift | 19 +- ...MSwift2JavaGenerator+JavaTranslation.swift | 4 +- Sources/JExtractSwiftLib/ImportedDecls.swift | 4 + ...ISwift2JavaGenerator+JavaTranslation.swift | 4 +- ...ift2JavaGenerator+SwiftThunkPrinting.swift | 13 ++ .../JExtractSwiftLib/Swift2JavaVisitor.swift | 151 +++++++++---- .../SwiftTypes/SwiftFunctionSignature.swift | 149 +++++++++--- .../JExtractSwiftLib/ThunkNameRegistry.swift | 4 +- .../Documentation.docc/SupportedFeatures.md | 2 +- .../FFM/FFMSubscriptsTests.swift | 212 ++++++++++++++++++ .../JNI/JNISubscriptsTests.swift | 155 +++++++++++++ 15 files changed, 717 insertions(+), 88 deletions(-) create mode 100644 Tests/JExtractSwiftTests/FFM/FFMSubscriptsTests.swift create mode 100644 Tests/JExtractSwiftTests/JNI/JNISubscriptsTests.swift diff --git a/Samples/SwiftJavaExtractFFMSampleApp/Sources/MySwiftLibrary/MySwiftStruct.swift b/Samples/SwiftJavaExtractFFMSampleApp/Sources/MySwiftLibrary/MySwiftStruct.swift index 363e0683..5b5c2d32 100644 --- a/Samples/SwiftJavaExtractFFMSampleApp/Sources/MySwiftLibrary/MySwiftStruct.swift +++ b/Samples/SwiftJavaExtractFFMSampleApp/Sources/MySwiftLibrary/MySwiftStruct.swift @@ -16,10 +16,14 @@ public struct MySwiftStruct { private var cap: Int private var len: Int + private var subscriptValue: Int + private var subscriptArray: [Int] public init(cap: Int, len: Int) { self.cap = cap self.len = len + self.subscriptValue = 0 + self.subscriptArray = [10, 20, 15, 75] } public func voidMethod() { @@ -61,4 +65,22 @@ public struct MySwiftStruct { public func makeRandomIntMethod() -> Int { return Int.random(in: 1..<256) } + + public func getSubscriptValue() -> Int { + return self.subscriptValue + } + + public func getSubscriptArrayValue(index: Int) -> Int { + return self.subscriptArray[index] + } + + public subscript() -> Int { + get { return subscriptValue } + set { subscriptValue = newValue } + } + + public subscript(index: Int) -> Int { + get { return subscriptArray[index] } + set { subscriptArray[index] = newValue } + } } diff --git a/Samples/SwiftJavaExtractFFMSampleApp/src/test/java/org/swift/swiftkitffm/MySwiftStructTest.java b/Samples/SwiftJavaExtractFFMSampleApp/src/test/java/org/swift/swiftkitffm/MySwiftStructTest.java index 6b994137..d904f7e8 100644 --- a/Samples/SwiftJavaExtractFFMSampleApp/src/test/java/org/swift/swiftkitffm/MySwiftStructTest.java +++ b/Samples/SwiftJavaExtractFFMSampleApp/src/test/java/org/swift/swiftkitffm/MySwiftStructTest.java @@ -33,4 +33,26 @@ void create_struct() { assertEquals(len, struct.getLength()); } } + + @Test + void testSubscript() { + try (var arena = AllocatingSwiftArena.ofConfined()) { + MySwiftStruct s = MySwiftStruct.init(1337, 42, arena); + long currentValue = s.getSubscript(); + s.setSubscript(66); + assertEquals(0, currentValue); + assertEquals(66, s.getSubscriptValue()); + } + } + + @Test + void testSubscriptWithParams() { + try (var arena = AllocatingSwiftArena.ofConfined()) { + MySwiftStruct s = MySwiftStruct.init(1337, 42, arena); + long currentValue = s.getSubscript(1); + s.setSubscript(1, 66); + assertEquals(20, currentValue); + assertEquals(66, s.getSubscriptArrayValue(1)); + } + } } diff --git a/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftStruct.swift b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftStruct.swift index ddd77132..34686f41 100644 --- a/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftStruct.swift +++ b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftStruct.swift @@ -15,10 +15,14 @@ public struct MySwiftStruct { private var cap: Int64 public var len: Int64 + private var subscriptValue: Int64 + private var subscriptArray: [Int64] public init(cap: Int64, len: Int64) { self.cap = cap self.len = len + self.subscriptValue = 0 + self.subscriptArray = [10, 20, 15, 75] } public init?(doInit: Bool) { @@ -38,4 +42,22 @@ public struct MySwiftStruct { self.cap += value return self.cap } + + public func getSubscriptValue() -> Int64 { + return self.subscriptValue + } + + public func getSubscriptArrayValue(index: Int64) -> Int64 { + return self.subscriptArray[Int(index)] + } + + public subscript() -> Int64 { + get { return subscriptValue } + set { subscriptValue = newValue } + } + + public subscript(index: Int64) -> Int64 { + get { return subscriptArray[Int(index)] } + set { subscriptArray[Int(index)] = newValue } + } } diff --git a/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/MySwiftStructTest.java b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/MySwiftStructTest.java index e52e1959..24b1fdbf 100644 --- a/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/MySwiftStructTest.java +++ b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/MySwiftStructTest.java @@ -61,4 +61,26 @@ void increaseCap() { assertEquals(1347, s.getCapacity()); } } + + @Test + void testSubscript() { + try (var arena = SwiftArena.ofConfined()) { + MySwiftStruct s = MySwiftStruct.init(1337, 42, arena); + long currentValue = s.getSubscript(); + s.setSubscript(66); + assertEquals(0, currentValue); + assertEquals(66, s.getSubscriptValue()); + } + } + + @Test + void testSubscriptWithParams() { + try (var arena = SwiftArena.ofConfined()) { + MySwiftStruct s = MySwiftStruct.init(1337, 42, arena); + long currentValue = s.getSubscript(1); + s.setSubscript(1, 66); + assertEquals(20, currentValue); + assertEquals(66, s.getSubscriptArrayValue(1)); + } + } } \ No newline at end of file diff --git a/Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift b/Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift index 832aff26..a7da370b 100644 --- a/Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift +++ b/Sources/JExtractSwiftLib/FFM/CDeclLowering/FFMSwift2JavaGenerator+FunctionLowering.swift @@ -812,11 +812,10 @@ extension LoweredFunctionSignature { // Build callee expression. let callee: ExprSyntax = if let selfExpr { - if case .initializer = apiKind { + switch apiKind { // Don't bother to create explicit ${Self}.init expression. - selfExpr - } else { - ExprSyntax(MemberAccessExprSyntax(base: selfExpr, name: .identifier(swiftAPIName))) + case .initializer, .subscriptGetter, .subscriptSetter: selfExpr + default: ExprSyntax(MemberAccessExprSyntax(base: selfExpr, name: .identifier(swiftAPIName))) } } else { ExprSyntax(DeclReferenceExprSyntax(baseName: .identifier(swiftAPIName))) @@ -845,6 +844,18 @@ extension LoweredFunctionSignature { case .enumCase: // This should not be called, but let's fatalError. fatalError("Enum cases are not supported with FFM.") + + case .subscriptGetter: + let parameters = paramExprs.map { $0.description }.joined(separator: ", ") + resultExpr = "\(callee)[\(raw: parameters)]" + case .subscriptSetter: + assert(paramExprs.count >= 1) + + var argumentsWithoutNewValue = paramExprs + let newValueArgument = argumentsWithoutNewValue.removeLast() + + let parameters = argumentsWithoutNewValue.map { $0.description }.joined(separator: ", ") + resultExpr = "\(callee)[\(raw: parameters)] = \(newValueArgument)" } // Lower the result. diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift index 72da323c..76284b78 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift @@ -144,8 +144,8 @@ extension FFMSwift2JavaGenerator { // Name. let javaName = switch decl.apiKind { - case .getter: decl.javaGetterName - case .setter: decl.javaSetterName + case .getter, .subscriptGetter: decl.javaGetterName + case .setter, .subscriptSetter: decl.javaSetterName case .function, .initializer, .enumCase: decl.name } diff --git a/Sources/JExtractSwiftLib/ImportedDecls.swift b/Sources/JExtractSwiftLib/ImportedDecls.swift index 9ba1cd6f..b9cc2d49 100644 --- a/Sources/JExtractSwiftLib/ImportedDecls.swift +++ b/Sources/JExtractSwiftLib/ImportedDecls.swift @@ -23,6 +23,8 @@ package enum SwiftAPIKind { case getter case setter case enumCase + case subscriptGetter + case subscriptSetter } /// Describes a Swift nominal type (e.g., a class, struct, enum) that has been @@ -179,6 +181,8 @@ public final class ImportedFunc: ImportedDecl, CustomStringConvertible { case .setter: "setter:" case .enumCase: "case:" case .function, .initializer: "" + case .subscriptGetter: "subscriptGetter:" + case .subscriptSetter: "subscriptSetter:" } let context = if let parentType { diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift index 9c3cdbf1..c8e4bbf3 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift @@ -176,8 +176,8 @@ extension JNISwift2JavaGenerator { // Name. let javaName = switch decl.apiKind { - case .getter: decl.javaGetterName - case .setter: decl.javaSetterName + case .getter, .subscriptGetter: decl.javaGetterName + case .setter, .subscriptSetter: decl.javaSetterName case .function, .initializer, .enumCase: decl.name } diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift index 91a0b0e7..d3b47732 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift @@ -348,6 +348,19 @@ extension JNISwift2JavaGenerator { } result = "\(callee).\(decl.name) = \(newValueArgument)" + case .subscriptGetter: + let parameters = arguments.joined(separator: ", ") + result = "\(callee)[\(parameters)]" + case .subscriptSetter: + guard let newValueArgument = arguments.last else { + fatalError("Setter did not contain newValue parameter: \(decl)") + } + + var argumentsWithoutNewValue = arguments + argumentsWithoutNewValue.removeLast() + + let parameters = argumentsWithoutNewValue.joined(separator: ", ") + result = "\(callee)[\(parameters)] = \(newValueArgument)" } // Lower the result. diff --git a/Sources/JExtractSwiftLib/Swift2JavaVisitor.swift b/Sources/JExtractSwiftLib/Swift2JavaVisitor.swift index 247b2662..ab1ce32f 100644 --- a/Sources/JExtractSwiftLib/Swift2JavaVisitor.swift +++ b/Sources/JExtractSwiftLib/Swift2JavaVisitor.swift @@ -13,9 +13,9 @@ //===----------------------------------------------------------------------===// import Foundation +import SwiftJavaConfigurationShared import SwiftParser import SwiftSyntax -import SwiftJavaConfigurationShared final class Swift2JavaVisitor { let translator: Swift2JavaTranslator @@ -53,9 +53,9 @@ final class Swift2JavaVisitor { case .extensionDecl(let node): self.visit(extensionDecl: node, in: parent, sourceFilePath: sourceFilePath) case .typeAliasDecl: - break // TODO: Implement; https://github.com/swiftlang/swift-java/issues/338 + break // TODO: Implement; https://github.com/swiftlang/swift-java/issues/338 case .associatedTypeDecl: - break // TODO: Implement associated types + break // TODO: Implement associated types case .initializerDecl(let node): self.visit(initializerDecl: node, in: parent) @@ -63,9 +63,8 @@ final class Swift2JavaVisitor { self.visit(functionDecl: node, in: parent, sourceFilePath: sourceFilePath) case .variableDecl(let node): self.visit(variableDecl: node, in: parent, sourceFilePath: sourceFilePath) - case .subscriptDecl: - // TODO: Implement subscripts - break + case .subscriptDecl(let node): + self.visit(subscriptDecl: node, in: parent) case .enumCaseDecl(let node): self.visit(enumCaseDecl: node, in: parent) @@ -75,7 +74,8 @@ final class Swift2JavaVisitor { } func visit( - nominalDecl node: some DeclSyntaxProtocol & DeclGroupSyntax & NamedDeclSyntax & WithAttributesSyntax & WithModifiersSyntax, + nominalDecl node: some DeclSyntaxProtocol & DeclGroupSyntax & NamedDeclSyntax + & WithAttributesSyntax & WithModifiersSyntax, in parent: ImportedNominalType?, sourceFilePath: String ) { @@ -115,7 +115,7 @@ final class Swift2JavaVisitor { } func visit( - functionDecl node: FunctionDeclSyntax, + functionDecl node: FunctionDeclSyntax, in typeContext: ImportedNominalType?, sourceFilePath: String ) { @@ -154,7 +154,7 @@ final class Swift2JavaVisitor { } func visit( - enumCaseDecl node: EnumCaseDeclSyntax, + enumCaseDecl node: EnumCaseDeclSyntax, in typeContext: ImportedNominalType? ) { guard let typeContext else { @@ -200,7 +200,7 @@ final class Swift2JavaVisitor { } func visit( - variableDecl node: VariableDeclSyntax, + variableDecl node: VariableDeclSyntax, in typeContext: ImportedNominalType?, sourceFilePath: String ) { @@ -216,37 +216,21 @@ final class Swift2JavaVisitor { self.log.debug("Import variable: \(node.kind) '\(node.qualifiedNameForDebug)'") - func importAccessor(kind: SwiftAPIKind) throws { - let signature = try SwiftFunctionSignature( - node, - isSet: kind == .setter, - enclosingType: typeContext?.swiftType, - lookupContext: translator.lookupContext - ) - - let imported = ImportedFunc( - module: translator.swiftModuleName, - swiftDecl: node, - name: varName, - apiKind: kind, - functionSignature: signature - ) - - log.debug("Record imported variable accessor \(kind == .getter ? "getter" : "setter"):\(node.qualifiedNameForDebug)") - if let typeContext { - typeContext.variables.append(imported) - } else { - translator.importedGlobalVariables.append(imported) - } - } - do { let supportedAccessors = node.supportedAccessorKinds(binding: binding) if supportedAccessors.contains(.get) { - try importAccessor(kind: .getter) + try importAccessor( + from: DeclSyntax(node), + in: typeContext, + kind: .getter, + name: varName) } if supportedAccessors.contains(.set) { - try importAccessor(kind: .setter) + try importAccessor( + from: DeclSyntax(node), + in: typeContext, + kind: .setter, + name: varName) } } catch { self.log.debug("Failed to import: \(node.qualifiedNameForDebug); \(error)") @@ -289,10 +273,89 @@ final class Swift2JavaVisitor { typeContext.initializers.append(imported) } + private func visit( + subscriptDecl node: SubscriptDeclSyntax, + in typeContext: ImportedNominalType?, + ) { + guard node.shouldExtract(config: config, log: log, in: typeContext) else { + return + } + + guard let accessorBlock = node.accessorBlock else { + return + } + + let name = "subscript" + let accessors = accessorBlock.supportedAccessorKinds() + + do { + if accessors.contains(.get) { + try importAccessor( + from: DeclSyntax(node), + in: typeContext, + kind: .subscriptGetter, + name: name) + } + if accessors.contains(.set) { + try importAccessor( + from: DeclSyntax(node), + in: typeContext, + kind: .subscriptSetter, + name: name) + } + } catch { + self.log.debug("Failed to import: \(node.qualifiedNameForDebug); \(error)") + } + } + + private func importAccessor( + from node: DeclSyntax, + in typeContext: ImportedNominalType?, + kind: SwiftAPIKind, + name: String + ) throws { + let signature: SwiftFunctionSignature + + switch node.as(DeclSyntaxEnum.self) { + case .variableDecl(let varNode): + signature = try SwiftFunctionSignature( + varNode, + isSet: kind == .setter, + enclosingType: typeContext?.swiftType, + lookupContext: translator.lookupContext) + case .subscriptDecl(let subscriptNode): + signature = try SwiftFunctionSignature( + subscriptNode, + isSet: kind == .subscriptSetter, + enclosingType: typeContext?.swiftType, + lookupContext: translator.lookupContext) + default: + log.warning("Not supported declaration type \(node.kind) while calling importAccessor!") + return + } + + let imported = ImportedFunc( + module: translator.swiftModuleName, + swiftDecl: node, + name: name, + apiKind: kind, + functionSignature: signature + ) + + log.debug( + "Record imported variable accessor \(kind == .getter || kind == .subscriptGetter ? "getter" : "setter"):\(node.qualifiedNameForDebug)" + ) + if let typeContext { + typeContext.variables.append(imported) + } else { + translator.importedGlobalVariables.append(imported) + } + } + private func synthesizeRawRepresentableConformance( enumDecl node: EnumDeclSyntax, in parent: ImportedNominalType? - ) { + ) { guard let imported = translator.importedNominalType(node, parent: parent) else { return } @@ -304,7 +367,9 @@ final class Swift2JavaVisitor { ), inheritanceType.isRawTypeCompatible { - if !imported.variables.contains(where: { $0.name == "rawValue" && $0.functionSignature.result.type != inheritanceType }) { + if !imported.variables.contains(where: { + $0.name == "rawValue" && $0.functionSignature.result.type != inheritanceType + }) { let decl: DeclSyntax = "public var rawValue: \(raw: inheritanceType.description) { get }" self.visit(decl: decl, in: imported, sourceFilePath: imported.sourceFilePath) } @@ -312,7 +377,11 @@ final class Swift2JavaVisitor { // FIXME: why is this un-used imported.variables.first?.signatureString - if !imported.initializers.contains(where: { $0.functionSignature.parameters.count == 1 && $0.functionSignature.parameters.first?.parameterName == "rawValue" && $0.functionSignature.parameters.first?.type == inheritanceType }) { + if !imported.initializers.contains(where: { + $0.functionSignature.parameters.count == 1 + && $0.functionSignature.parameters.first?.parameterName == "rawValue" + && $0.functionSignature.parameters.first?.type == inheritanceType + }) { let decl: DeclSyntax = "public init?(rawValue: \(raw: inheritanceType))" self.visit(decl: decl, in: imported, sourceFilePath: imported.sourceFilePath) } @@ -330,7 +399,9 @@ extension DeclSyntaxProtocol where Self: WithModifiersSyntax & WithAttributesSyn } guard meetsRequiredAccessLevel else { - log.debug("Skip import '\(self.qualifiedNameForDebug)': not at least \(config.effectiveMinimumInputAccessLevelMode)") + log.debug( + "Skip import '\(self.qualifiedNameForDebug)': not at least \(config.effectiveMinimumInputAccessLevelMode)" + ) return false } guard !attributes.contains(where: { $0.isJava }) else { diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftFunctionSignature.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftFunctionSignature.swift index 1f2fbd36..804769e5 100644 --- a/Sources/JExtractSwiftLib/SwiftTypes/SwiftFunctionSignature.swift +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftFunctionSignature.swift @@ -271,31 +271,10 @@ extension SwiftFunctionSignature { lookupContext: SwiftTypeLookupContext ) throws { - // If this is a member of a type, so we will have a self parameter. Figure out the - // type and convention for the self parameter. - if let enclosingType { - var isStatic = false - for modifier in varNode.modifiers { - switch modifier.name.tokenKind { - case .keyword(.static): isStatic = true - case .keyword(.class): throw SwiftFunctionTranslationError.classMethod(modifier.name) - default: break - } - } - - if isStatic { - self.selfParameter = .staticMethod(enclosingType) - } else { - self.selfParameter = .instance( - SwiftParameter( - convention: isSet && !enclosingType.isReferenceType ? .inout : .byValue, - type: enclosingType - ) - ) - } - } else { - self.selfParameter = nil - } + self.selfParameter = try Self.variableSelfParameter( + for: DeclSyntax(varNode), + enclosingType: enclosingType, + isSet: isSet) guard let binding = varNode.bindings.first, varNode.bindings.count == 1 else { throw SwiftFunctionTranslationError.multipleBindings(varNode) @@ -323,7 +302,9 @@ extension SwiftFunctionSignature { self.effectSpecifiers = effectSpecifiers ?? [] if isSet { - self.parameters = [SwiftParameter(convention: .byValue, parameterName: "newValue", type: valueType)] + self.parameters = [ + SwiftParameter(convention: .byValue, parameterName: "newValue", type: valueType) + ] self.result = .void } else { self.parameters = [] @@ -333,6 +314,50 @@ extension SwiftFunctionSignature { self.genericRequirements = [] } + init( + _ subscriptNode: SubscriptDeclSyntax, + isSet: Bool, + enclosingType: SwiftType?, + lookupContext: SwiftTypeLookupContext + ) throws { + self.selfParameter = try Self.variableSelfParameter( + for: DeclSyntax(subscriptNode), + enclosingType: enclosingType, + isSet: isSet) + + let valueType: SwiftType = try SwiftType(subscriptNode.returnClause.type, lookupContext: lookupContext) + var nodeParameters = try subscriptNode.parameterClause.parameters.map { param in + try SwiftParameter(param, lookupContext: lookupContext) + } + + var effectSpecifiers: [SwiftEffectSpecifier]? = nil + switch subscriptNode.accessorBlock?.accessors { + case .getter(let getter): + if let getter = getter.as(AccessorDeclSyntax.self) { + effectSpecifiers = try Self.effectSpecifiers(from: getter) + } + case .accessors(let accessors): + if let getter = accessors.first(where: { $0.accessorSpecifier.tokenKind == .keyword(.get) }) { + effectSpecifiers = try Self.effectSpecifiers(from: getter) + } + default: + break + } + + self.effectSpecifiers = effectSpecifiers ?? [] + + if isSet { + nodeParameters.append(SwiftParameter(convention: .byValue, parameterName: "newValue", type: valueType)) + self.result = .void + } else { + self.result = .init(convention: .direct, type: valueType) + } + + self.parameters = nodeParameters + self.genericParameters = [] + self.genericRequirements = [] + } + private static func effectSpecifiers(from decl: AccessorDeclSyntax) throws -> [SwiftEffectSpecifier] { var effectSpecifiers = [SwiftEffectSpecifier]() if decl.effectSpecifiers?.throwsClause != nil { @@ -343,27 +368,80 @@ extension SwiftFunctionSignature { } return effectSpecifiers } -} -extension VariableDeclSyntax { - struct SupportedAccessorKinds: OptionSet { - var rawValue: UInt8 + private static func variableSelfParameter( + for decl: DeclSyntax, + enclosingType: SwiftType?, + isSet: Bool + ) throws -> SwiftSelfParameter? { + let modifiers: DeclModifierListSyntax? = + switch decl.as(DeclSyntaxEnum.self) { + case .variableDecl(let varDecl): varDecl.modifiers + case .subscriptDecl(let subscriptDecl): subscriptDecl.modifiers + default: nil + } - static var get: Self = .init(rawValue: 1 << 0) - static var set: Self = .init(rawValue: 1 << 1) + guard let modifiers else { + return nil + } + + // If this is a member of a type, so we will have a self parameter. Figure out the + // type and convention for the self parameter. + if let enclosingType { + var isStatic = false + for modifier in modifiers { + switch modifier.name.tokenKind { + case .keyword(.static): isStatic = true + case .keyword(.class): throw SwiftFunctionTranslationError.classMethod(modifier.name) + default: break + } + } + + if isStatic { + return .staticMethod(enclosingType) + } else { + return .instance( + SwiftParameter( + convention: isSet && !enclosingType.isReferenceType ? .inout : .byValue, + type: enclosingType + ) + ) + } + } else { + return nil + } } +} +extension VariableDeclSyntax { /// Determine what operations (i.e. get and/or set) supported in this `VariableDeclSyntax` /// /// - Parameters: /// - binding the pattern binding in this declaration. - func supportedAccessorKinds(binding: PatternBindingSyntax) -> SupportedAccessorKinds { + func supportedAccessorKinds(binding: PatternBindingSyntax) -> AccessorBlockSyntax.SupportedAccessorKinds { if self.bindingSpecifier.tokenKind == .keyword(.let) { return [.get] } if let accessorBlock = binding.accessorBlock { - switch accessorBlock.accessors { + return accessorBlock.supportedAccessorKinds() + } + + return [.get, .set] + } +} + +extension AccessorBlockSyntax { + struct SupportedAccessorKinds: OptionSet { + var rawValue: UInt8 + + static var get: Self = .init(rawValue: 1 << 0) + static var set: Self = .init(rawValue: 1 << 1) + } + + /// Determine what operations (i.e. get and/or set) supported in this `AccessorBlockSyntax` + func supportedAccessorKinds() -> SupportedAccessorKinds { + switch self.accessors { case .getter: return [.get] case .accessors(let accessors): @@ -379,9 +457,6 @@ extension VariableDeclSyntax { } return [.get] } - } - - return [.get, .set] } } diff --git a/Sources/JExtractSwiftLib/ThunkNameRegistry.swift b/Sources/JExtractSwiftLib/ThunkNameRegistry.swift index 3369ec62..da2e95c1 100644 --- a/Sources/JExtractSwiftLib/ThunkNameRegistry.swift +++ b/Sources/JExtractSwiftLib/ThunkNameRegistry.swift @@ -32,9 +32,9 @@ package struct ThunkNameRegistry { let suffix: String switch decl.apiKind { - case .getter: + case .getter, .subscriptGetter: suffix = "$get" - case .setter: + case .setter, .subscriptSetter: suffix = "$set" default: suffix = decl.functionSignature.parameters diff --git a/Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md b/Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md index 7e8c66d3..849b7f01 100644 --- a/Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md +++ b/Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md @@ -83,7 +83,7 @@ SwiftJava's `swift-java jextract` tool automates generating Java bindings from S | Ownership modifiers: `inout`, `borrowing`, `consuming` | ❌ | ❌ | | Default parameter values: `func p(name: String = "")` | ❌ | ❌ | | Operators: `+`, `-`, user defined | ❌ | ❌ | -| Subscripts: `subscript()` | ❌ | ❌ | +| Subscripts: `subscript()` | ✅ | ✅ | | Equatable | ❌ | ❌ | | Pointers: `UnsafeRawPointer`, UnsafeBufferPointer (?) | 🟡 | ❌ | | Nested types: `struct Hello { struct World {} }` | ❌ | ✅ | diff --git a/Tests/JExtractSwiftTests/FFM/FFMSubscriptsTests.swift b/Tests/JExtractSwiftTests/FFM/FFMSubscriptsTests.swift new file mode 100644 index 00000000..89029dd7 --- /dev/null +++ b/Tests/JExtractSwiftTests/FFM/FFMSubscriptsTests.swift @@ -0,0 +1,212 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import JExtractSwiftLib +import Testing + +import JExtractSwiftLib +import Testing + +@Suite +struct FFMSubscriptsTests { + private let noParamsSubscriptSource = """ + public struct MyStruct { + private var testVariable: Double = 0 + + public subscript() -> Double { + get { return testVariable } + set { testVariable = newValue } + } + } + """ + + private let subscriptWithParamsSource = """ + public struct MyStruct { + private var testVariable: [Int32] = [] + + public subscript(index: Int32) -> Int32 { + get { return testVariable[Int(index)] } + set { testVariable[Int(index)] = newValue } + } + } + """ + + @Test("Test generation of JavaClass for subscript with no parameters") + func generatesJavaClassForNoParams() throws { + try assertOutput(input: noParamsSubscriptSource, .ffm, .java, expectedChunks: [ + """ + private static class swiftjava_SwiftModule_MyStruct_subscript$get { + private static final FunctionDescriptor DESC = FunctionDescriptor.of( + /* -> */SwiftValueLayout.SWIFT_DOUBLE, + /* self: */SwiftValueLayout.SWIFT_POINTER + ); + """, + """ + private static final MemorySegment ADDR = + SwiftModule.findOrThrow("swiftjava_SwiftModule_MyStruct_subscript$get"); + """, + """ + private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + public static double call(java.lang.foreign.MemorySegment self) { + try { + if (CallTraces.TRACE_DOWNCALLS) { + CallTraces.traceDowncall(self); + } + return (double) HANDLE.invokeExact(self); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + """, + """ + public double getSubscript() { + $ensureAlive(); + return swiftjava_SwiftModule_MyStruct_subscript$get.call(this.$memorySegment()); + """, + ]) + try assertOutput(input: noParamsSubscriptSource, .ffm, .java, expectedChunks: [ + """ + private static class swiftjava_SwiftModule_MyStruct_subscript$set { + private static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( + /* newValue: */SwiftValueLayout.SWIFT_DOUBLE, + /* self: */SwiftValueLayout.SWIFT_POINTER + ); + private static final MemorySegment ADDR = + SwiftModule.findOrThrow("swiftjava_SwiftModule_MyStruct_subscript$set"); + private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + public static void call(double newValue, java.lang.foreign.MemorySegment self) { + try { + if (CallTraces.TRACE_DOWNCALLS) { + CallTraces.traceDowncall(newValue, self); + } + HANDLE.invokeExact(newValue, self); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + """, + """ + public void setSubscript(double newValue) { + $ensureAlive(); + swiftjava_SwiftModule_MyStruct_subscript$set.call(newValue, this.$memorySegment()); + """ + ]) + } + + @Test("Test generation of JavaClass for subscript with parameters") + func generatesJavaClassForParameters() throws { + try assertOutput(input: subscriptWithParamsSource, .ffm, .java, expectedChunks: [ + """ + private static class swiftjava_SwiftModule_MyStruct_subscript$get { + private static final FunctionDescriptor DESC = FunctionDescriptor.of( + /* -> */SwiftValueLayout.SWIFT_INT32, + /* index: */SwiftValueLayout.SWIFT_INT32, + /* self: */SwiftValueLayout.SWIFT_POINTER + ); + private static final MemorySegment ADDR = + SwiftModule.findOrThrow("swiftjava_SwiftModule_MyStruct_subscript$get"); + private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + public static int call(int index, java.lang.foreign.MemorySegment self) { + try { + if (CallTraces.TRACE_DOWNCALLS) { + CallTraces.traceDowncall(index, self); + } + return (int) HANDLE.invokeExact(index, self); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + """, + """ + public int getSubscript(int index) { + $ensureAlive(); + return swiftjava_SwiftModule_MyStruct_subscript$get.call(index, this.$memorySegment()); + """, + ]) + try assertOutput(input: subscriptWithParamsSource, .ffm, .java, expectedChunks: [ + """ + private static class swiftjava_SwiftModule_MyStruct_subscript$set { + private static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( + /* index: */SwiftValueLayout.SWIFT_INT32, + /* newValue: */SwiftValueLayout.SWIFT_INT32, + /* self: */SwiftValueLayout.SWIFT_POINTER + ); + private static final MemorySegment ADDR = + SwiftModule.findOrThrow("swiftjava_SwiftModule_MyStruct_subscript$set"); + private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + public static void call(int index, int newValue, java.lang.foreign.MemorySegment self) { + try { + if (CallTraces.TRACE_DOWNCALLS) { + CallTraces.traceDowncall(index, newValue, self); + } + HANDLE.invokeExact(index, newValue, self); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + """, + """ + public void setSubscript(int index, int newValue) { + $ensureAlive(); + swiftjava_SwiftModule_MyStruct_subscript$set.call(index, newValue, this.$memorySegment()); + """, + ]) + } + + @Test("Test generation of Swift thunks for subscript without parameters") + func subscriptWithoutParamsMethodSwiftThunk() throws { + try assertOutput( + input: noParamsSubscriptSource, + .ffm, + .swift, + expectedChunks: [ + """ + @_cdecl("swiftjava_SwiftModule_MyStruct_subscript$get") + public func swiftjava_SwiftModule_MyStruct_subscript$get(_ self: UnsafeRawPointer) -> Double { + return self.assumingMemoryBound(to: MyStruct.self).pointee[] + } + """, + """ + @_cdecl("swiftjava_SwiftModule_MyStruct_subscript$set") + public func swiftjava_SwiftModule_MyStruct_subscript$set(_ newValue: Double, _ self: UnsafeMutableRawPointer) { + self.assumingMemoryBound(to: MyStruct.self).pointee[] = newValue + } + """ + ] + ) + } + + @Test("Test generation of Swift thunks for subscript with parameters") + func subscriptWithParamsMethodSwiftThunk() throws { + try assertOutput( + input: subscriptWithParamsSource, + .ffm, + .swift, + expectedChunks: [ + """ + @_cdecl("swiftjava_SwiftModule_MyStruct_subscript$get") + public func swiftjava_SwiftModule_MyStruct_subscript$get(_ index: Int32, _ self: UnsafeRawPointer) -> Int32 { + return self.assumingMemoryBound(to: MyStruct.self).pointee[index] + } + """, + """ + @_cdecl("swiftjava_SwiftModule_MyStruct_subscript$set") + public func swiftjava_SwiftModule_MyStruct_subscript$set(_ index: Int32, _ newValue: Int32, _ self: UnsafeMutableRawPointer) { + self.assumingMemoryBound(to: MyStruct.self).pointee[index] = newValue + } + """ + ] + ) + } +} diff --git a/Tests/JExtractSwiftTests/JNI/JNISubscriptsTests.swift b/Tests/JExtractSwiftTests/JNI/JNISubscriptsTests.swift new file mode 100644 index 00000000..0f7b131d --- /dev/null +++ b/Tests/JExtractSwiftTests/JNI/JNISubscriptsTests.swift @@ -0,0 +1,155 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import JExtractSwiftLib +import Testing + +@Suite +struct JNISubscriptsTests { + private let noParamsSubscriptSource = """ + public struct MyStruct { + private var testVariable: Double = 0 + + public subscript() -> Double { + get { return testVariable } + set { testVariable = newValue } + } + } + """ + + private let subscriptWithParamsSource = """ + public struct MyStruct { + private var testVariable: [Int32] = [] + + public subscript(index: Int32) -> Int32 { + get { return testVariable[Int(index)] } + set { testVariable[Int(index)] = newValue } + } + } + """ + + @Test("Test generation of JavaClass for subscript with no parameters") + func generatesJavaClassForNoParams() throws { + try assertOutput(input: noParamsSubscriptSource, .jni, .java, expectedChunks: [ + """ + public double getSubscript() { + return MyStruct.$getSubscript(this.$memoryAddress()); + """, + """ + private static native double $getSubscript(long self); + """, + """ + public void setSubscript(double newValue) { + MyStruct.$setSubscript(newValue, this.$memoryAddress()); + """, + """ + private static native void $setSubscript(double newValue, long self); + """ + ]) + try assertOutput( + input: noParamsSubscriptSource, .jni, .java, + expectedChunks: [ + """ + private static native void $destroy(long selfPointer); + """ + ]) + } + + @Test("Test generation of JavaClass for subscript with parameters") + func generatesJavaClassForParameters() throws { + try assertOutput(input: subscriptWithParamsSource, .jni, .java, expectedChunks: [ + """ + public int getSubscript(int index) { + return MyStruct.$getSubscript(index, this.$memoryAddress()); + + """, + """ + private static native int $getSubscript(int index, long self); + """, + """ + public void setSubscript(int index, int newValue) { + MyStruct.$setSubscript(index, newValue, this.$memoryAddress()); + """, + """ + private static native void $setSubscript(int index, int newValue, long self); + """ + ]) + } + + @Test("Test generation of Swift thunks for subscript without parameters") + func subscriptWithoutParamsMethodSwiftThunk() throws { + try assertOutput( + input: noParamsSubscriptSource, + .jni, + .swift, + expectedChunks: [ + """ + @_cdecl("Java_com_example_swift_MyStruct__00024getSubscript__J") + func Java_com_example_swift_MyStruct__00024getSubscript__J(environment: UnsafeMutablePointer!, thisClass: jclass, self: jlong) -> jdouble { + assert(self != 0, "self memory address was null") + let selfBits$ = Int(Int64(fromJNI: self, in: environment)) + let self$ = UnsafeMutablePointer(bitPattern: selfBits$) + guard let self$ else { + fatalError("self memory address was null in call to \\(#function)!") + } + return self$.pointee[].getJNIValue(in: environment) + """, + """ + @_cdecl("Java_com_example_swift_MyStruct__00024setSubscript__DJ") + func Java_com_example_swift_MyStruct__00024setSubscript__DJ(environment: UnsafeMutablePointer!, thisClass: jclass, newValue: jdouble, self: jlong) { + assert(self != 0, "self memory address was null") + let selfBits$ = Int(Int64(fromJNI: self, in: environment)) + let self$ = UnsafeMutablePointer(bitPattern: selfBits$) + guard let self$ else { + fatalError("self memory address was null in call to \\(#function)!") + } + self$.pointee[] = Double(fromJNI: newValue, in: environment) + """ + ] + ) + } + + @Test("Test generation of Swift thunks for subscript with parameters") + func subscriptWithParamsMethodSwiftThunk() throws { + try assertOutput( + input: subscriptWithParamsSource, + .jni, + .swift, + expectedChunks: [ + """ + @_cdecl("Java_com_example_swift_MyStruct__00024getSubscript__IJ") + func Java_com_example_swift_MyStruct__00024getSubscript__IJ(environment: UnsafeMutablePointer!, thisClass: jclass, index: jint, self: jlong) -> jint { + assert(self != 0, "self memory address was null") + let selfBits$ = Int(Int64(fromJNI: self, in: environment)) + let self$ = UnsafeMutablePointer(bitPattern: selfBits$) + guard let self$ else { + fatalError("self memory address was null in call to \\(#function)!") + } + return self$.pointee[Int32(fromJNI: index, in: environment)].getJNIValue(in: environment) + """, + """ + @_cdecl("Java_com_example_swift_MyStruct__00024setSubscript__IIJ") + func Java_com_example_swift_MyStruct__00024setSubscript__IIJ(environment: UnsafeMutablePointer!, thisClass: jclass, index: jint, newValue: jint, self: jlong) { + assert(self != 0, "self memory address was null") + let selfBits$ = Int(Int64(fromJNI: self, in: environment)) + let self$ = UnsafeMutablePointer(bitPattern: selfBits$) + guard let self$ else { + fatalError("self memory address was null in call to \\(#function)!") + } + self$.pointee[Int32(fromJNI: index, in: environment)] = Int32(fromJNI: newValue, in: environment) + """ + ] + ) + } +} From c0c6fd593f68d14d7084a0a5935e02331991193d Mon Sep 17 00:00:00 2001 From: Mads Odgaard Date: Mon, 1 Dec 2025 11:56:29 +0100 Subject: [PATCH 414/426] Use thread environment instead for JNI methods (#465) --- Sources/SwiftJava/AnyJavaObject.swift | 2 +- .../SwiftJava/JavaObject+MethodCalls.swift | 50 ++++++++++++------- Sources/SwiftJava/JavaObjectHolder.swift | 2 + Tests/SwiftJavaTests/BasicRuntimeTests.swift | 11 ++++ 4 files changed, 46 insertions(+), 19 deletions(-) diff --git a/Sources/SwiftJava/AnyJavaObject.swift b/Sources/SwiftJava/AnyJavaObject.swift index fe77bdbd..33a83159 100644 --- a/Sources/SwiftJava/AnyJavaObject.swift +++ b/Sources/SwiftJava/AnyJavaObject.swift @@ -66,7 +66,7 @@ extension AnyJavaObject { javaHolder.object } - /// Retrieve the environment in which this Java object resides. + /// Retrieve the environment in which this Java object was created. public var javaEnvironment: JNIEnvironment { javaHolder.environment } diff --git a/Sources/SwiftJava/JavaObject+MethodCalls.swift b/Sources/SwiftJava/JavaObject+MethodCalls.swift index 4880f750..0626be23 100644 --- a/Sources/SwiftJava/JavaObject+MethodCalls.swift +++ b/Sources/SwiftJava/JavaObject+MethodCalls.swift @@ -104,7 +104,8 @@ extension AnyJavaObject { resultType: Result.Type ) throws -> jmethodID { // Retrieve the Java class instance from the object. - let environment = javaEnvironment + let environment = try JavaVirtualMachine.shared().environment() + let thisClass = try environment.translatingJNIExceptions { environment.interface.GetObjectClass(environment, javaThis) }! @@ -115,7 +116,7 @@ extension AnyJavaObject { methodName: methodName, parameterTypes: repeat each parameterTypes, resultType: Result.javaType, - in: javaEnvironment + in: environment ) } } @@ -126,7 +127,8 @@ extension AnyJavaObject { parameterTypes: repeat (each Param).Type ) throws -> jmethodID { // Retrieve the Java class instance from the object. - let environment = javaEnvironment + let environment = try JavaVirtualMachine.shared().environment() + let thisClass = try environment.translatingJNIExceptions { environment.interface.GetObjectClass(environment, javaThis) }! @@ -137,7 +139,7 @@ extension AnyJavaObject { methodName: methodName, parameterTypes: repeat each parameterTypes, resultType: .void, - in: javaEnvironment + in: environment ) } } @@ -167,8 +169,10 @@ extension AnyJavaObject { method: jmethodID, args: repeat each Param ) throws -> Result { + let environment = try JavaVirtualMachine.shared().environment() + return try Self.javaMethodCall( - in: javaEnvironment, + in: environment, this: javaThis, method: method, args: repeat each args @@ -229,8 +233,10 @@ extension AnyJavaObject { method: jmethodID, args: repeat each Param ) throws { + let environment = try JavaVirtualMachine.shared().environment() + try Self.javaMethodCall( - in: javaEnvironment, + in: environment, this: javaThis, method: method, args: repeat each args @@ -276,7 +282,7 @@ extension AnyJavaObject { private func getJNIFieldID(_ fieldName: String, fieldType: FieldType.Type) -> jfieldID? where FieldType: ~Copyable { let this = javaThis - let environment = javaEnvironment + let environment = try! JavaVirtualMachine.shared().environment() // Retrieve the Java class instance from the object. let thisClass = environment.interface.GetObjectClass(environment, this)! @@ -289,15 +295,19 @@ extension AnyJavaObject { fieldType fieldType: FieldType.Type ) -> FieldType where FieldType: ~Copyable { get { + let environment = try! JavaVirtualMachine.shared().environment() + let fieldID = getJNIFieldID(fieldName, fieldType: fieldType)! - let jniMethod = FieldType.jniFieldGet(in: javaEnvironment) - return FieldType(fromJNI: jniMethod(javaEnvironment, javaThis, fieldID), in: javaEnvironment) + let jniMethod = FieldType.jniFieldGet(in: environment) + return FieldType(fromJNI: jniMethod(environment, javaThis, fieldID), in: environment) } nonmutating set { + let environment = try! JavaVirtualMachine.shared().environment() + let fieldID = getJNIFieldID(fieldName, fieldType: fieldType)! - let jniMethod = FieldType.jniFieldSet(in: javaEnvironment) - jniMethod(javaEnvironment, javaThis, fieldID, newValue.getJNIValue(in: javaEnvironment)) + let jniMethod = FieldType.jniFieldSet(in: environment) + jniMethod(environment, javaThis, fieldID, newValue.getJNIValue(in: environment)) } } } @@ -311,7 +321,7 @@ extension JavaClass { resultType: Result.Type ) throws -> Result { let thisClass = javaThis - let environment = javaEnvironment + let environment = try! JavaVirtualMachine.shared().environment() // Compute the method signature so we can find the right method, then look up the // method within the class. @@ -345,7 +355,7 @@ extension JavaClass { arguments: repeat each Param ) throws { let thisClass = javaThis - let environment = javaEnvironment + let environment = try JavaVirtualMachine.shared().environment() // Compute the method signature so we can find the right method, then look up the // method within the class. @@ -372,7 +382,7 @@ extension JavaClass { /// Retrieve the JNI field ID for a field with the given name and type. private func getJNIStaticFieldID(_ fieldName: String, fieldType: FieldType.Type) -> jfieldID? { - let environment = javaEnvironment + let environment = try! JavaVirtualMachine.shared().environment() return environment.interface.GetStaticFieldID(environment, javaThis, fieldName, FieldType.jniMangling) } @@ -382,15 +392,19 @@ extension JavaClass { fieldType fieldType: FieldType.Type ) -> FieldType { get { + let environment = try! JavaVirtualMachine.shared().environment() + let fieldID = getJNIStaticFieldID(fieldName, fieldType: fieldType)! - let jniMethod = FieldType.jniStaticFieldGet(in: javaEnvironment) - return FieldType(fromJNI: jniMethod(javaEnvironment, javaThis, fieldID), in: javaEnvironment) + let jniMethod = FieldType.jniStaticFieldGet(in: environment) + return FieldType(fromJNI: jniMethod(environment, javaThis, fieldID), in: environment) } set { + let environment = try! JavaVirtualMachine.shared().environment() + let fieldID = getJNIStaticFieldID(fieldName, fieldType: fieldType)! - let jniMethod = FieldType.jniStaticFieldSet(in: javaEnvironment) - jniMethod(javaEnvironment, javaThis, fieldID, newValue.getJNIValue(in: javaEnvironment)) + let jniMethod = FieldType.jniStaticFieldSet(in: environment) + jniMethod(environment, javaThis, fieldID, newValue.getJNIValue(in: environment)) } } } diff --git a/Sources/SwiftJava/JavaObjectHolder.swift b/Sources/SwiftJava/JavaObjectHolder.swift index 5930da59..b5e88835 100644 --- a/Sources/SwiftJava/JavaObjectHolder.swift +++ b/Sources/SwiftJava/JavaObjectHolder.swift @@ -32,6 +32,8 @@ public final class JavaObjectHolder { /// in Swift and the Java virtual machine is free to move or deallocate it. func forget() { if let object { + let environment = try! JavaVirtualMachine.shared().environment() + environment.interface.DeleteGlobalRef(environment, object) self.object = nil } diff --git a/Tests/SwiftJavaTests/BasicRuntimeTests.swift b/Tests/SwiftJavaTests/BasicRuntimeTests.swift index b6c18bee..292c2a68 100644 --- a/Tests/SwiftJavaTests/BasicRuntimeTests.swift +++ b/Tests/SwiftJavaTests/BasicRuntimeTests.swift @@ -82,6 +82,17 @@ class BasicRuntimeTests: XCTestCase { let nullString = String(fromJNI: nil, in: environment) XCTAssertEqual(nullString, "") } + + func testCrossThreadAccess() async throws { + let environment = try jvm.environment() + let url = try URL("https://swift.org", environment: environment) + let string = await Task.detached { + // This should be called on a different thread + url.toString() + }.value + + XCTAssertEqual(string, "https://swift.org") + } } @JavaClass("org.swift.javakit.Nonexistent") From 2ed85e25ed3831c4c9fdb00e3c92fc4b62255885 Mon Sep 17 00:00:00 2001 From: Mads Odgaard Date: Mon, 1 Dec 2025 12:21:21 +0100 Subject: [PATCH 415/426] [jextract] Add async legacy mode (#462) --- .../java/com/example/swift/AsyncTest.java | 33 +-- .../com/example/swift/MySwiftClassTest.java | 4 +- ...ISwift2JavaGenerator+JavaTranslation.swift | 71 +++--- ...wift2JavaGenerator+NativeTranslation.swift | 14 +- .../JavaTypes/JavaType+JDK.swift | 5 + .../JavaTypes/JavaType+SwiftKit.swift | 5 + .../JExtract/JExtractAsyncFuncMode.swift | 2 +- ...ltCaches.swift => JNIMethodIDCaches.swift} | 30 +++ .../core/SimpleCompletableFuture.java | 223 ++++++++++++++++++ .../core/SimpleCompletableFutureTest.java | 185 +++++++++++++++ .../JNI/JNIAsyncTests.swift | 92 ++++++-- 11 files changed, 597 insertions(+), 67 deletions(-) rename Sources/SwiftJavaRuntimeSupport/{DefaultCaches.swift => JNIMethodIDCaches.swift} (70%) create mode 100644 SwiftKitCore/src/main/java/org/swift/swiftkit/core/SimpleCompletableFuture.java create mode 100644 SwiftKitCore/src/test/java/org/swift/swiftkit/core/SimpleCompletableFutureTest.java diff --git a/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/AsyncTest.java b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/AsyncTest.java index 5fe7c131..400844fd 100644 --- a/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/AsyncTest.java +++ b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/AsyncTest.java @@ -26,31 +26,32 @@ import java.util.OptionalLong; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; import static org.junit.jupiter.api.Assertions.*; public class AsyncTest { @Test - void asyncSum() { - CompletableFuture future = MySwiftLibrary.asyncSum(10, 12); + void asyncSum() throws Exception { + Future future = MySwiftLibrary.asyncSum(10, 12); - Long result = future.join(); + Long result = future.get(); assertEquals(22, result); } @Test - void asyncSleep() { - CompletableFuture future = MySwiftLibrary.asyncSleep(); - future.join(); + void asyncSleep() throws Exception { + Future future = MySwiftLibrary.asyncSleep(); + future.get(); } @Test - void asyncCopy() { + void asyncCopy() throws Exception { try (var arena = SwiftArena.ofConfined()) { MySwiftClass obj = MySwiftClass.init(10, 5, arena); - CompletableFuture future = MySwiftLibrary.asyncCopy(obj, arena); + Future future = MySwiftLibrary.asyncCopy(obj, arena); - MySwiftClass result = future.join(); + MySwiftClass result = future.get(); assertEquals(10, result.getX()); assertEquals(5, result.getY()); @@ -59,7 +60,7 @@ void asyncCopy() { @Test void asyncThrows() { - CompletableFuture future = MySwiftLibrary.asyncThrows(); + Future future = MySwiftLibrary.asyncThrows(); ExecutionException ex = assertThrows(ExecutionException.class, future::get); @@ -70,14 +71,14 @@ void asyncThrows() { } @Test - void asyncOptional() { - CompletableFuture future = MySwiftLibrary.asyncOptional(42); - assertEquals(OptionalLong.of(42), future.join()); + void asyncOptional() throws Exception { + Future future = MySwiftLibrary.asyncOptional(42); + assertEquals(OptionalLong.of(42), future.get()); } @Test - void asyncString() { - CompletableFuture future = MySwiftLibrary.asyncString("hey"); - assertEquals("hey", future.join()); + void asyncString() throws Exception { + Future future = MySwiftLibrary.asyncString("hey"); + assertEquals("hey", future.get()); } } \ No newline at end of file diff --git a/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/MySwiftClassTest.java b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/MySwiftClassTest.java index a5838629..860f1641 100644 --- a/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/MySwiftClassTest.java +++ b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/MySwiftClassTest.java @@ -165,10 +165,10 @@ void addXWithJavaLong() { } @Test - void getAsyncVariable() { + void getAsyncVariable() throws Exception { try (var arena = SwiftArena.ofConfined()) { MySwiftClass c1 = MySwiftClass.init(20, 10, arena); - assertEquals(42, c1.getGetAsync().join()); + assertEquals(42, c1.getGetAsync().get()); } } } \ No newline at end of file diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift index c8e4bbf3..6a2771c3 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift @@ -501,40 +501,55 @@ extension JNISwift2JavaGenerator { originalFunctionSignature: SwiftFunctionSignature, mode: JExtractAsyncFuncMode ) { + // Update translated function + let nativeFutureType: JavaType + let translatedFutureType: JavaType + let completeMethodID: String + let completeExceptionallyMethodID: String + switch mode { case .completableFuture: - // Update translated function - - let nativeFutureType = JavaType.completableFuture(nativeFunctionSignature.result.javaType) + nativeFutureType = .completableFuture(nativeFunctionSignature.result.javaType) + translatedFutureType = .completableFuture(translatedFunctionSignature.resultType.javaType) + completeMethodID = "_JNIMethodIDCache.CompletableFuture.complete" + completeExceptionallyMethodID = "_JNIMethodIDCache.CompletableFuture.completeExceptionally" + + case .legacyFuture: + nativeFutureType = .simpleCompletableFuture(nativeFunctionSignature.result.javaType) + translatedFutureType = .future(translatedFunctionSignature.resultType.javaType) + completeMethodID = "_JNIMethodIDCache.SimpleCompletableFuture.complete" + completeExceptionallyMethodID = "_JNIMethodIDCache.SimpleCompletableFuture.completeExceptionally" + } - let futureOutParameter = OutParameter( - name: "$future", - type: nativeFutureType, - allocation: .new - ) + let futureOutParameter = OutParameter( + name: "future$", + type: nativeFutureType, + allocation: .new + ) - let result = translatedFunctionSignature.resultType - translatedFunctionSignature.resultType = TranslatedResult( - javaType: .completableFuture(translatedFunctionSignature.resultType.javaType), - annotations: result.annotations, - outParameters: result.outParameters + [futureOutParameter], - conversion: .aggregate(variable: nil, [ - .print(.placeholder), // Make the downcall - .method(.constant("$future"), function: "thenApply", arguments: [ - .lambda(args: ["futureResult$"], body: .replacingPlaceholder(result.conversion, placeholder: "futureResult$")) - ]) + let result = translatedFunctionSignature.resultType + translatedFunctionSignature.resultType = TranslatedResult( + javaType: translatedFutureType, + annotations: result.annotations, + outParameters: result.outParameters + [futureOutParameter], + conversion: .aggregate(variable: nil, [ + .print(.placeholder), // Make the downcall + .method(.constant("future$"), function: "thenApply", arguments: [ + .lambda(args: ["futureResult$"], body: .replacingPlaceholder(result.conversion, placeholder: "futureResult$")) ]) - ) + ]) + ) - // Update native function - nativeFunctionSignature.result.conversion = .asyncCompleteFuture( - swiftFunctionResultType: originalFunctionSignature.result.type, - nativeFunctionSignature: nativeFunctionSignature, - isThrowing: originalFunctionSignature.isThrowing - ) - nativeFunctionSignature.result.javaType = .void - nativeFunctionSignature.result.outParameters.append(.init(name: "result_future", type: nativeFutureType)) - } + // Update native function + nativeFunctionSignature.result.conversion = .asyncCompleteFuture( + swiftFunctionResultType: originalFunctionSignature.result.type, + nativeFunctionSignature: nativeFunctionSignature, + isThrowing: originalFunctionSignature.isThrowing, + completeMethodID: completeMethodID, + completeExceptionallyMethodID: completeExceptionallyMethodID + ) + nativeFunctionSignature.result.javaType = .void + nativeFunctionSignature.result.outParameters.append(.init(name: "result_future", type: nativeFutureType)) } func translateProtocolParameter( diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift index 1994dce0..24e46906 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift @@ -689,7 +689,9 @@ extension JNISwift2JavaGenerator { indirect case asyncCompleteFuture( swiftFunctionResultType: SwiftType, nativeFunctionSignature: NativeFunctionSignature, - isThrowing: Bool + isThrowing: Bool, + completeMethodID: String, + completeExceptionallyMethodID: String ) /// `{ (args) -> return body }` @@ -927,7 +929,9 @@ extension JNISwift2JavaGenerator { case .asyncCompleteFuture( let swiftFunctionResultType, let nativeFunctionSignature, - let isThrowing + let isThrowing, + let completeMethodID, + let completeExceptionallyMethodID ): var globalRefs: [String] = ["globalFuture"] @@ -954,7 +958,7 @@ extension JNISwift2JavaGenerator { printer.print("environment = try! JavaVirtualMachine.shared().environment()") let inner = nativeFunctionSignature.result.conversion.render(&printer, "swiftResult$") if swiftFunctionResultType.isVoid { - printer.print("environment.interface.CallBooleanMethodA(environment, globalFuture, _JNIMethodIDCache.CompletableFuture.complete, [jvalue(l: nil)])") + printer.print("environment.interface.CallBooleanMethodA(environment, globalFuture, \(completeMethodID), [jvalue(l: nil)])") } else { let result: String if nativeFunctionSignature.result.javaType.requiresBoxing { @@ -964,7 +968,7 @@ extension JNISwift2JavaGenerator { result = inner } - printer.print("environment.interface.CallBooleanMethodA(environment, globalFuture, _JNIMethodIDCache.CompletableFuture.complete, [jvalue(l: \(result))])") + printer.print("environment.interface.CallBooleanMethodA(environment, globalFuture, \(completeMethodID), [jvalue(l: \(result))])") } } @@ -986,7 +990,7 @@ extension JNISwift2JavaGenerator { """ let catchEnvironment = try! JavaVirtualMachine.shared().environment() let exception = catchEnvironment.interface.NewObjectA(catchEnvironment, _JNIMethodIDCache.Exception.class, _JNIMethodIDCache.Exception.constructWithMessage, [String(describing: error).getJValue(in: catchEnvironment)]) - catchEnvironment.interface.CallBooleanMethodA(catchEnvironment, globalFuture, _JNIMethodIDCache.CompletableFuture.completeExceptionally, [jvalue(l: exception)]) + catchEnvironment.interface.CallBooleanMethodA(catchEnvironment, globalFuture, \(completeExceptionallyMethodID), [jvalue(l: exception)]) """ ) } diff --git a/Sources/JExtractSwiftLib/JavaTypes/JavaType+JDK.swift b/Sources/JExtractSwiftLib/JavaTypes/JavaType+JDK.swift index 5e5a7268..511bf8de 100644 --- a/Sources/JExtractSwiftLib/JavaTypes/JavaType+JDK.swift +++ b/Sources/JExtractSwiftLib/JavaTypes/JavaType+JDK.swift @@ -44,4 +44,9 @@ extension JavaType { static func completableFuture(_ T: JavaType) -> JavaType { .class(package: "java.util.concurrent", name: "CompletableFuture", typeParameters: [T.boxedType]) } + + /// The description of the type java.util.concurrent.Future + static func future(_ T: JavaType) -> JavaType { + .class(package: "java.util.concurrent", name: "Future", typeParameters: [T.boxedType]) + } } diff --git a/Sources/JExtractSwiftLib/JavaTypes/JavaType+SwiftKit.swift b/Sources/JExtractSwiftLib/JavaTypes/JavaType+SwiftKit.swift index 2ab9c0a2..7319b294 100644 --- a/Sources/JExtractSwiftLib/JavaTypes/JavaType+SwiftKit.swift +++ b/Sources/JExtractSwiftLib/JavaTypes/JavaType+SwiftKit.swift @@ -85,4 +85,9 @@ extension JavaType { } } + /// The description of the type org.swift.swiftkit.core.SimpleCompletableFuture + static func simpleCompletableFuture(_ T: JavaType) -> JavaType { + .class(package: "org.swift.swiftkit.core", name: "SimpleCompletableFuture", typeParameters: [T.boxedType]) + } + } diff --git a/Sources/SwiftJavaConfigurationShared/JExtract/JExtractAsyncFuncMode.swift b/Sources/SwiftJavaConfigurationShared/JExtract/JExtractAsyncFuncMode.swift index 221649c5..d7fd8462 100644 --- a/Sources/SwiftJavaConfigurationShared/JExtract/JExtractAsyncFuncMode.swift +++ b/Sources/SwiftJavaConfigurationShared/JExtract/JExtractAsyncFuncMode.swift @@ -23,7 +23,7 @@ public enum JExtractAsyncFuncMode: String, Codable { /// Android 23 and below. /// /// - Note: Prefer using the `completableFuture` mode instead, if possible. -// case future + case legacyFuture } extension JExtractAsyncFuncMode { diff --git a/Sources/SwiftJavaRuntimeSupport/DefaultCaches.swift b/Sources/SwiftJavaRuntimeSupport/JNIMethodIDCaches.swift similarity index 70% rename from Sources/SwiftJavaRuntimeSupport/DefaultCaches.swift rename to Sources/SwiftJavaRuntimeSupport/JNIMethodIDCaches.swift index 1c3079bc..56fe0351 100644 --- a/Sources/SwiftJavaRuntimeSupport/DefaultCaches.swift +++ b/Sources/SwiftJavaRuntimeSupport/JNIMethodIDCaches.swift @@ -47,6 +47,36 @@ extension _JNIMethodIDCache { } } + public enum SimpleCompletableFuture { + private static let completeMethod = Method( + name: "complete", + signature: "(Ljava/lang/Object;)Z" + ) + + private static let completeExceptionallyMethod = Method( + name: "completeExceptionally", + signature: "(Ljava/lang/Throwable;)Z" + ) + + private static let cache = _JNIMethodIDCache( + environment: try! JavaVirtualMachine.shared().environment(), + className: "org/swift/swiftkit/core/SimpleCompletableFuture", + methods: [completeMethod, completeExceptionallyMethod] + ) + + public static var `class`: jclass { + cache.javaClass + } + + public static var complete: jmethodID { + cache.methods[completeMethod]! + } + + public static var completeExceptionally: jmethodID { + cache.methods[completeExceptionallyMethod]! + } + } + public enum Exception { private static let messageConstructor = Method(name: "", signature: "(Ljava/lang/String;)V") diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SimpleCompletableFuture.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SimpleCompletableFuture.java new file mode 100644 index 00000000..b9252723 --- /dev/null +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SimpleCompletableFuture.java @@ -0,0 +1,223 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package org.swift.swiftkit.core; + +import java.util.Deque; +import java.util.concurrent.*; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Function; + +/** + * A simple completable {@link Future} for platforms that do not support {@link java.util.concurrent.CompletableFuture}, + * e.g. before Java 8, and/or before Android 23. + *

+ * Prefer using the {@link CompletableFuture} for bridging Swift asynchronous functions, i.e. use the {@code completableFuture} + * mode in {@code swift-java jextract}. + * + * @param The result type + */ +public final class SimpleCompletableFuture implements Future { + // Marker object used to indicate the Future has not yet been completed. + private static final Object PENDING = new Object(); + private static final Object NULL = new Object(); + private final AtomicReference result = new AtomicReference<>(PENDING); + + private final Deque callbacks = new ConcurrentLinkedDeque<>(); + + /** + * Wrapper type we use to indicate that a recorded result was a failure (recorded using {@link SimpleCompletableFuture#completeExceptionally(Throwable)}. + * Since no-one else can instantiate this type, we know for sure that a recorded CompletedExceptionally indicates a failure. + */ + static final class CompletedExceptionally { + private final Throwable exception; + + private CompletedExceptionally(Throwable exception) { + this.exception = exception; + } + } + + /** + * Returns a new future that, when this stage completes + * normally, is executed with this stage's result as the argument + * to the supplied function. + * + *

This method is analogous to + * {@link java.util.Optional#map Optional.map} and + * {@link java.util.stream.Stream#map Stream.map}. + * + * @return the new Future + */ + public Future thenApply(Function fn) { + SimpleCompletableFuture newFuture = new SimpleCompletableFuture<>(); + addCallback(() -> { + Object observed = this.result.get(); + if (observed instanceof CompletedExceptionally) { + newFuture.completeExceptionally(((CompletedExceptionally) observed).exception); + } else { + try { + // We're guaranteed that an observed result is of type T. + // noinspection unchecked + U newResult = fn.apply(observed == NULL ? null : (T) observed); + newFuture.complete(newResult); + } catch (Throwable t) { + newFuture.completeExceptionally(t); + } + } + }); + return newFuture; + } + + /** + * If not already completed, sets the value returned by {@link #get()} and + * related methods to the given value. + * + * @param value the result value + * @return {@code true} if this invocation caused this CompletableFuture + * to transition to a completed state, else {@code false} + */ + public boolean complete(T value) { + if (result.compareAndSet(PENDING, value == null ? NULL : value)) { + synchronized (result) { + result.notifyAll(); + } + runCallbacks(); + return true; + } + + return false; + } + + /** + * If not already completed, causes invocations of {@link #get()} + * and related methods to throw the given exception. + * + * @param ex the exception + * @return {@code true} if this invocation caused this CompletableFuture + * to transition to a completed state, else {@code false} + */ + public boolean completeExceptionally(Throwable ex) { + if (result.compareAndSet(PENDING, new CompletedExceptionally(ex))) { + synchronized (result) { + result.notifyAll(); + } + runCallbacks(); + return true; + } + + return false; + } + + private void runCallbacks() { + // This is a pretty naive implementation; even if we enter this by racing a thenApply, + // with a completion; we're using a concurrent deque so we won't happen to trigger a callback twice. + Runnable callback; + while ((callback = callbacks.pollFirst()) != null) { + callback.run(); + } + } + + @Override + public boolean cancel(boolean mayInterruptIfRunning) { + // TODO: If we're representing a Swift Task computation with this future, + // we could trigger a Task.cancel() from here + return false; + } + + @Override + public boolean isCancelled() { + return false; + } + + @Override + public boolean isDone() { + return this.result.get() != PENDING; + } + + @Override + public T get() throws InterruptedException, ExecutionException { + Object observed; + // If PENDING check fails immediately, we have no need to take the result lock at all. + while ((observed = result.get()) == PENDING) { + synchronized (result) { + if (result.get() == PENDING) { + result.wait(); + } + } + } + + return getReturn(observed); + } + + @Override + public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { + Object observed; + + // Fast path: are we already completed and don't need to do any waiting? + if ((observed = result.get()) != PENDING) { + return get(); + } + + long nanos = unit.toNanos(timeout); + synchronized (result) { + if (!isDone()) { + if (nanos <= 0) { + throw new TimeoutException(); + } + long deadline = System.nanoTime() + nanos; + while (!isDone()) { + nanos = deadline - System.nanoTime(); + if (nanos <= 0L) { + throw new TimeoutException(); + } + result.wait(nanos / 1000000, (int) (nanos % 1000000)); + } + } + } + + // Seems we broke out of the wait loop, let's trigger the 'get()' implementation + observed = result.get(); + if (observed == PENDING) { + throw new ExecutionException("Unexpectedly finished wait-loop while future was not completed, this is a bug.", null); + } + return getReturn(observed); + } + + private T getReturn(Object observed) throws ExecutionException { + if (observed instanceof CompletedExceptionally) { + // We observed a failure, unwrap and throw it + Throwable exception = ((CompletedExceptionally) observed).exception; + if (exception instanceof CancellationException) { + throw (CancellationException) exception; + } + throw new ExecutionException(exception); + } else if (observed == NULL) { + return null; + } else { + // We're guaranteed that we only allowed registering completions of type `T` + // noinspection unchecked + return (T) observed; + } + } + + private void addCallback(Runnable action) { + callbacks.add(action); + if (isDone()) { + // This may race, but we don't care since triggering the callbacks is going to be at-most-once + // by means of using the concurrent deque as our list of callbacks. + runCallbacks(); + } + } + +} \ No newline at end of file diff --git a/SwiftKitCore/src/test/java/org/swift/swiftkit/core/SimpleCompletableFutureTest.java b/SwiftKitCore/src/test/java/org/swift/swiftkit/core/SimpleCompletableFutureTest.java new file mode 100644 index 00000000..b4bb98b3 --- /dev/null +++ b/SwiftKitCore/src/test/java/org/swift/swiftkit/core/SimpleCompletableFutureTest.java @@ -0,0 +1,185 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package org.swift.swiftkit.core; + +import org.junit.jupiter.api.Test; + +import java.util.Objects; +import java.util.concurrent.*; +import static org.junit.jupiter.api.Assertions.*; + +public class SimpleCompletableFutureTest { + + @Test + void testCompleteAndGet() throws ExecutionException, InterruptedException { + SimpleCompletableFuture future = new SimpleCompletableFuture<>(); + assertFalse(future.isDone()); + assertTrue(future.complete("test")); + assertTrue(future.isDone()); + assertEquals("test", future.get()); + } + + @Test + void testCompleteWithNullAndGet() throws ExecutionException, InterruptedException { + SimpleCompletableFuture future = new SimpleCompletableFuture<>(); + assertFalse(future.isDone()); + assertTrue(future.complete(null)); + assertTrue(future.isDone()); + assertNull(future.get()); + } + + @Test + void testCompleteExceptionallyAndGet() { + SimpleCompletableFuture future = new SimpleCompletableFuture<>(); + RuntimeException ex = new RuntimeException("Test Exception"); + assertTrue(future.completeExceptionally(ex)); + assertTrue(future.isDone()); + + ExecutionException thrown = assertThrows(ExecutionException.class, future::get); + assertEquals(ex, thrown.getCause()); + } + + @Test + void testGetWithTimeout_timesOut() { + SimpleCompletableFuture future = new SimpleCompletableFuture<>(); + assertThrows(TimeoutException.class, () -> future.get(10, TimeUnit.MILLISECONDS)); + } + + @Test + void testGetWithTimeout_completesInTime() throws ExecutionException, InterruptedException, TimeoutException { + SimpleCompletableFuture future = new SimpleCompletableFuture<>(); + future.complete("fast"); + assertEquals("fast", future.get(10, TimeUnit.MILLISECONDS)); + } + + @Test + void testGetWithTimeout_completesInTimeAfterWait() throws Exception { + SimpleCompletableFuture future = new SimpleCompletableFuture<>(); + Thread t = new Thread(() -> { + try { + Thread.sleep(50); + } catch (InterruptedException e) { + // ignore + } + future.complete("late"); + }); + t.start(); + assertEquals("late", future.get(200, TimeUnit.MILLISECONDS)); + } + + @Test + void testThenApply() throws ExecutionException, InterruptedException { + SimpleCompletableFuture future = new SimpleCompletableFuture<>(); + Future mapped = future.thenApply(String::length); + + future.complete("hello"); + + assertEquals(5, mapped.get()); + } + + @Test + void testThenApplyOnCompletedFuture() throws ExecutionException, InterruptedException { + SimpleCompletableFuture future = new SimpleCompletableFuture<>(); + future.complete("done"); + + Future mapped = future.thenApply(String::length); + + assertEquals(4, mapped.get()); + } + + @Test + void testThenApplyWithNull() throws ExecutionException, InterruptedException { + SimpleCompletableFuture future = new SimpleCompletableFuture<>(); + Future mapped = future.thenApply(Objects::isNull); + + future.complete(null); + + assertTrue(mapped.get()); + } + + @Test + void testThenApplyExceptionally() { + SimpleCompletableFuture future = new SimpleCompletableFuture<>(); + RuntimeException ex = new RuntimeException("Initial Exception"); + Future mapped = future.thenApply(String::length); + + future.completeExceptionally(ex); + + ExecutionException thrown = assertThrows(ExecutionException.class, mapped::get); + assertEquals(ex, thrown.getCause()); + } + + @Test + void testThenApplyTransformationThrows() { + SimpleCompletableFuture future = new SimpleCompletableFuture<>(); + RuntimeException ex = new RuntimeException("Transformation Exception"); + Future mapped = future.thenApply(s -> { + throw ex; + }); + + future.complete("hello"); + + ExecutionException thrown = assertThrows(ExecutionException.class, mapped::get); + assertEquals(ex, thrown.getCause()); + } + + @Test + void testCompleteTwice() throws ExecutionException, InterruptedException { + SimpleCompletableFuture future = new SimpleCompletableFuture<>(); + + assertTrue(future.complete("first")); + assertFalse(future.complete("second")); + + assertEquals("first", future.get()); + } + + @Test + void testCompleteThenCompleteExceptionally() throws ExecutionException, InterruptedException { + SimpleCompletableFuture future = new SimpleCompletableFuture<>(); + + assertTrue(future.complete("first")); + assertFalse(future.completeExceptionally(new RuntimeException("second"))); + + assertEquals("first", future.get()); + } + + @Test + void testCompleteExceptionallyThenComplete() { + SimpleCompletableFuture future = new SimpleCompletableFuture<>(); + RuntimeException ex = new RuntimeException("first"); + + assertTrue(future.completeExceptionally(ex)); + assertFalse(future.complete("second")); + + ExecutionException thrown = assertThrows(ExecutionException.class, future::get); + assertEquals(ex, thrown.getCause()); + } + + @Test + void testIsDone() { + SimpleCompletableFuture future = new SimpleCompletableFuture<>(); + assertFalse(future.isDone()); + future.complete("done"); + assertTrue(future.isDone()); + } + + @Test + void testIsDoneExceptionally() { + SimpleCompletableFuture future = new SimpleCompletableFuture<>(); + assertFalse(future.isDone()); + future.completeExceptionally(new RuntimeException()); + assertTrue(future.isDone()); + } +} diff --git a/Tests/JExtractSwiftTests/JNI/JNIAsyncTests.swift b/Tests/JExtractSwiftTests/JNI/JNIAsyncTests.swift index 1930e601..f246bd0f 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIAsyncTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIAsyncTests.swift @@ -14,6 +14,7 @@ import JExtractSwiftLib import Testing +import SwiftJavaConfigurationShared @Suite struct JNIAsyncTests { @@ -33,9 +34,9 @@ struct JNIAsyncTests { * } */ public static java.util.concurrent.CompletableFuture asyncVoid() { - java.util.concurrent.CompletableFuture $future = new java.util.concurrent.CompletableFuture(); - SwiftModule.$asyncVoid($future); - return $future.thenApply((futureResult$) -> { + java.util.concurrent.CompletableFuture future$ = new java.util.concurrent.CompletableFuture(); + SwiftModule.$asyncVoid(future$); + return future$.thenApply((futureResult$) -> { return futureResult$; } ); @@ -107,9 +108,9 @@ struct JNIAsyncTests { * } */ public static java.util.concurrent.CompletableFuture async() { - java.util.concurrent.CompletableFuture $future = new java.util.concurrent.CompletableFuture(); - SwiftModule.$async($future); - return $future.thenApply((futureResult$) -> { + java.util.concurrent.CompletableFuture future$ = new java.util.concurrent.CompletableFuture(); + SwiftModule.$async(future$); + return future$.thenApply((futureResult$) -> { return futureResult$; } ); @@ -195,9 +196,9 @@ struct JNIAsyncTests { * } */ public static java.util.concurrent.CompletableFuture async(long i) { - java.util.concurrent.CompletableFuture $future = new java.util.concurrent.CompletableFuture(); - SwiftModule.$async(i, $future); - return $future.thenApply((futureResult$) -> { + java.util.concurrent.CompletableFuture future$ = new java.util.concurrent.CompletableFuture(); + SwiftModule.$async(i, future$); + return future$.thenApply((futureResult$) -> { return futureResult$; } ); @@ -276,9 +277,9 @@ struct JNIAsyncTests { * } */ public static java.util.concurrent.CompletableFuture async(MyClass c, SwiftArena swiftArena$) { - java.util.concurrent.CompletableFuture $future = new java.util.concurrent.CompletableFuture(); - SwiftModule.$async(c.$memoryAddress(), $future); - return $future.thenApply((futureResult$) -> { + java.util.concurrent.CompletableFuture future$ = new java.util.concurrent.CompletableFuture(); + SwiftModule.$async(c.$memoryAddress(), future$); + return future$.thenApply((futureResult$) -> { return MyClass.wrapMemoryAddressUnsafe(futureResult$, swiftArena$); } ); @@ -365,9 +366,9 @@ struct JNIAsyncTests { expectedChunks: [ """ public static java.util.concurrent.CompletableFuture async(java.lang.String s) { - java.util.concurrent.CompletableFuture $future = new java.util.concurrent.CompletableFuture(); - SwiftModule.$async(s, $future); - return $future.thenApply((futureResult$) -> { + java.util.concurrent.CompletableFuture future$ = new java.util.concurrent.CompletableFuture(); + SwiftModule.$async(s, future$); + return future$.thenApply((futureResult$) -> { return futureResult$; } ); @@ -408,4 +409,65 @@ struct JNIAsyncTests { ] ) } + + @Test("Import: (MyClass) async -> MyClass (Java, LegacyFuture)") + func legacyFuture_asyncMyClassToMyClass_java() throws { + var config = Configuration() + config.asyncFuncMode = .legacyFuture + + try assertOutput( + input: """ + class MyClass { } + + public func async(c: MyClass) async -> MyClass + """, + config: config, + .jni, .java, + detectChunkByInitialLines: 1, + expectedChunks: [ + """ + public static java.util.concurrent.Future async(MyClass c, SwiftArena swiftArena$) { + org.swift.swiftkit.core.SimpleCompletableFuture future$ = new org.swift.swiftkit.core.SimpleCompletableFuture(); + SwiftModule.$async(c.$memoryAddress(), future$); + return future$.thenApply((futureResult$) -> { + return MyClass.wrapMemoryAddressUnsafe(futureResult$, swiftArena$); + } + ); + } + """, + """ + private static native void $async(long c, org.swift.swiftkit.core.SimpleCompletableFuture result_future); + """, + ] + ) + } + + @Test("Import: (MyClass) async -> MyClass (Swift, LegacyFuture)") + func legacyFuture_asyncMyClassToMyClass_swift() throws { + var config = Configuration() + config.asyncFuncMode = .legacyFuture + + try assertOutput( + input: """ + class MyClass { } + + public func async(c: MyClass) async -> MyClass + """, + config: config, + .jni, .swift, + detectChunkByInitialLines: 1, + expectedChunks: [ + """ + @_cdecl("Java_com_example_swift_SwiftModule__00024async__JLorg_swift_swiftkit_core_SimpleCompletableFuture_2") + func Java_com_example_swift_SwiftModule__00024async__JLorg_swift_swiftkit_core_SimpleCompletableFuture_2(environment: UnsafeMutablePointer!, thisClass: jclass, c: jlong, result_future: jobject?) { + ... + var task: Task? = nil + ... + environment.interface.CallBooleanMethodA(environment, globalFuture, _JNIMethodIDCache.SimpleCompletableFuture.complete, [jvalue(l: boxedResult$)]) + ... + } + """ + ] + ) + } } From eea0638c5573c89bf67698a7e131be04970042c8 Mon Sep 17 00:00:00 2001 From: Mads Odgaard Date: Mon, 1 Dec 2025 13:22:18 +0100 Subject: [PATCH 416/426] link log on android (#467) --- Package.swift | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Package.swift b/Package.swift index b4c20208..d877ae69 100644 --- a/Package.swift +++ b/Package.swift @@ -386,6 +386,9 @@ let package = Package( swiftSettings: [ .swiftLanguageMode(.v5), .unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"], .when(platforms: [.macOS, .linux, .windows])) + ], + linkerSettings: [ + .linkedLibrary("log", .when(platforms: [.android])) ] ), From 67c20f76d083e18a95abfd7c9a2c830ba350cb7d Mon Sep 17 00:00:00 2001 From: Mads Odgaard Date: Mon, 1 Dec 2025 15:21:23 +0100 Subject: [PATCH 417/426] Fix JNI caching for native threads (#464) --- ...ift2JavaGenerator+SwiftThunkPrinting.swift | 16 +- Sources/SwiftJava/generated/JavaThread.swift | 229 ++++++++++++++++++ Sources/SwiftJava/swift-java.config | 1 + Sources/SwiftJavaRuntimeSupport/JNI.swift | 31 +++ .../JNIMethodIDCaches.swift | 3 - .../_JNIBoxedConversions.swift | 8 - .../_JNIMethodIDCache.swift | 31 ++- 7 files changed, 302 insertions(+), 17 deletions(-) create mode 100644 Sources/SwiftJava/generated/JavaThread.swift create mode 100644 Sources/SwiftJavaRuntimeSupport/JNI.swift diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift index d3b47732..6628be33 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift @@ -119,6 +119,8 @@ extension JNISwift2JavaGenerator { private func printGlobalSwiftThunkSources(_ printer: inout CodePrinter) throws { printHeader(&printer) + printJNIOnLoad(&printer) + for decl in analysis.importedGlobalFuncs { printSwiftFunctionThunk(&printer, decl) printer.println() @@ -130,6 +132,18 @@ extension JNISwift2JavaGenerator { } } + private func printJNIOnLoad(_ printer: inout CodePrinter) { + printer.print( + """ + @_cdecl("JNI_OnLoad") + func JNI_OnLoad(javaVM: JavaVMPointer, reserved: UnsafeMutableRawPointer) -> jint { + SwiftJavaRuntimeSupport._JNI_OnLoad(javaVM, reserved) + return JNI_VERSION_1_6 + } + """ + ) + } + private func printNominalTypeThunks(_ printer: inout CodePrinter, _ type: ImportedNominalType) throws { printHeader(&printer) @@ -222,7 +236,7 @@ extension JNISwift2JavaGenerator { let methodSignature = MethodSignature(resultType: .void, parameterTypes: enumCase.parameterConversions.map(\.native.javaType)) let methods = #"[.init(name: "", signature: "\#(methodSignature.mangledName)")]"# - return #"_JNIMethodIDCache(environment: try! JavaVirtualMachine.shared().environment(), className: "\#(nativeParametersClassName)", methods: \#(methods))"# + return #"_JNIMethodIDCache(className: "\#(nativeParametersClassName)", methods: \#(methods))"# } private func printEnumGetAsCaseThunk( diff --git a/Sources/SwiftJava/generated/JavaThread.swift b/Sources/SwiftJava/generated/JavaThread.swift new file mode 100644 index 00000000..c71e933b --- /dev/null +++ b/Sources/SwiftJava/generated/JavaThread.swift @@ -0,0 +1,229 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import CSwiftJavaJNI + +@JavaClass("java.lang.Thread") +open class JavaThread: JavaObject { + @JavaMethod + @_nonoverride public convenience init(_ arg0: String, environment: JNIEnvironment? = nil) + + @JavaMethod + @_nonoverride public convenience init(environment: JNIEnvironment? = nil) + + @JavaMethod + open func getName() -> String + + @JavaMethod + open func run() + + @JavaMethod + open func interrupt() + + @JavaMethod + open override func toString() -> String + + @JavaMethod + open override func clone() throws -> JavaObject! + + @JavaMethod + open func join(_ arg0: Int64, _ arg1: Int32) throws + + @JavaMethod + open func join() throws + + @JavaMethod + open func join(_ arg0: Int64) throws + + @JavaMethod + open func setContextClassLoader(_ arg0: JavaClassLoader?) + + @JavaMethod + open func setPriority(_ arg0: Int32) + + @JavaMethod + open func setDaemon(_ arg0: Bool) + + @JavaMethod + open func start() + + @JavaMethod + open func getPriority() -> Int32 + + @JavaMethod + open func isDaemon() -> Bool + + @JavaMethod + open func getContextClassLoader() -> JavaClassLoader! + + @JavaMethod + open func isVirtual() -> Bool + + @JavaMethod + open func isAlive() -> Bool + + @JavaMethod + open func threadId() -> Int64 + + @JavaMethod + open func getUncaughtExceptionHandler() -> JavaThread.UncaughtExceptionHandler! + + @JavaMethod + open func stop() + + @JavaMethod + open func isInterrupted() -> Bool + + @JavaMethod + open func setName(_ arg0: String) + + @JavaMethod + open func checkAccess() + + @JavaMethod + open func getId() -> Int64 + + @JavaMethod + open func setUncaughtExceptionHandler(_ arg0: JavaThread.UncaughtExceptionHandler?) +} +extension JavaThread { + @JavaInterface("java.lang.Thread$Builder") + public struct Builder { + @JavaMethod + public func name(_ arg0: String) -> JavaThread.Builder! + + @JavaMethod + public func name(_ arg0: String, _ arg1: Int64) -> JavaThread.Builder! + + @JavaMethod + public func uncaughtExceptionHandler(_ arg0: JavaThread.UncaughtExceptionHandler?) -> JavaThread.Builder! + + @JavaMethod + public func inheritInheritableThreadLocals(_ arg0: Bool) -> JavaThread.Builder! + } +} +extension JavaThread.Builder { + @JavaInterface("java.lang.Thread$Builder$OfPlatform", extends: JavaThread.Builder.self) + public struct OfPlatform { + @JavaMethod + public func name(_ arg0: String, _ arg1: Int64) -> JavaThread.Builder! + + @JavaMethod + public func name(_ arg0: String, _ arg1: Int64) -> JavaThread.Builder.OfPlatform! + + @JavaMethod + public func name(_ arg0: String) -> JavaThread.Builder! + + @JavaMethod + public func name(_ arg0: String) -> JavaThread.Builder.OfPlatform! + + @JavaMethod + public func priority(_ arg0: Int32) -> JavaThread.Builder.OfPlatform! + + @JavaMethod + public func daemon() -> JavaThread.Builder.OfPlatform! + + @JavaMethod + public func daemon(_ arg0: Bool) -> JavaThread.Builder.OfPlatform! + + @JavaMethod + public func uncaughtExceptionHandler(_ arg0: JavaThread.UncaughtExceptionHandler?) -> JavaThread.Builder.OfPlatform! + + @JavaMethod + public func uncaughtExceptionHandler(_ arg0: JavaThread.UncaughtExceptionHandler?) -> JavaThread.Builder! + + @JavaMethod + public func stackSize(_ arg0: Int64) -> JavaThread.Builder.OfPlatform! + + @JavaMethod + public func inheritInheritableThreadLocals(_ arg0: Bool) -> JavaThread.Builder.OfPlatform! + + @JavaMethod + public func inheritInheritableThreadLocals(_ arg0: Bool) -> JavaThread.Builder! + } +} +extension JavaThread.Builder { + @JavaInterface("java.lang.Thread$Builder$OfVirtual", extends: JavaThread.Builder.self) + public struct OfVirtual { + @JavaMethod + public func name(_ arg0: String, _ arg1: Int64) -> JavaThread.Builder! + + @JavaMethod + public func name(_ arg0: String, _ arg1: Int64) -> JavaThread.Builder.OfVirtual! + + @JavaMethod + public func name(_ arg0: String) -> JavaThread.Builder! + + @JavaMethod + public func name(_ arg0: String) -> JavaThread.Builder.OfVirtual! + + @JavaMethod + public func uncaughtExceptionHandler(_ arg0: JavaThread.UncaughtExceptionHandler?) -> JavaThread.Builder! + + @JavaMethod + public func uncaughtExceptionHandler(_ arg0: JavaThread.UncaughtExceptionHandler?) -> JavaThread.Builder.OfVirtual! + + @JavaMethod + public func inheritInheritableThreadLocals(_ arg0: Bool) -> JavaThread.Builder.OfVirtual! + + @JavaMethod + public func inheritInheritableThreadLocals(_ arg0: Bool) -> JavaThread.Builder! + } +} +extension JavaThread { + @JavaInterface("java.lang.Thread$UncaughtExceptionHandler") + public struct UncaughtExceptionHandler { + @JavaMethod + public func uncaughtException(_ arg0: JavaThread?, _ arg1: Throwable?) + } +} +extension JavaClass { + @JavaStaticField(isFinal: true) + public var MIN_PRIORITY: Int32 + + @JavaStaticField(isFinal: true) + public var NORM_PRIORITY: Int32 + + @JavaStaticField(isFinal: true) + public var MAX_PRIORITY: Int32 + + @JavaStaticMethod + public func currentThread() -> JavaThread! + + @JavaStaticMethod + public func onSpinWait() + + @JavaStaticMethod + public func holdsLock(_ arg0: JavaObject?) -> Bool + + @JavaStaticMethod + public func interrupted() -> Bool + + @JavaStaticMethod + public func activeCount() -> Int32 + + @JavaStaticMethod + public func enumerate(_ arg0: [JavaThread?]) -> Int32 + + @JavaStaticMethod + public func yield() + + @JavaStaticMethod + public func sleep(_ arg0: Int64) throws + + @JavaStaticMethod + public func sleep(_ arg0: Int64, _ arg1: Int32) throws + + @JavaStaticMethod + public func ofPlatform() -> JavaThread.Builder.OfPlatform! + + @JavaStaticMethod + public func ofVirtual() -> JavaThread.Builder.OfVirtual! + + @JavaStaticMethod + public func dumpStack() + + @JavaStaticMethod + public func setDefaultUncaughtExceptionHandler(_ arg0: JavaThread.UncaughtExceptionHandler?) + + @JavaStaticMethod + public func getDefaultUncaughtExceptionHandler() -> JavaThread.UncaughtExceptionHandler! +} diff --git a/Sources/SwiftJava/swift-java.config b/Sources/SwiftJava/swift-java.config index d07ff162..d43096a7 100644 --- a/Sources/SwiftJava/swift-java.config +++ b/Sources/SwiftJava/swift-java.config @@ -23,6 +23,7 @@ "java.lang.Void" : "JavaVoid", "java.lang.CharSequence": "CharSequence", "java.lang.Appendable": "Appendable", + "java.lang.Thread": "JavaThread", "java.util.Optional": "JavaOptional", "java.util.OptionalDouble": "JavaOptionalDouble", "java.util.OptionalInt": "JavaOptionalInt", diff --git a/Sources/SwiftJavaRuntimeSupport/JNI.swift b/Sources/SwiftJavaRuntimeSupport/JNI.swift new file mode 100644 index 00000000..b6f0117d --- /dev/null +++ b/Sources/SwiftJavaRuntimeSupport/JNI.swift @@ -0,0 +1,31 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import SwiftJava +import CSwiftJavaJNI + +final class JNI { + static var shared: JNI! + + let applicationClassLoader: JavaClassLoader + + init(fromVM javaVM: JavaVirtualMachine) { + self.applicationClassLoader = try! JavaClass(environment: javaVM.environment()).currentThread().getContextClassLoader() + } +} + +// Called by generated code, and not automatically by Java. +public func _JNI_OnLoad(_ javaVM: JavaVMPointer, _ reserved: UnsafeMutableRawPointer) { + JNI.shared = JNI(fromVM: JavaVirtualMachine(adoptingJVM: javaVM)) +} diff --git a/Sources/SwiftJavaRuntimeSupport/JNIMethodIDCaches.swift b/Sources/SwiftJavaRuntimeSupport/JNIMethodIDCaches.swift index 56fe0351..16a9c899 100644 --- a/Sources/SwiftJavaRuntimeSupport/JNIMethodIDCaches.swift +++ b/Sources/SwiftJavaRuntimeSupport/JNIMethodIDCaches.swift @@ -27,7 +27,6 @@ extension _JNIMethodIDCache { ) private static let cache = _JNIMethodIDCache( - environment: try! JavaVirtualMachine.shared().environment(), className: "java/util/concurrent/CompletableFuture", methods: [completeMethod, completeExceptionallyMethod] ) @@ -59,7 +58,6 @@ extension _JNIMethodIDCache { ) private static let cache = _JNIMethodIDCache( - environment: try! JavaVirtualMachine.shared().environment(), className: "org/swift/swiftkit/core/SimpleCompletableFuture", methods: [completeMethod, completeExceptionallyMethod] ) @@ -81,7 +79,6 @@ extension _JNIMethodIDCache { private static let messageConstructor = Method(name: "", signature: "(Ljava/lang/String;)V") private static let cache = _JNIMethodIDCache( - environment: try! JavaVirtualMachine.shared().environment(), className: "java/lang/Exception", methods: [messageConstructor] ) diff --git a/Sources/SwiftJavaRuntimeSupport/_JNIBoxedConversions.swift b/Sources/SwiftJavaRuntimeSupport/_JNIBoxedConversions.swift index 68d98ffc..ad4572ca 100644 --- a/Sources/SwiftJavaRuntimeSupport/_JNIBoxedConversions.swift +++ b/Sources/SwiftJavaRuntimeSupport/_JNIBoxedConversions.swift @@ -26,47 +26,39 @@ public enum _JNIBoxedConversions { private static let doubleMethod = _JNIMethodIDCache.Method(name: "valueOf", signature: "(D)Ljava/lang/Double;", isStatic: true) private static let booleanCache = _JNIMethodIDCache( - environment: try! JavaVirtualMachine.shared().environment(), className: "java/lang/Boolean", methods: [booleanMethod] ) private static let byteCache = _JNIMethodIDCache( - environment: try! JavaVirtualMachine.shared().environment(), className: "java/lang/Byte", methods: [byteMethod] ) private static let charCache = _JNIMethodIDCache( - environment: try! JavaVirtualMachine.shared().environment(), className: "java/lang/Character", methods: [charMethod] ) private static let shortCache = _JNIMethodIDCache( - environment: try! JavaVirtualMachine.shared().environment(), className: "java/lang/Short", methods: [shortMethod] ) private static let intCache = _JNIMethodIDCache( - environment: try! JavaVirtualMachine.shared().environment(), className: "java/lang/Integer", methods: [intMethod] ) private static let longCache = _JNIMethodIDCache( - environment: try! JavaVirtualMachine.shared().environment(), className: "java/lang/Long", methods: [longMethod] ) private static let floatCache = _JNIMethodIDCache( - environment: try! JavaVirtualMachine.shared().environment(), className: "java/lang/Float", methods: [floatMethod] ) private static let doubleCache = _JNIMethodIDCache( - environment: try! JavaVirtualMachine.shared().environment(), className: "java/lang/Double", methods: [doubleMethod] ) diff --git a/Sources/SwiftJavaRuntimeSupport/_JNIMethodIDCache.swift b/Sources/SwiftJavaRuntimeSupport/_JNIMethodIDCache.swift index dd7eb5d1..fbadf191 100644 --- a/Sources/SwiftJavaRuntimeSupport/_JNIMethodIDCache.swift +++ b/Sources/SwiftJavaRuntimeSupport/_JNIMethodIDCache.swift @@ -39,11 +39,33 @@ public final class _JNIMethodIDCache: Sendable { self._class! } - public init(environment: UnsafeMutablePointer!, className: String, methods: [Method]) { - guard let clazz = environment.interface.FindClass(environment, className) else { - fatalError("Class \(className) could not be found!") + /// An optional reference to a java object holder + /// if we cached this class through the class loader + /// This is to make sure that the underlying reference remains valid + nonisolated(unsafe) private let javaObjectHolder: JavaObjectHolder? + + public init(className: String, methods: [Method]) { + let environment = try! JavaVirtualMachine.shared().environment() + + let clazz: jobject + if let jniClass = environment.interface.FindClass(environment, className) { + clazz = environment.interface.NewGlobalRef(environment, jniClass)! + self.javaObjectHolder = nil + } else { + // Clear any ClassNotFound exceptions from FindClass + environment.interface.ExceptionClear(environment) + + if let javaClass = try? JNI.shared.applicationClassLoader.loadClass( + className.replacingOccurrences(of: "/", with: ".") + ) { + clazz = javaClass.javaThis + self.javaObjectHolder = javaClass.javaHolder + } else { + fatalError("Class \(className) could not be found!") + } } - self._class = environment.interface.NewGlobalRef(environment, clazz)! + + self._class = clazz self.methods = methods.reduce(into: [:]) { (result, method) in if method.isStatic { if let methodID = environment.interface.GetStaticMethodID(environment, clazz, method.name, method.signature) { @@ -61,7 +83,6 @@ public final class _JNIMethodIDCache: Sendable { } } - public subscript(_ method: Method) -> jmethodID? { methods[method] } From 3be8df2d8d47f45cb8e14805de3685814adaba82 Mon Sep 17 00:00:00 2001 From: Mads Odgaard Date: Tue, 2 Dec 2025 15:35:58 +0100 Subject: [PATCH 418/426] jextract: add support for implementing Swift protocols in Java (#449) Co-authored-by: Konrad `ktoso` Malawski --- .../JExtractSwiftPlugin.swift | 199 +++++++++- Plugins/SwiftJavaPlugin/SwiftJavaPlugin.swift | 4 +- .../JavaDependencySampleApp/ci-validate.sh | 11 +- Samples/JavaKitSampleApp/ci-validate.sh | 10 +- Samples/JavaProbablyPrime/ci-validate.sh | 10 +- .../MySwiftLibrary/CallbackProtcol.swift | 77 ++++ .../Sources/MySwiftLibrary/Storage.swift | 36 ++ .../Sources/MySwiftLibrary/swift-java.config | 1 + .../SwiftJavaExtractJNISampleApp/build.gradle | 10 +- .../ci-validate.sh | 41 ++- .../example/swift/ProtocolCallbacksTest.java | 117 ++++++ .../java/com/example/swift/ProtocolTest.java | 30 ++ .../Convenience/JavaType+Extensions.swift | 2 +- .../Convenience/String+Extensions.swift | 2 +- .../Convenience/SwiftSyntax+Extensions.swift | 2 +- Sources/JExtractSwiftLib/ImportedDecls.swift | 9 + ...Generator+InterfaceWrapperGeneration.swift | 342 ++++++++++++++++++ ...t2JavaGenerator+JavaBindingsPrinting.swift | 63 +++- ...ISwift2JavaGenerator+JavaTranslation.swift | 59 +-- ...wift2JavaGenerator+NativeTranslation.swift | 133 +++++-- ...ift2JavaGenerator+SwiftThunkPrinting.swift | 226 +++++++++++- .../JNI/JNISwift2JavaGenerator.swift | 8 + .../JavaTypes/JavaType+JDK.swift | 6 + .../SwiftTypes/SwiftKnownTypeDecls.swift | 14 + .../SwiftTypes/SwiftType.swift | 6 +- .../Constructor+Utilities.swift | 5 - .../JavaLangReflect/HasJavaModifiers.swift | 47 +++ .../JavaLangReflect/Method+Utilities.swift | 22 -- .../SwiftJava/JVM/JavaVirtualMachine.swift | 2 +- Sources/SwiftJava/Macros.swift | 5 +- Sources/SwiftJava/String+Extensions.swift | 10 +- .../Configuration.swift | 12 +- .../Documentation.docc/index.md | 2 +- Sources/SwiftJavaMacros/JavaMethodMacro.swift | 18 +- .../JNIMethodIDCaches.swift | 29 ++ .../generated/JavaJNISwiftInstance.swift | 21 ++ .../Commands/ConfigureCommand.swift | 115 +++--- .../Commands/JExtractCommand.swift | 18 +- .../Commands/WrapJavaCommand.swift | 102 +++++- Sources/SwiftJavaTool/CommonOptions.swift | 5 +- .../SwiftJavaBaseAsyncParsableCommand.swift | 14 +- .../JavaClassTranslator.swift | 14 + Sources/SwiftJavaToolLib/StringExtras.swift | 5 + .../JExtractSwiftTests/JNI/JNIEnumTests.swift | 10 +- .../JNI/JNIProtocolTests.swift | 237 ++++++++---- .../MemoryManagementModeTests.swift | 2 +- .../WrapJavaTests/GenericsWrapJavaTests.swift | 41 ++- 47 files changed, 1871 insertions(+), 283 deletions(-) create mode 100644 Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/CallbackProtcol.swift create mode 100644 Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/Storage.swift create mode 100644 Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/ProtocolCallbacksTest.java create mode 100644 Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+InterfaceWrapperGeneration.swift create mode 100644 Sources/JavaStdlib/JavaLangReflect/HasJavaModifiers.swift create mode 100644 Sources/SwiftJavaRuntimeSupport/generated/JavaJNISwiftInstance.swift diff --git a/Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift b/Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift index 8d0be455..2808b6d3 100644 --- a/Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift +++ b/Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift @@ -25,9 +25,12 @@ struct JExtractSwiftBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin { func createBuildCommands(context: PluginContext, target: Target) throws -> [Command] { let toolURL = try context.tool(named: "SwiftJavaTool").url - + + var commands: [Command] = [] + guard let sourceModule = target.sourceModule else { return [] } + // Note: Target doesn't have a directoryURL counterpart to directory, // so we cannot eliminate this deprecation warning. for dependency in target.dependencies { @@ -80,7 +83,7 @@ struct JExtractSwiftBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin { let (moduleName, configFile) = moduleAndConfigFile return [ "--depends-on", - "\(configFile.path(percentEncoded: false))" + "\(moduleName)=\(configFile.path(percentEncoded: false))" ] } arguments += dependentConfigFilesArguments @@ -123,15 +126,165 @@ struct JExtractSwiftBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin { print("[swift-java-plugin] Output swift files:\n - \(outputSwiftFiles.map({$0.absoluteString}).joined(separator: "\n - "))") - return [ + var jextractOutputFiles = outputSwiftFiles + + // If the developer has enabled java callbacks in the configuration (default is false) + // and we are running in JNI mode, we will run additional phases in this build plugin + // to generate Swift wrappers using wrap-java that can be used to callback to Java. + let shouldRunJavaCallbacksPhases = + if let configuration, + configuration.enableJavaCallbacks == true, + configuration.effectiveMode == .jni { + true + } else { + false + } + + // Extract list of all sources + let javaSourcesListFileName = "jextract-generated-sources.txt" + let javaSourcesFile = outputJavaDirectory.appending(path: javaSourcesListFileName) + if shouldRunJavaCallbacksPhases { + arguments += [ + "--generated-java-sources-list-file-output", javaSourcesListFileName + ] + jextractOutputFiles += [javaSourcesFile] + } + + commands += [ .buildCommand( displayName: "Generate Java wrappers for Swift types", executable: toolURL, arguments: arguments, inputFiles: [ configFile ] + swiftFiles, - outputFiles: outputSwiftFiles + outputFiles: jextractOutputFiles + ) + ] + + // If we do not need Java callbacks, we can skip the remaining steps. + guard shouldRunJavaCallbacksPhases else { + return commands + } + + // The URL of the compiled Java sources + let javaCompiledClassesURL = context.pluginWorkDirectoryURL + .appending(path: "compiled-java-output") + + // Build SwiftKitCore and get the classpath + // as the jextracted sources will depend on that + + guard let swiftJavaDirectory = findSwiftJavaDirectory(for: target) else { + fatalError("Unable to find the path to the swift-java sources, please file an issue.") + } + log("Found swift-java at \(swiftJavaDirectory)") + + let swiftKitCoreClassPath = swiftJavaDirectory.appending(path: "SwiftKitCore/build/classes/java/main") + + // We need to use a different gradle home, because + // this plugin might be run from inside another gradle task + // and that would cause conflicts. + let gradleUserHome = context.pluginWorkDirectoryURL.appending(path: "gradle-user-home") + + let GradleUserHome = "GRADLE_USER_HOME" + let gradleUserHomePath = gradleUserHome.path(percentEncoded: false) + log("Prepare command: :SwiftKitCore:build in \(GradleUserHome)=\(gradleUserHomePath)") + var gradlewEnvironment = ProcessInfo.processInfo.environment + gradlewEnvironment[GradleUserHome] = gradleUserHomePath + log("Forward environment: \(gradlewEnvironment)") + + let gradleExecutable = findExecutable(name: "gradle") ?? // try using installed 'gradle' if available in PATH + swiftJavaDirectory.appending(path: "gradlew") // fallback to calling ./gradlew if gradle is not installed + log("Detected 'gradle' executable (or gradlew fallback): \(gradleExecutable)") + + commands += [ + .buildCommand( + displayName: "Build SwiftKitCore using Gradle (Java)", + executable: gradleExecutable, + arguments: [ + ":SwiftKitCore:build", + "--project-dir", swiftJavaDirectory.path(percentEncoded: false), + "--gradle-user-home", gradleUserHomePath, + "--configure-on-demand", + "--no-daemon" + ], + environment: gradlewEnvironment, + inputFiles: [swiftJavaDirectory], + outputFiles: [swiftKitCoreClassPath] + ) + ] + + // Compile the jextracted sources + let javaHome = URL(filePath: findJavaHome()) + + commands += [ + .buildCommand( + displayName: "Build extracted Java sources", + executable: javaHome + .appending(path: "bin") + .appending(path: self.javacName), + arguments: [ + "@\(javaSourcesFile.path(percentEncoded: false))", + "-d", javaCompiledClassesURL.path(percentEncoded: false), + "-parameters", + "-classpath", swiftKitCoreClassPath.path(percentEncoded: false) + ], + inputFiles: [javaSourcesFile, swiftKitCoreClassPath], + outputFiles: [javaCompiledClassesURL] + ) + ] + + // Run `configure` to extract a swift-java config to use for wrap-java + let swiftJavaConfigURL = context.pluginWorkDirectoryURL.appending(path: "swift-java.config") + + commands += [ + .buildCommand( + displayName: "Output swift-java.config that contains all extracted Java sources", + executable: toolURL, + arguments: [ + "configure", + "--output-directory", context.pluginWorkDirectoryURL.path(percentEncoded: false), + "--cp", javaCompiledClassesURL.path(percentEncoded: false), + "--swift-module", sourceModule.name, + "--swift-type-prefix", "Java" + ], + inputFiles: [javaCompiledClassesURL], + outputFiles: [swiftJavaConfigURL] ) ] + + let singleSwiftFileOutputName = "WrapJavaGenerated.swift" + + // In the end we can run wrap-java on the previous inputs + var wrapJavaArguments = [ + "wrap-java", + "--swift-module", sourceModule.name, + "--output-directory", outputSwiftDirectory.path(percentEncoded: false), + "--config", swiftJavaConfigURL.path(percentEncoded: false), + "--cp", swiftKitCoreClassPath.path(percentEncoded: false), + "--single-swift-file-output", singleSwiftFileOutputName + ] + + // Add any dependent config files as arguments + wrapJavaArguments += dependentConfigFilesArguments + + commands += [ + .buildCommand( + displayName: "Wrap compiled Java sources using wrap-java", + executable: toolURL, + arguments: wrapJavaArguments, + inputFiles: [swiftJavaConfigURL, swiftKitCoreClassPath], + outputFiles: [outputSwiftDirectory.appending(path: singleSwiftFileOutputName)] + ) + ] + + return commands + } + + var javacName: String { +#if os(Windows) + "javac.exe" +#else + "javac" +#endif } /// Find the manifest files from other swift-java executions in any targets @@ -181,5 +334,43 @@ struct JExtractSwiftBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin { return dependentConfigFiles } + + private func findSwiftJavaDirectory(for target: any Target) -> URL? { + for dependency in target.dependencies { + switch dependency { + case .target(let target): + continue + + case .product(let product): + guard let swiftJava = product.sourceModules.first(where: { $0.name == "SwiftJava" }) else { + return nil + } + + // We are inside Sources/SwiftJava + return swiftJava.directoryURL.deletingLastPathComponent().deletingLastPathComponent() + + @unknown default: + continue + } + } + + return nil + } } +func findExecutable(name: String) -> URL? { + let fileManager = FileManager.default + + guard let path = ProcessInfo.processInfo.environment["PATH"] else { + return nil + } + + for path in path.split(separator: ":") { + let fullURL = URL(fileURLWithPath: String(path)).appendingPathComponent(name) + if fileManager.isExecutableFile(atPath: fullURL.path) { + return fullURL + } + } + + return nil +} \ No newline at end of file diff --git a/Plugins/SwiftJavaPlugin/SwiftJavaPlugin.swift b/Plugins/SwiftJavaPlugin/SwiftJavaPlugin.swift index 7908932d..a578091f 100644 --- a/Plugins/SwiftJavaPlugin/SwiftJavaPlugin.swift +++ b/Plugins/SwiftJavaPlugin/SwiftJavaPlugin.swift @@ -171,8 +171,6 @@ struct SwiftJavaBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin { arguments += javaStdlibModules.flatMap { ["--depends-on", $0] } if !outputSwiftFiles.isEmpty { - arguments += [ configFile.path(percentEncoded: false) ] - let displayName = "Wrapping \(classes.count) Java classes in Swift target '\(sourceModule.name)'" log("Prepared: \(displayName)") commands += [ @@ -266,4 +264,4 @@ func getExtractedJavaStdlibModules() -> [String] { } return url.lastPathComponent }.sorted() -} \ No newline at end of file +} diff --git a/Samples/JavaDependencySampleApp/ci-validate.sh b/Samples/JavaDependencySampleApp/ci-validate.sh index feeb8767..1c3e2d55 100755 --- a/Samples/JavaDependencySampleApp/ci-validate.sh +++ b/Samples/JavaDependencySampleApp/ci-validate.sh @@ -3,9 +3,16 @@ set -e set -x +# WORKAROUND: prebuilts broken on Swift 6.2.1 and Linux and tests using macros https://github.com/swiftlang/swift-java/issues/418 +if [ "$(uname)" = "Darwin" ]; then + DISABLE_EXPERIMENTAL_PREBUILTS='' +else + DISABLE_EXPERIMENTAL_PREBUILTS='--disable-experimental-prebuilts' +fi + # invoke resolve as part of a build run swift build \ - --disable-experimental-prebuilts \ + $DISABLE_EXPERIMENTAL_PREBUILTS \ --disable-sandbox # explicitly invoke resolve without explicit path or dependency @@ -13,7 +20,7 @@ swift build \ # FIXME: until prebuilt swift-syntax isn't broken on 6.2 anymore: https://github.com/swiftlang/swift-java/issues/418 swift run \ - --disable-experimental-prebuilts \ + $DISABLE_EXPERIMENTAL_PREBUILTS \ swift-java resolve \ Sources/JavaCommonsCSV/swift-java.config \ --swift-module JavaCommonsCSV \ diff --git a/Samples/JavaKitSampleApp/ci-validate.sh b/Samples/JavaKitSampleApp/ci-validate.sh index 297f5c88..327baadf 100755 --- a/Samples/JavaKitSampleApp/ci-validate.sh +++ b/Samples/JavaKitSampleApp/ci-validate.sh @@ -3,8 +3,14 @@ set -e set -x -swift build \ - --disable-experimental-prebuilts # FIXME: until prebuilt swift-syntax isn't broken on 6.2 anymore: https://github.com/swiftlang/swift-java/issues/418 +# WORKAROUND: prebuilts broken on Swift 6.2.1 and Linux and tests using macros https://github.com/swiftlang/swift-java/issues/418 +if [ "$(uname)" = "Darwin" ]; then + DISABLE_EXPERIMENTAL_PREBUILTS='' +else + DISABLE_EXPERIMENTAL_PREBUILTS='--disable-experimental-prebuilts' +fi + +swift build $DISABLE_EXPERIMENTAL_PREBUILTS "$JAVA_HOME/bin/java" \ -cp .build/plugins/outputs/javakitsampleapp/JavaKitExample/destination/JavaCompilerPlugin/Java \ diff --git a/Samples/JavaProbablyPrime/ci-validate.sh b/Samples/JavaProbablyPrime/ci-validate.sh index dc624996..202dcbab 100755 --- a/Samples/JavaProbablyPrime/ci-validate.sh +++ b/Samples/JavaProbablyPrime/ci-validate.sh @@ -3,7 +3,13 @@ set -e set -x -# FIXME: until prebuilt swift-syntax isn't broken on 6.2 anymore: https://github.com/swiftlang/swift-java/issues/418 +# WORKAROUND: prebuilts broken on Swift 6.2.1 and Linux and tests using macros https://github.com/swiftlang/swift-java/issues/418 +if [ "$(uname)" = "Darwin" ]; then + DISABLE_EXPERIMENTAL_PREBUILTS='' +else + DISABLE_EXPERIMENTAL_PREBUILTS='--disable-experimental-prebuilts' +fi + swift run \ - --disable-experimental-prebuilts \ + $DISABLE_EXPERIMENTAL_PREBUILTS \ JavaProbablyPrime 1337 \ No newline at end of file diff --git a/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/CallbackProtcol.swift b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/CallbackProtcol.swift new file mode 100644 index 00000000..985771be --- /dev/null +++ b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/CallbackProtcol.swift @@ -0,0 +1,77 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import SwiftJava + +public protocol CallbackProtocol { + func withBool(_ input: Bool) -> Bool + func withInt8(_ input: Int8) -> Int8 + func withUInt16(_ input: UInt16) -> UInt16 + func withInt16(_ input: Int16) -> Int16 + func withInt32(_ input: Int32) -> Int32 + func withInt64(_ input: Int64) -> Int64 + func withFloat(_ input: Float) -> Float + func withDouble(_ input: Double) -> Double + func withString(_ input: String) -> String + func withVoid() + func withObject(_ input: MySwiftClass) -> MySwiftClass + func withOptionalInt64(_ input: Int64?) -> Int64? + func withOptionalObject(_ input: MySwiftClass?) -> Optional +} + +public struct CallbackOutput { + public let bool: Bool + public let int8: Int8 + public let uint16: UInt16 + public let int16: Int16 + public let int32: Int32 + public let int64: Int64 + public let _float: Float + public let _double: Double + public let string: String + public let object: MySwiftClass + public let optionalInt64: Int64? + public let optionalObject: MySwiftClass? +} + +public func outputCallbacks( + _ callbacks: some CallbackProtocol, + bool: Bool, + int8: Int8, + uint16: UInt16, + int16: Int16, + int32: Int32, + int64: Int64, + _float: Float, + _double: Double, + string: String, + object: MySwiftClass, + optionalInt64: Int64?, + optionalObject: MySwiftClass? +) -> CallbackOutput { + return CallbackOutput( + bool: callbacks.withBool(bool), + int8: callbacks.withInt8(int8), + uint16: callbacks.withUInt16(uint16), + int16: callbacks.withInt16(int16), + int32: callbacks.withInt32(int32), + int64: callbacks.withInt64(int64), + _float: callbacks.withFloat(_float), + _double: callbacks.withDouble(_double), + string: callbacks.withString(string), + object: callbacks.withObject(object), + optionalInt64: callbacks.withOptionalInt64(optionalInt64), + optionalObject: callbacks.withOptionalObject(optionalObject) + ) +} diff --git a/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/Storage.swift b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/Storage.swift new file mode 100644 index 00000000..488a78cc --- /dev/null +++ b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/Storage.swift @@ -0,0 +1,36 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import SwiftJava + +public class StorageItem { + public let value: Int64 + + public init(value: Int64) { + self.value = value + } +} + +public protocol Storage { + func load() -> StorageItem + func save(_ item: StorageItem) +} + +public func saveWithStorage(_ item: StorageItem, s: any Storage) { + s.save(item); +} + +public func loadWithStorage(s: any Storage) -> StorageItem { + return s.load(); +} diff --git a/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/swift-java.config b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/swift-java.config index 3d6a1201..52143b7f 100644 --- a/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/swift-java.config +++ b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/swift-java.config @@ -1,5 +1,6 @@ { "javaPackage": "com.example.swift", "mode": "jni", + "enableJavaCallbacks": true, "logLevel": "debug" } diff --git a/Samples/SwiftJavaExtractJNISampleApp/build.gradle b/Samples/SwiftJavaExtractJNISampleApp/build.gradle index a8ce51d2..7bb64c55 100644 --- a/Samples/SwiftJavaExtractJNISampleApp/build.gradle +++ b/Samples/SwiftJavaExtractJNISampleApp/build.gradle @@ -101,7 +101,7 @@ def jextract = tasks.register("jextract", Exec) { } // FIXME: disable prebuilts until swift-syntax isn't broken on 6.2 anymore: https://github.com/swiftlang/swift-java/issues/418 - def cmdArgs = ["build", "--disable-experimental-prebuilts"] + def cmdArgs = ["build", "--disable-experimental-prebuilts", "--disable-sandbox"] // Check if the 'swiftSdk' project property was passed if (project.hasProperty('swiftSdk')) { @@ -209,3 +209,11 @@ jmh { "-Djextract.trace.downcalls=false" ] } + +task printGradleHome { + doLast { + println "Gradle Home: ${gradle.gradleHomeDir}" + println "Gradle Version: ${gradle.gradleVersion}" + println "Gradle User Home: ${gradle.gradleUserHomeDir}" + } +} \ No newline at end of file diff --git a/Samples/SwiftJavaExtractJNISampleApp/ci-validate.sh b/Samples/SwiftJavaExtractJNISampleApp/ci-validate.sh index ff5c32c8..d62a0910 100755 --- a/Samples/SwiftJavaExtractJNISampleApp/ci-validate.sh +++ b/Samples/SwiftJavaExtractJNISampleApp/ci-validate.sh @@ -3,7 +3,44 @@ set -x set -e -swift build --disable-experimental-prebuilts # FIXME: until prebuilt swift-syntax isn't broken on 6.2 anymore: https://github.com/swiftlang/swift-java/issues/418 +# WORKAROUND: prebuilts broken on Swift 6.2.1 and Linux and tests using macros https://github.com/swiftlang/swift-java/issues/418 +if [ "$(uname)" = "Darwin" ]; then + DISABLE_EXPERIMENTAL_PREBUILTS='' +else + DISABLE_EXPERIMENTAL_PREBUILTS='--disable-experimental-prebuilts' +fi + +if [[ "$(uname)" == "Darwin" && -n "$GITHUB_ACTION" ]]; then + # WORKAROUND: GitHub Actions on macOS issue with downloading gradle wrapper + # We seem to be hitting a problem when the swiftpm plugin, needs to execute gradle wrapper in a new gradle_user_home. + # Normally, this would just download gradle again and kick off a build, this seems to timeout *specifically* on + # github actions runners. + # + # It is not a sandbox problem, becuase the ./gradlew is run without sandboxing as we already execute + # the entire swift build with '--disable-sandbox' for other reasons. + # + # We cannot use the same gradle user home as the default one since we might make gradle think we're + # building the same project concurrently, which we kind of are, however only a limited subset in order + # to trigger wrap-java with those dependencies. + # + # TODO: this may use some further improvements so normal usage does not incur another wrapper download. + + ./gradlew -h # prime ~/.gradle/wrapper/dists/... + + # Worst part of workaround here; we make sure to pre-load the resolved gradle wrapper downloaded distribution + # to the "known" location the plugin will use for its local builds, which are done in order to compile SwiftKitCore. + # This build is only necessary in order to drive wrap-java on sources generated during the build itself + # which enables the "Implement Swift protocols in Java" feature of jextract/jni mode. + GRADLE_USER_HOME="$(pwd)/.build/plugins/outputs/swiftjavaextractjnisampleapp/MySwiftLibrary/destination/JExtractSwiftPlugin/gradle-user-home" + if [ -d "$HOME/.gradle" ] ; then + echo "COPY $HOME/.gradle to $GRADLE_USER_HOME" + mkdir -p "$GRADLE_USER_HOME" + cp -r "$HOME/.gradle/"* "$GRADLE_USER_HOME/" || true + fi +fi + +# FIXME: disable prebuilts until prebuilt swift-syntax isn't broken on 6.2 anymore: https://github.com/swiftlang/swift-java/issues/418 +swift build $DISABLE_EXPERIMENTAL_PREBUILTS --disable-sandbox ./gradlew run -./gradlew test \ No newline at end of file +./gradlew test diff --git a/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/ProtocolCallbacksTest.java b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/ProtocolCallbacksTest.java new file mode 100644 index 00000000..e79fd4a3 --- /dev/null +++ b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/ProtocolCallbacksTest.java @@ -0,0 +1,117 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package com.example.swift; + +import org.junit.jupiter.api.Test; +import org.swift.swiftkit.core.SwiftArena; +import org.swift.swiftkit.core.annotations.Unsigned; + +import java.util.Optional; +import java.util.OptionalLong; + +import static org.junit.jupiter.api.Assertions.*; + +public class ProtocolCallbacksTest { + static class JavaCallbacks implements CallbackProtocol { + @Override + public boolean withBool(boolean input) { + return input; + } + + @Override + public byte withInt8(byte input) { + return input; + } + + @Override + public @Unsigned char withUInt16(char input) { + return input; + } + + @Override + public short withInt16(short input) { + return input; + } + + @Override + public int withInt32(int input) { + return input; + } + + @Override + public long withInt64(long input) { + return input; + } + + @Override + public float withFloat(float input) { + return input; + } + + @Override + public double withDouble(double input) { + return input; + } + + @Override + public String withString(String input) { + return input; + } + + @Override + public void withVoid() {} + + @Override + public MySwiftClass withObject(MySwiftClass input) { + return input; + } + + @Override + public OptionalLong withOptionalInt64(OptionalLong input) { + return input; + } + + @Override + public Optional withOptionalObject(Optional input) { + return input; + } + } + + @Test + void primitiveCallbacks() { + try (var arena = SwiftArena.ofConfined()) { + JavaCallbacks callbacks = new JavaCallbacks(); + var object = MySwiftClass.init(5, 3, arena); + var optionalObject = Optional.of(MySwiftClass.init(10, 10, arena)); + var output = MySwiftLibrary.outputCallbacks(callbacks, true, (byte) 1, (char) 16, (short) 16, (int) 32, 64L, 1.34f, 1.34, "Hello from Java!", object, OptionalLong.empty(), optionalObject, arena); + + assertEquals(1, output.getInt8()); + assertEquals(16, output.getUint16()); + assertEquals(16, output.getInt16()); + assertEquals(32, output.getInt32()); + assertEquals(64, output.getInt64()); + assertEquals(1.34f, output.get_float()); + assertEquals(1.34, output.get_double()); + assertEquals("Hello from Java!", output.getString()); + assertFalse(output.getOptionalInt64().isPresent()); + assertEquals(5, output.getObject(arena).getX()); + assertEquals(3, output.getObject(arena).getY()); + + var optionalObjectOutput = output.getOptionalObject(arena); + assertTrue(optionalObjectOutput.isPresent()); + assertEquals(10, optionalObjectOutput.get().getX()); + } + } +} \ No newline at end of file diff --git a/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/ProtocolTest.java b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/ProtocolTest.java index c095a42a..f5d1ffcf 100644 --- a/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/ProtocolTest.java +++ b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/ProtocolTest.java @@ -72,4 +72,34 @@ void protocolMethod() { assertEquals("ConcreteProtocolAB", proto1.name()); } } + + static class JavaStorage implements Storage { + StorageItem item; + + JavaStorage(StorageItem item) { + this.item = item; + } + + @Override + public StorageItem load() { + return item; + } + + @Override + public void save(StorageItem item) { + this.item = item; + } + } + + @Test + void useStorage() { + try (var arena = SwiftArena.ofConfined()) { + JavaStorage storage = new JavaStorage(null); + MySwiftLibrary.saveWithStorage(StorageItem.init(10, arena), storage); + assertEquals(10, MySwiftLibrary.loadWithStorage(storage, arena).getValue()); + MySwiftLibrary.saveWithStorage(StorageItem.init(7, arena), storage); + MySwiftLibrary.saveWithStorage(StorageItem.init(5, arena), storage); + assertEquals(5, MySwiftLibrary.loadWithStorage(storage, arena).getValue()); + } + } } \ No newline at end of file diff --git a/Sources/JExtractSwiftLib/Convenience/JavaType+Extensions.swift b/Sources/JExtractSwiftLib/Convenience/JavaType+Extensions.swift index 645e5aa4..9f7a19cc 100644 --- a/Sources/JExtractSwiftLib/Convenience/JavaType+Extensions.swift +++ b/Sources/JExtractSwiftLib/Convenience/JavaType+Extensions.swift @@ -102,7 +102,7 @@ extension JavaType { } } - /// Returns whether this type returns `JavaValue` from JavaKit + /// Returns whether this type returns `JavaValue` from SwiftJava var implementsJavaValue: Bool { return switch self { case .boolean, .byte, .char, .short, .int, .long, .float, .double, .void, .javaLangString: diff --git a/Sources/JExtractSwiftLib/Convenience/String+Extensions.swift b/Sources/JExtractSwiftLib/Convenience/String+Extensions.swift index 82ce5c1c..5641c7f2 100644 --- a/Sources/JExtractSwiftLib/Convenience/String+Extensions.swift +++ b/Sources/JExtractSwiftLib/Convenience/String+Extensions.swift @@ -68,7 +68,7 @@ extension String { /// Looks up self as a SwiftJava wrapped class name and converts it /// into a `JavaType.class` if it exists in `lookupTable`. - func parseJavaClassFromJavaKitName(in lookupTable: [String: String]) -> JavaType? { + func parseJavaClassFromSwiftJavaName(in lookupTable: [String: String]) -> JavaType? { guard let canonicalJavaName = lookupTable[self] else { return nil } diff --git a/Sources/JExtractSwiftLib/Convenience/SwiftSyntax+Extensions.swift b/Sources/JExtractSwiftLib/Convenience/SwiftSyntax+Extensions.swift index d3902aa4..c9f87b6d 100644 --- a/Sources/JExtractSwiftLib/Convenience/SwiftSyntax+Extensions.swift +++ b/Sources/JExtractSwiftLib/Convenience/SwiftSyntax+Extensions.swift @@ -128,7 +128,7 @@ extension WithModifiersSyntax { } extension AttributeListSyntax.Element { - /// Whether this node has `JavaKit` attributes. + /// Whether this node has `SwiftJava` attributes. var isJava: Bool { guard case let .attribute(attr) = self else { // FIXME: Handle #if. diff --git a/Sources/JExtractSwiftLib/ImportedDecls.swift b/Sources/JExtractSwiftLib/ImportedDecls.swift index b9cc2d49..aa4014d2 100644 --- a/Sources/JExtractSwiftLib/ImportedDecls.swift +++ b/Sources/JExtractSwiftLib/ImportedDecls.swift @@ -264,3 +264,12 @@ extension ImportedFunc { } } } + +extension ImportedNominalType: Hashable { + public func hash(into hasher: inout Hasher) { + hasher.combine(ObjectIdentifier(self)) + } + public static func == (lhs: ImportedNominalType, rhs: ImportedNominalType) -> Bool { + return lhs === rhs + } +} diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+InterfaceWrapperGeneration.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+InterfaceWrapperGeneration.swift new file mode 100644 index 00000000..f1e7c685 --- /dev/null +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+InterfaceWrapperGeneration.swift @@ -0,0 +1,342 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import JavaTypes +import SwiftJavaConfigurationShared +import SwiftSyntax + +extension JNISwift2JavaGenerator { + + func generateInterfaceWrappers( + _ types: [ImportedNominalType] + ) -> [ImportedNominalType: JavaInterfaceSwiftWrapper] { + var wrappers = [ImportedNominalType: JavaInterfaceSwiftWrapper]() + + for type in types { + do { + let translator = JavaInterfaceProtocolWrapperGenerator() + wrappers[type] = try translator.generate(for: type) + } catch { + self.logger.warning("Failed to generate protocol wrapper for: '\(type.swiftNominal.qualifiedName)'; \(error)") + } + } + + return wrappers + } + + /// A type that describes a Swift protocol + /// that uses an underlying wrap-java `@JavaInterface` + /// to make callbacks to Java from Swift using protocols. + struct JavaInterfaceSwiftWrapper { + let protocolType: SwiftNominalType + let functions: [Function] + let variables: [Variable] + + var wrapperName: String { + protocolType.nominalTypeDecl.javaInterfaceSwiftProtocolWrapperName + } + + var swiftName: String { + protocolType.nominalTypeDecl.qualifiedName + } + + var javaInterfaceVariableName: String { + protocolType.nominalTypeDecl.javaInterfaceVariableName + } + + var javaInterfaceName: String { + protocolType.nominalTypeDecl.javaInterfaceName + } + + struct Function { + let swiftFunctionName: String + let originalFunctionSignature: SwiftFunctionSignature + let swiftDecl: any DeclSyntaxProtocol + let parameterConversions: [UpcallConversionStep] + let resultConversion: UpcallConversionStep + } + + struct Variable { + let swiftDecl: any DeclSyntaxProtocol + let getter: Function + let setter: Function? + } + } + + + struct JavaInterfaceProtocolWrapperGenerator { + func generate(for type: ImportedNominalType) throws -> JavaInterfaceSwiftWrapper { + let functions = try type.methods.map { method in + try translate(function: method) + } + + // FIXME: Finish support for variables + if !type.variables.isEmpty { + throw JavaTranslationError.protocolVariablesNotSupported + } + + let variables = try Dictionary(grouping: type.variables, by: { $0.swiftDecl.id }).map { (id, funcs) in + precondition(funcs.count > 0 && funcs.count <= 2, "Variables must contain a getter and optionally a setter") + guard let getter = funcs.first(where: { $0.apiKind == .getter }) else { + fatalError("Getter not found for variable with imported funcs: \(funcs)") + } + let setter = funcs.first(where: { $0.apiKind == .setter }) + + return try self.translateVariable(getter: getter, setter: setter) + } + + return JavaInterfaceSwiftWrapper( + protocolType: SwiftNominalType(nominalTypeDecl: type.swiftNominal), + functions: functions, + variables: variables + ) + } + + private func translate(function: ImportedFunc) throws -> JavaInterfaceSwiftWrapper.Function { + let parameters = try function.functionSignature.parameters.map { + try self.translateParameter($0) + } + + let result = try translateResult(function.functionSignature.result, methodName: function.name) + + return JavaInterfaceSwiftWrapper.Function( + swiftFunctionName: function.name, + originalFunctionSignature: function.functionSignature, + swiftDecl: function.swiftDecl, + parameterConversions: parameters, + resultConversion: result + ) + } + + private func translateVariable(getter: ImportedFunc, setter: ImportedFunc?) throws -> JavaInterfaceSwiftWrapper.Variable { + return try JavaInterfaceSwiftWrapper.Variable( + swiftDecl: getter.swiftDecl, // they should be the same + getter: translate(function: getter), + setter: setter.map { try self.translate(function: $0) } + ) + } + + private func translateParameter(_ parameter: SwiftParameter) throws -> UpcallConversionStep { + try self.translateParameter(parameterName: parameter.parameterName!, type: parameter.type) + } + + private func translateParameter(parameterName: String, type: SwiftType) throws -> UpcallConversionStep { + + switch type { + case .nominal(let nominalType): + if let knownType = nominalType.nominalTypeDecl.knownTypeKind { + switch knownType { + case .optional: + guard let genericArgs = nominalType.genericArguments, genericArgs.count == 1 else { + throw JavaTranslationError.unsupportedSwiftType(type) + } + return try translateOptionalParameter( + name: parameterName, + wrappedType: genericArgs[0] + ) + + default: + guard knownType.isDirectlyTranslatedToWrapJava else { + throw JavaTranslationError.unsupportedSwiftType(type) + } + + return .placeholder + } + } + + // We assume this is then a JExtracted Swift class + return .toJavaWrapper( + .placeholder, + name: parameterName, + nominalType: nominalType + ) + + case .tuple([]): // void + return .placeholder + + case .optional(let wrappedType): + return try translateOptionalParameter( + name: parameterName, + wrappedType: wrappedType + ) + + case .genericParameter, .function, .metatype, .tuple, .existential, .opaque, .composite, .array: + throw JavaTranslationError.unsupportedSwiftType(type) + } + } + + private func translateOptionalParameter(name: String, wrappedType: SwiftType) throws -> UpcallConversionStep { + let wrappedConversion = try translateParameter(parameterName: name, type: wrappedType) + return .toJavaOptional(.map(.placeholder, body: wrappedConversion)) + } + + private func translateResult(_ result: SwiftResult, methodName: String) throws -> UpcallConversionStep { + try self.translateResult(type: result.type, methodName: methodName) + } + + private func translateResult( + type: SwiftType, + methodName: String, + allowNilForObjects: Bool = false + ) throws -> UpcallConversionStep { + switch type { + case .nominal(let nominalType): + if let knownType = nominalType.nominalTypeDecl.knownTypeKind { + switch knownType { + case .optional: + guard let genericArgs = nominalType.genericArguments, genericArgs.count == 1 else { + throw JavaTranslationError.unsupportedSwiftType(type) + } + return try self.translateOptionalResult( + wrappedType: genericArgs[0], + methodName: methodName + ) + + default: + guard knownType.isDirectlyTranslatedToWrapJava else { + throw JavaTranslationError.unsupportedSwiftType(type) + } + return .placeholder + } + } + + let inner: UpcallConversionStep = !allowNilForObjects ? + .unwrapOptional(.placeholder, message: "Upcall to \(methodName) unexpectedly returned nil") + : .placeholder + + // We assume this is then a JExtracted Swift class + return .toSwiftClass( + inner, + name: "result$", + nominalType: nominalType + ) + + case .tuple([]): // void + return .placeholder + + case .optional(let wrappedType): + return try self.translateOptionalResult(wrappedType: wrappedType, methodName: methodName) + + case .genericParameter, .function, .metatype, .tuple, .existential, .opaque, .composite, .array: + throw JavaTranslationError.unsupportedSwiftType(type) + } + } + + private func translateOptionalResult(wrappedType: SwiftType, methodName: String) throws -> UpcallConversionStep { + // The `fromJavaOptional` will handle the nullability + let wrappedConversion = try translateResult( + type: wrappedType, + methodName: methodName, + allowNilForObjects: true + ) + return .map(.fromJavaOptional(.placeholder), body: wrappedConversion) + } + } +} + + /// Describes how to convert values from and to wrap-java types + enum UpcallConversionStep { + case placeholder + + case constant(String) + + indirect case toJavaWrapper( + UpcallConversionStep, + name: String, + nominalType: SwiftNominalType + ) + + indirect case toSwiftClass( + UpcallConversionStep, + name: String, + nominalType: SwiftNominalType + ) + + indirect case unwrapOptional( + UpcallConversionStep, + message: String + ) + + indirect case toJavaOptional(UpcallConversionStep) + + indirect case fromJavaOptional(UpcallConversionStep) + + indirect case map(UpcallConversionStep, body: UpcallConversionStep) + + /// Returns the conversion string applied to the placeholder. + func render(_ printer: inout CodePrinter, _ placeholder: String) -> String { + switch self { + case .placeholder: + return placeholder + + case .constant(let constant): + return constant + + case .toJavaWrapper(let inner, let name, let nominalType): + let inner = inner.render(&printer, placeholder) + printer.print( + """ + let \(name)Class = try! JavaClass<\(nominalType.nominalTypeDecl.generatedJavaClassMacroName)>(environment: JavaVirtualMachine.shared().environment()) + let \(name)Pointer = UnsafeMutablePointer<\(nominalType.nominalTypeDecl.qualifiedName)>.allocate(capacity: 1) + \(name)Pointer.initialize(to: \(inner)) + """ + ) + + return "\(name)Class.wrapMemoryAddressUnsafe(Int64(Int(bitPattern: \(name)Pointer)))" + + case .toSwiftClass(let inner, let name, let nominalType): + let inner = inner.render(&printer, placeholder) + + // The wrap-java methods will return null + printer.print( + """ + let \(name)MemoryAddress$ = \(inner).as(JavaJNISwiftInstance.self)!.memoryAddress() + let \(name)Pointer = UnsafeMutablePointer<\(nominalType.nominalTypeDecl.qualifiedName)>(bitPattern: Int(\(name)MemoryAddress$))! + """ + ) + + return "\(name)Pointer.pointee" + + case .unwrapOptional(let inner, let message): + let inner = inner.render(&printer, placeholder) + + printer.print( + """ + guard let unwrapped$ = \(inner) else { + fatalError("\(message)") + } + """ + ) + + return "unwrapped$" + + case .toJavaOptional(let inner): + let inner = inner.render(&printer, placeholder) + return "\(inner).toJavaOptional()" + + case .fromJavaOptional(let inner): + let inner = inner.render(&printer, placeholder) + return "Optional(javaOptional: \(inner))" + + case .map(let inner, let body): + let inner = inner.render(&printer, placeholder) + var printer = CodePrinter() + printer.printBraceBlock("\(inner).map") { printer in + let body = body.render(&printer, "$0") + printer.print("return \(body)") + } + return printer.finalize() + } + } +} diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift index 1e18cbe8..c492d439 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift @@ -12,7 +12,9 @@ // //===----------------------------------------------------------------------===// +import Foundation import JavaTypes +import OrderedCollections // MARK: Defaults @@ -40,6 +42,8 @@ extension JNISwift2JavaGenerator { package func writeExportedJavaSources(_ printer: inout CodePrinter) throws { let importedTypes = analysis.importedTypes.sorted(by: { (lhs, rhs) in lhs.key < rhs.key }) + var exportedFileNames: OrderedSet = [] + // Each parent type goes into its own file // any nested types are printed inside the body as `static class` for (_, ty) in importedTypes.filter({ _, type in type.parent == nil }) { @@ -52,6 +56,7 @@ extension JNISwift2JavaGenerator { javaPackagePath: javaPackagePath, filename: filename ) { + exportedFileNames.append(outputFile.path(percentEncoded: false)) logger.info("[swift-java] Generated: \(ty.swiftNominal.name.bold).java (at \(outputFile))") } } @@ -65,10 +70,24 @@ extension JNISwift2JavaGenerator { javaPackagePath: javaPackagePath, filename: filename ) { + exportedFileNames.append(outputFile.path(percentEncoded: false)) logger.info("[swift-java] Generated: \(self.swiftModuleName).java (at \(outputFile))") } + + // Write java sources list file + if let generatedJavaSourcesListFileOutput = config.generatedJavaSourcesListFileOutput, !exportedFileNames.isEmpty { + let outputPath = URL(fileURLWithPath: javaOutputDirectory).appending(path: generatedJavaSourcesListFileOutput) + try exportedFileNames.joined(separator: "\n").write( + to: outputPath, + atomically: true, + encoding: .utf8 + ) + logger.info("Generated file at \(outputPath)") + } } + + private func printModule(_ printer: inout CodePrinter) { printHeader(&printer) printPackage(&printer) @@ -113,20 +132,29 @@ extension JNISwift2JavaGenerator { } private func printProtocol(_ printer: inout CodePrinter, _ decl: ImportedNominalType) { - let extends = ["JNISwiftInstance"] - printer.printBraceBlock("public interface \(decl.swiftNominal.name) extends \(extends.joined(separator: ", "))") { printer in + var extends = [String]() + + // If we cannot generate Swift wrappers + // that allows the user to implement the wrapped interface in Java + // then we require only JExtracted types can conform to this. + if !self.interfaceProtocolWrappers.keys.contains(decl) { + extends.append("JNISwiftInstance") + } + let extendsString = extends.isEmpty ? "" : " extends \(extends.joined(separator: ", "))" + + printer.printBraceBlock("public interface \(decl.swiftNominal.name)\(extendsString)") { printer in for initializer in decl.initializers { - printFunctionDowncallMethods(&printer, initializer, signaturesOnly: true) + printFunctionDowncallMethods(&printer, initializer, skipMethodBody: true, skipArenas: true) printer.println() } for method in decl.methods { - printFunctionDowncallMethods(&printer, method, signaturesOnly: true) + printFunctionDowncallMethods(&printer, method, skipMethodBody: true, skipArenas: true) printer.println() } for variable in decl.variables { - printFunctionDowncallMethods(&printer, variable, signaturesOnly: true) + printFunctionDowncallMethods(&printer, variable, skipMethodBody: true, skipArenas: true) printer.println() } } @@ -184,6 +212,10 @@ extension JNISwift2JavaGenerator { public static \(decl.swiftNominal.name) wrapMemoryAddressUnsafe(long selfPointer, SwiftArena swiftArena) { return new \(decl.swiftNominal.name)(selfPointer, swiftArena); } + + public static \(decl.swiftNominal.name) wrapMemoryAddressUnsafe(long selfPointer) { + return new \(decl.swiftNominal.name)(selfPointer, SwiftMemoryManagement.GLOBAL_SWIFT_JAVA_ARENA); + } """ ) @@ -359,10 +391,10 @@ extension JNISwift2JavaGenerator { ["\(conversion.native.javaType) \(value.parameter.name)"] } - printer.print("record $NativeParameters(\(nativeParameters.joined(separator: ", "))) {}") + printer.print("record _NativeParameters(\(nativeParameters.joined(separator: ", "))) {}") } - self.printJavaBindingWrapperMethod(&printer, translatedCase.getAsCaseFunction, signaturesOnly: false) + self.printJavaBindingWrapperMethod(&printer, translatedCase.getAsCaseFunction, skipMethodBody: false, skipArenas: false) printer.println() } } @@ -370,7 +402,8 @@ extension JNISwift2JavaGenerator { private func printFunctionDowncallMethods( _ printer: inout CodePrinter, _ decl: ImportedFunc, - signaturesOnly: Bool = false + skipMethodBody: Bool = false, + skipArenas: Bool = false ) { guard translatedDecl(for: decl) != nil else { // Failed to translate. Skip. @@ -381,7 +414,7 @@ extension JNISwift2JavaGenerator { printJavaBindingWrapperHelperClass(&printer, decl) - printJavaBindingWrapperMethod(&printer, decl, signaturesOnly: signaturesOnly) + printJavaBindingWrapperMethod(&printer, decl, skipMethodBody: skipMethodBody, skipArenas: skipArenas) } /// Print the helper type container for a user-facing Java API. @@ -427,19 +460,21 @@ extension JNISwift2JavaGenerator { private func printJavaBindingWrapperMethod( _ printer: inout CodePrinter, _ decl: ImportedFunc, - signaturesOnly: Bool + skipMethodBody: Bool, + skipArenas: Bool ) { guard let translatedDecl = translatedDecl(for: decl) else { fatalError("Decl was not translated, \(decl)") } - printJavaBindingWrapperMethod(&printer, translatedDecl, importedFunc: decl, signaturesOnly: signaturesOnly) + printJavaBindingWrapperMethod(&printer, translatedDecl, importedFunc: decl, skipMethodBody: skipMethodBody, skipArenas: skipArenas) } private func printJavaBindingWrapperMethod( _ printer: inout CodePrinter, _ translatedDecl: TranslatedFunctionDecl, importedFunc: ImportedFunc? = nil, - signaturesOnly: Bool + skipMethodBody: Bool, + skipArenas: Bool ) { var modifiers = ["public"] if translatedDecl.isStatic { @@ -494,14 +529,14 @@ extension JNISwift2JavaGenerator { printer.println() } - if translatedSignature.requiresSwiftArena { + if translatedSignature.requiresSwiftArena, !skipArenas { parameters.append("SwiftArena swiftArena$") } if let importedFunc { printDeclDocumentation(&printer, importedFunc) } let signature = "\(annotationsStr)\(modifiers.joined(separator: " ")) \(resultType) \(translatedDecl.name)(\(parameters.joined(separator: ", ")))\(throwsClause)" - if signaturesOnly { + if skipMethodBody { printer.print("\(signature);") } else { printer.printBraceBlock(signature) { printer in diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift index 6a2771c3..553b3e10 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift @@ -16,6 +16,17 @@ import JavaTypes import SwiftJavaConfigurationShared extension JNISwift2JavaGenerator { + var javaTranslator: JavaTranslation { + JavaTranslation( + config: config, + swiftModuleName: swiftModuleName, + javaPackage: self.javaPackage, + javaClassLookupTable: self.javaClassLookupTable, + knownTypes: SwiftKnownTypes(symbolTable: lookupContext.symbolTable), + protocolWrappers: self.interfaceProtocolWrappers + ) + } + func translatedDecl( for decl: ImportedFunc ) -> TranslatedFunctionDecl? { @@ -25,14 +36,7 @@ extension JNISwift2JavaGenerator { let translated: TranslatedFunctionDecl? do { - let translation = JavaTranslation( - config: config, - swiftModuleName: swiftModuleName, - javaPackage: self.javaPackage, - javaClassLookupTable: self.javaClassLookupTable, - knownTypes: SwiftKnownTypes(symbolTable: lookupContext.symbolTable) - ) - translated = try translation.translate(decl) + translated = try self.javaTranslator.translate(decl) } catch { self.logger.debug("Failed to translate: '\(decl.swiftDecl.qualifiedNameForDebug)'; \(error)") translated = nil @@ -56,7 +60,8 @@ extension JNISwift2JavaGenerator { swiftModuleName: swiftModuleName, javaPackage: self.javaPackage, javaClassLookupTable: self.javaClassLookupTable, - knownTypes: SwiftKnownTypes(symbolTable: lookupContext.symbolTable) + knownTypes: SwiftKnownTypes(symbolTable: lookupContext.symbolTable), + protocolWrappers: self.interfaceProtocolWrappers ) translated = try translation.translate(enumCase: decl) } catch { @@ -74,13 +79,15 @@ extension JNISwift2JavaGenerator { let javaPackage: String let javaClassLookupTable: JavaClassLookupTable var knownTypes: SwiftKnownTypes + let protocolWrappers: [ImportedNominalType: JavaInterfaceSwiftWrapper] func translate(enumCase: ImportedEnumCase) throws -> TranslatedEnumCase { let nativeTranslation = NativeJavaTranslation( config: self.config, javaPackage: self.javaPackage, javaClassLookupTable: self.javaClassLookupTable, - knownTypes: self.knownTypes + knownTypes: self.knownTypes, + protocolWrappers: self.protocolWrappers ) let methodName = "" // TODO: Used for closures, replace with better name? @@ -105,7 +112,7 @@ extension JNISwift2JavaGenerator { let caseName = enumCase.name.firstCharacterUppercased let enumName = enumCase.enumType.nominalTypeDecl.name - let nativeParametersType = JavaType.class(package: nil, name: "\(caseName).$NativeParameters") + let nativeParametersType = JavaType.class(package: nil, name: "\(caseName)._NativeParameters") let getAsCaseName = "getAs\(caseName)" // If the case has no parameters, we can skip the native call. let constructRecordConversion = JavaNativeConversionStep.method(.constant("Optional"), function: "of", arguments: [ @@ -168,7 +175,8 @@ extension JNISwift2JavaGenerator { config: self.config, javaPackage: self.javaPackage, javaClassLookupTable: self.javaClassLookupTable, - knownTypes: self.knownTypes + knownTypes: self.knownTypes, + protocolWrappers: self.protocolWrappers ) // Types with no parent will be outputted inside a "module" class. @@ -405,8 +413,8 @@ extension JNISwift2JavaGenerator { } } - if nominalType.isJavaKitWrapper { - guard let javaType = nominalTypeName.parseJavaClassFromJavaKitName(in: self.javaClassLookupTable) else { + if nominalType.isSwiftJavaWrapper { + guard let javaType = nominalTypeName.parseJavaClassFromSwiftJavaName(in: self.javaClassLookupTable) else { throw JavaTranslationError.wrappedJavaClassTranslationNotProvided(swiftType) } @@ -456,7 +464,7 @@ extension JNISwift2JavaGenerator { return try translateProtocolParameter( protocolType: proto, parameterName: parameterName, - javaGenericName: "$T\(parameterPosition)" + javaGenericName: "_T\(parameterPosition)" ) case .genericParameter(let generic): @@ -585,14 +593,14 @@ extension JNISwift2JavaGenerator { } } - // We assume this is a JExtract class. + // We just pass down the jobject return TranslatedParameter( parameter: JavaParameter( name: parameterName, type: .generic(name: javaGenericName, extends: javaProtocolTypes), annotations: [] ), - conversion: .commaSeparated([.valueMemoryAddress(.placeholder), .typeMetadataAddress(.placeholder)]) + conversion: .placeholder ) } @@ -628,8 +636,8 @@ extension JNISwift2JavaGenerator { ) } - if nominalType.isJavaKitWrapper { - guard let javaType = nominalTypeName.parseJavaClassFromJavaKitName(in: self.javaClassLookupTable) else { + if nominalType.isSwiftJavaWrapper { + guard let javaType = nominalTypeName.parseJavaClassFromSwiftJavaName(in: self.javaClassLookupTable) else { throw JavaTranslationError.wrappedJavaClassTranslationNotProvided(swiftType) } @@ -703,7 +711,7 @@ extension JNISwift2JavaGenerator { } } - if nominalType.isJavaKitWrapper { + if nominalType.isSwiftJavaWrapper { throw JavaTranslationError.unsupportedSwiftType(swiftType) } @@ -789,7 +797,7 @@ extension JNISwift2JavaGenerator { } } - guard !nominalType.isJavaKitWrapper else { + guard !nominalType.isSwiftJavaWrapper else { throw JavaTranslationError.unsupportedSwiftType(swiftType) } @@ -836,7 +844,7 @@ extension JNISwift2JavaGenerator { ) } - guard !nominalType.isJavaKitWrapper else { + guard !nominalType.isSwiftJavaWrapper else { throw JavaTranslationError.unsupportedSwiftType(elementType) } @@ -885,7 +893,7 @@ extension JNISwift2JavaGenerator { ) } - guard !nominalType.isJavaKitWrapper else { + guard !nominalType.isSwiftJavaWrapper else { throw JavaTranslationError.unsupportedSwiftType(elementType) } @@ -965,7 +973,7 @@ extension JNISwift2JavaGenerator { /// Function signature of the native function that will be implemented by Swift let nativeFunctionSignature: NativeFunctionSignature - + /// Annotations to include on the Java function declaration var annotations: [JavaAnnotation] { self.translatedFunctionSignature.annotations @@ -1332,5 +1340,8 @@ extension JNISwift2JavaGenerator { /// The user has not supplied a mapping from `SwiftType` to /// a java class. case wrappedJavaClassTranslationNotProvided(SwiftType) + + // FIXME: Remove once we support protocol variables + case protocolVariablesNotSupported } } diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift index 24e46906..b744a33b 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift @@ -22,6 +22,7 @@ extension JNISwift2JavaGenerator { let javaPackage: String let javaClassLookupTable: JavaClassLookupTable var knownTypes: SwiftKnownTypes + let protocolWrappers: [ImportedNominalType: JavaInterfaceSwiftWrapper] /// Translates a Swift function into the native JNI method signature. func translate( @@ -113,8 +114,8 @@ extension JNISwift2JavaGenerator { } } - if nominalType.isJavaKitWrapper { - guard let javaType = nominalTypeName.parseJavaClassFromJavaKitName(in: self.javaClassLookupTable) else { + if nominalType.isSwiftJavaWrapper { + guard let javaType = nominalTypeName.parseJavaClassFromSwiftJavaName(in: self.javaClassLookupTable) else { throw JavaTranslationError.wrappedJavaClassTranslationNotProvided(type) } @@ -122,7 +123,7 @@ extension JNISwift2JavaGenerator { parameters: [ JavaParameter(name: parameterName, type: javaType) ], - conversion: .initializeJavaKitWrapper( + conversion: .initializeSwiftJavaWrapper( .unwrapOptional( .placeholder, name: parameterName, @@ -181,14 +182,18 @@ extension JNISwift2JavaGenerator { case .opaque(let proto), .existential(let proto): return try translateProtocolParameter( protocolType: proto, - parameterName: parameterName + methodName: methodName, + parameterName: parameterName, + parentName: parentName ) case .genericParameter: if let concreteTy = type.typeIn(genericParameters: genericParameters, genericRequirements: genericRequirements) { return try translateProtocolParameter( protocolType: concreteTy, - parameterName: parameterName + methodName: methodName, + parameterName: parameterName, + parentName: parentName ) } @@ -207,22 +212,23 @@ extension JNISwift2JavaGenerator { func translateProtocolParameter( protocolType: SwiftType, - parameterName: String + methodName: String, + parameterName: String, + parentName: String? ) throws -> NativeParameter { switch protocolType { case .nominal(let nominalType): - let protocolName = nominalType.nominalTypeDecl.qualifiedName - return try translateProtocolParameter(protocolNames: [protocolName], parameterName: parameterName) + return try translateProtocolParameter(protocolTypes: [nominalType], methodName: methodName, parameterName: parameterName, parentName: parentName) case .composite(let types): - let protocolNames = try types.map { - guard let nominalTypeName = $0.asNominalType?.nominalTypeDecl.qualifiedName else { + let protocolTypes = try types.map { + guard let nominalTypeName = $0.asNominalType else { throw JavaTranslationError.unsupportedSwiftType($0) } return nominalTypeName } - return try translateProtocolParameter(protocolNames: protocolNames, parameterName: parameterName) + return try translateProtocolParameter(protocolTypes: protocolTypes, methodName: methodName, parameterName: parameterName, parentName: parentName) default: throw JavaTranslationError.unsupportedSwiftType(protocolType) @@ -230,18 +236,30 @@ extension JNISwift2JavaGenerator { } private func translateProtocolParameter( - protocolNames: [String], - parameterName: String + protocolTypes: [SwiftNominalType], + methodName: String, + parameterName: String, + parentName: String? ) throws -> NativeParameter { + // We allow Java implementations if we are able to generate the needed + // Swift wrappers for all the protocol types. + let allowsJavaImplementations = protocolTypes.allSatisfy { protocolType in + self.protocolWrappers.contains(where: { $0.value.protocolType == protocolType }) + } + return NativeParameter( parameters: [ - JavaParameter(name: parameterName, type: .long), - JavaParameter(name: "\(parameterName)_typeMetadataAddress", type: .long) + JavaParameter(name: parameterName, type: .javaLangObject) ], - conversion: .extractSwiftProtocolValue( + conversion: .interfaceToSwiftObject( .placeholder, - typeMetadataVariableName: .combinedName(component: "typeMetadataAddress"), - protocolNames: protocolNames + swiftWrapperClassName: JNISwift2JavaGenerator.protocolParameterWrapperClassName( + methodName: methodName, + parameterName: parameterName, + parentName: parentName + ), + protocolTypes: protocolTypes, + allowsJavaImplementations: allowsJavaImplementations ) ) } @@ -276,8 +294,8 @@ extension JNISwift2JavaGenerator { ) } - if nominalType.isJavaKitWrapper { - guard let javaType = nominalTypeName.parseJavaClassFromJavaKitName(in: self.javaClassLookupTable) else { + if nominalType.isSwiftJavaWrapper { + guard let javaType = nominalTypeName.parseJavaClassFromSwiftJavaName(in: self.javaClassLookupTable) else { throw JavaTranslationError.wrappedJavaClassTranslationNotProvided(swiftType) } @@ -285,7 +303,7 @@ extension JNISwift2JavaGenerator { parameters: [ JavaParameter(name: parameterName, type: javaType) ], - conversion: .optionalMap(.initializeJavaKitWrapper(.placeholder, wrapperName: nominalTypeName)) + conversion: .optionalMap(.initializeSwiftJavaWrapper(.placeholder, wrapperName: nominalTypeName)) ) } @@ -359,7 +377,7 @@ extension JNISwift2JavaGenerator { } } - guard !nominalType.isJavaKitWrapper else { + guard !nominalType.isSwiftJavaWrapper else { // TODO: Should be the same as above throw JavaTranslationError.unsupportedSwiftType(swiftType) } @@ -479,7 +497,7 @@ extension JNISwift2JavaGenerator { } } - if nominalType.isJavaKitWrapper { + if nominalType.isSwiftJavaWrapper { throw JavaTranslationError.unsupportedSwiftType(swiftResult.type) } @@ -526,7 +544,7 @@ extension JNISwift2JavaGenerator { ) } - guard !nominalType.isJavaKitWrapper else { + guard !nominalType.isSwiftJavaWrapper else { throw JavaTranslationError.unsupportedSwiftType(.array(elementType)) } @@ -574,7 +592,7 @@ extension JNISwift2JavaGenerator { ) } - guard !nominalType.isJavaKitWrapper else { + guard !nominalType.isSwiftJavaWrapper else { throw JavaTranslationError.unsupportedSwiftType(.array(elementType)) } @@ -645,6 +663,13 @@ extension JNISwift2JavaGenerator { /// `SwiftType(from: value, in: environment)` indirect case initFromJNI(NativeSwiftConversionStep, swiftType: SwiftType) + indirect case interfaceToSwiftObject( + NativeSwiftConversionStep, + swiftWrapperClassName: String, + protocolTypes: [SwiftNominalType], + allowsJavaImplementations: Bool + ) + indirect case extractSwiftProtocolValue( NativeSwiftConversionStep, typeMetadataVariableName: NativeSwiftConversionStep, @@ -668,7 +693,7 @@ extension JNISwift2JavaGenerator { indirect case closureLowering(parameters: [NativeParameter], result: NativeResult) - indirect case initializeJavaKitWrapper(NativeSwiftConversionStep, wrapperName: String) + indirect case initializeSwiftJavaWrapper(NativeSwiftConversionStep, wrapperName: String) indirect case optionalLowering(NativeSwiftConversionStep, discriminatorName: String, valueName: String) @@ -723,6 +748,60 @@ extension JNISwift2JavaGenerator { let inner = inner.render(&printer, placeholder) return "\(swiftType)(fromJNI: \(inner), in: environment)" + case .interfaceToSwiftObject( + let inner, + let swiftWrapperClassName, + let protocolTypes, + let allowsJavaImplementations + ): + let protocolNames = protocolTypes.map { $0.nominalTypeDecl.qualifiedName } + + let inner = inner.render(&printer, placeholder) + let variableName = "\(inner)swiftObject$" + let compositeProtocolName = "(\(protocolNames.joined(separator: " & ")))" + printer.print("let \(variableName): \(compositeProtocolName)") + + func printStandardJExtractBlock(_ printer: inout CodePrinter) { + let pointerVariableName = "\(inner)pointer$" + let typeMetadataVariableName = "\(inner)typeMetadata$" + printer.print( + """ + let \(pointerVariableName) = environment.interface.CallLongMethodA(environment, \(inner), _JNIMethodIDCache.JNISwiftInstance.memoryAddress, []) + let \(typeMetadataVariableName) = environment.interface.CallLongMethodA(environment, \(inner), _JNIMethodIDCache.JNISwiftInstance.typeMetadataAddress, []) + """ + ) + let existentialName = NativeSwiftConversionStep.extractSwiftProtocolValue( + .constant(pointerVariableName), + typeMetadataVariableName: .constant(typeMetadataVariableName), + protocolNames: protocolNames + ).render(&printer, placeholder) + + printer.print("\(variableName) = \(existentialName)") + } + + // If this protocol type supports being implemented by the user + // then we will check whether it is a JNI SwiftInstance type + // or if its a custom class implementing the interface. + if allowsJavaImplementations { + printer.printBraceBlock( + "if environment.interface.IsInstanceOf(environment, \(inner), _JNIMethodIDCache.JNISwiftInstance.class) != 0" + ) { printer in + printStandardJExtractBlock(&printer) + } + printer.printBraceBlock("else") { printer in + let arguments = protocolTypes.map { protocolType in + let nominalTypeDecl = protocolType.nominalTypeDecl + return "\(nominalTypeDecl.javaInterfaceVariableName): \(nominalTypeDecl.javaInterfaceName)(javaThis: \(inner)!, environment: environment)" + } + printer.print("\(variableName) = \(swiftWrapperClassName)(\(arguments.joined(separator: ", ")))") + } + } else { + printStandardJExtractBlock(&printer) + } + + + return variableName + case .extractSwiftProtocolValue(let inner, let typeMetadataVariableName, let protocolNames): let inner = inner.render(&printer, placeholder) let typeMetadataVariableName = typeMetadataVariableName.render(&printer, placeholder) @@ -839,7 +918,7 @@ extension JNISwift2JavaGenerator { return printer.finalize() - case .initializeJavaKitWrapper(let inner, let wrapperName): + case .initializeSwiftJavaWrapper(let inner, let wrapperName): let inner = inner.render(&printer, placeholder) return "\(wrapperName)(javaThis: \(inner), environment: environment)" diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift index 6628be33..85fdc640 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift @@ -116,6 +116,75 @@ extension JNISwift2JavaGenerator { } } + /// Prints the extension needed to make allow upcalls from Swift to Java for protocols + private func printSwiftInterfaceWrapper( + _ printer: inout CodePrinter, + _ translatedWrapper: JavaInterfaceSwiftWrapper + ) throws { + printer.printBraceBlock("protocol \(translatedWrapper.wrapperName): \(translatedWrapper.swiftName)") { printer in + printer.print("var \(translatedWrapper.javaInterfaceVariableName): \(translatedWrapper.javaInterfaceName) { get }") + } + printer.println() + printer.printBraceBlock("extension \(translatedWrapper.wrapperName)") { printer in + for function in translatedWrapper.functions { + printInterfaceWrapperFunctionImpl(&printer, function, inside: translatedWrapper) + printer.println() + } + + // FIXME: Add support for protocol variables https://github.com/swiftlang/swift-java/issues/457 +// for variable in translatedWrapper.variables { +// printerInterfaceWrapperVariable(&printer, variable, inside: translatedWrapper) +// printer.println() +// } + } + } + + private func printInterfaceWrapperFunctionImpl( + _ printer: inout CodePrinter, + _ function: JavaInterfaceSwiftWrapper.Function, + inside wrapper: JavaInterfaceSwiftWrapper + ) { + printer.printBraceBlock(function.swiftDecl.signatureString) { printer in + let upcallArguments = zip( + function.originalFunctionSignature.parameters, + function.parameterConversions + ).map { param, conversion in + // Wrap-java does not extract parameter names, so no labels + conversion.render(&printer, param.parameterName!) + } + + let javaUpcall = "\(wrapper.javaInterfaceVariableName).\(function.swiftFunctionName)(\(upcallArguments.joined(separator: ", ")))" + + let resultType = function.originalFunctionSignature.result.type + let result = function.resultConversion.render(&printer, javaUpcall) + if resultType.isVoid { + printer.print(result) + } else { + printer.print("return \(result)") + } + } + } + + private func printerInterfaceWrapperVariable( + _ printer: inout CodePrinter, + _ variable: JavaInterfaceSwiftWrapper.Variable, + inside wrapper: JavaInterfaceSwiftWrapper + ) { + // FIXME: Add support for variables. This won't get printed yet + // so we no need to worry about fatalErrors. + printer.printBraceBlock(variable.swiftDecl.signatureString) { printer in + printer.printBraceBlock("get") { printer in + printer.print("fatalError()") + } + + if let setter = variable.setter { + printer.printBraceBlock("set") { printer in + printer.print("fatalError()") + } + } + } + } + private func printGlobalSwiftThunkSources(_ printer: inout CodePrinter) throws { printHeader(&printer) @@ -154,7 +223,7 @@ extension JNISwift2JavaGenerator { case .actor, .class, .enum, .struct: printConcreteTypeThunks(&printer, type) case .protocol: - printProtocolThunks(&printer, type) + try printProtocolThunks(&printer, type) } } @@ -184,13 +253,18 @@ extension JNISwift2JavaGenerator { printer.println() } + printTypeMetadataAddressThunk(&printer, type) printer.println() printDestroyFunctionThunk(&printer, type) } - private func printProtocolThunks(_ printer: inout CodePrinter, _ type: ImportedNominalType) { - let protocolName = type.swiftNominal.name + private func printProtocolThunks(_ printer: inout CodePrinter, _ type: ImportedNominalType) throws { + guard let protocolWrapper = self.interfaceProtocolWrappers[type] else { + return + } + + try printSwiftInterfaceWrapper(&printer, protocolWrapper) } @@ -232,11 +306,19 @@ extension JNISwift2JavaGenerator { } private func renderEnumCaseCacheInit(_ enumCase: TranslatedEnumCase) -> String { - let nativeParametersClassName = "\(javaPackagePath)/\(enumCase.enumName)$\(enumCase.name)$$NativeParameters" + let nativeParametersClassName = "\(enumCase.enumName)$\(enumCase.name)$_NativeParameters" let methodSignature = MethodSignature(resultType: .void, parameterTypes: enumCase.parameterConversions.map(\.native.javaType)) - let methods = #"[.init(name: "", signature: "\#(methodSignature.mangledName)")]"# - return #"_JNIMethodIDCache(className: "\#(nativeParametersClassName)", methods: \#(methods))"# + return renderJNICacheInit(className: nativeParametersClassName, methods: [("", methodSignature)]) + } + + private func renderJNICacheInit(className: String, methods: [(String, MethodSignature)]) -> String { + let fullClassName = "\(javaPackagePath)/\(className)" + let methods = methods.map { name, signature in + #".init(name: "\#(name)", signature: "\#(signature.mangledName)")"# + }.joined(separator: ",\n") + + return #"_JNIMethodIDCache(className: "\#(fullClassName)", methods: [\#(methods)])"# } private func printEnumGetAsCaseThunk( @@ -287,6 +369,8 @@ extension JNISwift2JavaGenerator { return } + printSwiftFunctionHelperClasses(&printer, decl) + printCDecl( &printer, translatedDecl @@ -295,6 +379,96 @@ extension JNISwift2JavaGenerator { } } + + private func printSwiftFunctionHelperClasses( + _ printer: inout CodePrinter, + _ decl: ImportedFunc + ) { + let protocolParameters = decl.functionSignature.parameters.compactMap { parameter in + if let concreteType = parameter.type.typeIn( + genericParameters: decl.functionSignature.genericParameters, + genericRequirements: decl.functionSignature.genericRequirements + ) { + return (parameter, concreteType) + } + + switch parameter.type { + case .opaque(let protocolType), + .existential(let protocolType): + return (parameter, protocolType) + + default: + return nil + } + }.map { parameter, protocolType in + // We flatten any composite types + switch protocolType { + case .composite(let protocols): + return (parameter, protocols) + + default: + return (parameter, [protocolType]) + } + } + + // For each parameter that is a generic or a protocol, + // we generate a Swift class that conforms to all of those. + for (parameter, protocolTypes) in protocolParameters { + let protocolWrappers: [JavaInterfaceSwiftWrapper] = protocolTypes.compactMap { protocolType in + guard let importedType = self.asImportedNominalTypeDecl(protocolType), + let wrapper = self.interfaceProtocolWrappers[importedType] + else { + return nil + } + return wrapper + } + + // Make sure we can generate wrappers for all the protocols + // that the parameter requires + guard protocolWrappers.count == protocolTypes.count else { + // We cannot extract a wrapper for this class + // so it must only be passed in by JExtract instances + continue + } + + guard let parameterName = parameter.parameterName else { + // TODO: Throw + fatalError() + } + let swiftClassName = JNISwift2JavaGenerator.protocolParameterWrapperClassName( + methodName: decl.name, + parameterName: parameterName, + parentName: decl.parentType?.asNominalType?.nominalTypeDecl.qualifiedName ?? swiftModuleName + ) + let implementingProtocols = protocolWrappers.map(\.wrapperName).joined(separator: ", ") + + printer.printBraceBlock("final class \(swiftClassName): \(implementingProtocols)") { printer in + let variables: [(String, String)] = protocolWrappers.map { wrapper in + return (wrapper.javaInterfaceVariableName, wrapper.javaInterfaceName) + } + for (name, type) in variables { + printer.print("let \(name): \(type)") + } + printer.println() + let initializerParameters = variables.map { "\($0): \($1)" }.joined(separator: ", ") + + printer.printBraceBlock("init(\(initializerParameters))") { printer in + for (name, _) in variables { + printer.print("self.\(name) = \(name)") + } + } + } + } + } + + private func asImportedNominalTypeDecl(_ type: SwiftType) -> ImportedNominalType? { + self.analysis.importedTypes.first(where: ( { name, nominalType in + nominalType.swiftType == type + })).map { + $0.value + } + } + private func printFunctionDowncall( _ printer: inout CodePrinter, _ decl: ImportedFunc @@ -562,4 +736,44 @@ extension JNISwift2JavaGenerator { ) return newSelfParamName } + + static func protocolParameterWrapperClassName( + methodName: String, + parameterName: String, + parentName: String? + ) -> String { + let parent = if let parentName { + "\(parentName)_" + } else { + "" + } + return "_\(parent)\(methodName)_\(parameterName)_Wrapper" + } +} + +extension SwiftNominalTypeDeclaration { + private var safeProtocolName: String { + self.qualifiedName.replacingOccurrences(of: ".", with: "_") + } + + /// The name of the corresponding `@JavaInterface` of this type. + var javaInterfaceName: String { + "Java\(safeProtocolName)" + } + + var javaInterfaceSwiftProtocolWrapperName: String { + "SwiftJava\(safeProtocolName)Wrapper" + } + + var javaInterfaceVariableName: String { + "_\(javaInterfaceName.firstCharacterLowercased)Interface" + } + + var generatedJavaClassMacroName: String { + if let parent { + return "\(parent.generatedJavaClassMacroName).Java\(self.name)" + } + + return "Java\(self.name)" + } } diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator.swift index 3b84cfb9..692b66b6 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator.swift @@ -41,6 +41,7 @@ package class JNISwift2JavaGenerator: Swift2JavaGenerator { /// Cached Java translation result. 'nil' indicates failed translation. var translatedDecls: [ImportedFunc: TranslatedFunctionDecl] = [:] var translatedEnumCases: [ImportedEnumCase: TranslatedEnumCase] = [:] + var interfaceProtocolWrappers: [ImportedNominalType: JavaInterfaceSwiftWrapper] = [:] /// Because we need to write empty files for SwiftPM, keep track which files we didn't write yet, /// and write an empty file for those. @@ -78,6 +79,13 @@ package class JNISwift2JavaGenerator: Swift2JavaGenerator { } else { self.expectedOutputSwiftFiles = [] } + + if translator.config.enableJavaCallbacks ?? false { + // We translate all the protocol wrappers + // as we need them to know what protocols we can allow the user to implement themselves + // in Java. + self.interfaceProtocolWrappers = self.generateInterfaceWrappers(Array(self.analysis.importedTypes.values)) + } } func generate() throws { diff --git a/Sources/JExtractSwiftLib/JavaTypes/JavaType+JDK.swift b/Sources/JExtractSwiftLib/JavaTypes/JavaType+JDK.swift index 511bf8de..e1aabd7f 100644 --- a/Sources/JExtractSwiftLib/JavaTypes/JavaType+JDK.swift +++ b/Sources/JExtractSwiftLib/JavaTypes/JavaType+JDK.swift @@ -40,6 +40,12 @@ extension JavaType { .class(package: "java.lang", name: "Throwable") } + /// The description of the type java.lang.Object. + static var javaLangObject: JavaType { + .class(package: "java.lang", name: "Object") + } + + /// The description of the type java.util.concurrent.CompletableFuture static func completableFuture(_ T: JavaType) -> JavaType { .class(package: "java.util.concurrent", name: "CompletableFuture", typeParameters: [T.boxedType]) diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownTypeDecls.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownTypeDecls.swift index 4a0cb9e8..36366321 100644 --- a/Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownTypeDecls.swift +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftKnownTypeDecls.swift @@ -65,4 +65,18 @@ enum SwiftKnownTypeDeclKind: String, Hashable { return false } } + + /// Indicates whether this known type is translated by `wrap-java` + /// into the same type as `jextract`. + /// + /// This means we do not have to perform any mapping when passing + /// this type between jextract and wrap-java + var isDirectlyTranslatedToWrapJava: Bool { + switch self { + case .bool, .int, .uint, .int8, .uint8, .int16, .uint16, .int32, .uint32, .int64, .uint64, .float, .double, .string, .void: + return true + default: + return false + } + } } diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftType.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftType.swift index b2f8d6ea..aeb88bfb 100644 --- a/Sources/JExtractSwiftLib/SwiftTypes/SwiftType.swift +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftType.swift @@ -210,9 +210,13 @@ extension SwiftNominalType: CustomStringConvertible { extension SwiftNominalType { // TODO: Better way to detect Java wrapped classes. - var isJavaKitWrapper: Bool { + var isSwiftJavaWrapper: Bool { nominalTypeDecl.name.hasPrefix("Java") } + + var isProtocol: Bool { + nominalTypeDecl.kind == .protocol + } } extension SwiftType { diff --git a/Sources/JavaStdlib/JavaLangReflect/Constructor+Utilities.swift b/Sources/JavaStdlib/JavaLangReflect/Constructor+Utilities.swift index 8f57ffa5..4042ec76 100644 --- a/Sources/JavaStdlib/JavaLangReflect/Constructor+Utilities.swift +++ b/Sources/JavaStdlib/JavaLangReflect/Constructor+Utilities.swift @@ -13,11 +13,6 @@ //===----------------------------------------------------------------------===// extension Constructor { - /// Whether this is a 'public' constructor. - public var isPublic: Bool { - return (getModifiers() & 1) != 0 - } - /// Whether this is a 'native' constructor. public var isNative: Bool { return (getModifiers() & 256) != 0 diff --git a/Sources/JavaStdlib/JavaLangReflect/HasJavaModifiers.swift b/Sources/JavaStdlib/JavaLangReflect/HasJavaModifiers.swift new file mode 100644 index 00000000..fc10edfe --- /dev/null +++ b/Sources/JavaStdlib/JavaLangReflect/HasJavaModifiers.swift @@ -0,0 +1,47 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import SwiftJava + +public protocol HasJavaModifiers { + func getModifiers() -> Int32 +} + +extension HasJavaModifiers { + /// Whether the modifiers contain 'public'. + public var isPublic: Bool { + return (getModifiers() & 0x00000001) != 0 + } + + /// Whether the modifiers contain 'private'. + public var isPrivate: Bool { + return (getModifiers() & 0x00000002) != 0 + } + + /// Whether the modifiers contain 'protected'. + public var isProtected: Bool { + return (getModifiers() & 0x00000004) != 0 + } + + /// Whether the modifiers is equivelant to 'package'.. + /// + /// The "default" access level in Java is 'package', it is signified by lack of a different access modifier. + public var isPackage: Bool { + return !isPublic && !isPrivate && !isProtected + } +} + +extension Constructor: HasJavaModifiers {} +extension JavaClass: HasJavaModifiers {} +extension Method: HasJavaModifiers {} diff --git a/Sources/JavaStdlib/JavaLangReflect/Method+Utilities.swift b/Sources/JavaStdlib/JavaLangReflect/Method+Utilities.swift index ecc11b50..00ca3d6b 100644 --- a/Sources/JavaStdlib/JavaLangReflect/Method+Utilities.swift +++ b/Sources/JavaStdlib/JavaLangReflect/Method+Utilities.swift @@ -13,28 +13,6 @@ //===----------------------------------------------------------------------===// extension Method { - - /// Whether this is a 'public' method. - public var isPublic: Bool { - return (getModifiers() & 0x00000001) != 0 - } - - /// Whether this is a 'private' method. - public var isPrivate: Bool { - return (getModifiers() & 0x00000002) != 0 - } - - /// Whether this is a 'protected' method. - public var isProtected: Bool { - return (getModifiers() & 0x00000004) != 0 - } - - /// Whether this is a 'package' method. - /// - /// The "default" access level in Java is 'package', it is signified by lack of a different access modifier. - public var isPackage: Bool { - return !isPublic && !isPrivate && !isProtected - } /// Whether this is a 'static' method. public var isStatic: Bool { diff --git a/Sources/SwiftJava/JVM/JavaVirtualMachine.swift b/Sources/SwiftJava/JVM/JavaVirtualMachine.swift index 1c7936a3..bb574c8a 100644 --- a/Sources/SwiftJava/JVM/JavaVirtualMachine.swift +++ b/Sources/SwiftJava/JVM/JavaVirtualMachine.swift @@ -350,4 +350,4 @@ extension JavaVirtualMachine { enum JavaKitError: Error { case classpathEntryNotFound(entry: String, classpath: [String]) } -} \ No newline at end of file +} diff --git a/Sources/SwiftJava/Macros.swift b/Sources/SwiftJava/Macros.swift index eb9c4374..4c035366 100644 --- a/Sources/SwiftJava/Macros.swift +++ b/Sources/SwiftJava/Macros.swift @@ -141,6 +141,7 @@ public macro JavaStaticField(_ javaFieldName: String? = nil, isFinal: Bool = fal /// returning method signature, and then, convert the result to the expected `T` type on the Swift side. @attached(body) public macro JavaMethod( + _ javaMethodName: String? = nil, typeErasedResult: String? = nil ) = #externalMacro(module: "SwiftJavaMacros", type: "JavaMethodMacro") @@ -154,9 +155,7 @@ public macro JavaMethod( /// func sayHelloBack(_ i: Int32) -> Double /// ``` @attached(body) -public macro JavaStaticMethod( - typeErasedResult: String? = nil -) = #externalMacro(module: "SwiftJavaMacros", type: "JavaMethodMacro") +public macro JavaStaticMethod(_ javaMethodName: String? = nil) = #externalMacro(module: "SwiftJavaMacros", type: "JavaMethodMacro") /// Macro that marks extensions to specify that all of the @JavaMethod /// methods are implementations of Java methods spelled as `native`. diff --git a/Sources/SwiftJava/String+Extensions.swift b/Sources/SwiftJava/String+Extensions.swift index 0af0de10..b87e6a0c 100644 --- a/Sources/SwiftJava/String+Extensions.swift +++ b/Sources/SwiftJava/String+Extensions.swift @@ -27,10 +27,14 @@ extension String { } extension String { - /// Replace all of the $'s for nested names with "." to turn a Java class - /// name into a Java canonical class name, + /// Convert a Java class name to its canonical name. + /// Replaces `$` with `.` for nested classes but preserves `$` at the start of identifiers. package var javaClassNameToCanonicalName: String { - return replacing("$", with: ".") + self.replacingOccurrences( + of: #"(?<=\w)\$"#, + with: ".", + options: .regularExpression + ) } /// Whether this is the name of an anonymous class. diff --git a/Sources/SwiftJavaConfigurationShared/Configuration.swift b/Sources/SwiftJavaConfigurationShared/Configuration.swift index 661cf963..37d1e1e7 100644 --- a/Sources/SwiftJavaConfigurationShared/Configuration.swift +++ b/Sources/SwiftJavaConfigurationShared/Configuration.swift @@ -65,6 +65,10 @@ public struct Configuration: Codable { asyncFuncMode ?? .default } + public var enableJavaCallbacks: Bool? // FIXME: default it to false, but that plays not nice with Codable + + public var generatedJavaSourcesListFileOutput: String? + // ==== wrap-java --------------------------------------------------------- /// The Java class path that should be passed along to the swift-java tool. @@ -91,6 +95,8 @@ public struct Configuration: Codable { /// Exclude input Java types by their package prefix or exact match. public var filterExclude: [String]? + public var singleSwiftFileOutput: String? + // ==== dependencies --------------------------------------------------------- // Java dependencies we need to fetch for this target. @@ -162,7 +168,11 @@ public func readConfiguration(sourceDir: String, file: String = #fileID, line: U /// Configuration is expected to be "JSON-with-comments". /// Specifically "//" comments are allowed and will be trimmed before passing the rest of the config into a standard JSON parser. public func readConfiguration(configPath: URL, file: String = #fileID, line: UInt = #line) throws -> Configuration? { - guard let configData = try? Data(contentsOf: configPath) else { + let configData: Data + do { + configData = try Data(contentsOf: configPath) + } catch { + print("Failed to read SwiftJava configuration at '\(configPath.absoluteURL)', error: \(error)") return nil } diff --git a/Sources/SwiftJavaDocumentation/Documentation.docc/index.md b/Sources/SwiftJavaDocumentation/Documentation.docc/index.md index 460f396d..4383727d 100644 --- a/Sources/SwiftJavaDocumentation/Documentation.docc/index.md +++ b/Sources/SwiftJavaDocumentation/Documentation.docc/index.md @@ -20,7 +20,7 @@ Reasons why you might want to reach for Swift and Java interoperability include, - Reuse existing libraries which exist in one ecosystem, but don't have a direct equivalent in the other SwiftJava is offering several core libraries which support language interoperability: -- `JavaKit` (Swift -> Java) - JNI-based support library and Swift macros +- `SwiftJava` (Swift -> Java) - JNI-based support library and Swift macros - `SwiftKit` (Java -> Swift) - Support library for Java calling Swift code (either using JNI or FFM) - `swift-java` - command line tool; Supports source generation and also dependency management operations - Build tool integration - SwiftPM Plugin diff --git a/Sources/SwiftJavaMacros/JavaMethodMacro.swift b/Sources/SwiftJavaMacros/JavaMethodMacro.swift index f992ee76..09948452 100644 --- a/Sources/SwiftJavaMacros/JavaMethodMacro.swift +++ b/Sources/SwiftJavaMacros/JavaMethodMacro.swift @@ -50,15 +50,27 @@ extension JavaMethodMacro: BodyMacro { fatalError("not a function: \(declaration)") } + let funcName = + if case .argumentList(let arguments) = node.arguments, + let argument = arguments.first, + argument.label?.text != "typeErasedResult", + let stringLiteral = argument.expression.as(StringLiteralExprSyntax.self), + stringLiteral.segments.count == 1, + case let .stringSegment(funcNameSegment)? = stringLiteral.segments.first + { + funcNameSegment.content.text + } else { + funcDecl.name.text + } + let isStatic = node.attributeName.trimmedDescription == "JavaStaticMethod" - let funcName = funcDecl.name.text let params = funcDecl.signature.parameterClause.parameters let paramNames = params.map { param in param.parameterName?.text ?? "" }.joined(separator: ", ") let genericResultType: String? = if case let .argumentList(arguments) = node.arguments, - let firstElement = arguments.first, - let stringLiteral = firstElement.expression + let element = arguments.first(where: { $0.label?.text == "typeErasedResult" }), + let stringLiteral = element.expression .as(StringLiteralExprSyntax.self), stringLiteral.segments.count == 1, case let .stringSegment(wrapperName)? = stringLiteral.segments.first { diff --git a/Sources/SwiftJavaRuntimeSupport/JNIMethodIDCaches.swift b/Sources/SwiftJavaRuntimeSupport/JNIMethodIDCaches.swift index 16a9c899..7be79a9f 100644 --- a/Sources/SwiftJavaRuntimeSupport/JNIMethodIDCaches.swift +++ b/Sources/SwiftJavaRuntimeSupport/JNIMethodIDCaches.swift @@ -91,4 +91,33 @@ extension _JNIMethodIDCache { cache.methods[messageConstructor]! } } + + public enum JNISwiftInstance { + private static let memoryAddressMethod = Method( + name: "$memoryAddress", + signature: "()J" + ) + + private static let typeMetadataAddressMethod = Method( + name: "$typeMetadataAddress", + signature: "()J" + ) + + private static let cache = _JNIMethodIDCache( + className: "org/swift/swiftkit/core/JNISwiftInstance", + methods: [memoryAddressMethod, typeMetadataAddressMethod] + ) + + public static var `class`: jclass { + cache.javaClass + } + + public static var memoryAddress: jmethodID { + cache.methods[memoryAddressMethod]! + } + + public static var typeMetadataAddress: jmethodID { + cache.methods[typeMetadataAddressMethod]! + } + } } diff --git a/Sources/SwiftJavaRuntimeSupport/generated/JavaJNISwiftInstance.swift b/Sources/SwiftJavaRuntimeSupport/generated/JavaJNISwiftInstance.swift new file mode 100644 index 00000000..4040d0bc --- /dev/null +++ b/Sources/SwiftJavaRuntimeSupport/generated/JavaJNISwiftInstance.swift @@ -0,0 +1,21 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import SwiftJava + +@JavaInterface("org.swift.swiftkit.core.JNISwiftInstance") +public struct JavaJNISwiftInstance { + @JavaMethod("$memoryAddress") + public func memoryAddress() -> Int64 +} diff --git a/Sources/SwiftJavaTool/Commands/ConfigureCommand.swift b/Sources/SwiftJavaTool/Commands/ConfigureCommand.swift index 455cb962..05bf3b8f 100644 --- a/Sources/SwiftJavaTool/Commands/ConfigureCommand.swift +++ b/Sources/SwiftJavaTool/Commands/ConfigureCommand.swift @@ -59,8 +59,8 @@ extension SwiftJava { swiftModule } - @Argument(help: "The input file, which is either a swift-java configuration file or (if '-jar' was specified) a Jar file.") - var input: String? + @Option(help: "A prefix that will be added to the names of the Swift types") + var swiftTypePrefix: String? } } @@ -137,14 +137,19 @@ extension SwiftJava.ConfigureCommand { print("[debug][swift-java] Importing classpath entry: \(entry)") if entry.hasSuffix(".jar") { + print("[debug][swift-java] Importing classpath as JAR file: \(entry)") let jarFile = try JarFile(entry, false, environment: environment) try addJavaToSwiftMappings( to: &config, forJar: jarFile, environment: environment ) - } else if FileManager.default.fileExists(atPath: entry) { - log.warning("Currently unable handle directory classpath entries for config generation! Skipping: \(entry)") + } else if FileManager.default.fileExists(atPath: entry), let entryURL = URL(string: entry) { + print("[debug][swift-java] Importing classpath as directory: \(entryURL)") + try addJavaToSwiftMappings( + to: &config, + forDirectory: entryURL + ) } else { log.warning("Classpath entry does not exist, skipping: \(entry)") } @@ -162,62 +167,82 @@ extension SwiftJava.ConfigureCommand { ) } + mutating func addJavaToSwiftMappings( + to configuration: inout Configuration, + forDirectory url: Foundation.URL + ) throws { + let enumerator = FileManager.default.enumerator(atPath: url.path()) + + while let filePath = enumerator?.nextObject() as? String { + try addJavaToSwiftMappings(to: &configuration, fileName: filePath) + } + } + mutating func addJavaToSwiftMappings( to configuration: inout Configuration, forJar jarFile: JarFile, environment: JNIEnvironment ) throws { - let log = Self.log - for entry in jarFile.entries()! { - // We only look at class files in the Jar file. - guard entry.getName().hasSuffix(".class") else { - continue - } + try addJavaToSwiftMappings(to: &configuration, fileName: entry.getName()) + } + } - // Skip some "common" files we know that would be duplicated in every jar - guard !entry.getName().hasPrefix("META-INF") else { - continue - } - guard !entry.getName().hasSuffix("package-info") else { - continue - } - guard !entry.getName().hasSuffix("package-info.class") else { - continue - } + mutating func addJavaToSwiftMappings( + to configuration: inout Configuration, + fileName: String + ) throws { + // We only look at class files + guard fileName.hasSuffix(".class") else { + return + } - // If this is a local class, it cannot be mapped into Swift. - if entry.getName().isLocalJavaClass { - continue - } + // Skip some "common" files we know that would be duplicated in every jar + guard !fileName.hasPrefix("META-INF") else { + return + } + guard !fileName.hasSuffix("package-info") else { + return + } + guard !fileName.hasSuffix("package-info.class") else { + return + } - let javaCanonicalName = String(entry.getName().replacing("/", with: ".") - .dropLast(".class".count)) + // If this is a local class, it cannot be mapped into Swift. + if fileName.isLocalJavaClass { + return + } - guard SwiftJava.shouldImport(javaCanonicalName: javaCanonicalName, commonOptions: self.commonOptions) else { - log.info("Skip importing class: \(javaCanonicalName) due to include/exclude filters") - continue - } + let javaCanonicalName = String(fileName.replacing("/", with: ".") + .dropLast(".class".count)) - if configuration.classes?[javaCanonicalName] != nil { - // We never overwrite an existing class mapping configuration. - // E.g. the user may have configured a custom name for a type. - continue - } + guard SwiftJava.shouldImport(javaCanonicalName: javaCanonicalName, commonOptions: self.commonOptions) else { + log.info("Skip importing class: \(javaCanonicalName) due to include/exclude filters") + return + } - if configuration.classes == nil { - configuration.classes = [:] - } + if configuration.classes?[javaCanonicalName] != nil { + // We never overwrite an existing class mapping configuration. + // E.g. the user may have configured a custom name for a type. + return + } - if let configuredSwiftName = configuration.classes![javaCanonicalName] { - log.info("Java type '\(javaCanonicalName)' already configured as '\(configuredSwiftName)' Swift type.") - } else { - log.info("Configure Java type '\(javaCanonicalName)' as '\(javaCanonicalName.defaultSwiftNameForJavaClass.bold)' Swift type.") - } + if configuration.classes == nil { + configuration.classes = [:] + } - configuration.classes![javaCanonicalName] = - javaCanonicalName.defaultSwiftNameForJavaClass + var swiftName = javaCanonicalName.defaultSwiftNameForJavaClass + if let swiftTypePrefix { + swiftName = "\(swiftTypePrefix)\(swiftName)" } + + if let configuredSwiftName = configuration.classes![javaCanonicalName] { + log.info("Java type '\(javaCanonicalName)' already configured as '\(configuredSwiftName)' Swift type.") + } else { + log.info("Configure Java type '\(javaCanonicalName)' as '\(swiftName.bold)' Swift type.") + } + + configuration.classes![javaCanonicalName] = swiftName } } diff --git a/Sources/SwiftJavaTool/Commands/JExtractCommand.swift b/Sources/SwiftJavaTool/Commands/JExtractCommand.swift index b5c3a7bb..775ab604 100644 --- a/Sources/SwiftJavaTool/Commands/JExtractCommand.swift +++ b/Sources/SwiftJavaTool/Commands/JExtractCommand.swift @@ -81,6 +81,12 @@ extension SwiftJava { @Option(help: "The mode to use for extracting asynchronous Swift functions. By default async methods are extracted as Java functions returning CompletableFuture.") var asyncFuncMode: JExtractAsyncFuncMode? + + @Flag(help: "By enabling this mode, JExtract will generate Java code that allows you to implement Swift protocols using Java classes. This feature requires disabling the sandbox mode in SwiftPM. This only works in the 'jni' mode.") + var enableJavaCallbacks: Bool = false + + @Option(help: "If specified, JExtract will output to this file a list of paths to all generated Java source files") + var generatedJavaSourcesListFileOutput: String? } } @@ -96,10 +102,14 @@ extension SwiftJava.JExtractCommand { let writeEmptyFiles = CommandLine.arguments.contains("--write-empty-files") ? true : nil configure(&config.writeEmptyFiles, overrideWith: writeEmptyFiles) + let enableJavaCallbacks = CommandLine.arguments.contains("--enable-java-callbacks") ? true : nil + configure(&config.enableJavaCallbacks, overrideWith: enableJavaCallbacks) + configure(&config.unsignedNumbersMode, overrideWith: self.unsignedNumbersMode) configure(&config.minimumInputAccessLevelMode, overrideWith: self.minimumInputAccessLevelMode) configure(&config.memoryManagementMode, overrideWith: self.memoryManagementMode) configure(&config.asyncFuncMode, overrideWith: self.asyncFuncMode) + configure(&config.generatedJavaSourcesListFileOutput, overrideWith: self.generatedJavaSourcesListFileOutput) try checkModeCompatibility(config: config) @@ -126,11 +136,15 @@ extension SwiftJava.JExtractCommand { case .annotate: () // OK case .wrapGuava: - throw IllegalModeCombinationError("JNI mode does not support '\(JExtractUnsignedIntegerMode.wrapGuava)' Unsigned integer mode! \(Self.helpMessage)") + throw IllegalModeCombinationError("JNI mode does not support '\(JExtractUnsignedIntegerMode.wrapGuava)' Unsigned integer mode! \(Self.helpMessage())") } } else if config.effectiveMode == .ffm { guard config.effectiveMemoryManagementMode == .explicit else { - throw IllegalModeCombinationError("FFM mode does not support '\(self.memoryManagementMode)' memory management mode! \(Self.helpMessage)") + throw IllegalModeCombinationError("FFM mode does not support '\(self.memoryManagementMode ?? .default)' memory management mode! \(Self.helpMessage())") + } + + if let enableJavaCallbacks = config.enableJavaCallbacks, enableJavaCallbacks { + throw IllegalModeCombinationError("FFM mode does not support enabling Java callbacks! \(Self.helpMessage())") } } } diff --git a/Sources/SwiftJavaTool/Commands/WrapJavaCommand.swift b/Sources/SwiftJavaTool/Commands/WrapJavaCommand.swift index 51315102..3e4e482b 100644 --- a/Sources/SwiftJavaTool/Commands/WrapJavaCommand.swift +++ b/Sources/SwiftJavaTool/Commands/WrapJavaCommand.swift @@ -58,8 +58,8 @@ extension SwiftJava { @Option(help: "Match java package directory structure with generated Swift files") var swiftMatchPackageDirectoryStructure: Bool = false - @Argument(help: "Path to .jar file whose Java classes should be wrapped using Swift bindings") - var input: String + @Option(help: "If specified, a single Swift file will be generated containing all the generated code") + var singleSwiftFileOutput: String? } } @@ -69,6 +69,7 @@ extension SwiftJava.WrapJavaCommand { print("self.commonOptions.filterInclude = \(self.commonOptions.filterInclude)") configure(&config.filterInclude, append: self.commonOptions.filterInclude) configure(&config.filterExclude, append: self.commonOptions.filterExclude) + configure(&config.singleSwiftFileOutput, overrideWith: self.singleSwiftFileOutput) // Get base classpath configuration for this target and configuration var classpathSearchDirs = [self.effectiveSwiftModuleURL] @@ -78,7 +79,6 @@ extension SwiftJava.WrapJavaCommand { } else { print("[trace][swift-java] Cache directory: none") } - print("[trace][swift-java] INPUT: \(input)") var classpathEntries = self.configureCommandJVMClasspath( searchDirs: classpathSearchDirs, config: config, log: Self.log) @@ -151,21 +151,41 @@ extension SwiftJava.WrapJavaCommand { .getSystemClassLoader()! var javaClasses: [JavaClass] = [] for (javaClassName, _) in config.classes ?? [:] { + func remove() { + translator.translatedClasses.removeValue(forKey: javaClassName) + } + guard shouldImportJavaClass(javaClassName, config: config) else { + remove() continue } - log.info("Wrapping java type: \(javaClassName)") - guard let javaClass = try classLoader.loadClass(javaClassName) else { log.warning("Could not load Java class '\(javaClassName)', skipping.") + remove() + continue + } + + guard self.shouldExtract(javaClass: javaClass, config: config) else { + log.info("Skip Java type: \(javaClassName) (does not match minimum access level)") + remove() + continue + } + + guard !javaClass.isEnum() else { + log.info("Skip Java type: \(javaClassName) (enums do not currently work)") + remove() continue } + log.info("Wrapping java type: \(javaClassName)") + // Add this class to the list of classes we'll translate. javaClasses.append(javaClass) } + log.info("OK now we go to nested classes") + // Find all of the nested classes for each class, adding them to the list // of classes to be translated if they were already specified. var allClassesToVisit = javaClasses @@ -212,6 +232,16 @@ extension SwiftJava.WrapJavaCommand { return nil } + guard self.shouldExtract(javaClass: nestedClass, config: config) else { + log.info("Skip Java type: \(javaClassName) (does not match minimum access level)") + return nil + } + + guard !nestedClass.isEnum() else { + log.info("Skip Java type: \(javaClassName) (enums do not currently work)") + return nil + } + // Record this as a translated class. let swiftUnqualifiedName = javaClassName.javaClassNameToCanonicalName .defaultSwiftNameForJavaClass @@ -237,9 +267,13 @@ extension SwiftJava.WrapJavaCommand { try translator.validateClassConfiguration() // Translate all of the Java classes into Swift classes. - for javaClass in javaClasses { + + if let singleSwiftFileOutput = config.singleSwiftFileOutput { translator.startNewFile() - let swiftClassDecls = try translator.translateClass(javaClass) + + let swiftClassDecls = try javaClasses.flatMap { + try translator.translateClass($0) + } let importDecls = translator.getImportDecls() let swiftFileText = """ @@ -249,19 +283,53 @@ extension SwiftJava.WrapJavaCommand { """ - var generatedFileOutputDir = self.actualOutputDirectory - if self.swiftMatchPackageDirectoryStructure { - generatedFileOutputDir?.append(path: javaClass.getPackageName().replacing(".", with: "/")) - } - - let swiftFileName = try! translator.getSwiftTypeName(javaClass, preferValueTypes: false) - .swiftName.replacing(".", with: "+") + ".swift" try writeContents( swiftFileText, - outputDirectory: generatedFileOutputDir, - to: swiftFileName, - description: "Java class '\(javaClass.getName())' translation" + outputDirectory: self.actualOutputDirectory, + to: singleSwiftFileOutput, + description: "Java class translation" ) + } else { + for javaClass in javaClasses { + translator.startNewFile() + + let swiftClassDecls = try translator.translateClass(javaClass) + let importDecls = translator.getImportDecls() + + let swiftFileText = """ + // Auto-generated by Java-to-Swift wrapper generator. + \(importDecls.map { $0.description }.joined()) + \(swiftClassDecls.map { $0.description }.joined(separator: "\n")) + + """ + + var generatedFileOutputDir = self.actualOutputDirectory + if self.swiftMatchPackageDirectoryStructure { + generatedFileOutputDir?.append(path: javaClass.getPackageName().replacing(".", with: "/")) + } + + let swiftFileName = try translator.getSwiftTypeName(javaClass, preferValueTypes: false) + .swiftName.replacing(".", with: "+") + ".swift" + try writeContents( + swiftFileText, + outputDirectory: generatedFileOutputDir, + to: swiftFileName, + description: "Java class '\(javaClass.getName())' translation" + ) + } + } + } + + /// Determines whether a method should be extracted for translation. + /// Only look at public and protected methods here. + private func shouldExtract(javaClass: JavaClass, config: Configuration) -> Bool { + switch config.effectiveMinimumInputAccessLevelMode { + case .internal: + return javaClass.isPublic || javaClass.isProtected || javaClass.isPackage + case .package: + return javaClass.isPublic || javaClass.isProtected || javaClass.isPackage + case .public: + return javaClass.isPublic || javaClass.isProtected } } diff --git a/Sources/SwiftJavaTool/CommonOptions.swift b/Sources/SwiftJavaTool/CommonOptions.swift index c313202b..4627381e 100644 --- a/Sources/SwiftJavaTool/CommonOptions.swift +++ b/Sources/SwiftJavaTool/CommonOptions.swift @@ -67,6 +67,9 @@ extension SwiftJava { @Option(name: .long, help: "While scanning a classpath, skip types which match the filter prefix") var filterExclude: [String] = [] + + @Option(help: "A path to a custom swift-java.config to use") + var config: String? = nil } struct CommonJVMOptions: ParsableArguments { @@ -145,4 +148,4 @@ extension HasCommonJVMOptions { func makeJVM(classpathEntries: [String]) throws -> JavaVirtualMachine { try JavaVirtualMachine.shared(classpath: classpathEntries) } -} \ No newline at end of file +} diff --git a/Sources/SwiftJavaTool/SwiftJavaBaseAsyncParsableCommand.swift b/Sources/SwiftJavaTool/SwiftJavaBaseAsyncParsableCommand.swift index 9763b4b3..92818e43 100644 --- a/Sources/SwiftJavaTool/SwiftJavaBaseAsyncParsableCommand.swift +++ b/Sources/SwiftJavaTool/SwiftJavaBaseAsyncParsableCommand.swift @@ -163,14 +163,24 @@ extension SwiftJavaBaseAsyncParsableCommand { func readInitialConfiguration(command: some SwiftJavaBaseAsyncParsableCommand) throws -> Configuration { var earlyConfig: Configuration? - if let moduleBaseDir { + if let configPath = commonOptions.config { + let configURL = URL(filePath: configPath, directoryHint: .notDirectory) + print("[debug][swift-java] Load config from passed in path: \(configURL)") + earlyConfig = try readConfiguration(configPath: configURL) + } else if let moduleBaseDir { print("[debug][swift-java] Load config from module base directory: \(moduleBaseDir.path)") earlyConfig = try readConfiguration(sourceDir: moduleBaseDir.path) } else if let inputSwift = commonOptions.inputSwift { print("[debug][swift-java] Load config from module swift input directory: \(inputSwift)") earlyConfig = try readConfiguration(sourceDir: inputSwift) } - var config = earlyConfig ?? Configuration() + var config: Configuration + if let earlyConfig { + config = earlyConfig + } else { + log.warning("[swift-java] Failed to load initial configuration. Proceeding with empty configuration.") + config = Configuration() + } // override configuration with options from command line config.logLevel = command.logLevel return config diff --git a/Sources/SwiftJavaToolLib/JavaClassTranslator.swift b/Sources/SwiftJavaToolLib/JavaClassTranslator.swift index 0f7aa45d..ce780f90 100644 --- a/Sources/SwiftJavaToolLib/JavaClassTranslator.swift +++ b/Sources/SwiftJavaToolLib/JavaClassTranslator.swift @@ -228,6 +228,11 @@ struct JavaClassTranslator { continue } + guard method.getName().isValidSwiftFunctionName else { + log.warning("Skipping method \(method.getName()) because it is not a valid Swift function name") + continue + } + addMethod(method, isNative: false) } @@ -604,6 +609,15 @@ extension JavaClassTranslator { } } + // --- Parameter types + for parameter in method.getParameters() { + if let parameterizedType = parameter?.getParameterizedType() { + if parameterizedType.isEqualTo(typeParam.as(Type.self)) { + return true + } + } + } + return false } diff --git a/Sources/SwiftJavaToolLib/StringExtras.swift b/Sources/SwiftJavaToolLib/StringExtras.swift index e69f379c..c3ac5390 100644 --- a/Sources/SwiftJavaToolLib/StringExtras.swift +++ b/Sources/SwiftJavaToolLib/StringExtras.swift @@ -35,6 +35,11 @@ extension String { return "`\(self)`" } + /// Returns whether this is a valid Swift function name + var isValidSwiftFunctionName: Bool { + !self.starts(with: "$") + } + /// Replace all occurrences of one character in the string with another. public func replacing(_ character: Character, with replacement: Character) -> String { return replacingOccurrences(of: String(character), with: String(replacement)) diff --git a/Tests/JExtractSwiftTests/JNI/JNIEnumTests.swift b/Tests/JExtractSwiftTests/JNI/JNIEnumTests.swift index 38ef8789..2188bcd6 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIEnumTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIEnumTests.swift @@ -170,17 +170,17 @@ struct JNIEnumTests { """, """ public record First() implements Case { - record $NativeParameters() {} + record _NativeParameters() {} } """, """ public record Second(java.lang.String arg0) implements Case { - record $NativeParameters(java.lang.String arg0) {} + record _NativeParameters(java.lang.String arg0) {} } """, """ public record Third(long x, int y) implements Case { - record $NativeParameters(long x, int y) {} + record _NativeParameters(long x, int y) {} } """ ]) @@ -268,7 +268,7 @@ struct JNIEnumTests { if (getDiscriminator() != Discriminator.SECOND) { return Optional.empty(); } - Second.$NativeParameters $nativeParameters = MyEnum.$getAsSecond(this.$memoryAddress()); + Second._NativeParameters $nativeParameters = MyEnum.$getAsSecond(this.$memoryAddress()); return Optional.of(new Second($nativeParameters.arg0)); } """, @@ -277,7 +277,7 @@ struct JNIEnumTests { if (getDiscriminator() != Discriminator.THIRD) { return Optional.empty(); } - Third.$NativeParameters $nativeParameters = MyEnum.$getAsThird(this.$memoryAddress()); + Third._NativeParameters $nativeParameters = MyEnum.$getAsThird(this.$memoryAddress()); return Optional.of(new Third($nativeParameters.x, $nativeParameters.y)); } """ diff --git a/Tests/JExtractSwiftTests/JNI/JNIProtocolTests.swift b/Tests/JExtractSwiftTests/JNI/JNIProtocolTests.swift index c5302ca6..231c4d25 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIProtocolTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIProtocolTests.swift @@ -12,16 +12,22 @@ // //===----------------------------------------------------------------------===// +import SwiftJavaConfigurationShared import JExtractSwiftLib import Testing @Suite struct JNIProtocolTests { + var config: Configuration { + var config = Configuration() + config.enableJavaCallbacks = true + return config + } + let source = """ public protocol SomeProtocol { - var x: Int64 { get set } - public func method() {} + public func withObject(c: SomeClass) -> SomeClass {} } public protocol B {} @@ -37,6 +43,7 @@ struct JNIProtocolTests { func generatesJavaInterface() throws { try assertOutput( input: source, + config: config, .jni, .java, detectChunkByInitialLines: 1, expectedChunks: [ @@ -50,18 +57,13 @@ struct JNIProtocolTests { import org.swift.swiftkit.core.util.*; """, """ - public interface SomeProtocol extends JNISwiftInstance { - ... + public interface SomeProtocol { + ... + public void method(); + ... + public SomeClass withObject(SomeClass c); + ... } - """, - """ - public long getX(); - """, - """ - public void setX(long newValue); - """, - """ - public void method(); """ ]) } @@ -70,6 +72,7 @@ struct JNIProtocolTests { func generatesJavaClassWithExtends() throws { try assertOutput( input: source, + config: config, .jni, .java, detectChunkByInitialLines: 1, expectedChunks: [ @@ -83,16 +86,17 @@ struct JNIProtocolTests { func takeProtocol_java() throws { try assertOutput( input: source, + config: config, .jni, .java, detectChunkByInitialLines: 1, expectedChunks: [ """ - public static <$T0 extends SomeProtocol, $T1 extends SomeProtocol> void takeProtocol($T0 x, $T1 y) { - SwiftModule.$takeProtocol(x.$memoryAddress(), x.$typeMetadataAddress(), y.$memoryAddress(), y.$typeMetadataAddress()); + public static <_T0 extends SomeProtocol, _T1 extends SomeProtocol> void takeProtocol(_T0 x, _T1 y) { + SwiftModule.$takeProtocol(x, y); } """, """ - private static native void $takeProtocol(long x, long x_typeMetadataAddress, long y, long y_typeMetadataAddress); + private static native void $takeProtocol(java.lang.Object x, java.lang.Object y); """ ]) } @@ -101,43 +105,50 @@ struct JNIProtocolTests { func takeProtocol_swift() throws { try assertOutput( input: source, + config: config, .jni, .swift, detectChunkByInitialLines: 1, expectedChunks: [ """ - @_cdecl("Java_com_example_swift_SwiftModule__00024takeProtocol__JJJJ") - func Java_com_example_swift_SwiftModule__00024takeProtocol__JJJJ(environment: UnsafeMutablePointer!, thisClass: jclass, x: jlong, x_typeMetadataAddress: jlong, y: jlong, y_typeMetadataAddress: jlong) { - guard let xTypeMetadataPointer$ = UnsafeRawPointer(bitPattern: Int(Int64(fromJNI: x_typeMetadataAddress, in: environment))) else { - fatalError("x_typeMetadataAddress memory address was null") - } - let xDynamicType$: Any.Type = unsafeBitCast(xTypeMetadataPointer$, to: Any.Type.self) - guard let xRawPointer$ = UnsafeMutableRawPointer(bitPattern: Int(Int64(fromJNI: x, in: environment))) else { - fatalError("x memory address was null") + final class _SwiftModule_takeGeneric_s_Wrapper: SwiftJavaSomeProtocolWrapper { + let _javaSomeProtocolInterface: JavaSomeProtocol + init(_javaSomeProtocolInterface: JavaSomeProtocol) { + self._javaSomeProtocolInterface = _javaSomeProtocolInterface } - #if hasFeature(ImplicitOpenExistentials) - let xExistential$ = xRawPointer$.load(as: xDynamicType$) as! any (SomeProtocol) - #else - func xDoLoad(_ ty: Ty.Type) -> any (SomeProtocol) { - xRawPointer$.load(as: ty) as! any (SomeProtocol) + } + """, + """ + @_cdecl("Java_com_example_swift_SwiftModule__00024takeProtocol__Ljava_lang_Object_2Ljava_lang_Object_2") + func Java_com_example_swift_SwiftModule__00024takeProtocol__Ljava_lang_Object_2Ljava_lang_Object_2(environment: UnsafeMutablePointer!, thisClass: jclass, x: jobject?, y: jobject?) { + let xswiftObject$: (SomeProtocol) + if environment.interface.IsInstanceOf(environment, x, _JNIMethodIDCache.JNISwiftInstance.class) != 0 { + ... + let xpointer$DynamicType$: Any.Type = unsafeBitCast(xpointer$TypeMetadataPointer$, to: Any.Type.self) + guard let xpointer$RawPointer$ = UnsafeMutableRawPointer(bitPattern: Int(Int64(fromJNI: xpointer$, in: environment))) else { + fatalError("xpointer$ memory address was null") + } + #if hasFeature(ImplicitOpenExistentials) + let xpointer$Existential$ = xpointer$RawPointer$.load(as: xpointer$DynamicType$) as! any (SomeProtocol) + #else + func xpointer$DoLoad(_ ty: Ty.Type) -> any (SomeProtocol) { + xpointer$RawPointer$.load(as: ty) as! any (SomeProtocol) + } + let xpointer$Existential$ = _openExistential(xpointer$DynamicType$, do: xpointer$DoLoad) + #endif + xswiftObject$ = xpointer$Existential$ } - let xExistential$ = _openExistential(xDynamicType$, do: xDoLoad) - #endif - guard let yTypeMetadataPointer$ = UnsafeRawPointer(bitPattern: Int(Int64(fromJNI: y_typeMetadataAddress, in: environment))) else { - fatalError("y_typeMetadataAddress memory address was null") + else { + xswiftObject$ = _SwiftModule_takeProtocol_x_Wrapper(_javaSomeProtocolInterface: JavaSomeProtocol(javaThis: x!, environment: environment)) } - let yDynamicType$: Any.Type = unsafeBitCast(yTypeMetadataPointer$, to: Any.Type.self) - guard let yRawPointer$ = UnsafeMutableRawPointer(bitPattern: Int(Int64(fromJNI: y, in: environment))) else { - fatalError("y memory address was null") + let yswiftObject$: (SomeProtocol) + if environment.interface.IsInstanceOf(environment, y, _JNIMethodIDCache.JNISwiftInstance.class) != 0 { + ... + yswiftObject$ = ypointer$Existential$ } - #if hasFeature(ImplicitOpenExistentials) - let yExistential$ = yRawPointer$.load(as: yDynamicType$) as! any (SomeProtocol) - #else - func yDoLoad(_ ty: Ty.Type) -> any (SomeProtocol) { - yRawPointer$.load(as: ty) as! any (SomeProtocol) + else { + yswiftObject$ = _SwiftModule_takeProtocol_y_Wrapper(_javaSomeProtocolInterface: JavaSomeProtocol(javaThis: y!, environment: environment)) } - let yExistential$ = _openExistential(yDynamicType$, do: yDoLoad) - #endif - SwiftModule.takeProtocol(x: xExistential$, y: yExistential$) + SwiftModule.takeProtocol(x: xswiftObject$, y: yswiftObject$) } """ ] @@ -148,16 +159,17 @@ struct JNIProtocolTests { func takeGeneric_java() throws { try assertOutput( input: source, + config: config, .jni, .java, detectChunkByInitialLines: 1, expectedChunks: [ """ public static void takeGeneric(S s) { - SwiftModule.$takeGeneric(s.$memoryAddress(), s.$typeMetadataAddress()); + SwiftModule.$takeGeneric(s); } """, """ - private static native void $takeGeneric(long s, long s_typeMetadataAddress); + private static native void $takeGeneric(java.lang.Object s); """ ]) } @@ -166,28 +178,30 @@ struct JNIProtocolTests { func takeGeneric_swift() throws { try assertOutput( input: source, + config: config, .jni, .swift, detectChunkByInitialLines: 1, expectedChunks: [ """ - @_cdecl("Java_com_example_swift_SwiftModule__00024takeGeneric__JJ") - func Java_com_example_swift_SwiftModule__00024takeGeneric__JJ(environment: UnsafeMutablePointer!, thisClass: jclass, s: jlong, s_typeMetadataAddress: jlong) { - guard let sTypeMetadataPointer$ = UnsafeRawPointer(bitPattern: Int(Int64(fromJNI: s_typeMetadataAddress, in: environment))) else { - fatalError("s_typeMetadataAddress memory address was null") + final class _SwiftModule_takeGeneric_s_Wrapper: SwiftJavaSomeProtocolWrapper { + let _javaSomeProtocolInterface: JavaSomeProtocol + init(_javaSomeProtocolInterface: JavaSomeProtocol) { + self._javaSomeProtocolInterface = _javaSomeProtocolInterface } - let sDynamicType$: Any.Type = unsafeBitCast(sTypeMetadataPointer$, to: Any.Type.self) - guard let sRawPointer$ = UnsafeMutableRawPointer(bitPattern: Int(Int64(fromJNI: s, in: environment))) else { - fatalError("s memory address was null") + } + """, + """ + @_cdecl("Java_com_example_swift_SwiftModule__00024takeGeneric__Ljava_lang_Object_2") + func Java_com_example_swift_SwiftModule__00024takeGeneric__Ljava_lang_Object_2(environment: UnsafeMutablePointer!, thisClass: jclass, s: jobject?) { + let sswiftObject$: (SomeProtocol) + if environment.interface.IsInstanceOf(environment, s, _JNIMethodIDCache.JNISwiftInstance.class) != 0 { + ... + sswiftObject$ = spointer$Existential$ } - #if hasFeature(ImplicitOpenExistentials) - let sExistential$ = sRawPointer$.load(as: sDynamicType$) as! any (SomeProtocol) - #else - func sDoLoad(_ ty: Ty.Type) -> any (SomeProtocol) { - sRawPointer$.load(as: ty) as! any (SomeProtocol) + else { + sswiftObject$ = _SwiftModule_takeGeneric_s_Wrapper(_javaSomeProtocolInterface: JavaSomeProtocol(javaThis: s!, environment: environment)) } - let sExistential$ = _openExistential(sDynamicType$, do: sDoLoad) - #endif - SwiftModule.takeGeneric(s: sExistential$) + SwiftModule.takeGeneric(s: sswiftObject$) } """ ] @@ -198,16 +212,17 @@ struct JNIProtocolTests { func takeComposite_java() throws { try assertOutput( input: source, + config: config, .jni, .java, detectChunkByInitialLines: 1, expectedChunks: [ """ - public static <$T0 extends SomeProtocol & B> void takeComposite($T0 x) { - SwiftModule.$takeComposite(x.$memoryAddress(), x.$typeMetadataAddress()); + public static <_T0 extends SomeProtocol & B> void takeComposite(_T0 x) { + SwiftModule.$takeComposite(x); } """, """ - private static native void $takeComposite(long x, long x_typeMetadataAddress); + private static native void $takeComposite(java.lang.Object x); """ ]) } @@ -216,28 +231,92 @@ struct JNIProtocolTests { func takeComposite_swift() throws { try assertOutput( input: source, + config: config, .jni, .swift, detectChunkByInitialLines: 1, expectedChunks: [ """ - @_cdecl("Java_com_example_swift_SwiftModule__00024takeComposite__JJ") - func Java_com_example_swift_SwiftModule__00024takeComposite__JJ(environment: UnsafeMutablePointer!, thisClass: jclass, x: jlong, x_typeMetadataAddress: jlong) { - guard let xTypeMetadataPointer$ = UnsafeRawPointer(bitPattern: Int(Int64(fromJNI: x_typeMetadataAddress, in: environment))) else { - fatalError("x_typeMetadataAddress memory address was null") + final class _SwiftModule_takeComposite_x_Wrapper: SwiftJavaSomeProtocolWrapper, SwiftJavaBWrapper { + let _javaSomeProtocolInterface: JavaSomeProtocol + let _javaBInterface: JavaB + init(_javaSomeProtocolInterface: JavaSomeProtocol, _javaBInterface: JavaB) { + self._javaSomeProtocolInterface = _javaSomeProtocolInterface + self._javaBInterface = _javaBInterface } - let xDynamicType$: Any.Type = unsafeBitCast(xTypeMetadataPointer$, to: Any.Type.self) - guard let xRawPointer$ = UnsafeMutableRawPointer(bitPattern: Int(Int64(fromJNI: x, in: environment))) else { - fatalError("x memory address was null") + } + """, + """ + @_cdecl("Java_com_example_swift_SwiftModule__00024takeComposite__Ljava_lang_Object_2") + func Java_com_example_swift_SwiftModule__00024takeComposite__Ljava_lang_Object_2(environment: UnsafeMutablePointer!, thisClass: jclass, x: jobject?) { + let xswiftObject$: (SomeProtocol & B) + if environment.interface.IsInstanceOf(environment, x, _JNIMethodIDCache.JNISwiftInstance.class) != 0 { + let xpointer$ = environment.interface.CallLongMethodA(environment, x, _JNIMethodIDCache.JNISwiftInstance.memoryAddress, []) + let xtypeMetadata$ = environment.interface.CallLongMethodA(environment, x, _JNIMethodIDCache.JNISwiftInstance.typeMetadataAddress, []) + guard let xpointer$TypeMetadataPointer$ = UnsafeRawPointer(bitPattern: Int(Int64(fromJNI: xtypeMetadata$, in: environment))) else { + fatalError("xtypeMetadata$ memory address was null") + } + let xpointer$DynamicType$: Any.Type = unsafeBitCast(xpointer$TypeMetadataPointer$, to: Any.Type.self) + guard let xpointer$RawPointer$ = UnsafeMutableRawPointer(bitPattern: Int(Int64(fromJNI: xpointer$, in: environment))) else { + fatalError("xpointer$ memory address was null") + } + #if hasFeature(ImplicitOpenExistentials) + let xpointer$Existential$ = xpointer$RawPointer$.load(as: xpointer$DynamicType$) as! any (SomeProtocol & B) + #else + func xpointer$DoLoad(_ ty: Ty.Type) -> any (SomeProtocol & B) { + xpointer$RawPointer$.load(as: ty) as! any (SomeProtocol & B) + } + let xpointer$Existential$ = _openExistential(xpointer$DynamicType$, do: xpointer$DoLoad) + #endif + xswiftObject$ = xpointer$Existential$ } - #if hasFeature(ImplicitOpenExistentials) - let xExistential$ = xRawPointer$.load(as: xDynamicType$) as! any (SomeProtocol & B) - #else - func xDoLoad(_ ty: Ty.Type) -> any (SomeProtocol & B) { - xRawPointer$.load(as: ty) as! any (SomeProtocol & B) + else { + xswiftObject$ = _SwiftModule_takeComposite_x_Wrapper(_javaSomeProtocolInterface: JavaSomeProtocol(javaThis: x!, environment: environment), _javaBInterface: JavaB(javaThis: x!, environment: environment)) } - let xExistential$ = _openExistential(xDynamicType$, do: xDoLoad) - #endif - SwiftModule.takeComposite(x: xExistential$) + SwiftModule.takeComposite(x: xswiftObject$) + } + """ + ] + ) + } + + @Test + func generatesProtocolWrappers() throws { + try assertOutput( + input: source, + config: config, + .jni, .swift, + detectChunkByInitialLines: 1, + expectedChunks: [ + """ + protocol SwiftJavaSomeProtocolWrapper: SomeProtocol { + var _javaSomeProtocolInterface: JavaSomeProtocol { get } + } + """, + """ + extension SwiftJavaSomeProtocolWrapper { + public func method() { + _javaSomeProtocolInterface.method() + } + public func withObject(c: SomeClass) -> SomeClass { + let cClass = try! JavaClass(environment: JavaVirtualMachine.shared().environment()) + let cPointer = UnsafeMutablePointer.allocate(capacity: 1) + cPointer.initialize(to: c) + guard let unwrapped$ = _javaSomeProtocolInterface.withObject(cClass.wrapMemoryAddressUnsafe(Int64(Int(bitPattern: cPointer)))) else { + fatalError("Upcall to withObject unexpectedly returned nil") + } + let result$MemoryAddress$ = unwrapped$.as(JavaJNISwiftInstance.self)!.memoryAddress() + let result$Pointer = UnsafeMutablePointer(bitPattern: Int(result$MemoryAddress$))! + return result$Pointer.pointee + } + } + """, + """ + protocol SwiftJavaBWrapper: B { + var _javaBInterface: JavaB { get } + } + """, + """ + extension SwiftJavaBWrapper { } """ ] diff --git a/Tests/JExtractSwiftTests/MemoryManagementModeTests.swift b/Tests/JExtractSwiftTests/MemoryManagementModeTests.swift index 2228aad8..7e78434d 100644 --- a/Tests/JExtractSwiftTests/MemoryManagementModeTests.swift +++ b/Tests/JExtractSwiftTests/MemoryManagementModeTests.swift @@ -99,7 +99,7 @@ struct MemoryManagementModeTests { } """, """ - public MyClass f(SwiftArena swiftArena$); + public MyClass f(); """ ] ) diff --git a/Tests/SwiftJavaToolLibTests/WrapJavaTests/GenericsWrapJavaTests.swift b/Tests/SwiftJavaToolLibTests/WrapJavaTests/GenericsWrapJavaTests.swift index cba7b38f..ceb05df9 100644 --- a/Tests/SwiftJavaToolLibTests/WrapJavaTests/GenericsWrapJavaTests.swift +++ b/Tests/SwiftJavaToolLibTests/WrapJavaTests/GenericsWrapJavaTests.swift @@ -338,6 +338,45 @@ final class GenericsWrapJavaTests: XCTestCase { ) } + func test_wrapJava_genericMethodTypeErasure_customInterface_staticMethods() async throws { + let classpathURL = try await compileJava( + """ + package com.example; + + interface MyInterface {} + + final class Public { + public static void useInterface(T myInterface) { } + } + """) + + try assertWrapJavaOutput( + javaClassNames: [ + "com.example.MyInterface", + "com.example.Public" + ], + classpath: [classpathURL], + expectedChunks: [ + """ + @JavaInterface("com.example.MyInterface") + public struct MyInterface { + """, + """ + @JavaClass("com.example.Public") + open class Public: JavaObject { + """, + """ + extension JavaClass { + """, + """ + @JavaStaticMethod + public func useInterface(_ arg0: T?) + } + """ + ] + ) + } + // TODO: this should be improved some more, we need to generated a `: Map` on the Swift side func test_wrapJava_genericMethodTypeErasure_genericExtendsMap() async throws { let classpathURL = try await compileJava( @@ -370,4 +409,4 @@ final class GenericsWrapJavaTests: XCTestCase { ) } -} \ No newline at end of file +} From a33d709b28bb09b81cce248212f804e21b57f59d Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Wed, 3 Dec 2025 12:44:21 +0900 Subject: [PATCH 419/426] test: add tests for @Unsigned in methods in jextract JNI mode (#475) --- .../JExtract/JExtractGenerationMode.swift | 2 +- .../UnsignedNumberTests.swift | 487 +++++++++++------- 2 files changed, 315 insertions(+), 174 deletions(-) diff --git a/Sources/SwiftJavaConfigurationShared/JExtract/JExtractGenerationMode.swift b/Sources/SwiftJavaConfigurationShared/JExtract/JExtractGenerationMode.swift index 1ad331da..8e11d82b 100644 --- a/Sources/SwiftJavaConfigurationShared/JExtract/JExtractGenerationMode.swift +++ b/Sources/SwiftJavaConfigurationShared/JExtract/JExtractGenerationMode.swift @@ -13,7 +13,7 @@ //===----------------------------------------------------------------------===// /// Determines which source generation mode JExtract should be using: JNI or Foreign Function and Memory. -public enum JExtractGenerationMode: String, Codable { +public enum JExtractGenerationMode: String, Sendable, Codable { /// Foreign Value and Memory API case ffm diff --git a/Tests/JExtractSwiftTests/UnsignedNumberTests.swift b/Tests/JExtractSwiftTests/UnsignedNumberTests.swift index 8109714c..f3f78409 100644 --- a/Tests/JExtractSwiftTests/UnsignedNumberTests.swift +++ b/Tests/JExtractSwiftTests/UnsignedNumberTests.swift @@ -18,251 +18,392 @@ import Testing final class UnsignedNumberTests { - @Test("Import: UInt16 (char)") - func unsignedChar() throws { + @Test( + "Import: UInt16 (char)", + arguments: [ + ( + JExtractGenerationMode.ffm, + /* expected chunks */ + [ + """ + /** + * {@snippet lang=c : + * void swiftjava_SwiftModule_unsignedChar__(uint16_t arg) + * } + */ + private static class swiftjava_SwiftModule_unsignedChar__ { + private static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( + /* arg: */SwiftValueLayout.SWIFT_UINT16 + ); + """, + """ + public static void unsignedChar(@Unsigned char arg) { + swiftjava_SwiftModule_unsignedChar__.call(arg); + } + """, + ] + ), + ( + JExtractGenerationMode.jni, + /* expected chunks */ + [ + """ + public static void unsignedChar(@Unsigned char arg) { + SwiftModule.$unsignedChar(arg); + } + private static native void $unsignedChar(char arg); + """, + ] + ) + ]) + func unsignedChar(mode: JExtractGenerationMode, expectedChunks: [String]) throws { try assertOutput( input: "public func unsignedChar(_ arg: UInt16)", - .ffm, .java, + mode, .java, detectChunkByInitialLines: 2, - expectedChunks: [ - """ - /** - * {@snippet lang=c : - * void swiftjava_SwiftModule_unsignedChar__(uint16_t arg) - * } - */ - private static class swiftjava_SwiftModule_unsignedChar__ { - private static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( - /* arg: */SwiftValueLayout.SWIFT_UINT16 - ); - """, - """ - public static void unsignedChar(@Unsigned char arg) { - swiftjava_SwiftModule_unsignedChar__.call(arg); - } - """, - ] + expectedChunks: expectedChunks ) } - @Test("Import: UInt32 (wrap)") - func unsignedInt() throws { + @Test( + "Import: UInt32 (wrap)", + arguments: [ + ( + JExtractGenerationMode.ffm, + /* expected chunks */ + [ + """ + /** + * {@snippet lang=c : + * void swiftjava_SwiftModule_unsignedInt__(uint32_t arg) + * } + */ + private static class swiftjava_SwiftModule_unsignedInt__ { + private static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( + /* arg: */SwiftValueLayout.SWIFT_UINT32 + ); + """, + """ + public static void unsignedInt(com.google.common.primitives.UnsignedInteger arg) { + swiftjava_SwiftModule_unsignedInt__.call(UnsignedNumbers.toPrimitive(arg)); + } + """, + ] + ), + // JNI mode does not support the "wrap" mode + ]) + func unsignedInt_wrap(mode: JExtractGenerationMode, expectedChunks: [String]) throws { var config = Configuration() config.unsignedNumbersMode = .wrapGuava try assertOutput( input: "public func unsignedInt(_ arg: UInt32)", config: config, - .ffm, .java, + mode, .java, detectChunkByInitialLines: 2, - expectedChunks: [ - """ - /** - * {@snippet lang=c : - * void swiftjava_SwiftModule_unsignedInt__(uint32_t arg) - * } - */ - private static class swiftjava_SwiftModule_unsignedInt__ { - private static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( - /* arg: */SwiftValueLayout.SWIFT_UINT32 - ); - """, - """ - public static void unsignedInt(com.google.common.primitives.UnsignedInteger arg) { - swiftjava_SwiftModule_unsignedInt__.call(UnsignedNumbers.toPrimitive(arg)); - } - """, - ] + expectedChunks: expectedChunks ) } - @Test("Import: UInt32 (annotate)") - func unsignedIntAnnotate() throws { + @Test( + "Import: UInt32 (annotate)", + arguments: [ + ( + JExtractGenerationMode.ffm, + /* expected chunks */ + [ + """ + /** + * {@snippet lang=c : + * void swiftjava_SwiftModule_unsignedInt__(uint32_t arg) + * } + */ + private static class swiftjava_SwiftModule_unsignedInt__ { + private static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( + /* arg: */SwiftValueLayout.SWIFT_UINT32 + ); + """, + """ + public static void unsignedInt(@Unsigned int arg) { + swiftjava_SwiftModule_unsignedInt__.call(arg); + } + """, + ] + ), + ( + JExtractGenerationMode.jni, + /* expected chunks */ + [ + """ + public static void unsignedInt(@Unsigned int arg) { + SwiftModule.$unsignedInt(arg); + } + private static native void $unsignedInt(int arg); + """, + ] + ) + ]) + func unsignedIntAnnotate(mode: JExtractGenerationMode, expectedChunks: [String]) throws { var config = Configuration() config.unsignedNumbersMode = .annotate try assertOutput( input: "public func unsignedInt(_ arg: UInt32)", config: config, - .ffm, .java, + mode, .java, detectChunkByInitialLines: 2, - expectedChunks: [ - """ - /** - * {@snippet lang=c : - * void swiftjava_SwiftModule_unsignedInt__(uint32_t arg) - * } - */ - private static class swiftjava_SwiftModule_unsignedInt__ { - private static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( - /* arg: */SwiftValueLayout.SWIFT_UINT32 - ); - """, - """ - public static void unsignedInt(@Unsigned int arg) { - swiftjava_SwiftModule_unsignedInt__.call(arg); - } - """, - ] + expectedChunks: expectedChunks ) } - @Test("Import: return UInt32 (default)") - func returnUnsignedIntDefault() throws { + @Test( + "Import: return UInt32 (default)", + arguments: [ + ( + JExtractGenerationMode.ffm, + /* expected chunks */ + [ + """ + /** + * {@snippet lang=c : + * uint32_t swiftjava_SwiftModule_returnUnsignedInt(void) + * } + */ + private static class swiftjava_SwiftModule_returnUnsignedInt { + private static final FunctionDescriptor DESC = FunctionDescriptor.of( + /* -> */SwiftValueLayout.SWIFT_UINT32 + ); + """, + """ + @Unsigned + public static int returnUnsignedInt() { + return swiftjava_SwiftModule_returnUnsignedInt.call(); + } + """, + ] + ), + ( + JExtractGenerationMode.jni, + /* expected chunks */ + [ + """ + @Unsigned + public static int returnUnsignedInt() { + return SwiftModule.$returnUnsignedInt(); + } + private static native int $returnUnsignedInt(); + """, + ] + ) + ]) + func returnUnsignedIntDefault(mode: JExtractGenerationMode, expectedChunks: [String]) throws { let config = Configuration() try assertOutput( input: "public func returnUnsignedInt() -> UInt32", config: config, - .ffm, .java, + mode, .java, detectChunkByInitialLines: 2, - expectedChunks: [ - """ - /** - * {@snippet lang=c : - * uint32_t swiftjava_SwiftModule_returnUnsignedInt(void) - * } - */ - private static class swiftjava_SwiftModule_returnUnsignedInt { - private static final FunctionDescriptor DESC = FunctionDescriptor.of( - /* -> */SwiftValueLayout.SWIFT_UINT32 - ); - """, - """ - @Unsigned - public static int returnUnsignedInt() { - return swiftjava_SwiftModule_returnUnsignedInt.call(); - } - """, - ] + expectedChunks: expectedChunks ) } - @Test("Import: return UInt64 (wrap)") - func return_unsignedLongWrap() throws { + @Test( + "Import: return UInt64 (wrap)", + arguments: [ + ( + JExtractGenerationMode.ffm, + /* expected chunks */ + [ + """ + /** + * {@snippet lang=c : + * uint64_t swiftjava_SwiftModule_returnUnsignedLong(void) + * } + */ + private static class swiftjava_SwiftModule_returnUnsignedLong { + private static final FunctionDescriptor DESC = FunctionDescriptor.of( + /* -> */SwiftValueLayout.SWIFT_UINT64 + ); + """, + """ + public static com.google.common.primitives.UnsignedLong returnUnsignedLong() { + return com.google.common.primitives.UnsignedLong.fromLongBits(swiftjava_SwiftModule_returnUnsignedLong.call()); + } + """, + ] + ), + // JNI mode does not support "wrap" mode + ]) + func return_unsignedLongWrap(mode: JExtractGenerationMode, expectedChunks: [String]) throws { var config = Configuration() config.unsignedNumbersMode = .wrapGuava try assertOutput( input: "public func returnUnsignedLong() -> UInt64", config: config, - .ffm, .java, + mode, .java, detectChunkByInitialLines: 2, - expectedChunks: [ - """ - /** - * {@snippet lang=c : - * uint64_t swiftjava_SwiftModule_returnUnsignedLong(void) - * } - */ - private static class swiftjava_SwiftModule_returnUnsignedLong { - private static final FunctionDescriptor DESC = FunctionDescriptor.of( - /* -> */SwiftValueLayout.SWIFT_UINT64 - ); - """, - """ - public static com.google.common.primitives.UnsignedLong returnUnsignedLong() { - return com.google.common.primitives.UnsignedLong.fromLongBits(swiftjava_SwiftModule_returnUnsignedLong.call()); - } - """, - ] + expectedChunks: expectedChunks ) } - @Test("Import: return UInt64 (annotate)") - func return_unsignedLong_annotate() throws { + @Test( + "Import: return UInt64 (annotate)", + arguments: [ + ( + JExtractGenerationMode.ffm, + /* expected chunks */ + [ + """ + /** + * {@snippet lang=c : + * uint64_t swiftjava_SwiftModule_returnUnsignedLong(void) + * } + */ + private static class swiftjava_SwiftModule_returnUnsignedLong { + private static final FunctionDescriptor DESC = FunctionDescriptor.of( + /* -> */SwiftValueLayout.SWIFT_UINT64 + ); + """, + """ + @Unsigned + public static long returnUnsignedLong() { + return swiftjava_SwiftModule_returnUnsignedLong.call(); + } + """, + ] + ), + ( + JExtractGenerationMode.jni, + /* expected chunks */ + [ + """ + @Unsigned + public static long returnUnsignedLong() { + return SwiftModule.$returnUnsignedLong(); + } + private static native long $returnUnsignedLong(); + """, + ] + ) + ]) + func return_unsignedLong_annotate(mode: JExtractGenerationMode, expectedChunks: [String]) throws { var config = Configuration() config.unsignedNumbersMode = .annotate try assertOutput( input: "public func returnUnsignedLong() -> UInt64", config: config, - .ffm, .java, + mode, .java, detectChunkByInitialLines: 2, - expectedChunks: [ - """ - /** - * {@snippet lang=c : - * uint64_t swiftjava_SwiftModule_returnUnsignedLong(void) - * } - */ - private static class swiftjava_SwiftModule_returnUnsignedLong { - private static final FunctionDescriptor DESC = FunctionDescriptor.of( - /* -> */SwiftValueLayout.SWIFT_UINT64 - ); - """, - """ - @Unsigned - public static long returnUnsignedLong() { - return swiftjava_SwiftModule_returnUnsignedLong.call(); - } - """, - ] + expectedChunks: expectedChunks ) } - @Test("Import: take UInt64 (annotate)") - func take_unsignedLong_annotate() throws { + @Test( + "Import: take UInt64 (annotate)", + arguments: [ + ( + JExtractGenerationMode.ffm, + /* expected chunks */ + [ + """ + /** + * {@snippet lang=c : + * void swiftjava_SwiftModule_takeUnsignedLong_arg(uint64_t arg) + * } + */ + private static class swiftjava_SwiftModule_takeUnsignedLong_arg { + private static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( + /* arg: */SwiftValueLayout.SWIFT_UINT64 + ); + """, + """ + public static void takeUnsignedLong(@Unsigned long arg) { + swiftjava_SwiftModule_takeUnsignedLong_arg.call(arg); + } + """, + ] + ), + ( + JExtractGenerationMode.jni, + /* expected chunks */ + [ + """ + public static void takeUnsignedLong(@Unsigned long arg) { + SwiftModule.$takeUnsignedLong(arg); + } + private static native void $takeUnsignedLong(long arg); + """, + ] + ) + ]) + func take_unsignedLong_annotate(mode: JExtractGenerationMode, expectedChunks: [String]) throws { var config = Configuration() config.unsignedNumbersMode = .annotate try assertOutput( input: "public func takeUnsignedLong(arg: UInt64)", config: config, - .ffm, .java, + mode, .java, detectChunkByInitialLines: 2, - expectedChunks: [ - """ - /** - * {@snippet lang=c : - * void swiftjava_SwiftModule_takeUnsignedLong_arg(uint64_t arg) - * } - */ - private static class swiftjava_SwiftModule_takeUnsignedLong_arg { - private static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( - /* arg: */SwiftValueLayout.SWIFT_UINT64 - ); - """, - """ - public static void takeUnsignedLong(@Unsigned long arg) { - swiftjava_SwiftModule_takeUnsignedLong_arg.call(arg); - } - """, - ] + expectedChunks: expectedChunks ) } - @Test("Import: take UInt64 return UInt32 (annotate)") - func echo_unsignedLong_annotate() throws { + @Test( + "Import: take UInt64 return UInt32 (annotate)", + arguments: [ + ( + JExtractGenerationMode.ffm, + /* expected chunks */ + [ + """ + /** + * {@snippet lang=c : + * uint32_t swiftjava_SwiftModule_unsignedLong_first_second(uint64_t first, uint32_t second) + * } + */ + private static class swiftjava_SwiftModule_unsignedLong_first_second { + private static final FunctionDescriptor DESC = FunctionDescriptor.of( + /* -> */SwiftValueLayout.SWIFT_UINT32 + /* first: */SwiftValueLayout.SWIFT_UINT64 + /* second: */SwiftValueLayout.SWIFT_UINT32 + ); + """, + """ + @Unsigned + public static int unsignedLong(@Unsigned long first, @Unsigned int second) { + return swiftjava_SwiftModule_unsignedLong_first_second.call(first, second); + } + """, + ] + ), + ( + JExtractGenerationMode.jni, + /* expected chunks */ + [ + """ + @Unsigned + public static int unsignedLong(@Unsigned long first, @Unsigned int second) { + return SwiftModule.$unsignedLong(first, second); + } + private static native int $unsignedLong(long first, int second); + """, + ] + ), + ]) + func echo_unsignedLong_annotate(mode: JExtractGenerationMode, expectedChunks: [String]) throws { var config = Configuration() config.unsignedNumbersMode = .annotate try assertOutput( input: "public func unsignedLong(first: UInt64, second: UInt32) -> UInt32", config: config, - .ffm, .java, + mode, .java, detectChunkByInitialLines: 2, - expectedChunks: [ - """ - /** - * {@snippet lang=c : - * uint32_t swiftjava_SwiftModule_unsignedLong_first_second(uint64_t first, uint32_t second) - * } - */ - private static class swiftjava_SwiftModule_unsignedLong_first_second { - private static final FunctionDescriptor DESC = FunctionDescriptor.of( - /* -> */SwiftValueLayout.SWIFT_UINT32 - /* first: */SwiftValueLayout.SWIFT_UINT64 - /* second: */SwiftValueLayout.SWIFT_UINT32 - ); - """, - """ - @Unsigned - public static int unsignedLong(@Unsigned long first, @Unsigned int second) { - return swiftjava_SwiftModule_unsignedLong_first_second.call(first, second); - } - """, - ] + expectedChunks: expectedChunks ) } } From 670f640522e5094a3f7b94e02859b25253dc6c8d Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Wed, 3 Dec 2025 16:53:24 +0900 Subject: [PATCH 420/426] Move some tests ouf of sample app into tests (#476) --- .../MySwiftLibrary/MySwiftLibrary.swift | 18 ++++++ .../com/example/swift/HelloJava2Swift.java | 4 +- .../com/example/swift/WithBufferTest.java | 60 +++++++++++++++++++ 3 files changed, 79 insertions(+), 3 deletions(-) create mode 100644 Samples/SwiftJavaExtractFFMSampleApp/src/test/java/com/example/swift/WithBufferTest.java diff --git a/Samples/SwiftJavaExtractFFMSampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift b/Samples/SwiftJavaExtractFFMSampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift index cdd61c12..9929f888 100644 --- a/Samples/SwiftJavaExtractFFMSampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift +++ b/Samples/SwiftJavaExtractFFMSampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift @@ -63,6 +63,24 @@ public func withBuffer(body: (UnsafeRawBufferPointer) -> Void) { body(globalBuffer) } +public func getArray() -> [UInt8] { + return [1, 2, 3] +} + +public func sumAllByteArrayElements(actuallyAnArray: UnsafeRawPointer, count: Int) -> Int { + let bufferPointer = UnsafeRawBufferPointer(start: actuallyAnArray, count: count) + let array = Array(bufferPointer) + return Int(array.reduce(0, { partialResult, element in partialResult + element })) +} + +public func sumAllByteArrayElements(array: [UInt8]) -> Int { + return Int(array.reduce(0, { partialResult, element in partialResult + element })) +} + +public func withArray(body: ([UInt8]) -> Void) { + body([1, 2, 3]) +} + public func globalReceiveSomeDataProtocol(data: some DataProtocol) -> Int { p(Array(data).description) return data.count diff --git a/Samples/SwiftJavaExtractFFMSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java b/Samples/SwiftJavaExtractFFMSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java index cecb1231..a1312547 100644 --- a/Samples/SwiftJavaExtractFFMSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java +++ b/Samples/SwiftJavaExtractFFMSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java @@ -52,9 +52,7 @@ static void examples() { CallTraces.trace("getGlobalBuffer().byteSize()=" + MySwiftLibrary.getGlobalBuffer().byteSize()); - MySwiftLibrary.withBuffer((buf) -> { - CallTraces.trace("withBuffer{$0.byteSize()}=" + buf.byteSize()); - }); + // Example of using an arena; MyClass.deinit is run at end of scope try (var arena = AllocatingSwiftArena.ofConfined()) { MySwiftClass obj = MySwiftClass.init(2222, 7777, arena); diff --git a/Samples/SwiftJavaExtractFFMSampleApp/src/test/java/com/example/swift/WithBufferTest.java b/Samples/SwiftJavaExtractFFMSampleApp/src/test/java/com/example/swift/WithBufferTest.java new file mode 100644 index 00000000..54206423 --- /dev/null +++ b/Samples/SwiftJavaExtractFFMSampleApp/src/test/java/com/example/swift/WithBufferTest.java @@ -0,0 +1,60 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package com.example.swift; + +import org.junit.jupiter.api.Test; +import org.swift.swiftkit.core.*; +import org.swift.swiftkit.ffm.*; + +import static org.junit.jupiter.api.Assertions.*; + +import java.lang.foreign.ValueLayout; +import java.util.Arrays; +import java.util.concurrent.atomic.AtomicLong; +import java.util.stream.IntStream; + +public class WithBufferTest { + @Test + void test_withBuffer() { + AtomicLong bufferSize = new AtomicLong(); + MySwiftLibrary.withBuffer((buf) -> { + CallTraces.trace("withBuffer{$0.byteSize()}=" + buf.byteSize()); + bufferSize.set(buf.byteSize()); + }); + + assertEquals(124, bufferSize.get()); + } + + @Test + void test_sumAllByteArrayElements_throughMemorySegment() { + byte[] bytes = new byte[124]; + Arrays.fill(bytes, (byte) 1); + + try (var arena = AllocatingSwiftArena.ofConfined()) { + // NOTE: We cannot use MemorySegment.ofArray because that creates a HEAP backed segment and therefore cannot pass into native: + // java.lang.IllegalArgumentException: Heap segment not allowed: MemorySegment{ kind: heap, heapBase: [B@5b6ec132, address: 0x0, byteSize: 124 } + // MemorySegment bytesSegment = MemorySegment.ofArray(bytes); // NO COPY (!) + // MySwiftLibrary.sumAllByteArrayElements(bytesSegment, bytes.length); + + var bytesCopy = arena.allocateFrom(ValueLayout.JAVA_BYTE, bytes); + var swiftSideSum = MySwiftLibrary.sumAllByteArrayElements(bytesCopy, bytes.length); + + System.out.println("swiftSideSum = " + swiftSideSum); + + int javaSideSum = IntStream.range(0, bytes.length).map(i -> bytes[i]).sum(); + assertEquals(javaSideSum, swiftSideSum); + } + } +} From 7519b4c2915566c4c80a3436d6b71a889fd56f10 Mon Sep 17 00:00:00 2001 From: Mads Odgaard Date: Wed, 3 Dec 2025 10:32:10 +0100 Subject: [PATCH 421/426] extract `CustomStringConvertible` as `toString()` and fix extensions (#473) * fix extensions * add runtime test * update docs * add `toString` and `toDebugString` * fix merge --- .../Sources/MySwiftLibrary/MySwiftClass.swift | 12 +++ .../com/example/swift/MySwiftClassTest.java | 16 ++++ ...t2JavaGenerator+JavaBindingsPrinting.swift | 26 +++++ ...ift2JavaGenerator+SwiftThunkPrinting.swift | 44 ++++++++- .../JExtractSwiftLib/Swift2JavaVisitor.swift | 9 +- .../SwiftTypes/SwiftTypeLookupContext.swift | 11 +++ .../Documentation.docc/SupportedFeatures.md | 2 +- .../JNI/JNIExtensionTests.swift | 65 +++++++++++++ .../JNI/JNIToStringTests.swift | 96 +++++++++++++++++++ 9 files changed, 276 insertions(+), 5 deletions(-) create mode 100644 Tests/JExtractSwiftTests/JNI/JNIExtensionTests.swift create mode 100644 Tests/JExtractSwiftTests/JNI/JNIToStringTests.swift diff --git a/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftClass.swift b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftClass.swift index e6aed287..72f2fa35 100644 --- a/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftClass.swift +++ b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftClass.swift @@ -99,3 +99,15 @@ public class MySwiftClass { return self.x + other.longValue() } } + +extension MySwiftClass: CustomStringConvertible { + public var description: String { + "MySwiftClass(x: \(x), y: \(y))" + } +} + +extension MySwiftClass: CustomDebugStringConvertible { + public var debugDescription: String { + "debug: MySwiftClass(x: \(x), y: \(y))" + } +} diff --git a/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/MySwiftClassTest.java b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/MySwiftClassTest.java index 860f1641..a1f8a452 100644 --- a/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/MySwiftClassTest.java +++ b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/MySwiftClassTest.java @@ -171,4 +171,20 @@ void getAsyncVariable() throws Exception { assertEquals(42, c1.getGetAsync().get()); } } + + @Test + void toStringTest() { + try (var arena = SwiftArena.ofConfined()) { + MySwiftClass c1 = MySwiftClass.init(20, 10, arena); + assertEquals("MySwiftClass(x: 20, y: 10)", c1.toString()); + } + } + + @Test + void toDebugStringTest() { + try (var arena = SwiftArena.ofConfined()) { + MySwiftClass c1 = MySwiftClass.init(20, 10, arena); + assertEquals("debug: MySwiftClass(x: 20, y: 10)", c1.toDebugString()); + } + } } \ No newline at end of file diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift index c492d439..78cf7d41 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift @@ -260,12 +260,38 @@ extension JNISwift2JavaGenerator { printer.println() } + printToStringMethods(&printer, decl) + printer.println() + printTypeMetadataAddressFunction(&printer, decl) printer.println() printDestroyFunction(&printer, decl) } } + + private func printToStringMethods(_ printer: inout CodePrinter, _ decl: ImportedNominalType) { + printer.printBraceBlock("public String toString()") { printer in + printer.print( + """ + return $toString(this.$memoryAddress()); + """ + ) + } + printer.print("private static native java.lang.String $toString(long selfPointer);") + + printer.println() + + printer.printBraceBlock("public String toDebugString()") { printer in + printer.print( + """ + return $toDebugString(this.$memoryAddress()); + """ + ) + } + printer.print("private static native java.lang.String $toDebugString(long selfPointer);") + } + private func printHeader(_ printer: inout CodePrinter) { printer.print( """ diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift index 85fdc640..13955430 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift @@ -253,7 +253,7 @@ extension JNISwift2JavaGenerator { printer.println() } - + printToStringMethods(&printer, type) printTypeMetadataAddressThunk(&printer, type) printer.println() printDestroyFunctionThunk(&printer, type) @@ -267,6 +267,48 @@ extension JNISwift2JavaGenerator { try printSwiftInterfaceWrapper(&printer, protocolWrapper) } + private func printToStringMethods(_ printer: inout CodePrinter, _ type: ImportedNominalType) { + let selfPointerParam = JavaParameter(name: "selfPointer", type: .long) + let parentName = type.qualifiedName + + printCDecl( + &printer, + javaMethodName: "$toString", + parentName: type.swiftNominal.qualifiedName, + parameters: [ + selfPointerParam + ], + resultType: .javaLangString + ) { printer in + let selfVar = self.printSelfJLongToUnsafeMutablePointer(&printer, swiftParentName: parentName, selfPointerParam) + + printer.print( + """ + return String(describing: \(selfVar).pointee).getJNIValue(in: environment) + """ + ) + } + + printer.println() + + printCDecl( + &printer, + javaMethodName: "$toDebugString", + parentName: type.swiftNominal.qualifiedName, + parameters: [ + selfPointerParam + ], + resultType: .javaLangString + ) { printer in + let selfVar = self.printSelfJLongToUnsafeMutablePointer(&printer, swiftParentName: parentName, selfPointerParam) + + printer.print( + """ + return String(reflecting: \(selfVar).pointee).getJNIValue(in: environment) + """ + ) + } + } private func printEnumDiscriminator(_ printer: inout CodePrinter, _ type: ImportedNominalType) { let selfPointerParam = JavaParameter(name: "selfPointer", type: .long) diff --git a/Sources/JExtractSwiftLib/Swift2JavaVisitor.swift b/Sources/JExtractSwiftLib/Swift2JavaVisitor.swift index ab1ce32f..cf99d11b 100644 --- a/Sources/JExtractSwiftLib/Swift2JavaVisitor.swift +++ b/Sources/JExtractSwiftLib/Swift2JavaVisitor.swift @@ -109,6 +109,12 @@ final class Swift2JavaVisitor { guard let importedNominalType = translator.importedNominalType(node.extendedType) else { return } + + // Add any conforming protocols in the extension + importedNominalType.inheritedTypes += node.inheritanceClause?.inheritedTypes.compactMap { + try? SwiftType($0.type, lookupContext: translator.lookupContext) + } ?? [] + for memberItem in node.memberBlock.members { self.visit(decl: memberItem.decl, in: importedNominalType, sourceFilePath: sourceFilePath) } @@ -374,9 +380,6 @@ final class Swift2JavaVisitor { self.visit(decl: decl, in: imported, sourceFilePath: imported.sourceFilePath) } - // FIXME: why is this un-used - imported.variables.first?.signatureString - if !imported.initializers.contains(where: { $0.functionSignature.parameters.count == 1 && $0.functionSignature.parameters.first?.parameterName == "rawValue" diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftTypeLookupContext.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftTypeLookupContext.swift index 33759a2c..4489b4f6 100644 --- a/Sources/JExtractSwiftLib/SwiftTypes/SwiftTypeLookupContext.swift +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftTypeLookupContext.swift @@ -105,6 +105,17 @@ class SwiftTypeLookupContext { typeDecl = try nominalTypeDeclaration(for: node, sourceFilePath: sourceFilePath) case .protocolDecl(let node): typeDecl = try nominalTypeDeclaration(for: node, sourceFilePath: sourceFilePath) + case .extensionDecl(let node): + // For extensions, we have to perform a unqualified lookup, + // as the extentedType is just the identifier of the type. + + guard case .identifierType(let id) = Syntax(node.extendedType).as(SyntaxEnum.self), + let lookupResult = try unqualifiedLookup(name: Identifier(id.name)!, from: node) + else { + throw TypeLookupError.notType(Syntax(node)) + } + + typeDecl = lookupResult case .typeAliasDecl: fatalError("typealias not implemented") case .associatedTypeDecl: diff --git a/Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md b/Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md index 849b7f01..7161a26c 100644 --- a/Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md +++ b/Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md @@ -92,7 +92,7 @@ SwiftJava's `swift-java jextract` tool automates generating Java bindings from S | Non-escaping closures with primitive arguments/results: `func callMe(maybe: (Int) -> (Double))` | ✅ | ✅ | | Non-escaping closures with object arguments/results: `func callMe(maybe: (JavaObj) -> (JavaObj))` | ❌ | ❌ | | `@escaping` closures: `func callMe(_: @escaping () -> ())` | ❌ | ❌ | -| Swift type extensions: `extension String { func uppercased() }` | 🟡 | 🟡 | +| Swift type extensions: `extension String { func uppercased() }` | ✅ | ✅ | | Swift macros (maybe) | ❌ | ❌ | | Result builders | ❌ | ❌ | | Automatic Reference Counting of class types / lifetime safety | ✅ | ✅ | diff --git a/Tests/JExtractSwiftTests/JNI/JNIExtensionTests.swift b/Tests/JExtractSwiftTests/JNI/JNIExtensionTests.swift new file mode 100644 index 00000000..e6cb1060 --- /dev/null +++ b/Tests/JExtractSwiftTests/JNI/JNIExtensionTests.swift @@ -0,0 +1,65 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import JExtractSwiftLib +import Testing + +@Suite +struct JNIExtensionTests { + let interfaceFile = + """ + extension MyStruct { + public var variableInExtension: String { get } + public func methodInExtension() {} + } + + public protocol MyProtocol {} + public struct MyStruct {} + extension MyStruct: MyProtocol {} + """ + + @Test("Import extensions: Java methods") + func import_javaMethods() throws { + try assertOutput( + input: interfaceFile, + .jni, .java, + detectChunkByInitialLines: 1, + expectedChunks: [ + """ + public final class MyStruct implements JNISwiftInstance, MyProtocol { + ... + public void methodInExtension() { + ... + } + """ + ]) + } + + @Test("Import extensions: Computed variables") + func import_computedVariables() throws { + try assertOutput( + input: interfaceFile, + .jni, .java, + detectChunkByInitialLines: 1, + expectedChunks: [ + """ + public final class MyStruct implements JNISwiftInstance, MyProtocol { + ... + public java.lang.String getVariableInExtension() { + ... + } + """ + ]) + } +} diff --git a/Tests/JExtractSwiftTests/JNI/JNIToStringTests.swift b/Tests/JExtractSwiftTests/JNI/JNIToStringTests.swift new file mode 100644 index 00000000..1059002b --- /dev/null +++ b/Tests/JExtractSwiftTests/JNI/JNIToStringTests.swift @@ -0,0 +1,96 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import JExtractSwiftLib +import Testing +import SwiftJavaConfigurationShared + +@Suite +struct JNIToStringTests { + let source = + """ + public struct MyType {} + """ + + @Test("JNI toString (Java)") + func toString_java() throws { + try assertOutput( + input: source, + .jni, .java, + detectChunkByInitialLines: 1, + expectedChunks: [ + """ + public String toString() { + return $toString(this.$memoryAddress()); + } + """, + """ + private static native java.lang.String $toString(long selfPointer); + """ + ] + ) + } + + @Test("JNI toString (Swift)") + func toString_swift() throws { + try assertOutput( + input: source, + .jni, .swift, + detectChunkByInitialLines: 1, + expectedChunks: [ + """ + @_cdecl("Java_com_example_swift_MyType__00024toString__J") + func Java_com_example_swift_MyType__00024toString__J(environment: UnsafeMutablePointer!, thisClass: jclass, selfPointer: jlong) -> jstring? { + ... + return String(describing: self$.pointee).getJNIValue(in: environment) + } + """, + ] + ) + } + + @Test("JNI toDebugString (Java)") + func toDebugString_java() throws { + try assertOutput( + input: source, + .jni, .java, + detectChunkByInitialLines: 1, + expectedChunks: [ + """ + public String toDebugString() { + return $toDebugString(this.$memoryAddress()); + } + """, + ] + ) + } + + @Test("JNI toDebugString (Swift)") + func toDebugString_swift() throws { + try assertOutput( + input: source, + .jni, .swift, + detectChunkByInitialLines: 1, + expectedChunks: [ + """ + @_cdecl("Java_com_example_swift_MyType__00024toDebugString__J") + func Java_com_example_swift_MyType__00024toDebugString__J(environment: UnsafeMutablePointer!, thisClass: jclass, selfPointer: jlong) -> jstring? { + ... + return String(reflecting: self$.pointee).getJNIValue(in: environment) + } + """, + ] + ) + } +} From c6a56cd61bf11c88b003b8d34cb5ffb98db7a7eb Mon Sep 17 00:00:00 2001 From: Mads Odgaard Date: Wed, 3 Dec 2025 16:13:25 +0100 Subject: [PATCH 422/426] jextract: fix protocols that return java classes. (#479) * fix protocols * remove comments * comments * cleanup --- Package.swift | 1 + .../MySwiftLibrary/ConcreteProtocolAB.swift | 4 ++ .../Sources/MySwiftLibrary/ProtocolA.swift | 1 + .../example/swift/ProtocolCallbacksTest.java | 4 +- .../java/com/example/swift/ProtocolTest.java | 10 ++++- ...t2JavaGenerator+JavaBindingsPrinting.swift | 39 ++++++++++++------- .../Configuration.swift | 5 ++- .../JNI/JNIProtocolTests.swift | 34 ++++++++++++++-- .../MemoryManagementModeTests.swift | 2 +- 9 files changed, 78 insertions(+), 22 deletions(-) diff --git a/Package.swift b/Package.swift index d877ae69..2c56a287 100644 --- a/Package.swift +++ b/Package.swift @@ -460,6 +460,7 @@ let package = Package( .product(name: "SwiftSyntax", package: "swift-syntax"), .product(name: "SwiftSyntaxBuilder", package: "swift-syntax"), .product(name: "ArgumentParser", package: "swift-argument-parser"), + .product(name: "OrderedCollections", package: "swift-collections"), "JavaTypes", "SwiftJavaShared", "SwiftJavaConfigurationShared", diff --git a/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/ConcreteProtocolAB.swift b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/ConcreteProtocolAB.swift index ed55d039..d83fbb28 100644 --- a/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/ConcreteProtocolAB.swift +++ b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/ConcreteProtocolAB.swift @@ -21,6 +21,10 @@ public class ConcreteProtocolAB: ProtocolA, ProtocolB { return "ConcreteProtocolAB" } + public func makeClass() -> MySwiftClass { + return MySwiftClass(x: 10, y: 50) + } + public init(constantA: Int64, constantB: Int64) { self.constantA = constantA self.constantB = constantB diff --git a/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/ProtocolA.swift b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/ProtocolA.swift index d5281b81..6e19596f 100644 --- a/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/ProtocolA.swift +++ b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/ProtocolA.swift @@ -17,6 +17,7 @@ public protocol ProtocolA { var mutable: Int64 { get set } func name() -> String + func makeClass() -> MySwiftClass } public func takeProtocol(_ proto1: any ProtocolA, _ proto2: some ProtocolA) -> Int64 { diff --git a/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/ProtocolCallbacksTest.java b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/ProtocolCallbacksTest.java index e79fd4a3..b4ebe853 100644 --- a/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/ProtocolCallbacksTest.java +++ b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/ProtocolCallbacksTest.java @@ -74,7 +74,7 @@ public String withString(String input) { public void withVoid() {} @Override - public MySwiftClass withObject(MySwiftClass input) { + public MySwiftClass withObject(MySwiftClass input, SwiftArena swiftArena$) { return input; } @@ -84,7 +84,7 @@ public OptionalLong withOptionalInt64(OptionalLong input) { } @Override - public Optional withOptionalObject(Optional input) { + public Optional withOptionalObject(Optional input, SwiftArena swiftArena$) { return input; } } diff --git a/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/ProtocolTest.java b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/ProtocolTest.java index f5d1ffcf..b8159b8a 100644 --- a/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/ProtocolTest.java +++ b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/ProtocolTest.java @@ -73,6 +73,14 @@ void protocolMethod() { } } + @Test + void protocolClassMethod() { + try (var arena = SwiftArena.ofConfined()) { + ProtocolA proto1 = ConcreteProtocolAB.init(10, 5, arena); + assertEquals(10, proto1.makeClass().getX()); + } + } + static class JavaStorage implements Storage { StorageItem item; @@ -81,7 +89,7 @@ static class JavaStorage implements Storage { } @Override - public StorageItem load() { + public StorageItem load(SwiftArena swiftArena$) { return item; } diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift index 78cf7d41..bfa2ff12 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift @@ -144,17 +144,17 @@ extension JNISwift2JavaGenerator { printer.printBraceBlock("public interface \(decl.swiftNominal.name)\(extendsString)") { printer in for initializer in decl.initializers { - printFunctionDowncallMethods(&printer, initializer, skipMethodBody: true, skipArenas: true) + printFunctionDowncallMethods(&printer, initializer, skipMethodBody: true) printer.println() } for method in decl.methods { - printFunctionDowncallMethods(&printer, method, skipMethodBody: true, skipArenas: true) + printFunctionDowncallMethods(&printer, method, skipMethodBody: true) printer.println() } for variable in decl.variables { - printFunctionDowncallMethods(&printer, variable, skipMethodBody: true, skipArenas: true) + printFunctionDowncallMethods(&printer, variable, skipMethodBody: true) printer.println() } } @@ -420,7 +420,7 @@ extension JNISwift2JavaGenerator { printer.print("record _NativeParameters(\(nativeParameters.joined(separator: ", "))) {}") } - self.printJavaBindingWrapperMethod(&printer, translatedCase.getAsCaseFunction, skipMethodBody: false, skipArenas: false) + self.printJavaBindingWrapperMethod(&printer, translatedCase.getAsCaseFunction, skipMethodBody: false) printer.println() } } @@ -428,8 +428,7 @@ extension JNISwift2JavaGenerator { private func printFunctionDowncallMethods( _ printer: inout CodePrinter, _ decl: ImportedFunc, - skipMethodBody: Bool = false, - skipArenas: Bool = false + skipMethodBody: Bool = false ) { guard translatedDecl(for: decl) != nil else { // Failed to translate. Skip. @@ -440,7 +439,7 @@ extension JNISwift2JavaGenerator { printJavaBindingWrapperHelperClass(&printer, decl) - printJavaBindingWrapperMethod(&printer, decl, skipMethodBody: skipMethodBody, skipArenas: skipArenas) + printJavaBindingWrapperMethod(&printer, decl, skipMethodBody: skipMethodBody) } /// Print the helper type container for a user-facing Java API. @@ -486,21 +485,19 @@ extension JNISwift2JavaGenerator { private func printJavaBindingWrapperMethod( _ printer: inout CodePrinter, _ decl: ImportedFunc, - skipMethodBody: Bool, - skipArenas: Bool + skipMethodBody: Bool ) { guard let translatedDecl = translatedDecl(for: decl) else { fatalError("Decl was not translated, \(decl)") } - printJavaBindingWrapperMethod(&printer, translatedDecl, importedFunc: decl, skipMethodBody: skipMethodBody, skipArenas: skipArenas) + printJavaBindingWrapperMethod(&printer, translatedDecl, importedFunc: decl, skipMethodBody: skipMethodBody) } private func printJavaBindingWrapperMethod( _ printer: inout CodePrinter, _ translatedDecl: TranslatedFunctionDecl, importedFunc: ImportedFunc? = nil, - skipMethodBody: Bool, - skipArenas: Bool + skipMethodBody: Bool ) { var modifiers = ["public"] if translatedDecl.isStatic { @@ -531,14 +528,28 @@ extension JNISwift2JavaGenerator { let parametersStr = parameters.joined(separator: ", ") // Print default global arena variation + // If we have enabled javaCallbacks we must emit default + // arena methods for protocols, as this is what + // Swift will call into, when you call a interface from Swift. + let shouldGenerateGlobalArenaVariation: Bool + let isParentProtocol = importedFunc?.parentType?.asNominalType?.isProtocol ?? false + if config.effectiveMemoryManagementMode.requiresGlobalArena && translatedSignature.requiresSwiftArena { + shouldGenerateGlobalArenaVariation = true + } else if isParentProtocol, translatedSignature.requiresSwiftArena, config.effectiveEnableJavaCallbacks { + shouldGenerateGlobalArenaVariation = true + } else { + shouldGenerateGlobalArenaVariation = false + } + + if shouldGenerateGlobalArenaVariation { if let importedFunc { printDeclDocumentation(&printer, importedFunc) } var modifiers = modifiers // If we are a protocol, we emit this as default method - if importedFunc?.parentType?.asNominalTypeDeclaration?.kind == .protocol { + if isParentProtocol { modifiers.insert("default", at: 1) } @@ -555,7 +566,7 @@ extension JNISwift2JavaGenerator { printer.println() } - if translatedSignature.requiresSwiftArena, !skipArenas { + if translatedSignature.requiresSwiftArena { parameters.append("SwiftArena swiftArena$") } if let importedFunc { diff --git a/Sources/SwiftJavaConfigurationShared/Configuration.swift b/Sources/SwiftJavaConfigurationShared/Configuration.swift index 37d1e1e7..e0c40f1c 100644 --- a/Sources/SwiftJavaConfigurationShared/Configuration.swift +++ b/Sources/SwiftJavaConfigurationShared/Configuration.swift @@ -65,7 +65,10 @@ public struct Configuration: Codable { asyncFuncMode ?? .default } - public var enableJavaCallbacks: Bool? // FIXME: default it to false, but that plays not nice with Codable + public var enableJavaCallbacks: Bool? + public var effectiveEnableJavaCallbacks: Bool { + enableJavaCallbacks ?? false + } public var generatedJavaSourcesListFileOutput: String? diff --git a/Tests/JExtractSwiftTests/JNI/JNIProtocolTests.swift b/Tests/JExtractSwiftTests/JNI/JNIProtocolTests.swift index 231c4d25..3b47fd10 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIProtocolTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIProtocolTests.swift @@ -32,7 +32,9 @@ struct JNIProtocolTests { public protocol B {} - public class SomeClass: SomeProtocol {} + public class SomeClass: SomeProtocol { + public func makeClass() -> SomeClass {} + } public func takeProtocol(x: some SomeProtocol, y: any SomeProtocol) public func takeGeneric(s: S) @@ -61,7 +63,29 @@ struct JNIProtocolTests { ... public void method(); ... - public SomeClass withObject(SomeClass c); + public SomeClass withObject(SomeClass c, SwiftArena swiftArena$); + ... + } + """ + ]) + } + + @Test + func emitsDefault() throws { + try assertOutput( + input: source, + config: config, + .jni, .java, + detectChunkByInitialLines: 1, + expectedChunks: [ + """ + public interface SomeProtocol { + ... + public default SomeClass withObject(SomeClass c) { + return withObject(c, SwiftMemoryManagement.GLOBAL_SWIFT_JAVA_ARENA); + } + ... + public SomeClass withObject(SomeClass c, SwiftArena swiftArena$); ... } """ @@ -78,7 +102,11 @@ struct JNIProtocolTests { expectedChunks: [ """ public final class SomeClass implements JNISwiftInstance, SomeProtocol { - """ + ... + public SomeClass makeClass(SwiftArena swiftArena$) { + ... + } + """, ]) } diff --git a/Tests/JExtractSwiftTests/MemoryManagementModeTests.swift b/Tests/JExtractSwiftTests/MemoryManagementModeTests.swift index 7e78434d..2228aad8 100644 --- a/Tests/JExtractSwiftTests/MemoryManagementModeTests.swift +++ b/Tests/JExtractSwiftTests/MemoryManagementModeTests.swift @@ -99,7 +99,7 @@ struct MemoryManagementModeTests { } """, """ - public MyClass f(); + public MyClass f(SwiftArena swiftArena$); """ ] ) From 8d517bf9cd7cebd4c59ff515b4487fefdef78954 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Thu, 4 Dec 2025 22:25:52 +0900 Subject: [PATCH 423/426] Fix jextract subdirectory handling in input Sources (#456) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * config: log-level should encode as string * Properly handle nested directories of Swift Sources in jextract * wip * fix test and cleanup (#1) Co-authored-by: pelekon <13712101+pelekon@users.noreply.github.com> Co-authored-by: Konrad `ktoso` Malawski Co-authored-by: Bartłomiej Bukowiecki Fix `allowGlobalAutomatic` mode for interfaces (#466) Fix JNI caching for native threads (#464) fix extensions (#473) fix protocols that return java classes. (#479) --------- Co-authored-by: Mads Odgaard Co-authored-by: pelekon <13712101+pelekon@users.noreply.github.com> Co-authored-by: Bartłomiej Bukowiecki --- .../JExtractSwiftPlugin.swift | 3 +- Plugins/SwiftJavaPlugin/SwiftJavaPlugin.swift | 4 + .../SwiftTypeInSubDirectory.swift | 21 ++++ .../swift/SwiftTypeInSubDirectoryTest.java | 38 +++++++ .../SwiftTypeInSubDirectory.swift | 21 ++++ .../swift/SwiftTypeInSubDirectoryTest.java | 33 ++++++ Sources/JExtractSwiftLib/CodePrinter.swift | 6 +- ...ift2JavaGenerator+SwiftThunkPrinting.swift | 13 +-- .../FFM/FFMSwift2JavaGenerator.swift | 24 ++-- ...ift2JavaGenerator+SwiftThunkPrinting.swift | 15 ++- .../JNI/JNISwift2JavaGenerator.swift | 26 +++-- Sources/JExtractSwiftLib/Swift2Java.swift | 106 ++++++++++++++---- .../Swift2JavaTranslator.swift | 2 +- .../Configuration.swift | 2 +- 14 files changed, 253 insertions(+), 61 deletions(-) create mode 100644 Samples/SwiftJavaExtractFFMSampleApp/Sources/MySwiftLibrary/LibrarySubDirectory/SwiftTypeInSubDirectory.swift create mode 100644 Samples/SwiftJavaExtractFFMSampleApp/src/test/java/com/example/swift/SwiftTypeInSubDirectoryTest.java create mode 100644 Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/LibrarySubDirectory/SwiftTypeInSubDirectory.swift create mode 100644 Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/SwiftTypeInSubDirectoryTest.java diff --git a/Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift b/Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift index 2808b6d3..e000a6ba 100644 --- a/Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift +++ b/Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift @@ -96,7 +96,7 @@ struct JExtractSwiftBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin { $0.pathExtension == "swift" } - // Output Swift files are just Java filename based converted to Swift files one-to-one + // Output files are flattened filenames of the inputs, with the appended +SwiftJava suffix. var outputSwiftFiles: [URL] = swiftFiles.compactMap { sourceFileURL in guard sourceFileURL.isFileURL else { return nil as URL? @@ -107,7 +107,6 @@ struct JExtractSwiftBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin { fatalError("Could not get relative path for source file \(sourceFilePath)") } let outputURL = outputSwiftDirectory - .appending(path: String(sourceFilePath.dropFirst(sourceDir.count).dropLast(sourceFileURL.lastPathComponent.count + 1))) let inputFileName = sourceFileURL.deletingPathExtension().lastPathComponent return outputURL.appending(path: "\(inputFileName)+SwiftJava.swift") diff --git a/Plugins/SwiftJavaPlugin/SwiftJavaPlugin.swift b/Plugins/SwiftJavaPlugin/SwiftJavaPlugin.swift index a578091f..d7c773aa 100644 --- a/Plugins/SwiftJavaPlugin/SwiftJavaPlugin.swift +++ b/Plugins/SwiftJavaPlugin/SwiftJavaPlugin.swift @@ -173,6 +173,10 @@ struct SwiftJavaBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin { if !outputSwiftFiles.isEmpty { let displayName = "Wrapping \(classes.count) Java classes in Swift target '\(sourceModule.name)'" log("Prepared: \(displayName)") + + for f in outputSwiftFiles { + log("Swift output file: \(f)") + } commands += [ .buildCommand( displayName: displayName, diff --git a/Samples/SwiftJavaExtractFFMSampleApp/Sources/MySwiftLibrary/LibrarySubDirectory/SwiftTypeInSubDirectory.swift b/Samples/SwiftJavaExtractFFMSampleApp/Sources/MySwiftLibrary/LibrarySubDirectory/SwiftTypeInSubDirectory.swift new file mode 100644 index 00000000..e03eab0b --- /dev/null +++ b/Samples/SwiftJavaExtractFFMSampleApp/Sources/MySwiftLibrary/LibrarySubDirectory/SwiftTypeInSubDirectory.swift @@ -0,0 +1,21 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +public final class SwiftTypeInSubDirectory { + public init() {} + + public func hello() -> Int { + 12 + } +} \ No newline at end of file diff --git a/Samples/SwiftJavaExtractFFMSampleApp/src/test/java/com/example/swift/SwiftTypeInSubDirectoryTest.java b/Samples/SwiftJavaExtractFFMSampleApp/src/test/java/com/example/swift/SwiftTypeInSubDirectoryTest.java new file mode 100644 index 00000000..87bcfde8 --- /dev/null +++ b/Samples/SwiftJavaExtractFFMSampleApp/src/test/java/com/example/swift/SwiftTypeInSubDirectoryTest.java @@ -0,0 +1,38 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package com.example.swift; + +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.swift.swiftkit.core.SwiftLibraries; +import org.swift.swiftkit.ffm.AllocatingSwiftArena; + +import java.io.File; +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.*; + +public class SwiftTypeInSubDirectoryTest { + + @Test + void test_MySwiftClass_voidMethod() { + try (var arena = AllocatingSwiftArena.ofConfined()) { + SwiftTypeInSubDirectory o = SwiftTypeInSubDirectory.init(arena); + var num = o.hello(); + assertEquals(12, num); + } + } + +} diff --git a/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/LibrarySubDirectory/SwiftTypeInSubDirectory.swift b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/LibrarySubDirectory/SwiftTypeInSubDirectory.swift new file mode 100644 index 00000000..96b200e8 --- /dev/null +++ b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/LibrarySubDirectory/SwiftTypeInSubDirectory.swift @@ -0,0 +1,21 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +public final class SwiftTypeInSubDirectory { + public init() {} + + public func hello() -> Int64 { + 12 + } +} diff --git a/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/SwiftTypeInSubDirectoryTest.java b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/SwiftTypeInSubDirectoryTest.java new file mode 100644 index 00000000..0debf8f8 --- /dev/null +++ b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/SwiftTypeInSubDirectoryTest.java @@ -0,0 +1,33 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package com.example.swift; + +import org.junit.jupiter.api.Test; +import org.swift.swiftkit.core.SwiftArena; + +import static org.junit.jupiter.api.Assertions.*; + +public class SwiftTypeInSubDirectoryTest { + + @Test + void test_SwiftTypeInSubDirectory_hello() { + try (var arena = SwiftArena.ofConfined()) { + SwiftTypeInSubDirectory o = SwiftTypeInSubDirectory.init(arena); + var num = o.hello(); + assertEquals(12, num); + } + } + +} diff --git a/Sources/JExtractSwiftLib/CodePrinter.swift b/Sources/JExtractSwiftLib/CodePrinter.swift index 1497a61a..ebbe83db 100644 --- a/Sources/JExtractSwiftLib/CodePrinter.swift +++ b/Sources/JExtractSwiftLib/CodePrinter.swift @@ -14,7 +14,11 @@ import Foundation -let PATH_SEPARATOR = "/" // TODO: Windows +#if os(Windows) +let PATH_SEPARATOR = "\\" +#else +let PATH_SEPARATOR = "/" +#endif public struct CodePrinter { var contents: String = "" diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+SwiftThunkPrinting.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+SwiftThunkPrinting.swift index f233ef00..09de1778 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+SwiftThunkPrinting.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+SwiftThunkPrinting.swift @@ -22,16 +22,15 @@ extension FFMSwift2JavaGenerator { } package func writeSwiftExpectedEmptySources() throws { - let pendingFileCount = self.expectedOutputSwiftFiles.count + let pendingFileCount = self.expectedOutputSwiftFileNames.count guard pendingFileCount > 0 else { return // no need to write any empty files, yay } - print("[swift-java] Write empty [\(self.expectedOutputSwiftFiles.count)] 'expected' files in: \(swiftOutputDirectory)/") + log.info("[swift-java] Write empty [\(self.expectedOutputSwiftFileNames.count)] 'expected' files in: \(swiftOutputDirectory)/") - for expectedFileName in self.expectedOutputSwiftFiles { - log.debug("Write SwiftPM-'expected' empty file: \(expectedFileName.bold)") - + for expectedFileName in self.expectedOutputSwiftFileNames { + log.info("Write SwiftPM-'expected' empty file: \(expectedFileName.bold)") var printer = CodePrinter() printer.print("// Empty file generated on purpose") @@ -55,7 +54,7 @@ extension FFMSwift2JavaGenerator { javaPackagePath: nil, filename: moduleFilename) { log.info("Generated: \(moduleFilenameBase.bold).swift (at \(outputFile.absoluteString))") - self.expectedOutputSwiftFiles.remove(moduleFilename) + self.expectedOutputSwiftFileNames.remove(moduleFilename) } } catch { log.warning("Failed to write to Swift thunks: \(moduleFilename)") @@ -93,7 +92,7 @@ extension FFMSwift2JavaGenerator { javaPackagePath: nil, filename: filename) { log.info("Done writing Swift thunks to: \(outputFile.absoluteString)") - self.expectedOutputSwiftFiles.remove(filename) + self.expectedOutputSwiftFileNames.remove(filename) } } catch { log.warning("Failed to write to Swift thunks: \(filename), error: \(error)") diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift index c445d5c9..a0f68ee0 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift @@ -39,7 +39,10 @@ package class FFMSwift2JavaGenerator: Swift2JavaGenerator { /// Because we need to write empty files for SwiftPM, keep track which files we didn't write yet, /// and write an empty file for those. - var expectedOutputSwiftFiles: Set + /// + /// Since Swift files in SwiftPM builds needs to be unique, we use this fact to flatten paths into plain names here. + /// For uniqueness checking "did we write this file already", just checking the name should be sufficient. + var expectedOutputSwiftFileNames: Set package init( config: Configuration, @@ -57,19 +60,22 @@ package class FFMSwift2JavaGenerator: Swift2JavaGenerator { self.javaOutputDirectory = javaOutputDirectory self.lookupContext = translator.lookupContext - // If we are forced to write empty files, construct the expected outputs + // If we are forced to write empty files, construct the expected outputs. + // It is sufficient to use file names only, since SwiftPM requires names to be unique within a module anyway. if translator.config.writeEmptyFiles ?? false { - self.expectedOutputSwiftFiles = Set(translator.inputs.compactMap { (input) -> String? in - guard let filePathPart = input.path.split(separator: "/\(translator.swiftModuleName)/").last else { + self.expectedOutputSwiftFileNames = Set(translator.inputs.compactMap { (input) -> String? in + guard let fileName = input.path.split(separator: PATH_SEPARATOR).last else { return nil } - - return String(filePathPart.replacing(".swift", with: "+SwiftJava.swift")) + guard fileName.hasSuffix(".swift") else { + return nil + } + return String(fileName.replacing(".swift", with: "+SwiftJava.swift")) }) - self.expectedOutputSwiftFiles.insert("\(translator.swiftModuleName)Module+SwiftJava.swift") - self.expectedOutputSwiftFiles.insert("Foundation+SwiftJava.swift") + self.expectedOutputSwiftFileNames.insert("\(translator.swiftModuleName)Module+SwiftJava.swift") + self.expectedOutputSwiftFileNames.insert("Foundation+SwiftJava.swift") } else { - self.expectedOutputSwiftFiles = [] + self.expectedOutputSwiftFileNames = [] } } diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift index 13955430..648c340b 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift @@ -26,16 +26,15 @@ extension JNISwift2JavaGenerator { } package func writeSwiftExpectedEmptySources() throws { - let pendingFileCount = self.expectedOutputSwiftFiles.count + let pendingFileCount = self.expectedOutputSwiftFileNames.count guard pendingFileCount > 0 else { return // no need to write any empty files, yay } - - print("[swift-java] Write empty [\(self.expectedOutputSwiftFiles.count)] 'expected' files in: \(swiftOutputDirectory)/") - - for expectedFileName in self.expectedOutputSwiftFiles { - logger.debug("Write SwiftPM-'expected' empty file: \(expectedFileName.bold)") + logger.info("[swift-java] Write empty [\(self.expectedOutputSwiftFileNames.count)] 'expected' files in: \(swiftOutputDirectory)/") + + for expectedFileName in self.expectedOutputSwiftFileNames { + logger.info("Write SwiftPM-'expected' empty file: \(expectedFileName.bold)") var printer = CodePrinter() printer.print("// Empty file generated on purpose") @@ -61,7 +60,7 @@ extension JNISwift2JavaGenerator { filename: moduleFilename ) { logger.info("Generated: \(moduleFilenameBase.bold).swift (at \(outputFile.absoluteString))") - self.expectedOutputSwiftFiles.remove(moduleFilename) + self.expectedOutputSwiftFileNames.remove(moduleFilename) } // === All types @@ -96,7 +95,7 @@ extension JNISwift2JavaGenerator { javaPackagePath: nil, filename: filename) { logger.info("Done writing Swift thunks to: \(outputFile.absoluteString)") - self.expectedOutputSwiftFiles.remove(filename) + self.expectedOutputSwiftFileNames.remove(filename) } } catch { logger.warning("Failed to write to Swift thunks: \(filename), error: \(error)") diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator.swift index 692b66b6..6c7d9168 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator.swift @@ -45,7 +45,10 @@ package class JNISwift2JavaGenerator: Swift2JavaGenerator { /// Because we need to write empty files for SwiftPM, keep track which files we didn't write yet, /// and write an empty file for those. - var expectedOutputSwiftFiles: Set + /// + /// Since Swift files in SwiftPM builds needs to be unique, we use this fact to flatten paths into plain names here. + /// For uniqueness checking "did we write this file already", just checking the name should be sufficient. + var expectedOutputSwiftFileNames: Set package init( config: Configuration, @@ -65,19 +68,22 @@ package class JNISwift2JavaGenerator: Swift2JavaGenerator { self.javaClassLookupTable = javaClassLookupTable self.lookupContext = translator.lookupContext - // If we are forced to write empty files, construct the expected outputs + // If we are forced to write empty files, construct the expected outputs. + // It is sufficient to use file names only, since SwiftPM requires names to be unique within a module anyway. if translator.config.writeEmptyFiles ?? false { - self.expectedOutputSwiftFiles = Set(translator.inputs.compactMap { (input) -> String? in - guard let filePathPart = input.path.split(separator: "/\(translator.swiftModuleName)/").last else { + self.expectedOutputSwiftFileNames = Set(translator.inputs.compactMap { (input) -> String? in + guard let fileName = input.path.split(separator: PATH_SEPARATOR).last else { return nil } - - return String(filePathPart.replacing(".swift", with: "+SwiftJava.swift")) + guard fileName.hasSuffix(".swift") else { + return nil + } + return String(fileName.replacing(".swift", with: "+SwiftJava.swift")) }) - self.expectedOutputSwiftFiles.insert("\(translator.swiftModuleName)Module+SwiftJava.swift") - self.expectedOutputSwiftFiles.insert("Foundation+SwiftJava.swift") + self.expectedOutputSwiftFileNames.insert("\(translator.swiftModuleName)Module+SwiftJava.swift") + self.expectedOutputSwiftFileNames.insert("Foundation+SwiftJava.swift") } else { - self.expectedOutputSwiftFiles = [] + self.expectedOutputSwiftFileNames = [] } if translator.config.enableJavaCallbacks ?? false { @@ -92,7 +98,7 @@ package class JNISwift2JavaGenerator: Swift2JavaGenerator { try writeSwiftThunkSources() try writeExportedJavaSources() - let pendingFileCount = self.expectedOutputSwiftFiles.count + let pendingFileCount = self.expectedOutputSwiftFileNames.count if pendingFileCount > 0 { print("[swift-java] Write empty [\(pendingFileCount)] 'expected' files in: \(swiftOutputDirectory)/") try writeSwiftExpectedEmptySources() diff --git a/Sources/JExtractSwiftLib/Swift2Java.swift b/Sources/JExtractSwiftLib/Swift2Java.swift index ed76483e..30b6bd92 100644 --- a/Sources/JExtractSwiftLib/Swift2Java.swift +++ b/Sources/JExtractSwiftLib/Swift2Java.swift @@ -17,6 +17,7 @@ import SwiftSyntax import SwiftSyntaxBuilder import SwiftJavaShared import SwiftJavaConfigurationShared +import OrderedCollections public struct SwiftToJava { let config: Configuration @@ -34,6 +35,7 @@ public struct SwiftToJava { let translator = Swift2JavaTranslator(config: config) translator.log.logLevel = config.logLevel ?? .info + let log = translator.log if config.javaPackage == nil || config.javaPackage!.isEmpty { translator.log.warning("Configured java package is '', consider specifying concrete package for generated sources.") @@ -43,28 +45,14 @@ public struct SwiftToJava { fatalError("Missing '--swift-input' directory!") } - translator.log.info("Input swift = \(inputSwift)") + log.info("Input swift = \(inputSwift)") let inputPaths = inputSwift.split(separator: ",").map { URL(string: String($0))! } - translator.log.info("Input paths = \(inputPaths)") + log.info("Input paths = \(inputPaths)") - var allFiles: [URL] = [] - let fileManager = FileManager.default - let log = translator.log - - for path in inputPaths { - log.info("Input path: \(path)") - if isDirectory(url: path) { - if let enumerator = fileManager.enumerator(at: path, includingPropertiesForKeys: nil) { - for case let fileURL as URL in enumerator { - allFiles.append(fileURL) - } - } - } else if path.isFileURL { - allFiles.append(path) - } - } + let allFiles = collectAllFiles(suffix: ".swift", in: inputPaths, log: translator.log) // Register files to the translator. + let fileManager = FileManager.default for file in allFiles { guard canExtract(from: file) else { continue @@ -137,8 +125,82 @@ public struct SwiftToJava { } -func isDirectory(url: URL) -> Bool { - var isDirectory: ObjCBool = false - _ = FileManager.default.fileExists(atPath: url.path, isDirectory: &isDirectory) - return isDirectory.boolValue +extension URL { + var isDirectory: Bool { + var isDir: ObjCBool = false + _ = FileManager.default.fileExists(atPath: self.path, isDirectory: &isDir) + return isDir.boolValue + } +} + +/// Collect all files with given 'suffix', will explore directories recursively. +public func collectAllFiles(suffix: String, in inputPaths: [URL], log: Logger) -> OrderedSet { + guard !inputPaths.isEmpty else { + return [] + } + + let fileManager = FileManager.default + var allFiles: OrderedSet = [] + allFiles.reserveCapacity(32) // rough guesstimate + + let resourceKeys: [URLResourceKey] = [ + .isRegularFileKey, + .isDirectoryKey, + .nameKey + ] + + for path in inputPaths { + do { + try collectFilesFromPath( + path, + suffix: suffix, + fileManager: fileManager, + resourceKeys: resourceKeys, + into: &allFiles, + log: log + ) + } catch { + log.trace("Failed to collect paths in: \(path), skipping.") + } + } + + return allFiles +} + +private func collectFilesFromPath( + _ path: URL, + suffix: String, + fileManager: FileManager, + resourceKeys: [URLResourceKey], + into allFiles: inout OrderedSet, + log: Logger +) throws { + guard fileManager.fileExists(atPath: path.path) else { + return + } + + if path.isDirectory { + let enumerator = fileManager.enumerator( + at: path, + includingPropertiesForKeys: resourceKeys, + options: [.skipsHiddenFiles], + errorHandler: { url, error in + return true + }) + guard let enumerator else { + return + } + + for case let fileURL as URL in enumerator { + try? collectFilesFromPath(fileURL, suffix: suffix, fileManager: fileManager, resourceKeys: resourceKeys, into: &allFiles, log: log) + } + } + + guard path.isFileURL else { + return + } + guard path.lastPathComponent.hasSuffix(suffix) else { + return + } + allFiles.append(path) } diff --git a/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift b/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift index 60b99a63..212a8e46 100644 --- a/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift +++ b/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift @@ -78,7 +78,7 @@ extension Swift2JavaTranslator { } package func add(filePath: String, text: String) { - log.trace("Adding: \(filePath)") + log.info("Adding: \(filePath)") let sourceFileSyntax = Parser.parse(source: text) self.inputs.append(SwiftJavaInputFile(syntax: sourceFileSyntax, path: filePath)) } diff --git a/Sources/SwiftJavaConfigurationShared/Configuration.swift b/Sources/SwiftJavaConfigurationShared/Configuration.swift index e0c40f1c..6e3e2a52 100644 --- a/Sources/SwiftJavaConfigurationShared/Configuration.swift +++ b/Sources/SwiftJavaConfigurationShared/Configuration.swift @@ -322,7 +322,7 @@ public enum LogLevel: String, ExpressibleByStringLiteral, Codable, Hashable { extension LogLevel { public init(from decoder: any Decoder) throws { - var container = try decoder.singleValueContainer() + let container = try decoder.singleValueContainer() let string = try container.decode(String.self) switch string { case "trace": self = .trace From bf5ca011725fcf3917b77a864566b27609595636 Mon Sep 17 00:00:00 2001 From: Mads Odgaard Date: Thu, 4 Dec 2025 14:26:22 +0100 Subject: [PATCH 424/426] fix optional name (#480) --- Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift | 4 ++-- Sources/SwiftJavaToolLib/JavaClassTranslator.swift | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift b/Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift index e000a6ba..0b584721 100644 --- a/Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift +++ b/Plugins/JExtractSwiftPlugin/JExtractSwiftPlugin.swift @@ -342,7 +342,7 @@ struct JExtractSwiftBuildToolPlugin: SwiftJavaPluginProtocol, BuildToolPlugin { case .product(let product): guard let swiftJava = product.sourceModules.first(where: { $0.name == "SwiftJava" }) else { - return nil + continue } // We are inside Sources/SwiftJava @@ -372,4 +372,4 @@ func findExecutable(name: String) -> URL? { } return nil -} \ No newline at end of file +} diff --git a/Sources/SwiftJavaToolLib/JavaClassTranslator.swift b/Sources/SwiftJavaToolLib/JavaClassTranslator.swift index ce780f90..f5b0b890 100644 --- a/Sources/SwiftJavaToolLib/JavaClassTranslator.swift +++ b/Sources/SwiftJavaToolLib/JavaClassTranslator.swift @@ -682,7 +682,8 @@ extension JavaClassTranslator { // --- Handle other effects let throwsStr = javaMethod.throwsCheckedException ? "throws" : "" let swiftMethodName = javaMethod.getName().escapedSwiftName - + let swiftOptionalMethodName = "\(javaMethod.getName())Optional".escapedSwiftName + // Compute the parameters for '@...JavaMethod(...)' let methodAttribute: AttributeSyntax if implementedInSwift { @@ -743,7 +744,7 @@ extension JavaClassTranslator { """ \(methodAttribute)\(raw: accessModifier)\(raw: overrideOpt)func \(raw: swiftMethodName)\(raw: genericParameterClauseStr)(\(raw: parametersStr))\(raw: throwsStr)\(raw: resultTypeStr)\(raw: whereClause) - \(raw: accessModifier)\(raw: overrideOpt)func \(raw: swiftMethodName)Optional\(raw: genericParameterClauseStr)(\(raw: parameters.map(\.clause.description).joined(separator: ", ")))\(raw: throwsStr) -> \(raw: resultOptional)\(raw: whereClause) { + \(raw: accessModifier)\(raw: overrideOpt)func \(raw: swiftOptionalMethodName)\(raw: genericParameterClauseStr)(\(raw: parameters.map(\.clause.description).joined(separator: ", ")))\(raw: throwsStr) -> \(raw: resultOptional)\(raw: whereClause) { \(body) } """ From c6184a36c97035efa86cb01eae001668087003e1 Mon Sep 17 00:00:00 2001 From: Mads Odgaard Date: Fri, 5 Dec 2025 09:25:23 +0100 Subject: [PATCH 425/426] jextract: add array and throwing functions support to java callbacks (#481) --- .../MySwiftLibrary/CallbackProtcol.swift | 30 +++++- .../example/swift/ProtocolCallbacksTest.java | 75 ++++++++++++- ...Generator+InterfaceWrapperGeneration.swift | 102 ++++++++++++++++-- ...ift2JavaGenerator+SwiftThunkPrinting.swift | 3 +- 4 files changed, 198 insertions(+), 12 deletions(-) diff --git a/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/CallbackProtcol.swift b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/CallbackProtcol.swift index 985771be..a874c595 100644 --- a/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/CallbackProtcol.swift +++ b/Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/CallbackProtcol.swift @@ -28,6 +28,11 @@ public protocol CallbackProtocol { func withObject(_ input: MySwiftClass) -> MySwiftClass func withOptionalInt64(_ input: Int64?) -> Int64? func withOptionalObject(_ input: MySwiftClass?) -> Optional + func withInt64Array(_ input: [Int64]) -> [Int64] + func withStringArray(_ input: [String]) -> [String] + func withObjectArray(_ input: [MySwiftClass]) -> [MySwiftClass] + func successfulThrowingFunction() throws + func throwingFunction() throws } public struct CallbackOutput { @@ -43,6 +48,21 @@ public struct CallbackOutput { public let object: MySwiftClass public let optionalInt64: Int64? public let optionalObject: MySwiftClass? + public let int64Array: [Int64] + public let stringArray: [String] + public let objectArray: [MySwiftClass] +} + +public func callProtocolVoid(_ callbacks: some CallbackProtocol) { + callbacks.withVoid(); +} + +public func callProtocolWithFailedThrowingFunction(_ callbacks: some CallbackProtocol) throws { + try callbacks.throwingFunction(); +} + +public func callProtocolWithSuccessfulThrowingFunction(_ callbacks: some CallbackProtocol) throws { + try callbacks.successfulThrowingFunction(); } public func outputCallbacks( @@ -58,7 +78,10 @@ public func outputCallbacks( string: String, object: MySwiftClass, optionalInt64: Int64?, - optionalObject: MySwiftClass? + optionalObject: MySwiftClass?, + int64Array: [Int64], + stringArray: [String], + objectArray: [MySwiftClass] ) -> CallbackOutput { return CallbackOutput( bool: callbacks.withBool(bool), @@ -72,6 +95,9 @@ public func outputCallbacks( string: callbacks.withString(string), object: callbacks.withObject(object), optionalInt64: callbacks.withOptionalInt64(optionalInt64), - optionalObject: callbacks.withOptionalObject(optionalObject) + optionalObject: callbacks.withOptionalObject(optionalObject), + int64Array: callbacks.withInt64Array(int64Array), + stringArray: callbacks.withStringArray(stringArray), + objectArray: callbacks.withObjectArray(objectArray) ) } diff --git a/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/ProtocolCallbacksTest.java b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/ProtocolCallbacksTest.java index b4ebe853..6d70d019 100644 --- a/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/ProtocolCallbacksTest.java +++ b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/ProtocolCallbacksTest.java @@ -87,6 +87,50 @@ public OptionalLong withOptionalInt64(OptionalLong input) { public Optional withOptionalObject(Optional input, SwiftArena swiftArena$) { return input; } + + @Override + public long[] withInt64Array(long[] input) { + return input; + } + + @Override + public String[] withStringArray(String[] input) { + return input; + } + + @Override + public MySwiftClass[] withObjectArray(MySwiftClass[] input, SwiftArena swiftArena$) { + return input; + } + + @Override + public void throwingFunction() throws Exception { + throw new Exception("Failed in Java"); + } + + @Override + public void successfulThrowingFunction() throws Exception { + + } + } + + @Test + void voidTest() { + JavaCallbacks callbacks = new JavaCallbacks(); + MySwiftLibrary.callProtocolVoid(callbacks); + } + + @Test + void throwingFunction_thatDoesNotThrow() { + JavaCallbacks callbacks = new JavaCallbacks(); + assertDoesNotThrow(() -> MySwiftLibrary.callProtocolWithSuccessfulThrowingFunction(callbacks)); + } + + @Test + void throwingFunction_thatThrows() { + JavaCallbacks callbacks = new JavaCallbacks(); + Exception exception = assertThrows(Exception.class, () -> MySwiftLibrary.callProtocolWithFailedThrowingFunction(callbacks)); + assertEquals("Failed in Java", exception.getMessage()); } @Test @@ -95,7 +139,28 @@ void primitiveCallbacks() { JavaCallbacks callbacks = new JavaCallbacks(); var object = MySwiftClass.init(5, 3, arena); var optionalObject = Optional.of(MySwiftClass.init(10, 10, arena)); - var output = MySwiftLibrary.outputCallbacks(callbacks, true, (byte) 1, (char) 16, (short) 16, (int) 32, 64L, 1.34f, 1.34, "Hello from Java!", object, OptionalLong.empty(), optionalObject, arena); + var int64Array = new long[]{1, 2, 3}; + var stringArray = new String[]{"Hey", "there"}; + var objectArray = new MySwiftClass[]{MySwiftClass.init(1, 1, arena), MySwiftClass.init(2, 2, arena)}; + var output = MySwiftLibrary.outputCallbacks( + callbacks, + true, + (byte) 1, + (char) 16, + (short) 16, + (int) 32, + 64L, + 1.34f, + 1.34, + "Hello from Java!", + object, + OptionalLong.empty(), + optionalObject, + int64Array, + stringArray, + objectArray, + arena + ); assertEquals(1, output.getInt8()); assertEquals(16, output.getUint16()); @@ -112,6 +177,14 @@ void primitiveCallbacks() { var optionalObjectOutput = output.getOptionalObject(arena); assertTrue(optionalObjectOutput.isPresent()); assertEquals(10, optionalObjectOutput.get().getX()); + + assertArrayEquals(new long[]{1, 2,3}, output.getInt64Array()); + assertArrayEquals(new String[]{"Hey", "there"}, output.getStringArray()); + + var objectArrayOutput = output.getObjectArray(arena); + assertEquals(2, objectArrayOutput.length); + assertEquals(1, objectArrayOutput[0].getX()); + assertEquals(2, objectArrayOutput[1].getX()); } } } \ No newline at end of file diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+InterfaceWrapperGeneration.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+InterfaceWrapperGeneration.swift index f1e7c685..abf67f3e 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+InterfaceWrapperGeneration.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+InterfaceWrapperGeneration.swift @@ -133,6 +133,10 @@ extension JNISwift2JavaGenerator { private func translateParameter(parameterName: String, type: SwiftType) throws -> UpcallConversionStep { + if type.isDirectlyTranslatedToWrapJava { + return .placeholder + } + switch type { case .nominal(let nominalType): if let knownType = nominalType.nominalTypeDecl.knownTypeKind { @@ -146,12 +150,17 @@ extension JNISwift2JavaGenerator { wrappedType: genericArgs[0] ) - default: - guard knownType.isDirectlyTranslatedToWrapJava else { + case .array: + guard let genericArgs = nominalType.genericArguments, genericArgs.count == 1 else { throw JavaTranslationError.unsupportedSwiftType(type) } + return try translateArrayParameter( + name: parameterName, + elementType: genericArgs[0] + ) - return .placeholder + default: + throw JavaTranslationError.unsupportedSwiftType(type) } } @@ -171,11 +180,32 @@ extension JNISwift2JavaGenerator { wrappedType: wrappedType ) - case .genericParameter, .function, .metatype, .tuple, .existential, .opaque, .composite, .array: + case .array(let elementType): + return try translateArrayParameter(name: parameterName, elementType: elementType) + + case .genericParameter, .function, .metatype, .tuple, .existential, .opaque, .composite: throw JavaTranslationError.unsupportedSwiftType(type) } } + private func translateArrayParameter(name: String, elementType: SwiftType) throws -> UpcallConversionStep { + switch elementType { + case .nominal(let nominalType): + // We assume this is a JExtracted type + return .map( + .placeholder, + body: .toJavaWrapper( + .placeholder, + name: "arrayElement", + nominalType: nominalType + ) + ) + + case .array, .composite, .existential, .function, .genericParameter, .metatype, .opaque, .optional, .tuple: + throw JavaTranslationError.unsupportedSwiftType(.array(elementType)) + } + } + private func translateOptionalParameter(name: String, wrappedType: SwiftType) throws -> UpcallConversionStep { let wrappedConversion = try translateParameter(parameterName: name, type: wrappedType) return .toJavaOptional(.map(.placeholder, body: wrappedConversion)) @@ -190,6 +220,10 @@ extension JNISwift2JavaGenerator { methodName: String, allowNilForObjects: Bool = false ) throws -> UpcallConversionStep { + if type.isDirectlyTranslatedToWrapJava { + return .placeholder + } + switch type { case .nominal(let nominalType): if let knownType = nominalType.nominalTypeDecl.knownTypeKind { @@ -203,11 +237,14 @@ extension JNISwift2JavaGenerator { methodName: methodName ) - default: - guard knownType.isDirectlyTranslatedToWrapJava else { + case .array: + guard let genericArgs = nominalType.genericArguments, genericArgs.count == 1 else { throw JavaTranslationError.unsupportedSwiftType(type) } - return .placeholder + return try self.translateArrayResult(elementType: genericArgs[0]) + + default: + throw JavaTranslationError.unsupportedSwiftType(type) } } @@ -228,11 +265,32 @@ extension JNISwift2JavaGenerator { case .optional(let wrappedType): return try self.translateOptionalResult(wrappedType: wrappedType, methodName: methodName) - case .genericParameter, .function, .metatype, .tuple, .existential, .opaque, .composite, .array: + case .array(let elementType): + return try self.translateArrayResult(elementType: elementType) + + case .genericParameter, .function, .metatype, .tuple, .existential, .opaque, .composite: throw JavaTranslationError.unsupportedSwiftType(type) } } + private func translateArrayResult(elementType: SwiftType) throws -> UpcallConversionStep { + switch elementType { + case .nominal(let nominalType): + // We assume this is a JExtracted type + return .map( + .placeholder, + body: .toSwiftClass( + .unwrapOptional(.placeholder, message: "Element of array was nil"), + name: "arrayElement", + nominalType: nominalType + ) + ) + + case .array, .composite, .existential, .function, .genericParameter, .metatype, .opaque, .optional, .tuple: + throw JavaTranslationError.unsupportedSwiftType(.array(elementType)) + } + } + private func translateOptionalResult(wrappedType: SwiftType, methodName: String) throws -> UpcallConversionStep { // The `fromJavaOptional` will handle the nullability let wrappedConversion = try translateResult( @@ -340,3 +398,31 @@ extension JNISwift2JavaGenerator { } } } + +extension SwiftType { + /// Indicates whether this type is translated by `wrap-java` + /// into the same type as `jextract`. + /// + /// This means we do not have to perform any mapping when passing + /// this type between jextract and wrap-java + var isDirectlyTranslatedToWrapJava: Bool { + switch self { + case .nominal(let swiftNominalType): + guard let knownType = swiftNominalType.nominalTypeDecl.knownTypeKind else { + return false + } + switch knownType { + case .bool, .int, .uint, .int8, .uint8, .int16, .uint16, .int32, .uint32, .int64, .uint64, .float, .double, .string, .void: + return true + default: + return false + } + + case .array(let elementType): + return elementType.isDirectlyTranslatedToWrapJava + + case .genericParameter, .function, .metatype, .optional, .tuple, .existential, .opaque, .composite: + return false + } + } +} diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift index 648c340b..99bd3dff 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift @@ -152,7 +152,8 @@ extension JNISwift2JavaGenerator { conversion.render(&printer, param.parameterName!) } - let javaUpcall = "\(wrapper.javaInterfaceVariableName).\(function.swiftFunctionName)(\(upcallArguments.joined(separator: ", ")))" + let tryClause = function.originalFunctionSignature.isThrowing ? "try " : "" + let javaUpcall = "\(tryClause)\(wrapper.javaInterfaceVariableName).\(function.swiftFunctionName)(\(upcallArguments.joined(separator: ", ")))" let resultType = function.originalFunctionSignature.result.type let result = function.resultConversion.render(&printer, javaUpcall) From 2534f41d61bf118096655d7e60286912a8b36282 Mon Sep 17 00:00:00 2001 From: Zaph <142690769+0xZaph@users.noreply.github.com> Date: Sat, 6 Dec 2025 07:08:20 +0000 Subject: [PATCH 426/426] Ignore unused jboolean (#482) --- ...wift2JavaGenerator+NativeTranslation.swift | 8 +++--- .../JNI/JNIAsyncTests.swift | 26 +++++++++---------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift index b744a33b..d8b0a1d1 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift @@ -1037,7 +1037,7 @@ extension JNISwift2JavaGenerator { printer.print("environment = try! JavaVirtualMachine.shared().environment()") let inner = nativeFunctionSignature.result.conversion.render(&printer, "swiftResult$") if swiftFunctionResultType.isVoid { - printer.print("environment.interface.CallBooleanMethodA(environment, globalFuture, \(completeMethodID), [jvalue(l: nil)])") + printer.print("_ = environment.interface.CallBooleanMethodA(environment, globalFuture, \(completeMethodID), [jvalue(l: nil)])") } else { let result: String if nativeFunctionSignature.result.javaType.requiresBoxing { @@ -1047,7 +1047,7 @@ extension JNISwift2JavaGenerator { result = inner } - printer.print("environment.interface.CallBooleanMethodA(environment, globalFuture, \(completeMethodID), [jvalue(l: \(result))])") + printer.print("_ = environment.interface.CallBooleanMethodA(environment, globalFuture, \(completeMethodID), [jvalue(l: \(result))])") } } @@ -1069,7 +1069,7 @@ extension JNISwift2JavaGenerator { """ let catchEnvironment = try! JavaVirtualMachine.shared().environment() let exception = catchEnvironment.interface.NewObjectA(catchEnvironment, _JNIMethodIDCache.Exception.class, _JNIMethodIDCache.Exception.constructWithMessage, [String(describing: error).getJValue(in: catchEnvironment)]) - catchEnvironment.interface.CallBooleanMethodA(catchEnvironment, globalFuture, \(completeExceptionallyMethodID), [jvalue(l: exception)]) + _ = catchEnvironment.interface.CallBooleanMethodA(catchEnvironment, globalFuture, \(completeExceptionallyMethodID), [jvalue(l: exception)]) """ ) } @@ -1111,4 +1111,4 @@ extension JNISwift2JavaGenerator { } } } -} +} \ No newline at end of file diff --git a/Tests/JExtractSwiftTests/JNI/JNIAsyncTests.swift b/Tests/JExtractSwiftTests/JNI/JNIAsyncTests.swift index f246bd0f..67fe2e7a 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIAsyncTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIAsyncTests.swift @@ -71,7 +71,7 @@ struct JNIAsyncTests { } let swiftResult$ = await SwiftModule.asyncVoid() environment = try! JavaVirtualMachine.shared().environment() - environment.interface.CallBooleanMethodA(environment, globalFuture, _JNIMethodIDCache.CompletableFuture.complete, [jvalue(l: nil)]) + _ = environment.interface.CallBooleanMethodA(environment, globalFuture, _JNIMethodIDCache.CompletableFuture.complete, [jvalue(l: nil)]) } } #endif @@ -84,7 +84,7 @@ struct JNIAsyncTests { } let swiftResult$ = await SwiftModule.asyncVoid() environment = try! JavaVirtualMachine.shared().environment() - environment.interface.CallBooleanMethodA(environment, globalFuture, _JNIMethodIDCache.CompletableFuture.complete, [jvalue(l: nil)]) + _ = environment.interface.CallBooleanMethodA(environment, globalFuture, _JNIMethodIDCache.CompletableFuture.complete, [jvalue(l: nil)]) } } } @@ -146,12 +146,12 @@ struct JNIAsyncTests { do { let swiftResult$ = await try SwiftModule.async() environment = try! JavaVirtualMachine.shared().environment() - environment.interface.CallBooleanMethodA(environment, globalFuture, _JNIMethodIDCache.CompletableFuture.complete, [jvalue(l: nil)]) + _ = environment.interface.CallBooleanMethodA(environment, globalFuture, _JNIMethodIDCache.CompletableFuture.complete, [jvalue(l: nil)]) } catch { let catchEnvironment = try! JavaVirtualMachine.shared().environment() let exception = catchEnvironment.interface.NewObjectA(catchEnvironment, _JNIMethodIDCache.Exception.class, _JNIMethodIDCache.Exception.constructWithMessage, [String(describing: error).getJValue(in: catchEnvironment)]) - catchEnvironment.interface.CallBooleanMethodA(catchEnvironment, globalFuture, _JNIMethodIDCache.CompletableFuture.completeExceptionally, [jvalue(l: exception)]) + _ = catchEnvironment.interface.CallBooleanMethodA(catchEnvironment, globalFuture, _JNIMethodIDCache.CompletableFuture.completeExceptionally, [jvalue(l: exception)]) } } } @@ -166,12 +166,12 @@ struct JNIAsyncTests { do { let swiftResult$ = await try SwiftModule.async() environment = try! JavaVirtualMachine.shared().environment() - environment.interface.CallBooleanMethodA(environment, globalFuture, _JNIMethodIDCache.CompletableFuture.complete, [jvalue(l: nil)]) + _ = environment.interface.CallBooleanMethodA(environment, globalFuture, _JNIMethodIDCache.CompletableFuture.complete, [jvalue(l: nil)]) } catch { let catchEnvironment = try! JavaVirtualMachine.shared().environment() let exception = catchEnvironment.interface.NewObjectA(catchEnvironment, _JNIMethodIDCache.Exception.class, _JNIMethodIDCache.Exception.constructWithMessage, [String(describing: error).getJValue(in: catchEnvironment)]) - catchEnvironment.interface.CallBooleanMethodA(catchEnvironment, globalFuture, _JNIMethodIDCache.CompletableFuture.completeExceptionally, [jvalue(l: exception)]) + _ = catchEnvironment.interface.CallBooleanMethodA(catchEnvironment, globalFuture, _JNIMethodIDCache.CompletableFuture.completeExceptionally, [jvalue(l: exception)]) } } } @@ -234,7 +234,7 @@ struct JNIAsyncTests { let swiftResult$ = await SwiftModule.async(i: Int64(fromJNI: i, in: environment)) environment = try! JavaVirtualMachine.shared().environment() let boxedResult$ = SwiftJavaRuntimeSupport._JNIBoxedConversions.box(swiftResult$.getJNIValue(in: environment), in: environment) - environment.interface.CallBooleanMethodA(environment, globalFuture, _JNIMethodIDCache.CompletableFuture.complete, [jvalue(l: boxedResult$)]) + _ = environment.interface.CallBooleanMethodA(environment, globalFuture, _JNIMethodIDCache.CompletableFuture.complete, [jvalue(l: boxedResult$)]) } } #endif // end of swift(>=6.2) @@ -248,7 +248,7 @@ struct JNIAsyncTests { let swiftResult$ = await SwiftModule.async(i: Int64(fromJNI: i, in: environment)) environment = try! JavaVirtualMachine.shared().environment() let boxedResult$ = SwiftJavaRuntimeSupport._JNIBoxedConversions.box(swiftResult$.getJNIValue(in: environment), in: environment) - environment.interface.CallBooleanMethodA(environment, globalFuture, _JNIMethodIDCache.CompletableFuture.complete, [jvalue(l: boxedResult$)]) + _ = environment.interface.CallBooleanMethodA(environment, globalFuture, _JNIMethodIDCache.CompletableFuture.complete, [jvalue(l: boxedResult$)]) } } return @@ -328,7 +328,7 @@ struct JNIAsyncTests { result$.initialize(to: swiftResult$) let resultBits$ = Int64(Int(bitPattern: result$)) let boxedResult$ = SwiftJavaRuntimeSupport._JNIBoxedConversions.box(resultBits$.getJNIValue(in: environment), in: environment) - environment.interface.CallBooleanMethodA(environment, globalFuture, _JNIMethodIDCache.CompletableFuture.complete, [jvalue(l: boxedResult$)]) + _ = environment.interface.CallBooleanMethodA(environment, globalFuture, _JNIMethodIDCache.CompletableFuture.complete, [jvalue(l: boxedResult$)]) } } #endif @@ -345,7 +345,7 @@ struct JNIAsyncTests { result$.initialize(to: swiftResult$) let resultBits$ = Int64(Int(bitPattern: result$)) let boxedResult$ = SwiftJavaRuntimeSupport._JNIBoxedConversions.box(resultBits$.getJNIValue(in: environment), in: environment) - environment.interface.CallBooleanMethodA(environment, globalFuture, _JNIMethodIDCache.CompletableFuture.complete, [jvalue(l: boxedResult$)]) + _ = environment.interface.CallBooleanMethodA(environment, globalFuture, _JNIMethodIDCache.CompletableFuture.complete, [jvalue(l: boxedResult$)]) } } return @@ -402,7 +402,7 @@ struct JNIAsyncTests { deferEnvironment.interface.DeleteGlobalRef(deferEnvironment, s) } ... - environment.interface.CallBooleanMethodA(environment, globalFuture, _JNIMethodIDCache.CompletableFuture.complete, [jvalue(l: swiftResult$.getJNIValue(in: environment))]) + _ = environment.interface.CallBooleanMethodA(environment, globalFuture, _JNIMethodIDCache.CompletableFuture.complete, [jvalue(l: swiftResult$.getJNIValue(in: environment))]) ... } """ @@ -463,11 +463,11 @@ struct JNIAsyncTests { ... var task: Task? = nil ... - environment.interface.CallBooleanMethodA(environment, globalFuture, _JNIMethodIDCache.SimpleCompletableFuture.complete, [jvalue(l: boxedResult$)]) + _ = environment.interface.CallBooleanMethodA(environment, globalFuture, _JNIMethodIDCache.SimpleCompletableFuture.complete, [jvalue(l: boxedResult$)]) ... } """ ] ) } -} +} \ No newline at end of file